Skip boundry neutral characters in bidi itemization
authorJiang Jiang <jiang.jiang@nokia.com>
Wed, 22 Jun 2011 12:23:47 +0000 (14:23 +0200)
committerQt by Nokia <qt-info@nokia.com>
Thu, 14 Jul 2011 09:21:55 +0000 (11:21 +0200)
According to UAX #9, bidiItemize should act as if those characters
don't exist. If we don't, dir and status.eor here may become
QChar::DirBN, thus interfere the result of bidiItemize.

Task-number: QTBUG-19949
Reviewed-by: Lars Knoll
(cherry picked from commit a5c3064439a9f1483565e5d9dfbf0342cd9236f0)

Change-Id: I224cfdf5b38433a31d33b6d944d5770accf74546
Reviewed-on: http://codereview.qt.nokia.com/1631
Reviewed-by: Jiang Jiang <jiang.jiang@nokia.com>
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
src/gui/text/qtextengine.cpp
tests/auto/qcomplextext/bidireorderstring.h

index ceba926..a7e4748 100644 (file)
@@ -319,6 +319,26 @@ static void appendItems(QScriptAnalysis *analysis, int &start, int &stop, const
     start = stop;
 }
 
+static QChar::Direction skipBoundryNeutrals(QScriptAnalysis *analysis,
+                                            const ushort *unicode, int length,
+                                            int &sor, int &eor, QBidiControl &control)
+{
+    QChar::Direction dir;
+    int level = sor > 0 ? analysis[sor - 1].bidiLevel : control.level;
+    while (sor < length) {
+        dir = QChar::direction(unicode[sor]);
+        // Keep skipping DirBN as if it doesn't exist
+        if (dir != QChar::DirBN)
+            break;
+        analysis[sor++].bidiLevel = level;
+    }
+
+    eor = sor;
+    if (eor == length)
+        dir = control.basicDirection();
+
+    return dir;
+}
 
 // creates the next QScript items.
 static bool bidiItemize(QTextEngine *engine, QScriptAnalysis *analysis, QBidiControl &control)
@@ -430,8 +450,7 @@ static bool bidiItemize(QTextEngine *engine, QScriptAnalysis *analysis, QBidiCon
                 case QChar::DirAN:
                     if (eor >= 0) {
                         appendItems(analysis, sor, eor, control, dir);
-                        dir = eor < length ? QChar::direction(unicode[eor]) : control.basicDirection();
-                        status.eor = dir;
+                        status.eor = dir = skipBoundryNeutrals(analysis, unicode, length, sor, eor, control);
                     } else {
                         eor = current; status.eor = dir;
                     }
@@ -455,8 +474,7 @@ static bool bidiItemize(QTextEngine *engine, QScriptAnalysis *analysis, QBidiCon
                             }
                             eor = current - 1;
                             appendItems(analysis, sor, eor, control, dir);
-                            dir = eor < length ? QChar::direction(unicode[eor]) : control.basicDirection();
-                            status.eor = dir;
+                            status.eor = dir = skipBoundryNeutrals(analysis, unicode, length, sor, eor, control);
                         } else {
                             if(status.eor != QChar::DirL) {
                                 appendItems(analysis, sor, eor, control, dir);
index e51011e..e0bbf6e 100644 (file)
@@ -145,6 +145,7 @@ const LV logical_visual[] = {
     { "embed10", "\342\200\253x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\254y \327\235\327\225\327\234\327\251 x\342\200\253", QChar::DirL },
     { "embed11", "\342\200\252x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\252x \327\235\327\225\327\234\327\251 y\342\200\254", QChar::DirR },
     { "embed12", "\342\200\253x \327\251\327\234\327\225\327\235 y\342\200\254", "\342\200\254y \327\235\327\225\327\234\327\251 x\342\200\253", QChar::DirR },
+    { "zwsp", "+0\342\200\213f-1", "+0\342\200\213f-1", QChar::DirL },
 
     { 0, 0, 0, QChar::DirON }
 };