diff options
author | Konstantin Ritt <ritt.ks@gmail.com> | 2014-02-03 20:38:20 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-04 13:37:14 +0100 |
commit | 19463c5c3f4b5b25eff557c813d6e6975ebc2491 (patch) | |
tree | b67027716972882ab23379586bee705326739783 | |
parent | 2edf3ba5a718415e5a9a327156289bed4484cdea (diff) |
Fix character mirroring issue with HarfBuzz-NG
HarfBuzz-NG does character mirroring where appropriate.
A simple solution is to unset RightToLeft shaper flag when
text gets shaped with HB-NG. Instead, move the mirroring code
right to HB-old proxy function and decrease code duplication.
Change-Id: Icdcd50b73b3e6a43da4b85addc7d8f51edf86512
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r-- | src/gui/text/qfontengine.cpp | 42 | ||||
-rw-r--r-- | src/gui/text/qfontengine_ft.cpp | 3 | ||||
-rw-r--r-- | src/gui/text/qfontengine_p.h | 1 | ||||
-rw-r--r-- | src/gui/text/qfontengine_qpa.cpp | 5 | ||||
-rw-r--r-- | src/gui/text/qtextengine.cpp | 6 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowsfontengine.cpp | 39 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowsfontengine.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp | 9 |
8 files changed, 44 insertions, 63 deletions
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index a3fce197ce..32225750e4 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -89,18 +89,48 @@ static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint { QFontEngine *fe = (QFontEngine *)font->userData; + const QChar *str = reinterpret_cast<const QChar *>(string); + QGlyphLayout qglyphs; qglyphs.numGlyphs = *numGlyphs; qglyphs.glyphs = glyphs; - - QFontEngine::ShaperFlags shaperFlags(QFontEngine::GlyphIndicesOnly); - if (rightToLeft) - shaperFlags |= QFontEngine::RightToLeft; - int nGlyphs = *numGlyphs; - bool result = fe->stringToCMap(reinterpret_cast<const QChar *>(string), length, &qglyphs, &nGlyphs, shaperFlags); + bool result = fe->stringToCMap(str, length, &qglyphs, &nGlyphs, QFontEngine::GlyphIndicesOnly); *numGlyphs = nGlyphs; + if (rightToLeft && result && !fe->symbol) { + uint glyph_pos = 0; + for (uint i = 0; i < length; ++i, ++glyph_pos) { + uint ucs4 = str[i].unicode(); + if (Q_UNLIKELY(QChar::isHighSurrogate(ucs4) && i + 1 < length)) { + uint low = str[i + 1].unicode(); + if (Q_LIKELY(QChar::isLowSurrogate(low))) { + ucs4 = QChar::surrogateToUcs4(ucs4, low); + ++i; + } + } + + uint mirrored = QChar::mirroredChar(ucs4); + if (Q_UNLIKELY(mirrored != ucs4)) { + QChar chars[2]; + uint numChars = 0; + if (Q_UNLIKELY(QChar::requiresSurrogates(mirrored))) { + chars[numChars++] = QChar(QChar::highSurrogate(mirrored)); + chars[numChars++] = QChar(QChar::lowSurrogate(mirrored)); + } else { + chars[numChars++] = QChar(mirrored); + } + + qglyphs.numGlyphs = numChars; + qglyphs.glyphs = glyphs + glyph_pos; + nGlyphs = numChars; + if (!fe->stringToCMap(chars, numChars, &qglyphs, &nGlyphs, QFontEngine::GlyphIndicesOnly)) + Q_UNREACHABLE(); + Q_ASSERT(nGlyphs == 1); + } + } + } + return result; } diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 630ba78477..438c7b2141 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -1516,7 +1516,6 @@ bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs return false; } - bool mirrored = flags & QFontEngine::RightToLeft; int glyph_pos = 0; if (freetype->symbol_map) { FT_Face face = freetype->face; @@ -1552,8 +1551,6 @@ bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs FT_Face face = freetype->face; for (int i = 0; i < len; ++i) { unsigned int uc = getChar(str, i, len); - if (mirrored) - uc = QChar::mirroredChar(uc); glyphs->glyphs[glyph_pos] = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0; if (!glyphs->glyphs[glyph_pos]) { { diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index c181d61d73..9bc1900b99 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -120,7 +120,6 @@ public: }; enum ShaperFlag { - RightToLeft = 0x0001, DesignMetrics = 0x0002, GlyphIndicesOnly = 0x0004 }; diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp index 46f9071f07..cb40a5388a 100644 --- a/src/gui/text/qfontengine_qpa.cpp +++ b/src/gui/text/qfontengine_qpa.cpp @@ -353,13 +353,10 @@ bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph const uchar *cmap = externalCMap ? externalCMap : (fontData + cmapOffset); - bool mirrored = flags & QFontEngine::RightToLeft; int glyph_pos = 0; if (symbol) { for (int i = 0; i < len; ++i) { unsigned int uc = getChar(str, i, len); - if (mirrored) - uc = QChar::mirroredChar(uc); glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); if(!glyphs->glyphs[glyph_pos] && uc < 0x100) glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); @@ -368,8 +365,6 @@ bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph } else { for (int i = 0; i < len; ++i) { unsigned int uc = getChar(str, i, len); - if (mirrored) - uc = QChar::mirroredChar(uc); glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); #if 0 && defined(DEBUG_FONTENGINE) QChar c(uc); diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 739935fdd5..14bdc3167e 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -932,9 +932,6 @@ void QTextEngine::shapeText(int item) const int nGlyphs = initialGlyphs.numGlyphs; QFontEngine::ShaperFlags shaperFlags(QFontEngine::GlyphIndicesOnly); - if (si.analysis.bidiLevel % 2) - shaperFlags |= QFontEngine::RightToLeft; - if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags)) { nGlyphs = qMax(nGlyphs, itemLength); // ### needed for QFontEngine::stringToCMap() to not fail twice if (!ensureSpace(nGlyphs)) { @@ -1274,7 +1271,8 @@ int QTextEngine::shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *stri engineIdx = uint(availableGlyphs(&si).glyphs[glyph_pos] >> 24); actualFontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx); - shaper_item.glyphIndicesPresent = true; + if ((si.analysis.bidiLevel % 2) == 0) + shaper_item.glyphIndicesPresent = true; } shaper_item.font = (HB_Font)actualFontEngine->harfbuzzFont(); diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index 35346e5b45..1676b73658 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -219,44 +219,11 @@ inline unsigned int getChar(const QChar *str, int &i, const int len) return uc; } -int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout *glyphs, bool mirrored) const +int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout *glyphs) const { int i = 0; int glyph_pos = 0; - if (mirrored) { -#if defined(Q_OS_WINCE) - { -#else - if (symbol) { - for (; i < numChars; ++i, ++glyph_pos) { - unsigned int uc = getChar(str, i, numChars); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); - if (!glyphs->glyphs[glyph_pos] && uc < 0x100) - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); - } - } else if (ttf) { - for (; i < numChars; ++i, ++glyph_pos) { - unsigned int uc = getChar(str, i, numChars); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, QChar::mirroredChar(uc)); - } - } else { -#endif - wchar_t first = tm.tmFirstChar; - wchar_t last = tm.tmLastChar; - - for (; i < numChars; ++i, ++glyph_pos) { - uint ucs = QChar::mirroredChar(getChar(str, i, numChars)); - if ( -#ifdef Q_WS_WINCE - tm.tmFirstChar > 60000 || -#endif - ucs >= first && ucs <= last) - glyphs->glyphs[glyph_pos] = ucs; - else - glyphs->glyphs[glyph_pos] = 0; - } - } - } else { + { #if defined(Q_OS_WINCE) { #else @@ -390,7 +357,7 @@ bool QWindowsFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *g } glyphs->numGlyphs = *nglyphs; - *nglyphs = getGlyphIndexes(str, len, glyphs, flags & RightToLeft); + *nglyphs = getGlyphIndexes(str, len, glyphs); if (!(flags & GlyphIndicesOnly)) recalcAdvances(glyphs, flags); diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h index acf84d270c..e3fb3281a3 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.h +++ b/src/plugins/platforms/windows/qwindowsfontengine.h @@ -127,7 +127,7 @@ public: virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0); #endif - int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs, bool mirrored) const; + int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs) const; void getCMap(); bool getOutlineMetrics(glyph_t glyph, const QTransform &t, glyph_metrics_t *metrics) const; diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index f603dd5c53..ce5ea8167f 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -325,13 +325,8 @@ bool QWindowsFontEngineDirectWrite::stringToCMap(const QChar *str, int len, QGly QVarLengthArray<UINT32> codePoints(len); int actualLength = 0; - if (flags & QFontEngine::RightToLeft) { - for (int i = 0; i < len; ++i) - codePoints[actualLength++] = QChar::mirroredChar(getChar(str, i, len)); - } else { - for (int i = 0; i < len; ++i) - codePoints[actualLength++] = getChar(str, i, len); - } + for (int i = 0; i < len; ++i) + codePoints[actualLength++] = getChar(str, i, len); QVarLengthArray<UINT16> glyphIndices(actualLength); HRESULT hr = m_directWriteFontFace->GetGlyphIndicesW(codePoints.data(), actualLength, |