From 847fe03d91730fb8bf5318a6b0e0ea6c00f9c007 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Sun, 21 Feb 2016 15:42:05 +0400 Subject: [PATCH] Make PDF handling in CoreText shaper consistent with OT The CoreText backend will remove the PDF token from the end of the string (instead of producing a zero-width glyph for it), thus the output will be different from the OpenType backend and the client will get confused. To fix this, we replace the PDF token with a visible grapheme starter and handle it after. Task-number: QTBUG-38113 Change-Id: I1bf6927aa2fa214d33f98afec8eb57bcab639379 Reviewed-by: Oswald Buddenhagen Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qtextengine.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 67cafa53fe..f3ed8ef63a 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1165,6 +1165,20 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, hb_buffer_clear_contents(buffer); hb_buffer_add_utf16(buffer, reinterpret_cast(string) + item_pos, item_length, 0, item_length); +#if defined(Q_OS_DARWIN) + // ### temporary workaround for QTBUG-38113 + // CoreText throws away the PDF token, while the OpenType backend will replace it with + // a zero-advance glyph. This becomes a real issue when PDF is the last character, + // since it gets treated like if it were a grapheme extender, so we + // temporarily replace it with some visible grapheme starter. + bool endsWithPDF = actualFontEngine->type() == QFontEngine::Mac && string[item_pos + item_length - 1] == 0x202c; + if (Q_UNLIKELY(endsWithPDF)) { + uint num_glyphs; + hb_glyph_info_t *infos = hb_buffer_get_glyph_infos(buffer, &num_glyphs); + infos[num_glyphs - 1].codepoint = '.'; + } +#endif + hb_buffer_set_segment_properties(buffer, &props); hb_buffer_guess_segment_properties(buffer); @@ -1286,6 +1300,20 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, while (str_pos < item_length) log_clusters[str_pos++] = last_glyph_pos; +#if defined(Q_OS_DARWIN) + if (Q_UNLIKELY(endsWithPDF)) { + int last_glyph_idx = num_glyphs - 1; + g.glyphs[last_glyph_idx] = 0xffff; + g.advances[last_glyph_idx] = QFixed(); + g.offsets[last_glyph_idx].x = QFixed(); + g.offsets[last_glyph_idx].y = QFixed(); + g.attributes[last_glyph_idx].clusterStart = true; + g.attributes[last_glyph_idx].dontPrint = true; + + log_clusters[item_length - 1] = glyphs_shaped + last_glyph_idx; + } +#endif + if (Q_UNLIKELY(engineIdx != 0)) { for (quint32 i = 0; i < num_glyphs; ++i) g.glyphs[i] |= (engineIdx << 24);