Bitmap_Font :: struct {
font_texture : Bitmap_Font_Texture;
+ em: f32; // Width of 'M'
+
glyphs : map.Map(u32, Glyph);
Glyph :: struct {
x0, y0, x1, y1: f32;
+ w, h: f32;
}
get_glyph :: (use bmp: ^Bitmap_Font, char: u8) -> ^Glyph {
// NOTE: Assumes pixels are laid out in RGBA format.
get_pixel :: (use texture: ^Bitmap_Font_Texture, x: u32, y: u32) -> u32 {
- return (cast(u32) data[(y * width + x) * Components_Per_Pixel + 0] << 24)
- | (cast(u32) data[(y * width + x) * Components_Per_Pixel + 1] << 16)
- | (cast(u32) data[(y * width + x) * Components_Per_Pixel + 2] << 8)
- | (cast(u32) data[(y * width + x) * Components_Per_Pixel + 3] << 0);
+ return (cast(^u32) data.data)[y * width + x];
+
+ // SPEED: All of these values could be read simultaneously by treating the data
+ // array as a slice of u32, and then not multiplying by Components_Per_Pixel.
+ //
+ // return (cast(u32) data[(y * width + x) * Components_Per_Pixel + 0] << 24)
+ // | (cast(u32) data[(y * width + x) * Components_Per_Pixel + 1] << 16)
+ // | (cast(u32) data[(y * width + x) * Components_Per_Pixel + 2] << 8)
+ // | (cast(u32) data[(y * width + x) * Components_Per_Pixel + 3] << 0);
}
}
bmp: Bitmap_Font;
bmp.font_texture = bft;
- map.init(^bmp.glyphs, .{0,0,0,0});
+ map.init(^bmp.glyphs, .{0,0,0,0,0,0});
success := bitmap_font_prepare_glyphs(^bmp, glyph_str);
assert(success, "Failed to load glyphs out of font.");
g_x0, g_y0 = 0, 0;
for glyph_char: glyph_str {
+ if g_y0 >= font_texture.height do return false;
+
// These will need to be converted to floating point when they are inserted into the glyph,
// but it is easier to think about them as actual pixel coordinates when parsing the glyphs.
x0, y0, x1, y1: u32;
y0 = cast(f32) y0 / ~~font_texture.height,
x1 = cast(f32) x1 / ~~font_texture.width,
y1 = cast(f32) y1 / ~~font_texture.height,
+ w = cast(f32) (x1 - x0) / ~~font_texture.width,
+ h = cast(f32) (y1 - y0) / ~~font_texture.height,
});
g_x0 = x1 + 1;
}
}
+ M_glyph := map.get_ptr(^glyphs, #char "M");
+ if M_glyph != null {
+ em = M_glyph.w * ~~font_texture.width;
+ } else {
+ // ROBUSTNESS: If there is no 'M' in the character set, then just use 16. It will probably be very wrong.
+ em = 16;
+ }
+
return true;
}
init_font();
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+
start_loop :: () -> void #foreign "game" "start_loop" ---
start_loop();
}
init_font :: () {
- font_data := #file_contents "src/res/font.data";
+ font_data := #file_contents "src/res/font_2.data";
bft := bitmap_font.Bitmap_Font_Texture.{
data = font_data,
height = 256,
};
- font = bitmap_font.bitmap_font_create(bft, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 \xff");
+ font = bitmap_font.bitmap_font_create(bft, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 \xff:");
font_texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, font_texture);
gl.setSize(event.resize.width, event.resize.height);
gl.viewport(0, 0, event.resize.width, event.resize.height);
+ gfx.use_ortho_projection(0, ~~window_width, 0, ~~window_height);
}
}
}
+fps := 0;
+fps_timer := 1.0f;
+frames := 0
update :: (dt: f32) {
+ fps_timer -= dt;
+ frames += 1;
+ if fps_timer < 0 {
+ fps = frames;
+ frames = 0;
+ fps_timer = 1.0f;
+ }
}
draw :: () {
gl.clearColor(0.1, 0.1, 0.1, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
- gfx.use_ortho_projection(0, ~~window_width, 0, ~~window_height);
+ fps_buffer : [16] u8;
+ fps_str := conv.str_format("FPS: %i", ~~ fps_buffer, fps);
+ draw_text(fps_str, 0, 0, 32, .{0,1,0});
draw_text("Hello World", 100, 100, 128);
- draw_text("something else...", 100, 230, 32);
+ draw_text("something else...", 100, 230, 32, .{1,0,0});
+
+ draw_text("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 100, 300, 16);
+ draw_text("abcdefghijklmnopqrstuvwxyz", 100, 340, 16);
gfx.flush();
}
-draw_text :: (text: str, x: f32, y: f32, size := 32.0f) {
+draw_text :: (text: str, x: f32, y: f32, size := 32.0f, color := gfx.Color4.{1,1,1}) {
gl.bindTexture(gl.TEXTURE_2D, font_texture);
gfx.set_texture(0);
- gfx.use_ortho_projection(0, ~~window_width, 0, ~~window_height);
for char: text {
glyph := font->get_glyph(char);
assert(glyph != null, "NO NULL GLYPH");
}
- gfx.textured_quad(
+ gfx.textured_rect(
.{ x, y },
- .{ size, size },
+ .{ glyph.w * size * font.em, glyph.h * size * font.em },
.{ glyph.x0, glyph.y0 },
- .{ glyph.x1 - glyph.x0, glyph.y1 - glyph.y0 });
+ .{ glyph.x1 - glyph.x0, glyph.y1 - glyph.y0 },
+ color = color);
- x += size;
+ x += glyph.w * size * 16;
}
gfx.flush();