From 3c5cf13eb51e94d18d2e78c6a12d1f04717f4d51 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 54bfd064..99c776f7 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 174c65e9..b2f029d2 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) {