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>
This commit is contained in:
parent
2edf3ba5a7
commit
19463c5c3f
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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]) {
|
||||
{
|
||||
|
@ -120,7 +120,6 @@ public:
|
||||
};
|
||||
|
||||
enum ShaperFlag {
|
||||
RightToLeft = 0x0001,
|
||||
DesignMetrics = 0x0002,
|
||||
GlyphIndicesOnly = 0x0004
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user