From a0a68b7b3a5430fea5aaa2ad1da75fdda5cd5c7a Mon Sep 17 00:00:00 2001 From: Fabrice Date: Wed, 11 Feb 2026 22:50:21 +0100 Subject: packing corrections --- src/rendering.cc | 28 ++++++++++++++++++++++++++++ src/rendering.h | 12 ++++++++++++ src/text.cc | 17 +++++++++-------- src/text.h | 3 ++- src/utils.h | 5 +++++ 5 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/rendering.cc b/src/rendering.cc index 89a64ac..65a89b1 100644 --- a/src/rendering.cc +++ b/src/rendering.cc @@ -4,6 +4,7 @@ #include +#include "cglm/types.h" #include "utils.h" bool wayc_image_init(texture_t* texture, image_type_e type, @@ -126,3 +127,30 @@ void wayc_atlas_deinit(atlas_s* atlas) { wayc_sampler_deinit(&atlas->sampler); wayc_image_deinit(&atlas->texture); } + +static inline void wayc_atlas_packer_wrap(struct atlas_packer_s* packer) { + WAYC_X(packer->cursor) = 0; + WAYC_Y(packer->cursor) += packer->row_height; + packer->row_height = 0; +} + +bool wayc_atlas_packer_allocate(struct atlas_packer_s* packer, u32 width, + u32 height, ivec2 out) { + wayc_notnull(packer); + + struct atlas_s* atlas = packer->atlas; + wayc_notnull(atlas); + + if (width > atlas->width || height > atlas->height) return false; + + if (WAYC_X(packer->cursor) + width > atlas->width) + wayc_atlas_packer_wrap(packer); + + if (WAYC_Y(packer->cursor) + height > atlas->height) return false; + + glm_ivec2_copy(packer->cursor, out); + WAYC_X(packer->cursor) += width; + packer->row_height = wayc_max(packer->row_height, height); + + return true; +} \ No newline at end of file diff --git a/src/rendering.h b/src/rendering.h index 98f70ce..f8db68e 100644 --- a/src/rendering.h +++ b/src/rendering.h @@ -67,3 +67,15 @@ void wayc_atlas_use(atlas_s* atlas, u32 slot); bool wayc_atlas_set(atlas_s* atlas, image_data_type_e data_type, ivec2 offset, u32 width, u32 height, i32 alignment, const u8* data); void wayc_atlas_deinit(atlas_s* atlas); + +struct atlas_packer_s { + struct atlas_s* atlas; + u32 row_height; + ivec2 cursor; +}; + +#define WAYC_ATLAS_PACKER_INIT(atlas) \ + atlas_packer_s { atlas, 0, {0, 0} } + +bool wayc_atlas_packer_allocate(struct atlas_packer_s* packer, u32 width, + u32 height, ivec2 out); diff --git a/src/text.cc b/src/text.cc index 2bfc7a3..d02cc77 100644 --- a/src/text.cc +++ b/src/text.cc @@ -5,7 +5,7 @@ #include #include -#include "cglm/ivec2.h" +#include "cglm/types.h" #include "freetype/freetype.h" #include "hash.h" #include "rendering.h" @@ -72,13 +72,13 @@ enum font_error_e wayc_font_init(struct font_s* font, font->data = data; wayc_hashmap_init(&font->cache); - glm_ivec2_zero(font->cursor); success = true; return FONT_ERROR_NONE; } enum font_error_e wayc_font_lookup(struct font_s* font, struct atlas_s* atlas, + struct atlas_packer_s* packer, codepoint_t codepoint, struct glyph_s* out) { wayc_notnull(font); wayc_notnull(atlas); @@ -100,20 +100,21 @@ enum font_error_e wayc_font_lookup(struct font_s* font, struct atlas_s* atlas, if (bitmap.pitch != (i32)bitmap.width) wayc_panic("unsupported pitch"); ivec2 size = {(i32)bitmap.width, (i32)bitmap.rows}; + ivec2 uv0; - wayc_atlas_set(atlas, IMAGE_DATA_TYPE_UNSIGNED_BYTE, font->cursor, size[0], - size[1], IMAGE_FORMAT_RED_ALIGNMENT, bitmap.buffer); + bool ok = wayc_atlas_packer_allocate(packer, WAYC_X(size), WAYC_Y(size), uv0); + if (!ok) return FONT_ERROR_ATLAS_FULL; + + ok = wayc_atlas_set(atlas, IMAGE_DATA_TYPE_UNSIGNED_BYTE, uv0, WAYC_X(size), + WAYC_Y(size), IMAGE_FORMAT_RED_ALIGNMENT, bitmap.buffer); + if (!ok) return FONT_ERROR_ATLAS_FULL; struct glyph_s glyph = {}; glyph.bearing_x = slot->bitmap_left; glyph.bearing_y = slot->bitmap_top; glyph.advance = (f32)slot->advance.x / WAYC_SCALE; - glm_ivec2(font->cursor, glyph.uv0); - glm_ivec2_add(glyph.uv0, size, glyph.uv1); - wayc_font_cache_insert(font, codepoint, glyph); - glm_ivec2_add(font->cursor, size, font->cursor); *out = glyph; return FONT_ERROR_NONE; diff --git a/src/text.h b/src/text.h index a04fa99..73b4e03 100644 --- a/src/text.h +++ b/src/text.h @@ -32,18 +32,19 @@ enum font_error_e { FONT_ERROR_FILE_LOAD, FONT_ERROR_FONT_LOAD, FONT_ERROR_NOT_MATCH, + FONT_ERROR_ATLAS_FULL, }; struct font_s { u8* data; FT_Face face; struct hashmap_s cache; - ivec2 cursor; }; enum font_error_e wayc_font_init(struct font_s* font, struct font_context_s* ctx, u32 fsize, const char* path); enum font_error_e wayc_font_lookup(struct font_s* font, struct atlas_s* atlas, + struct atlas_packer_s* packer, codepoint_t codepoint, struct glyph_s* out); void wayc_font_deinit(struct font_s* font); diff --git a/src/utils.h b/src/utils.h index 10bdd88..00be767 100644 --- a/src/utils.h +++ b/src/utils.h @@ -74,6 +74,11 @@ static inline u32 wayc_min(u32 a, u32 b) { return a > b ? a : b; } #define WAYC_FRAC_BITS 6 #define WAYC_SCALE (1 << WAYC_FRAC_BITS) +#define WAYC_X(v) ((v)[0]) +#define WAYC_Y(v) ((v)[1]) + +static inline usize wayc_max(usize a, usize b) { return a > b ? a : b; } + template struct is_same { static constexpr bool value = false; -- cgit v1.2.3