From: Brendan Hansen Date: Wed, 9 Jun 2021 19:34:45 +0000 (-0500) Subject: switched to new font system (bmfont) X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=3a679e846f812d1cc71aba066b1b203f697ea286;p=onyx.git switched to new font system (bmfont) --- diff --git a/modules/bmfont/utils.onyx b/modules/bmfont/utils.onyx new file mode 100644 index 00000000..c4702976 --- /dev/null +++ b/modules/bmfont/utils.onyx @@ -0,0 +1,51 @@ +package bmfont + +#private_file math :: package core.math + +@Incomplete // does not use the size parameter +get_width :: (use font: ^BMFont, text: str, size: f32) -> f32 { + max_x := 0.0f; + x := 0.0f; + + for char: text { + if char == #char "\n" { + max_x = math.max(max_x, x); + x = 0.0f; + continue; + } + + glyph := font->get_glyph(char); + + if glyph == null { + glyph = font->get_glyph(0); + } + + x += ~~ glyph.xadvance * size; + } + + return math.max(max_x, x); +} + +@Incomplete // does not use the size parameter +get_height :: (use font: ^BMFont, text: str, size: f32) -> f32 { + max_y := 0.0f; + y := 0.0f; + + for char: text { + if char == #char "\n" { + y += max_y; + max_y = 0; + continue; + } + + glyph := font->get_glyph(char); + + if glyph == null { + glyph = font->get_glyph(0); + } + + max_y = math.max(max_y, ~~glyph.h * size); + } + + return y + max_y; +} \ No newline at end of file diff --git a/modules/immediate_mode/shaders/alpha_fragment.glsl b/modules/immediate_mode/shaders/alpha_fragment.glsl new file mode 100644 index 00000000..38d89add --- /dev/null +++ b/modules/immediate_mode/shaders/alpha_fragment.glsl @@ -0,0 +1,15 @@ +#version 300 es + +precision mediump float; + +uniform sampler2D u_texture; + +in vec4 v_color; +in vec2 v_texture; + +out vec4 fragColor; + +void main() { + float alpha = texture(u_texture, v_texture).a; + fragColor = v_color * alpha; +} \ No newline at end of file diff --git a/modules/ui/components/button.onyx b/modules/ui/components/button.onyx index c2923805..f5e3d947 100644 --- a/modules/ui/components/button.onyx +++ b/modules/ui/components/button.onyx @@ -54,12 +54,12 @@ button :: (use r: Rectangle, text: str, theme := ^default_button_theme, site := } if is_hot_item(hash) { - move_towards(^button_state.hover_time, 1.0f, 0.1f); + move_towards(^button_state.hover_time, 1.0f, 0.1f); @ThemeConfiguration } else { - move_towards(^button_state.hover_time, 0.0f, 0.1f); + move_towards(^button_state.hover_time, 0.0f, 0.1f); @ThemeConfiguration } - move_towards(^button_state.click_time, 0.0f, 0.08f); + move_towards(^button_state.click_time, 0.0f, 0.08f); @ThemeConfiguration border_width := theme.border_width; width, height := Rectangle.dimensions(r); @@ -70,10 +70,11 @@ button :: (use r: Rectangle, text: str, theme := ^default_button_theme, site := surface_color = color_lerp(button_state.click_time, surface_color, theme.click_color); gfx.rect(.{ x0 + border_width, y0 + border_width }, .{ width - border_width * 2, height - border_width * 2 }, surface_color); - text_width := 0.0f; @Cleanup // font->get_width(text, theme.font_size); - text_height := 0.0f; @Cleanup // font->get_height(text, theme.font_size); + text_width := bmfont.get_width(^font, text, theme.font_size); + text_height := bmfont.get_height(^font, text, theme.font_size); - draw_text_raw(text, x0 + (width - text_width) / 2, y0 + (height - text_height) / 2, theme.font_size, theme.text_color); + @ThemeConfiguration // This always draws the text centered on the button surface. + draw_text_raw(text, x0 + (width - text_width) / 2, y0 + ~~ font.common.baseline * theme.font_size + (height - text_height) / 2, theme.font_size, theme.text_color); if button_state.click_time > 0 || button_state.hover_time > 0 { map.put(^button_states, hash, button_state); diff --git a/modules/ui/resources/fonts/test.fnt b/modules/ui/resources/fonts/test.fnt new file mode 100644 index 00000000..15addba6 --- /dev/null +++ b/modules/ui/resources/fonts/test.fnt @@ -0,0 +1,100 @@ +info face="Fira Code Retina" size=32 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 +common lineHeight=32 base=24 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4 +page id=0 file="test_0.tga" +chars count=96 +char id=-1 x=159 y=0 width=16 height=22 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15 +char id=32 x=252 y=0 width=3 height=1 xoffset=-1 yoffset=31 xadvance=16 page=0 chnl=15 +char id=33 x=249 y=42 width=6 height=19 xoffset=5 yoffset=5 xadvance=16 page=0 chnl=15 +char id=34 x=226 y=79 width=10 height=7 xoffset=3 yoffset=4 xadvance=16 page=0 chnl=15 +char id=35 x=129 y=46 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=36 x=5 y=0 width=14 height=28 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=15 +char id=37 x=97 y=26 width=16 height=20 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 +char id=38 x=98 y=47 width=15 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=39 x=237 y=79 width=4 height=7 xoffset=6 yoffset=4 xadvance=16 page=0 chnl=15 +char id=40 x=56 y=0 width=10 height=27 xoffset=2 yoffset=1 xadvance=16 page=0 chnl=15 +char id=41 x=67 y=0 width=10 height=27 xoffset=4 yoffset=1 xadvance=16 page=0 chnl=15 +char id=42 x=161 y=86 width=14 height=14 xoffset=1 yoffset=8 xadvance=16 page=0 chnl=15 +char id=43 x=176 y=84 width=14 height=13 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15 +char id=44 x=191 y=83 width=6 height=10 xoffset=5 yoffset=19 xadvance=16 page=0 chnl=15 +char id=45 x=17 y=71 width=12 height=3 xoffset=2 yoffset=13 xadvance=16 page=0 chnl=15 +char id=46 x=17 y=111 width=6 height=5 xoffset=5 yoffset=19 xadvance=16 page=0 chnl=15 +char id=47 x=96 y=0 width=14 height=25 xoffset=1 yoffset=2 xadvance=16 page=0 chnl=15 +char id=48 x=15 y=75 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=49 x=44 y=71 width=13 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15 +char id=50 x=72 y=70 width=13 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=51 x=100 y=67 width=13 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=52 x=114 y=26 width=14 height=20 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15 +char id=53 x=128 y=67 width=13 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=54 x=0 y=75 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=55 x=129 y=25 width=12 height=20 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15 +char id=56 x=114 y=47 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=57 x=237 y=0 width=14 height=21 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=58 x=154 y=86 width=6 height=15 xoffset=5 yoffset=9 xadvance=16 page=0 chnl=15 +char id=59 x=142 y=25 width=6 height=20 xoffset=5 yoffset=9 xadvance=16 page=0 chnl=15 +char id=60 x=128 y=87 width=12 height=15 xoffset=2 yoffset=8 xadvance=16 page=0 chnl=15 +char id=61 x=213 y=79 width=12 height=8 xoffset=2 yoffset=11 xadvance=16 page=0 chnl=15 +char id=62 x=60 y=90 width=13 height=15 xoffset=2 yoffset=8 xadvance=16 page=0 chnl=15 +char id=63 x=181 y=63 width=12 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15 +char id=64 x=176 y=0 width=16 height=22 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 +char id=65 x=17 y=51 width=16 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 +char id=66 x=114 y=67 width=13 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15 +char id=67 x=82 y=50 width=15 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=68 x=50 y=50 width=15 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=69 x=86 y=70 width=13 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15 +char id=70 x=168 y=64 width=12 height=19 xoffset=3 yoffset=5 xadvance=16 page=0 chnl=15 +char id=71 x=34 y=51 width=15 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 +char id=72 x=204 y=43 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=73 x=155 y=66 width=12 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15 +char id=74 x=58 y=70 width=13 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=75 x=189 y=43 width=14 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15 +char id=76 x=142 y=66 width=12 height=19 xoffset=3 yoffset=5 xadvance=16 page=0 chnl=15 +char id=77 x=0 y=55 width=16 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 +char id=78 x=159 y=44 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=79 x=168 y=23 width=16 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 +char id=80 x=234 y=43 width=14 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15 +char id=81 x=126 y=0 width=17 height=24 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 +char id=82 x=144 y=46 width=14 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15 +char id=83 x=66 y=50 width=15 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 +char id=84 x=236 y=22 width=16 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 +char id=85 x=174 y=43 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=86 x=219 y=23 width=16 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 +char id=87 x=149 y=24 width=18 height=19 xoffset=-1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=88 x=202 y=23 width=16 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 +char id=89 x=185 y=23 width=16 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15 +char id=90 x=219 y=43 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=91 x=78 y=0 width=8 height=26 xoffset=4 yoffset=1 xadvance=16 page=0 chnl=15 +char id=92 x=111 y=0 width=14 height=25 xoffset=1 yoffset=2 xadvance=16 page=0 chnl=15 +char id=93 x=87 y=0 width=8 height=26 xoffset=4 yoffset=1 xadvance=16 page=0 chnl=15 +char id=94 x=198 y=79 width=14 height=9 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=15 +char id=95 x=24 y=111 width=14 height=3 xoffset=1 yoffset=26 xadvance=16 page=0 chnl=15 +char id=96 x=242 y=79 width=8 height=5 xoffset=4 yoffset=3 xadvance=16 page=0 chnl=15 +char id=97 x=45 y=91 width=14 height=15 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15 +char id=98 x=56 y=28 width=13 height=21 xoffset=2 yoffset=3 xadvance=16 page=0 chnl=15 +char id=99 x=243 y=63 width=12 height=15 xoffset=2 yoffset=9 xadvance=16 page=0 chnl=15 +char id=100 x=42 y=28 width=13 height=21 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15 +char id=101 x=228 y=63 width=14 height=15 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15 +char id=102 x=28 y=29 width=13 height=21 xoffset=2 yoffset=3 xadvance=16 page=0 chnl=15 +char id=103 x=144 y=0 width=14 height=23 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15 +char id=104 x=84 y=27 width=12 height=21 xoffset=2 yoffset=3 xadvance=16 page=0 chnl=15 +char id=105 x=208 y=0 width=13 height=22 xoffset=2 yoffset=2 xadvance=16 page=0 chnl=15 +char id=106 x=20 y=0 width=11 height=28 xoffset=2 yoffset=2 xadvance=16 page=0 chnl=15 +char id=107 x=193 y=0 width=14 height=22 xoffset=2 yoffset=2 xadvance=16 page=0 chnl=15 +char id=108 x=0 y=33 width=13 height=21 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15 +char id=109 x=211 y=63 width=16 height=15 xoffset=0 yoffset=9 xadvance=16 page=0 chnl=15 +char id=110 x=102 y=87 width=12 height=15 xoffset=2 yoffset=9 xadvance=16 page=0 chnl=15 +char id=111 x=0 y=95 width=14 height=15 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15 +char id=112 x=70 y=28 width=13 height=21 xoffset=2 yoffset=9 xadvance=16 page=0 chnl=15 +char id=113 x=14 y=29 width=13 height=21 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15 +char id=114 x=74 y=90 width=13 height=15 xoffset=2 yoffset=9 xadvance=16 page=0 chnl=15 +char id=115 x=88 y=90 width=13 height=15 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15 +char id=116 x=30 y=71 width=13 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15 +char id=117 x=115 y=87 width=12 height=15 xoffset=2 yoffset=9 xadvance=16 page=0 chnl=15 +char id=118 x=15 y=95 width=14 height=15 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15 +char id=119 x=194 y=63 width=16 height=15 xoffset=0 yoffset=9 xadvance=16 page=0 chnl=15 +char id=120 x=30 y=91 width=14 height=15 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15 +char id=121 x=222 y=0 width=14 height=21 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15 +char id=122 x=141 y=87 width=12 height=15 xoffset=2 yoffset=9 xadvance=16 page=0 chnl=15 +char id=123 x=44 y=0 width=11 height=27 xoffset=2 yoffset=1 xadvance=16 page=0 chnl=15 +char id=124 x=0 y=0 width=4 height=32 xoffset=6 yoffset=0 xadvance=16 page=0 chnl=15 +char id=125 x=32 y=0 width=11 height=27 xoffset=3 yoffset=1 xadvance=16 page=0 chnl=15 +char id=126 x=0 y=111 width=16 height=5 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15 diff --git a/modules/ui/resources/fonts/test_0.data b/modules/ui/resources/fonts/test_0.data new file mode 100644 index 00000000..7b2450bd Binary files /dev/null and b/modules/ui/resources/fonts/test_0.data differ diff --git a/modules/ui/ui.onyx b/modules/ui/ui.onyx index 48e4cd2d..16767989 100644 --- a/modules/ui/ui.onyx +++ b/modules/ui/ui.onyx @@ -8,7 +8,7 @@ use package core #private font_texture : gl.GLTexture; @Temporary -DEFAULT_TEXT_SIZE :: 40.0f +DEFAULT_TEXT_SIZE :: 1.0f UI_Id :: #type u32 @@ -34,7 +34,7 @@ mouse_state: MouseState = MouseState.{}; init_ui :: () { init_font(); - map.init(^button_states, default=.{}); + map.init(^button_states, default=.{}, hash_count=4); } clear_buttons :: () { @@ -100,13 +100,15 @@ is_hot_item :: (id: UI_Id) -> bool { return hot_item == id; } -draw_text_raw :: (text: str, x: f32, y: f32, line_height := DEFAULT_TEXT_SIZE, color := gfx.Color4.{1,1,1}) { +draw_text_raw :: (text: str, x: f32, y: f32, size := DEFAULT_TEXT_SIZE, color := gfx.Color4.{1,1,1}) { gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, font_texture); - gfx.set_texture(0); + gfx.use_alpha_shader(0); original_x := x; - baseline := cast(f32) font.common.baseline; + baseline := cast(f32) font.common.baseline * size; + + line_height := cast(f32) font.common.line_height * size; for char: text { if char == #char "\n" { @@ -122,19 +124,14 @@ draw_text_raw :: (text: str, x: f32, y: f32, line_height := DEFAULT_TEXT_SIZE, c assert(glyph != null, "NO NULL GLYPH"); } - // Round to the nearest pixel - tx, ty := math.floor(x + ~~glyph.xoffset + .5), math.floor(y + ~~glyph.yoffset + baseline + .5); - w := math.floor(cast(f32) glyph.w + .5); - h := math.floor(cast(f32) glyph.h + .5); + // Round to the nearest pixel to avoid bleeding to the next glyph + tx, ty := math.floor(x + ~~glyph.xoffset * size + .5), math.floor(y + ~~glyph.yoffset * size - baseline + .5); + w := math.floor(cast(f32) glyph.w * size + .5); + h := math.floor(cast(f32) glyph.h * size + .5); - gfx.textured_rect( - .{ tx, ty }, - .{ w, h }, - .{ glyph.tex_x, glyph.tex_y }, - .{ glyph.tex_w, glyph.tex_h }, - color = color); + gfx.textured_rect(.{ tx, ty }, .{ w, h }, .{ glyph.tex_x, glyph.tex_y }, .{ glyph.tex_w, glyph.tex_h }, color = color); - x += ~~glyph.xadvance; + x += ~~glyph.xadvance * size; } gfx.flush(); @@ -157,7 +154,7 @@ draw_rect :: proc { @Themeing draw_text :: (use r: Rectangle, text: str, theme := ^default_text_theme, site := #callsite) -> bool { - draw_text_raw(text, x0, y0, theme.font_size, theme.text_color); + draw_text_raw(text, x0, y0 + ~~font.common.baseline * theme.font_size, theme.font_size, theme.text_color); } Rectangle :: struct { @@ -195,7 +192,7 @@ Rectangle :: struct { @Relocate Text_Theme :: struct { text_color := gfx.Color4.{ 1, 1, 1 }; - font_size := 18.0f; + font_size := 1.0f; } default_text_theme: Text_Theme = Text_Theme.{}; @@ -217,14 +214,18 @@ get_site_hash :: (site: CallSite, increment := 0) -> UI_Id { } get_text_width :: (text: str, size := DEFAULT_TEXT_SIZE) -> f32 { - @Cleanup - return 0; // font->get_width(text, size); + return font->get_width(text, size); } +@Cleanup +// There should be a way to load multiple fonts and have a font cache. +// The font cache pointers should be stable so you can take a pointer +// to a font and it will remain valid. Probably want some kind of arena +// with a map from i32 -> ^BMFont. #private init_font :: () { - fnt_file_data := #file_contents "./resources/fonts/FiraCode.fnt"; - texture_data := #file_contents "./resources/fonts/FiraCode.data"; + fnt_file_data := #file_contents "./resources/fonts/test.fnt"; + texture_data := #file_contents "./resources/fonts/test_0.data"; font = bmfont.load_bmfont(fnt_file_data); @@ -232,7 +233,7 @@ get_text_width :: (text: str, size := DEFAULT_TEXT_SIZE) -> f32 { font_texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, font_texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, tex_width, tex_height, 0, gl.RGBA, gl.UNSIGNED_BYTE, texture_data); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, tex_width, tex_height, 0, gl.ALPHA, gl.UNSIGNED_BYTE, texture_data); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); diff --git a/src/onyxutils.c b/src/onyxutils.c index 8d1d9ac9..cca3892d 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -225,7 +225,7 @@ void scope_clear(Scope* scope) { // Polymorphic Procedures // -AstNode node_that_signals_a_yield = {}; +AstNode node_that_signals_a_yield = { 0 }; static void ensure_polyproc_cache_is_created(AstPolyProc* pp) { if (pp->concrete_funcs == NULL) {