Support preedit text in QSGTextInput
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
Thu, 15 Sep 2011 09:49:12 +0000 (11:49 +0200)
committerQt by Nokia <qt-info@nokia.com>
Thu, 15 Sep 2011 11:37:51 +0000 (13:37 +0200)
We need to support merged additional formats with backgrounds
in the QSGTextInput as well, so that code has been separated
into its own function. We also need to account for the position
in the bounding rect, so that the decorations are painted at
the correct location when there text input is scrolled.

Task-number: QTBUG-21261
Change-Id: I0799a62bf26e6a7a2c1a6eef9bbdf889c1c8e870
Reviewed-on: http://codereview.qt-project.org/4964
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Jiang Jiang <jiang.jiang@nokia.com>
src/declarative/items/qsgtextnode.cpp
src/declarative/items/qsgtextnode_p.h

index 8e31903..5ff8395 100644 (file)
@@ -213,6 +213,7 @@ namespace {
         {
             int newIndex = binaryTree->size();
             QRectF searchRect = glyphRun.boundingRect();
+            searchRect.translate(position);
 
             if (qFuzzyIsNull(searchRect.width()) || qFuzzyIsNull(searchRect.height()))
                 return;
@@ -786,6 +787,59 @@ namespace {
     }
 }
 
+void QSGTextNode::mergeFormats(QTextLayout *textLayout,
+                               QVarLengthArray<QTextLayout::FormatRange> *mergedFormats)
+{
+    Q_ASSERT(mergedFormats != 0);
+    if (textLayout == 0)
+        return;
+
+    QList<QTextLayout::FormatRange> additionalFormats = textLayout->additionalFormats();
+    for (int i=0; i<additionalFormats.size(); ++i) {
+        QTextLayout::FormatRange additionalFormat = additionalFormats.at(i);
+        if (additionalFormat.format.hasProperty(QTextFormat::ForegroundBrush)
+         || additionalFormat.format.hasProperty(QTextFormat::BackgroundBrush)) {
+            // Merge overlapping formats
+            if (!mergedFormats->isEmpty()) {
+                QTextLayout::FormatRange *lastFormat = mergedFormats->data() + mergedFormats->size() - 1;
+
+                if (additionalFormat.start < lastFormat->start + lastFormat->length) {
+                    QTextLayout::FormatRange *mergedRange = 0;
+
+                    int length = additionalFormat.length;
+                    if (additionalFormat.start > lastFormat->start) {
+                        lastFormat->length = additionalFormat.start - lastFormat->start;
+                        length -= lastFormat->length;
+
+                        mergedFormats->append(QTextLayout::FormatRange());
+                        mergedRange = mergedFormats->data() + mergedFormats->size() - 1;
+                        lastFormat = mergedFormats->data() + mergedFormats->size() - 2;
+                    } else {
+                        mergedRange = lastFormat;
+                    }
+
+                    mergedRange->format = lastFormat->format;
+                    mergedRange->format.merge(additionalFormat.format);
+                    mergedRange->start = additionalFormat.start;
+
+                    int end = qMin(additionalFormat.start + additionalFormat.length,
+                                   lastFormat->start + lastFormat->length);
+
+                    mergedRange->length = end - mergedRange->start;
+                    length -= mergedRange->length;
+
+                    additionalFormat.start = end;
+                    additionalFormat.length = length;
+                }
+            }
+
+            if (additionalFormat.length > 0)
+                mergedFormats->append(additionalFormat);
+        }
+    }
+
+}
+
 void QSGTextNode::addTextDocument(const QPointF &, QTextDocument *textDocument,
                                   const QColor &textColor,
                                   QSGText::TextStyle style, const QColor &styleColor,
@@ -808,53 +862,8 @@ void QSGTextNode::addTextDocument(const QPointF &, QTextDocument *textDocument,
         int preeditLength = block.isValid() ? block.layout()->preeditAreaText().length() : 0;
         int preeditPosition = block.isValid() ? block.layout()->preeditAreaPosition() : -1;
 
-        QTextLayout *textLayout = block.layout();
-        QList<QTextLayout::FormatRange> additionalFormats;
-        if (textLayout != 0)
-            additionalFormats = textLayout->additionalFormats();
         QVarLengthArray<QTextLayout::FormatRange> colorChanges;
-        for (int i=0; i<additionalFormats.size(); ++i) {
-            QTextLayout::FormatRange additionalFormat = additionalFormats.at(i);
-            if (additionalFormat.format.hasProperty(QTextFormat::ForegroundBrush)
-             || additionalFormat.format.hasProperty(QTextFormat::BackgroundBrush)) {
-                // Merge overlapping formats
-                if (!colorChanges.isEmpty()) {
-                    QTextLayout::FormatRange *lastFormat = colorChanges.data() + colorChanges.size() - 1;
-
-                    if (additionalFormat.start < lastFormat->start + lastFormat->length) {
-                        QTextLayout::FormatRange *mergedRange = 0;
-
-                        int length = additionalFormat.length;
-                        if (additionalFormat.start > lastFormat->start) {
-                            lastFormat->length = additionalFormat.start - lastFormat->start;
-                            length -= lastFormat->length;
-
-                            colorChanges.append(QTextLayout::FormatRange());
-                            mergedRange = colorChanges.data() + colorChanges.size() - 1;
-                            lastFormat = colorChanges.data() + colorChanges.size() - 2;
-                        } else {
-                            mergedRange = lastFormat;
-                        }
-
-                        mergedRange->format = lastFormat->format;
-                        mergedRange->format.merge(additionalFormat.format);
-                        mergedRange->start = additionalFormat.start;
-
-                        int end = qMin(additionalFormat.start + additionalFormat.length,
-                                       lastFormat->start + lastFormat->length);
-
-                        mergedRange->length = end - mergedRange->start;
-                        length -= mergedRange->length;
-
-                        additionalFormat.start = end;
-                        additionalFormat.length = length;
-                    }
-                }
-
-                if (additionalFormat.length > 0)
-                    colorChanges.append(additionalFormat);
-            }
-        }
+        mergeFormats(block.layout(), &colorChanges);
 
         QTextBlock::iterator blockIterator = block.begin();
         int textPos = block.position();
@@ -918,20 +927,27 @@ void QSGTextNode::addTextLayout(const QPointF &position, QTextLayout *textLayout
     engine.setSelectionColor(selectionColor);
     engine.setPosition(position);
 
-    QList<QTextLayout::FormatRange> additionalFormats = textLayout->additionalFormats();
+    int preeditLength = textLayout->preeditAreaText().length();
+    int preeditPosition = textLayout->preeditAreaPosition();
+
     QVarLengthArray<QTextLayout::FormatRange> colorChanges;
-    for (int i=0; i<additionalFormats.size(); ++i) {
-        if (additionalFormats.at(i).format.hasProperty(QTextFormat::ForegroundBrush))
-            colorChanges.append(additionalFormats.at(i));
-    }
+    mergeFormats(textLayout, &colorChanges);
 
     for (int i=0; i<textLayout->lineCount(); ++i) {
         QTextLine line = textLayout->lineAt(i);
 
+        int start = line.textStart();
+        int length = line.textLength();
+        int end = start + length;
+
+        if (preeditPosition >= 0
+         && preeditPosition >= start
+         && preeditPosition < end) {
+            end += preeditLength;
+        }
+
         engine.setCurrentLine(line);
-        engine.addGlyphsForRanges(colorChanges,
-                                  line.textStart(), line.textStart() + line.textLength(),
-                                  selectionStart, selectionEnd);
+        engine.addGlyphsForRanges(colorChanges, start, end, selectionStart, selectionEnd);
     }
 
     engine.addToSceneGraph(this, style, styleColor);
index 6d68fd1..b8e8cd6 100644 (file)
 #include <qglyphrun.h>
 
 #include <QtGui/qcolor.h>
+#include <QtGui/qtextlayout.h>
+#include <QtCore/qvarlengtharray.h>
 
 QT_BEGIN_NAMESPACE
 
-class QTextLayout;
 class QSGGlyphNode;
 class QTextBlock;
 class QColor;
@@ -95,6 +96,8 @@ public:
                             QSGNode *parentNode = 0);
 
 private:
+    void mergeFormats(QTextLayout *textLayout, QVarLengthArray<QTextLayout::FormatRange> *mergedFormats);
+
     QSGContext *m_context;
     QSGSimpleRectNode *m_cursorNode;
 };