Another ugly hack to make bidi cursor work with Core Text
authorJiang Jiang <jiang.jiang@nokia.com>
Wed, 27 Apr 2011 09:39:09 +0000 (11:39 +0200)
committerJiang Jiang <jiang.jiang@nokia.com>
Fri, 29 Apr 2011 09:02:24 +0000 (11:02 +0200)
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)

src/gui/text/qfontengine_coretext.mm
tests/auto/qcomplextext/tst_qcomplextext.cpp

index ff440de..c4d2d47 100644 (file)
@@ -180,6 +180,8 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
                                                               &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
         typeSetter = CTTypesetterCreateWithAttributedStringAndOptions(attributedString, options);
     } else
+#else
+    Q_UNUSED(flags);
 #endif
         typeSetter = CTTypesetterCreateWithAttributedString(attributedString);
 
@@ -219,6 +221,25 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
 
         Q_ASSERT((CTRunGetStatus(run) & kCTRunStatusRightToLeft) == rtl);
         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);
         bool endWithPDF = QChar::direction(endGlyph) == QChar::DirPDF;
         if (endWithPDF)
@@ -271,9 +292,9 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
 
                 CFIndex k = 0;
                 CFIndex i = 0;
-                for (i = stringRange.location;
+                for (i = stringRange.location + prepend;
                      (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;
                         outAttributes[k].clusterStart = true;
                         ++k;
@@ -308,7 +329,7 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
                     : QFixed::fromReal(lastGlyphAdvance.width);
 
             if (endWithPDF) {
-                logClusters[stringRange.location + stringRange.length - 1] = glyphCount;
+                logClusters[stringRange.location + stringRange.length - 1] = glyphCount + prepend;
                 outGlyphs[glyphCount] = 0xFFFF;
                 outAdvances_x[glyphCount] = 0;
                 outAdvances_y[glyphCount] = 0;
index 04943c5..58b31b4 100644 (file)
@@ -214,6 +214,7 @@ void tst_QComplexText::bidiCursorMovement()
     QTextOption option = layout.textOption();
     option.setTextDirection(basicDir == QChar::DirL ? Qt::LeftToRight : Qt::RightToLeft);
     layout.setTextOption(option);
+    layout.setCursorMoveStyle(QTextCursor::Visual);
     bool moved;
     int oldPos, newPos = 0;
     qreal x, newX;