From 26f5f1ccd0681797e49cf932dd417b7221adaa06 Mon Sep 17 00:00:00 2001 From: Jonathan Bradley Date: Fri, 7 Feb 2025 16:08:09 -0500 Subject: pke: chkpt: store font and glyph geometry --- editor/editor.cpp | 49 +++++++++++++++++++++++++++++++++++-------------- src/font.hpp | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 15 deletions(-) diff --git a/editor/editor.cpp b/editor/editor.cpp index 4ce15e1..6e7db59 100644 --- a/editor/editor.cpp +++ b/editor/editor.cpp @@ -13,10 +13,7 @@ #include "imgui.h" #include "level.hpp" #include "math-helpers.hpp" -#include "msdf-atlas-gen/GlyphGeometry.h" -#include "msdf-atlas-gen/glyph-generators.h" -#include "msdf-atlas-gen/image-save.h" -#include "msdf-atlas-gen/types.h" +#include "msdf-atlas-gen/msdf-atlas-gen.h" #include "player-input.hpp" #include "plugins.hpp" #include "project.hpp" @@ -25,7 +22,6 @@ #include "vendor-tinyfiledialogs.h" #include "window.hpp" #include "pk.h" -#include "msdf-atlas-gen/msdf-atlas-gen.h" #include #include @@ -719,9 +715,11 @@ int SortFontGlyphChar(const void *a, const void *b) { return ((FontGlyphChar*)a)->unicode > ((FontGlyphChar*)b)->unicode; } -void GenerateMTSDF(const Asset *a) { +void GenerateMTSDF(FontTypeMSDFSettings *msdf_settings, const Asset *a) { assert(PK_HAS_FLAG(a->type, PKE_ASSET_TYPE_FONT)); - glm::ivec4 bounds; + FontTypeSpacing ft_spacing{}; + glm::ivec4 ibounds; + glm::dvec4 dbounds; NULL_CHAR_ARR(path_txtr, 128); NULL_CHAR_ARR(path_glyphs, 128); std::error_code e; @@ -747,15 +745,25 @@ void GenerateMTSDF(const Asset *a) { const double maxCornerAngle = 3.0; for (msdf_atlas::GlyphGeometry &glyph : glyphs) glyph.edgeColoring(&msdfgen::edgeColoringByDistance, maxCornerAngle, 0); + + auto &metrics = fontGeometry.getMetrics(); + ft_spacing.geometryScale = fontGeometry.getGeometryScale(); + ft_spacing.em_size = metrics.emSize; + ft_spacing.ascender_y = metrics.ascenderY; + ft_spacing.descender_y = metrics.descenderY; + ft_spacing.line_height = metrics.lineHeight; + ft_spacing.underline_y = metrics.underlineY; + ft_spacing.underline_thickness = metrics.underlineThickness; + // TightAtlasPacker class computes the layout of the atlas. msdf_atlas::TightAtlasPacker packer; // Set atlas parameters: // setDimensions or setDimensionsConstraint to find the best value packer.setDimensionsConstraint(msdf_atlas::DimensionsConstraint::SQUARE); // setScale for a fixed size or setMinimumScale to use the largest that fits - packer.setMinimumScale(24.0); + packer.setMinimumScale(msdf_settings->minimum_scale); // setPixelRange or setUnitRange - packer.setPixelRange(2.0); + packer.setPixelRange(msdf_settings->px_range); packer.setMiterLimit(1.0); // Compute atlas layout - pack glyphs packer.pack(glyphs.data(), glyphs.size()); @@ -788,13 +796,20 @@ void GenerateMTSDF(const Asset *a) { pk_arr_resize(&arr_glyphs, glyphs.size()); FontGlyphChar *arr = reinterpret_cast(arr_glyphs.data); for (uint64_t i = 0; i < glyphs.size(); ++i) { + arr[i].advance = glyphs[i].getAdvance(); arr[i].unicode = glyphs[i].getCodepoint(); + arr[i].is_whitespace = glyphs[i].isWhitespace(); + + glyphs[i].getBoxRect(ibounds.x, ibounds.y, ibounds.z, ibounds.a); + + // TODO double-check this math + glyphs[i].getQuadAtlasBounds(dbounds.x, dbounds.y, dbounds.z, dbounds.a); + arr[i].baseline_bounding_box = dbounds - glm::dvec4(ibounds); - glyphs[i].getBoxRect(bounds.x, bounds.y, bounds.z, bounds.a); // library counts up from the bottom of the image to the bottom of the glyph - bounds.y = height - (bounds.y + bounds.a); - arr[i].sprite_region_min = glm::vec2(bounds.x, bounds.y); - arr[i].sprite_region_max = glm::vec2(bounds.x, bounds.y) + glm::vec2(bounds.z, bounds.a); + ibounds.y = height - (ibounds.y + ibounds.a); + arr[i].sprite_region_min = glm::vec2(ibounds.x, ibounds.y); + arr[i].sprite_region_max = glm::vec2(ibounds.x, ibounds.y) + glm::vec2(ibounds.z, ibounds.a); } qsort(arr_glyphs.data, arr_glyphs.next, arr_glyphs.stride, SortFontGlyphChar); @@ -818,6 +833,7 @@ void GenerateMTSDF(const Asset *a) { font_title.val = pk_new(font_title.reserved); snprintf((char *)font_title.val, AssetKeyLength, "%s", a->key); assert(ah_image != ah_glyphs && ah_image != AssetHandle_MAX); + // TODO pass FontTypeSpacing either here or another way FontType_RegisterFont(font_title, ah_image, ah_glyphs); } @@ -826,6 +842,11 @@ void RecordImGuiAssets() { ImGui::End(); return; } + // TODO this needs stored somewhere. + // User should input these values on a per-font basis. + struct FontTypeMSDFSettings msdf_settings{}; + msdf_settings.minimum_scale = 7 * 4; + msdf_settings.px_range = 2; static ImGuiTableFlags tableFlags{ ImGuiTableFlags_Borders | @@ -855,7 +876,7 @@ void RecordImGuiAssets() { ImGui::TableSetColumnIndex(0); if ((asset.type & PKE_ASSET_TYPE_FONT) != PKE_ASSET_TYPE_UNSET) { if (ImGui::Button("Create MTSDF")) { - GenerateMTSDF(&asset); + GenerateMTSDF(&msdf_settings, &asset); } } ImGui::TableSetColumnIndex(1); diff --git a/src/font.hpp b/src/font.hpp index 5b3646c..4d0d0a7 100644 --- a/src/font.hpp +++ b/src/font.hpp @@ -6,19 +6,53 @@ #include "pk.h" #include +#include TypeSafeInt_H(FontTypeIndex, uint16_t, 0xFFFF); TypeSafeInt_H(FontRenderIndex, uint16_t, 0xFFFF); +enum FONT_RENDER_SURFACE_AREA_TYPE_FLAGS : uint8_t { + FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_NONE = 0, + FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_GROW_VERTICAL = (1 << 0), + FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_GROW_HORIZONTAL = (1 << 1), + + FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_STATIC = 0, + FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_FLUID = (1 << 0) | (1 << 1), +}; + struct FontGlyphChar { - uint32_t unicode; + double advance; glm::vec2 sprite_region_min; glm::vec2 sprite_region_max; + glm::dvec4 baseline_bounding_box; + uint32_t unicode; + bool is_whitespace; +}; +struct FontRenderSettings { + float char_scale; + float line_height_scale; + float char_spacing_scale; + glm::ivec2 surface_area_size; + FONT_RENDER_SURFACE_AREA_TYPE_FLAGS surface_area_type_flags; }; struct FontRender { uint32_t len; FontTypeIndex index_ft; FontRenderIndex index_fr; + FontRenderSettings settings; +}; +struct FontTypeMSDFSettings { + float minimum_scale; + float px_range; +}; +struct FontTypeSpacing { + double geometryScale; + double em_size; + double ascender_y; + double descender_y; + double line_height; + double underline_y; + double underline_thickness; }; struct FontType : public Entity_Base { pk_cstr title; @@ -31,6 +65,8 @@ struct FontType : public Entity_Base { FontRenderIndex n_render = FontRenderIndex{0}; FontRenderIndex h_render = FontRenderIndex{0}; FontTypeIndex index_ft = FontTypeIndex{0}; + struct FontTypeMSDFSettings msdf_settings; + struct FontTypeSpacing spacing; struct FontTypeGraphics { VkDeviceMemory deviceMemoryVert = VK_NULL_HANDLE; VkDeviceMemory deviceMemoryTexture = VK_NULL_HANDLE; -- cgit v1.2.3