diff options
Diffstat (limited to 'src/font.cpp')
| -rw-r--r-- | src/font.cpp | 78 |
1 files changed, 75 insertions, 3 deletions
diff --git a/src/font.cpp b/src/font.cpp index 3dba635..3204f58 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -108,6 +108,47 @@ float FontType_Inner_LookAheadWordLength(const FontType *const ft, const FontRen return ret; } +float FontType_Inner_LookAheadLineLength(const FontType *const ft, const FontRender *const fr, uint32_t index, float font_glyph_spacing) { + uint32_t i; + float ret = 0; + FontGlyphChar *fgc; + for (i = index; i < fr->n_glyphs; ++i) { + fgc = &ft->glyphs[fr->glyph_indices[i]]; + if (PK_HAS_FLAG(fgc->flags, FONT_GLYPH_CHAR_FLAGS_NEW_LINE) == true) { + break; + } + if (ret + (fgc->advance * font_glyph_spacing) > fr->settings.surface_area_size.x) { + break; + } + ret += fgc->advance * font_glyph_spacing; + } + return ret; +} + +float FontType_Inner_LookAheadLineCount(const FontType *const ft, const FontRender *const fr, const uint32_t index) { + uint32_t i, u; + float ret = 1; + FontGlyphChar *fgc; + for (i = index; i < fr->n_glyphs; ++i) { + fgc = &ft->glyphs[fr->glyph_indices[i]]; + if (PK_HAS_FLAG(fgc->flags, FONT_GLYPH_CHAR_FLAGS_NEW_LINE) == true) { + if (i+1 < fr->n_glyphs) { + if (fgc->unicode == 10) { + u = 11; + } else { + u = 10; + } + // handle \r\n + if (ft->glyphs[fr->glyph_indices[i+1]].unicode == u) { + i += 1; // burn + } + } + ret += 1; + } + } + return ret; +} + void FontType_Inner_CalcTransforms(const FontType *ft, FontRender *fr, FontInstanceBufferItem *ptr_dst) { assert(ft != nullptr); assert(fr != nullptr); @@ -117,7 +158,7 @@ void FontType_Inner_CalcTransforms(const FontType *ft, FontRender *fr, FontInsta bool new_word = true; uint32_t i; float font_glyph_spacing; - float cursor_head, line_index, line_height; + float cursor_head, line_index, line_height, line_length, line_offset; glm::vec2 glyph_size; glm::vec3 translate; glm::vec3 scale; @@ -129,12 +170,31 @@ void FontType_Inner_CalcTransforms(const FontType *ft, FontRender *fr, FontInsta // Trying to get pixel-perfect rendering with mannequin-7. // Everything is now sized and positioned correctly. // However, there is a ghost layer around the letter. + // 2025-09-22 - JCB + // I believe this is because of how the anti-aliasing works. + // When this gets re-visited, attempt to disable anti-aliasing entirely. + // Suggestion: require min distance to be 0? + // Also note that I don't think we're doing any calculations to make sure the + // left-most pixel is exact to the Extent (screen size). font_glyph_spacing = ft->spacing.em_size * fr->settings.char_scale; cursor_head = 0; line_index = 0; + line_offset = 0; line_height = font_glyph_spacing * ft->spacing.line_height * fr->settings.line_height_scale; + line_length = FontType_Inner_LookAheadLineLength(ft, fr, 0, font_glyph_spacing); + if (PK_HAS_FLAG(fr->settings.surface_area_type_flags, FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_CENTER_HORIZONTAL)) { + cursor_head = (fr->settings.surface_area_size.x - line_length) / 2.0; + } + if (PK_HAS_FLAG(fr->settings.surface_area_type_flags, FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_CENTER_VERTICAL)) { + float text_height = FontType_Inner_LookAheadLineCount(ft, fr, 0) * line_height; + // TODO + // This is wrong but I'm not sure how/why. + // Mathematically it should be ` / 2.0`. + line_offset += (fr->settings.surface_area_size.y - text_height) / 4.0; + } + for (i = 0; i < fr->n_glyphs; ++i) { translate = glm::vec3(0); scale = glm::vec3(1); @@ -149,7 +209,12 @@ void FontType_Inner_CalcTransforms(const FontType *ft, FontRender *fr, FontInsta } } line_index += 1; - cursor_head = 0; + line_length = FontType_Inner_LookAheadLineLength(ft, fr, i+1, font_glyph_spacing); + if (PK_HAS_FLAG(fr->settings.surface_area_type_flags, FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_CENTER_HORIZONTAL)) { + cursor_head = (fr->settings.surface_area_size.x - line_length) / 2.0; + } else { + cursor_head = 0; + } continue; } if (PK_HAS_FLAG(fgc->flags, FONT_GLYPH_CHAR_FLAGS_WHITESPACE) == true) { @@ -172,7 +237,13 @@ void FontType_Inner_CalcTransforms(const FontType *ft, FontRender *fr, FontInsta float word_width = FontType_Inner_LookAheadWordLength(ft, fr, i, font_glyph_spacing); if (cursor_head + word_width > fr->settings.surface_area_size.x) { line_index += 1; - cursor_head = 0; + line_length = FontType_Inner_LookAheadLineLength(ft, fr, i+1, font_glyph_spacing); + + if (PK_HAS_FLAG(fr->settings.surface_area_type_flags, FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_CENTER_HORIZONTAL)) { + cursor_head = (fr->settings.surface_area_size.x - line_length) / 2.0; + } else { + cursor_head = 0; + } } new_word = false; } @@ -207,6 +278,7 @@ void FontType_Inner_CalcTransforms(const FontType *ft, FontRender *fr, FontInsta translate.y = fr->settings.surface_area_pos.y; // baseline - current line (+1 to not draw above the box) translate.y += ((line_index + 1) * line_height); + translate.y += line_offset; // places the top line of the glyph on the baseline translate.y += (font_glyph_spacing / 2.0) + (glyph_size.y / 2.0); // move glyph to the height relative to the baseline (cursor) |
