diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/atlas.cc | 53 | ||||
| -rw-r--r-- | src/atlas.h | 10 | ||||
| -rw-r--r-- | src/text.cc | 36 | ||||
| -rw-r--r-- | src/text.h | 21 | ||||
| -rw-r--r-- | src/wayclock.cc | 17 |
5 files changed, 129 insertions, 8 deletions
diff --git a/src/atlas.cc b/src/atlas.cc index ad697f1..5e7d5c2 100644 --- a/src/atlas.cc +++ b/src/atlas.cc @@ -2,6 +2,7 @@ #include <cstring> +#include "cglm/types.h" #include "mimalloc.h" #include "utils.h" @@ -55,12 +56,62 @@ enum atlas_error_e wayc_atlas_init(struct atlas_s* atlas, u32 width, u32 height, atlas->format = format; atlas->cpu_atlas = cpu_atlas; atlas->gpu_atlas = gpu_atlas; - atlas->cpu_dirty = false; success = true; return ATLAS_ERROR_NONE; } +enum atlas_error_e wayc_atlas_insert(struct atlas_s* atlas, u32 width, + u32 height, const u8* data, vec2* uv0, + vec2* uv1) { + wayc_notnull(atlas); + wayc_notnull(data); + wayc_notnull(uv0); + wayc_notnull(uv1); + + struct atlas_packer_s* packer = &atlas->packer; + + u32 x = WAYC_X(packer->cursor); + u32 y = WAYC_Y(packer->cursor); + + // wrap + if (x + width > atlas->width) { + x = 0; + y += packer->row_height; + packer->row_height = 0; + } + + if (y + height > atlas->height) return ATLAS_ERROR_ATLAS_FULL; + + const int atlas_pitch = + sg_query_surface_pitch(atlas->format, atlas->width, 1, 1); + const int bpp = sg_query_surface_pitch(atlas->format, 1, 1, 1); + const int src_pitch = width * bpp; + + for (u32 row = 0; row < height; row++) { + const u8* src_row = data + row * src_pitch; + u8* dst_row = atlas->cpu_atlas + (y + row) * atlas_pitch; + u8* dst_px = dst_row + x * bpp; + + memcpy(dst_px, src_row, src_pitch); + } + + const f32 W = (f32)atlas->width; + const f32 H = (f32)atlas->height; + + WAYC_X(*uv0) = (f32)x / W; + WAYC_Y(*uv0) = (f32)y / H; + WAYC_X(*uv1) = (f32)(x + width) / W; + WAYC_Y(*uv1) = (f32)(y + height) / H; + + WAYC_X(packer->cursor) = x + width; + WAYC_Y(packer->cursor) = y; + packer->row_height = wayc_max(packer->row_height, height); + atlas->cpu_dirty = true; + + return ATLAS_ERROR_NONE; +} + enum atlas_error_e wayc_atlas_flush(struct atlas_s* atlas) { wayc_notnull(atlas); if (!atlas->cpu_dirty) return ATLAS_ERROR_NONE; diff --git a/src/atlas.h b/src/atlas.h index 66813a8..993b8f3 100644 --- a/src/atlas.h +++ b/src/atlas.h @@ -1,5 +1,6 @@ #pragma once +#include "cglm/types.h" #include "sokol_gfx.h" #include "utils.h" @@ -10,15 +11,24 @@ enum atlas_error_e : u8 { ATLAS_ERROR_UPLOAD_FAILED, }; +struct atlas_packer_s { + vec2 cursor; + u32 row_height; +}; + struct atlas_s { u32 width, height; enum sg_pixel_format format; struct sg_image gpu_atlas; u8* cpu_atlas; bool cpu_dirty; + struct atlas_packer_s packer; }; enum atlas_error_e wayc_atlas_init(struct atlas_s* atlas, u32 width, u32 height, enum sg_pixel_format format); +enum atlas_error_e wayc_atlas_insert(struct atlas_s* atlas, u32 width, + u32 height, const u8* data, vec2* uv0, + vec2* uv1); enum atlas_error_e wayc_atlas_flush(struct atlas_s* atlas); void wayc_atlas_deinit(struct atlas_s* atlas); diff --git a/src/text.cc b/src/text.cc index b703ad1..6de3506 100644 --- a/src/text.cc +++ b/src/text.cc @@ -4,7 +4,10 @@ #include <cstring> #include "atlas.h" +#include "cglm/types.h" +#include "cglm/vec2.h" #include "freetype/freetype.h" +#include "freetype/fttypes.h" #include "hash.h" #include "shaders.h" #include "utils.h" @@ -124,9 +127,10 @@ enum font_error_e wayc_font_init(struct font_s* font, FT_Face face; FT_Error fterr = FT_New_Face(context->ft, path, 0, &face); if (fterr) return FONT_ERROR_LOAD_FACE; - wayc_defer_cond(FT_Done_Face(face), success, true); + FT_Set_Pixel_Sizes(face, 0, font_size); + struct atlas_s atlas; enum atlas_error_e aterr = wayc_atlas_init(&atlas, atlas_width, atlas_height, SG_PIXELFORMAT_R8); @@ -146,14 +150,36 @@ enum font_error_e wayc_font_render(struct font_s* font, codepoint_t codepoint, wayc_notnull(font); wayc_notnull(glyph); - struct glyph_s cached; - if (wayc_hashmap_get(&font->cached, &codepoint, &cached)) { - *glyph = cached; + struct glyph_s got; + if (wayc_hashmap_get(&font->cached, &codepoint, &got)) { + *glyph = got; return FONT_ERROR_NONE; } - + u32 index = FT_Get_Char_Index(font->face, codepoint); + if (index == 0) return FONT_ERROR_LOAD_GLYPH; + + FT_Error fterr = FT_Load_Glyph(font->face, index, FT_LOAD_RENDER); + if (fterr) return FONT_ERROR_LOAD_GLYPH; + + FT_GlyphSlot slot = font->face->glyph; + FT_Bitmap bitmap = slot->bitmap; + + vec2 uv0, uv1; + + enum atlas_error_e aterr = wayc_atlas_insert( + &font->atlas, bitmap.width, bitmap.rows, bitmap.buffer, &uv0, &uv1); + if (aterr) return FONT_ERROR_ATLAS_FAILED; + + vec2 bearing = {(f32)slot->bitmap_left, (f32)slot->bitmap_top}; + f32 advance = (f32)slot->advance.x / WAYC_SCALE; + + glm_vec2_copy(uv0, got.uv0); + glm_vec2_copy(uv1, got.uv1); + glm_vec2_copy(bearing, got.bearing); + got.advance = advance; + wayc_hashmap_insert(&font->cached, &codepoint, &got); return FONT_ERROR_NONE; } @@ -33,15 +33,27 @@ enum font_context_error_e wayc_font_context_init( void wayc_font_context_deinit(struct font_context_s* context); struct glyph_s { + vec2 uv0, uv1; vec2 bearing; - vec2 size; - vec2 uv; + f32 advance; }; +static inline void glyph_print(struct glyph_s* glyph) { + u32 uv0x = WAYC_X(glyph->uv0); + u32 uv0y = WAYC_Y(glyph->uv0); + u32 uv1x = WAYC_X(glyph->uv1); + u32 uv1y = WAYC_Y(glyph->uv1); + fprintf(stderr, + "uv0: (%u, %u), uv1: (%u, %u), bearing: (%f, %f), advance: %f\n", + uv0x, uv0y, uv1x, uv1y, WAYC_X(glyph->bearing), + WAYC_Y(glyph->bearing), glyph->advance); +} + enum font_error_e : u8 { FONT_ERROR_NONE = 0, FONT_ERROR_LOAD_FACE, FONT_ERROR_ATLAS_FAILED, + FONT_ERROR_LOAD_GLYPH, }; struct font_s { @@ -58,4 +70,9 @@ enum font_error_e wayc_font_init(struct font_s* font, u32 atlas_width, u32 atlas_height); enum font_error_e wayc_font_render(struct font_s* font, codepoint_t codepoint, struct glyph_s* glyph); +static inline enum font_error_e wayc_font_flush(struct font_s* font) { + enum atlas_error_e atlas_err = wayc_atlas_flush(&font->atlas); + return atlas_err == ATLAS_ERROR_NONE ? FONT_ERROR_NONE + : FONT_ERROR_ATLAS_FAILED; +} void wayc_font_deinit(struct font_s* font); diff --git a/src/wayclock.cc b/src/wayclock.cc index bd8491e..dc52aed 100644 --- a/src/wayclock.cc +++ b/src/wayclock.cc @@ -101,6 +101,23 @@ int main() { wayc_panic("Failed to initialize font"); wayc_defer(wayc_font_deinit(&font)); + struct glyph_s glyph_A; + if (wayc_font_render(&font, (codepoint_t)'A', &glyph_A) != FONT_ERROR_NONE) + wayc_panic("Failed to render glyph"); + glyph_print(&glyph_A); + + struct glyph_s glyph_X; + if (wayc_font_render(&font, (codepoint_t)'X', &glyph_X) != FONT_ERROR_NONE) + wayc_panic("Failed to render glyph"); + glyph_print(&glyph_X); + + struct glyph_s glyph_0; + if (wayc_font_render(&font, (codepoint_t)'0', &glyph_0) != FONT_ERROR_NONE) + wayc_panic("Failed to render glyph"); + glyph_print(&glyph_0); + + wayc_font_flush(&font); + struct app_s app = {&renderer}; while (wayc_eventloop_running(&loop)) { |
