Another ugly hack to make bidi cursor work with Core Text

If the text is wrapped with LRE/LRO/RLE/RLO override/embed marks,
Core Text in Mac OS X 10.5 doesn't produce an empty glyph at the
beginning of the glyphs (while it does in Mac OS X 10.6), thus
we need to prepend an empty glyph here, otherwise cursor position
calculation will consider the first two characters as a ligature
of the same glyph.

Reviewed-by: Eskil
(cherry picked from commit a36ac6c34bafa801c2c30d76f59e4a3594efc4d5)
This commit is contained in:
Jiang Jiang 2011-04-27 11:39:09 +02:00
parent d64460fffb
commit bbbfc9b0eb
2 changed files with 25 additions and 3 deletions

View File

@ -180,6 +180,8 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
&kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
typeSetter = CTTypesetterCreateWithAttributedStringAndOptions(attributedString, options); typeSetter = CTTypesetterCreateWithAttributedStringAndOptions(attributedString, options);
} else } else
#else
Q_UNUSED(flags);
#endif #endif
typeSetter = CTTypesetterCreateWithAttributedString(attributedString); typeSetter = CTTypesetterCreateWithAttributedString(attributedString);
@ -219,6 +221,25 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
Q_ASSERT((CTRunGetStatus(run) & kCTRunStatusRightToLeft) == rtl); Q_ASSERT((CTRunGetStatus(run) & kCTRunStatusRightToLeft) == rtl);
CFRange stringRange = CTRunGetStringRange(run); CFRange stringRange = CTRunGetStringRange(run);
int prepend = 0;
#if MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_5
UniChar beginGlyph = CFStringGetCharacterAtIndex(cfstring, stringRange.location);
QChar dir = QChar::direction(beginGlyph);
bool beginWithOverride = dir == QChar::DirLRO || dir == QChar::DirRLO || dir == QChar::DirLRE || dir == QChar::DirRLE;
if (beginWithOverride) {
logClusters[stringRange.location] = 0;
outGlyphs[0] = 0xFFFF;
outAdvances_x[0] = 0;
outAdvances_y[0] = 0;
outAttributes[0].clusterStart = true;
outAttributes[0].dontPrint = true;
outGlyphs++;
outAdvances_x++;
outAdvances_y++;
outAttributes++;
prepend = 1;
}
#endif
UniChar endGlyph = CFStringGetCharacterAtIndex(cfstring, stringRange.location + stringRange.length - 1); UniChar endGlyph = CFStringGetCharacterAtIndex(cfstring, stringRange.location + stringRange.length - 1);
bool endWithPDF = QChar::direction(endGlyph) == QChar::DirPDF; bool endWithPDF = QChar::direction(endGlyph) == QChar::DirPDF;
if (endWithPDF) if (endWithPDF)
@ -271,9 +292,9 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
CFIndex k = 0; CFIndex k = 0;
CFIndex i = 0; CFIndex i = 0;
for (i = stringRange.location; for (i = stringRange.location + prepend;
(i < stringRange.location + stringRange.length) && (k < glyphCount); ++i) { (i < stringRange.location + stringRange.length) && (k < glyphCount); ++i) {
if (tmpIndices[k * rtlSign + rtlOffset] == i || i == stringRange.location) { if (tmpIndices[k * rtlSign + rtlOffset] == i || i == stringRange.location + prepend) {
logClusters[i] = k + firstGlyphIndex; logClusters[i] = k + firstGlyphIndex;
outAttributes[k].clusterStart = true; outAttributes[k].clusterStart = true;
++k; ++k;
@ -308,7 +329,7 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
: QFixed::fromReal(lastGlyphAdvance.width); : QFixed::fromReal(lastGlyphAdvance.width);
if (endWithPDF) { if (endWithPDF) {
logClusters[stringRange.location + stringRange.length - 1] = glyphCount; logClusters[stringRange.location + stringRange.length - 1] = glyphCount + prepend;
outGlyphs[glyphCount] = 0xFFFF; outGlyphs[glyphCount] = 0xFFFF;
outAdvances_x[glyphCount] = 0; outAdvances_x[glyphCount] = 0;
outAdvances_y[glyphCount] = 0; outAdvances_y[glyphCount] = 0;

View File

@ -214,6 +214,7 @@ void tst_QComplexText::bidiCursorMovement()
QTextOption option = layout.textOption(); QTextOption option = layout.textOption();
option.setTextDirection(basicDir == QChar::DirL ? Qt::LeftToRight : Qt::RightToLeft); option.setTextDirection(basicDir == QChar::DirL ? Qt::LeftToRight : Qt::RightToLeft);
layout.setTextOption(option); layout.setTextOption(option);
layout.setCursorMoveStyle(QTextCursor::Visual);
bool moved; bool moved;
int oldPos, newPos = 0; int oldPos, newPos = 0;
qreal x, newX; qreal x, newX;