aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/items/qsgtextnode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/items/qsgtextnode.cpp')
-rw-r--r--src/declarative/items/qsgtextnode.cpp103
1 files changed, 81 insertions, 22 deletions
diff --git a/src/declarative/items/qsgtextnode.cpp b/src/declarative/items/qsgtextnode.cpp
index ef0f98bf1d..a8a29bad24 100644
--- a/src/declarative/items/qsgtextnode.cpp
+++ b/src/declarative/items/qsgtextnode.cpp
@@ -132,6 +132,15 @@ QSGGlyphNode *QSGTextNode::addGlyphs(const QPointF &position, const QGlyphRun &g
node->setColor(color);
node->update();
+ /* We flag the geometry as static, but we never call markVertexDataDirty
+ or markIndexDataDirty on them. This is because all text nodes are
+ discarded when a change occurs. If we start appending/removing from
+ existing geometry, then we also need to start marking the geometry as
+ dirty.
+ */
+ node->geometry()->setIndexDataPattern(QSGGeometry::StaticPattern);
+ node->geometry()->setVertexDataPattern(QSGGeometry::StaticPattern);
+
if (parentNode == 0)
parentNode = this;
parentNode->appendChildNode(node);
@@ -272,6 +281,8 @@ namespace {
void addSelectedGlyphs(const QGlyphRun &glyphRun);
void addUnselectedGlyphs(const QGlyphRun &glyphRun);
+ void addGlyphsInRange(int rangeStart, int rangeEnd, const QColor &color,
+ int selectionStart, int selectionEnd);
void addToSceneGraph(QSGTextNode *parent,
QSGText::TextStyle style = QSGText::Normal,
@@ -559,6 +570,45 @@ namespace {
m_hasSelection = m_hasSelection || m_currentLineTree.size() > currentSize;
}
+ void SelectionEngine::addGlyphsInRange(int rangeStart, int rangeLength,
+ const QColor &color,
+ int selectionStart, int selectionEnd)
+ {
+ QColor oldColor = m_textColor;
+ m_textColor = color;
+
+ QTextLine &line = m_currentLine;
+ int rangeEnd = rangeStart + rangeLength;
+ if (selectionStart > rangeEnd || selectionEnd < rangeStart) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(rangeStart, rangeLength);
+ for (int j=0; j<glyphRuns.size(); ++j)
+ addUnselectedGlyphs(glyphRuns.at(j));
+ } else {
+ if (rangeStart < selectionStart) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(rangeStart,
+ qMin(selectionStart - rangeStart,
+ rangeLength));
+
+ for (int j=0; j<glyphRuns.size(); ++j)
+ addUnselectedGlyphs(glyphRuns.at(j));
+ }
+
+ if (rangeEnd >= selectionStart && selectionStart >= rangeStart) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(selectionStart, selectionEnd - selectionStart + 1);
+
+ for (int j=0; j<glyphRuns.size(); ++j)
+ addSelectedGlyphs(glyphRuns.at(j));
+ }
+
+ if (selectionEnd >= rangeStart && selectionEnd < rangeEnd) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(selectionEnd + 1, rangeEnd - selectionEnd);
+ for (int j=0; j<glyphRuns.size(); ++j)
+ addUnselectedGlyphs(glyphRuns.at(j));
+ }
+ }
+ m_textColor = oldColor;
+ }
+
void SelectionEngine::addToSceneGraph(QSGTextNode *parentNode,
QSGText::TextStyle style,
const QColor &styleColor)
@@ -752,39 +802,48 @@ void QSGTextNode::addTextLayout(const QPointF &position, QTextLayout *textLayout
engine.setSelectionColor(selectionColor);
engine.setPosition(position);
+ QList<QTextLayout::FormatRange> additionalFormats = textLayout->additionalFormats();
+ 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));
+ }
+
for (int i=0; i<textLayout->lineCount(); ++i) {
QTextLine line = textLayout->lineAt(i);
engine.setCurrentLine(line);
- int lineEnd = line.textStart() + line.textLength();
- if (selectionStart > lineEnd || selectionEnd < line.textStart()) {
- QList<QGlyphRun> glyphRuns = line.glyphRuns();
- for (int j=0; j<glyphRuns.size(); ++j)
- engine.addUnselectedGlyphs(glyphRuns.at(j));
- } else {
- if (line.textStart() < selectionStart) {
- QList<QGlyphRun> glyphRuns = line.glyphRuns(line.textStart(),
- qMin(selectionStart - line.textStart(),
- line.textLength()));
+ int currentPosition = line.textStart();
+ int remainingLength = line.textLength();
+ for (int j=0; j<colorChanges.size(); ++j) {
+ const QTextLayout::FormatRange &range = colorChanges.at(j);
+ if (range.start + range.length >= currentPosition
+ && range.start < currentPosition + remainingLength) {
- for (int j=0; j<glyphRuns.size(); ++j)
- engine.addUnselectedGlyphs(glyphRuns.at(j));
- }
+ if (range.start > currentPosition) {
+ engine.addGlyphsInRange(currentPosition, range.start - currentPosition,
+ color, selectionStart, selectionEnd);
+ }
- if (lineEnd >= selectionStart && selectionStart >= line.textStart()) {
- QList<QGlyphRun> glyphRuns = line.glyphRuns(selectionStart, selectionEnd - selectionStart + 1);
+ int rangeEnd = qMin(range.start + range.length, currentPosition + remainingLength);
+ QColor rangeColor = range.format.foreground().color();
- for (int j=0; j<glyphRuns.size(); ++j)
- engine.addSelectedGlyphs(glyphRuns.at(j));
- }
+ engine.addGlyphsInRange(range.start, rangeEnd - range.start, rangeColor,
+ selectionStart, selectionEnd);
- if (selectionEnd >= line.textStart() && selectionEnd < lineEnd) {
- QList<QGlyphRun> glyphRuns = line.glyphRuns(selectionEnd + 1, lineEnd - selectionEnd);
- for (int j=0; j<glyphRuns.size(); ++j)
- engine.addUnselectedGlyphs(glyphRuns.at(j));
+ currentPosition = range.start + range.length;
+ remainingLength = line.textStart() + line.textLength() - currentPosition;
+
+ } else if (range.start > currentPosition + remainingLength || remainingLength <= 0) {
+ break;
}
}
+
+ if (remainingLength > 0) {
+ engine.addGlyphsInRange(currentPosition, remainingLength, color,
+ selectionStart, selectionEnd);
+ }
}
engine.addToSceneGraph(this, style, styleColor);