From 251ec5586b31f781974338eaf1ee5930ddad7719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pomiet=C5=82o?= <46203179+lpogic@users.noreply.github.com> Date: Mon, 2 Sep 2024 10:44:31 +0200 Subject: [PATCH] loader/ttf: Spaces and invalid glyphs rendering fix If for any reason an invalid glyph is found in text, it will now be skipped when rendering (instead of increasing offset by last valid glyph advance). Issue: #2687 --- src/loaders/ttf/tvgTtfLoader.cpp | 12 ++++++++---- src/loaders/ttf/tvgTtfReader.cpp | 13 +++++++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/loaders/ttf/tvgTtfLoader.cpp b/src/loaders/ttf/tvgTtfLoader.cpp index 59143966..7d1c6cc7 100644 --- a/src/loaders/ttf/tvgTtfLoader.cpp +++ b/src/loaders/ttf/tvgTtfLoader.cpp @@ -282,6 +282,7 @@ bool TtfLoader::read() Point offset = {0.0f, reader.metrics.hhea.ascent}; Point kerning = {0.0f, 0.0f}; auto lglyph = INVALID_GLYPH; + auto loadMinw = true; size_t idx = 0; while (code[idx] && idx < n) { @@ -289,11 +290,14 @@ bool TtfLoader::read() if (rglyph != INVALID_GLYPH) { if (lglyph != INVALID_GLYPH) reader.kerning(lglyph, rglyph, kerning); if (!reader.convert(shape, gmetrics, offset, kerning, 1U)) break; + offset.x += (gmetrics.advanceWidth + kerning.x); + lglyph = rglyph; + //store the first glyph with outline min size for italic transform. + if (loadMinw && gmetrics.outline) { + reader.metrics.minw = gmetrics.minw; + loadMinw = false; + } } - offset.x += (gmetrics.advanceWidth + kerning.x); - lglyph = rglyph; - //store the first glyph min size for italic transform. - if (idx == 0) reader.metrics.minw = gmetrics.minw; ++idx; } diff --git a/src/loaders/ttf/tvgTtfReader.cpp b/src/loaders/ttf/tvgTtfReader.cpp index df2d787f..4a52c4b8 100644 --- a/src/loaders/ttf/tvgTtfReader.cpp +++ b/src/loaders/ttf/tvgTtfReader.cpp @@ -387,12 +387,11 @@ uint32_t TtfReader::glyph(uint32_t codepoint) uint32_t TtfReader::glyph(uint32_t codepoint, TtfGlyphMetrics& gmetrics) { auto glyph = this->glyph(codepoint); - if (glyph == INVALID_GLYPH) { + if (glyph == INVALID_GLYPH || !glyphMetrics(glyph, gmetrics)) { TVGERR("TTF", "invalid glyph id, codepoint(0x%x)", codepoint); return INVALID_GLYPH; } - - return glyphMetrics(glyph, gmetrics) ? glyph : INVALID_GLYPH; + return glyph; } bool TtfReader::glyphMetrics(uint32_t glyphIndex, TtfGlyphMetrics& gmetrics) @@ -420,7 +419,12 @@ bool TtfReader::glyphMetrics(uint32_t glyphIndex, TtfGlyphMetrics& gmetrics) } gmetrics.outline = outlineOffset(glyphIndex); - if (!gmetrics.outline || !validate(gmetrics.outline, 10)) return false; + // glyph without outline + if (gmetrics.outline == 0) { + gmetrics.minw = gmetrics.minh = gmetrics.yOffset = 0; + return true; + } + if (!validate(gmetrics.outline, 10)) return false; //read the bounding box from the font file verbatim. float bbox[4]; @@ -442,6 +446,7 @@ bool TtfReader::convert(Shape* shape, TtfGlyphMetrics& gmetrics, const Point& of { #define ON_CURVE 0x01 + if (!gmetrics.outline) return true; auto outlineCnt = _i16(data, gmetrics.outline); if (outlineCnt == 0) return false; if (outlineCnt < 0) {