1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtCore/qlist.h>
5#include <QtCore/qvarlengtharray.h>
6#include <QtGui/qcolor.h>
7#include <QtGui/qglyphrun.h>
8#include <QtGui/qimage.h>
9#include <QtGui/qtextdocument.h>
10#include <QtGui/qtextlayout.h>
11#include "qquickclipnode_p.h"
12#include "qquicktextnode_p.h"
13
14#ifndef QQUICKTEXTNODEENGINE_P_H
15#define QQUICKTEXTNODEENGINE_P_H
16
17//
18// W A R N I N G
19// -------------
20//
21// This file is not part of the Qt API. It exists purely as an
22// implementation detail. This header file may change from version to
23// version without notice, or even be removed.
24//
25// We mean it.
26//
27
28QT_BEGIN_NAMESPACE
29
30// Engine that takes glyph runs as input, and produces a set of glyph nodes, clip nodes,
31// and rectangle nodes to represent the text, decorations and selection. Will try to minimize
32// number of nodes, and join decorations in neighbouring items
33
34class QQuickTextNodeEngine {
35public:
36 enum Decoration {
37 NoDecoration = 0x0,
38 Underline = 0x1,
39 Overline = 0x2,
40 StrikeOut = 0x4,
41 Background = 0x8
42 };
43 Q_DECLARE_FLAGS(Decorations, Decoration)
44
45 enum SelectionState {
46 Unselected,
47 Selected
48 };
49
50 struct BinaryTreeNode {
51
52 BinaryTreeNode()
53 : selectionState(Unselected), clipNode(0), decorations(Decoration::NoDecoration)
54 , ascent(0.0), leftChildIndex(-1), rightChildIndex(-1)
55 {
56 }
57
58 BinaryTreeNode(const QRectF &brect, const QImage &i, SelectionState selState, qreal a)
59 : boundingRect(brect), selectionState(selState), clipNode(0), decorations(Decoration::NoDecoration)
60 , image(i), ascent(a), leftChildIndex(-1), rightChildIndex(-1)
61 {
62 }
63
64 BinaryTreeNode(const QGlyphRun &g, SelectionState selState, const QRectF &brect,
65 const Decorations &decs, const QColor &c, const QColor &bc, const QColor &dc,
66 const QPointF &pos, qreal a);
67
68 QGlyphRun glyphRun;
69 QRectF boundingRect;
70 SelectionState selectionState;
71 QQuickDefaultClipNode *clipNode;
72 Decorations decorations;
73 QColor color;
74 QColor backgroundColor;
75 QColor decorationColor;
76 QPointF position;
77 QImage image;
78 qreal ascent;
79
80 int leftChildIndex;
81 int rightChildIndex;
82
83 QList<QPair<int, int> > ranges;
84
85 static void insert(QVarLengthArray<BinaryTreeNode, 16> *binaryTree, const QRectF &rect, const QImage &image, qreal ascent, SelectionState selectionState)
86 { insert(binaryTree, binaryTreeNode: BinaryTreeNode(rect, image, selectionState, ascent)); }
87
88 static void insert(QVarLengthArray<BinaryTreeNode, 16> *binaryTree, const QGlyphRun &glyphRun, SelectionState selectionState,
89 Decorations decorations, const QColor &textColor, const QColor &backgroundColor, const QColor &underlineColor, const QPointF &position);
90 static void insert(QVarLengthArray<BinaryTreeNode, 16> *binaryTree, const BinaryTreeNode &binaryTreeNode);
91 static void inOrder(const QVarLengthArray<BinaryTreeNode, 16> &binaryTree, QVarLengthArray<int> *sortedIndexes, int currentIndex = 0);
92 };
93
94 struct BinaryTreeNodeKey
95 {
96 BinaryTreeNodeKey(BinaryTreeNode *node);
97
98 bool operator==(const BinaryTreeNodeKey &otherKey) const
99 {
100 return fontEngine == otherKey.fontEngine
101 && clipNode == otherKey.clipNode
102 && color == otherKey.color
103 && selectionState == otherKey.selectionState;
104 }
105
106 QFontEngine *fontEngine;
107 QQuickDefaultClipNode *clipNode;
108 QRgb color;
109 int selectionState;
110 };
111
112 QQuickTextNodeEngine()
113 : m_currentTextDirection(Qt::LeftToRight)
114 , m_hasSelection(false)
115 , m_hasContents(false)
116 {}
117
118 bool hasContents() const { return m_hasContents; }
119 void addTextBlock(QTextDocument *, const QTextBlock &, const QPointF &position, const QColor &textColor,
120 const QColor& anchorColor, int selectionStart, int selectionEnd, const QRectF &viewport = QRectF());
121 QTextLine currentLine() const { return m_currentLine; }
122
123 void setCurrentLine(const QTextLine &currentLine)
124 {
125 if (m_currentLine.isValid())
126 processCurrentLine();
127
128 m_currentLine = currentLine;
129 }
130
131 void setCurrentTextDirection(Qt::LayoutDirection textDirection)
132 {
133 m_currentTextDirection = textDirection;
134 }
135
136 void addBorder(const QRectF &rect, qreal border, QTextFrameFormat::BorderStyle borderStyle,
137 const QBrush &borderBrush);
138 void addFrameDecorations(QTextDocument *document, QTextFrame *frame);
139 void addImage(const QRectF &rect, const QImage &image, qreal ascent,
140 SelectionState selectionState,
141 QTextFrameFormat::Position layoutPosition);
142 int addText(const QTextBlock &block,
143 const QTextCharFormat &charFormat,
144 const QColor &textColor,
145 const QVarLengthArray<QTextLayout::FormatRange> &colorChanges,
146 int textPos, int fragmentEnd,
147 int selectionStart, int selectionEnd);
148 void addTextObject(const QTextBlock &block, const QPointF &position, const QTextCharFormat &format,
149 SelectionState selectionState,
150 QTextDocument *textDocument, int pos,
151 QTextFrameFormat::Position layoutPosition = QTextFrameFormat::InFlow);
152 void addSelectedGlyphs(const QGlyphRun &glyphRun);
153 void addUnselectedGlyphs(const QGlyphRun &glyphRun);
154 void addGlyphsInRange(int rangeStart, int rangeEnd,
155 const QColor &color, const QColor &backgroundColor, const QColor &underlineColor,
156 int selectionStart, int selectionEnd);
157 void addGlyphsForRanges(const QVarLengthArray<QTextLayout::FormatRange> &ranges,
158 int start, int end,
159 int selectionStart, int selectionEnd);
160
161 void mergeProcessedNodes(QList<BinaryTreeNode *> *regularNodes,
162 QList<BinaryTreeNode *> *imageNodes);
163 void addToSceneGraph(QQuickTextNode *parent,
164 QQuickText::TextStyle style = QQuickText::Normal,
165 const QColor &styleColor = QColor());
166
167 void setSelectionColor(const QColor &selectionColor)
168 {
169 m_selectionColor = selectionColor;
170 }
171
172 void setSelectedTextColor(const QColor &selectedTextColor)
173 {
174 m_selectedTextColor = selectedTextColor;
175 }
176
177 void setTextColor(const QColor &textColor)
178 {
179 m_textColor = textColor;
180 }
181
182 void setAnchorColor(const QColor &anchorColor)
183 {
184 m_anchorColor = anchorColor;
185 }
186
187 void setPosition(const QPointF &position)
188 {
189 m_position = position;
190 }
191
192
193
194
195private:
196 struct TextDecoration
197 {
198 TextDecoration() : selectionState(Unselected) {}
199 TextDecoration(const SelectionState &s,
200 const QRectF &r,
201 const QColor &c)
202 : selectionState(s)
203 , rect(r)
204 , color(c)
205 {
206 }
207
208 SelectionState selectionState;
209 QRectF rect;
210 QColor color;
211 };
212
213 void processCurrentLine();
214 void addTextDecorations(const QVarLengthArray<TextDecoration> &textDecorations, qreal offset, qreal thickness);
215 void mergeFormats(QTextLayout *textLayout, QVarLengthArray<QTextLayout::FormatRange> *mergedFormats);
216
217 QColor m_selectionColor;
218 QColor m_textColor;
219 QColor m_backgroundColor;
220 QColor m_decorationColor;
221 QColor m_selectedTextColor;
222 QColor m_anchorColor;
223 QPointF m_position;
224
225 QTextLine m_currentLine;
226 Qt::LayoutDirection m_currentTextDirection;
227
228 QList<QPair<QRectF, QColor> > m_backgrounds;
229 QList<QRectF> m_selectionRects;
230 QVarLengthArray<BinaryTreeNode, 16> m_currentLineTree;
231
232 QList<TextDecoration> m_lines;
233 QVector<BinaryTreeNode> m_processedNodes;
234
235 bool m_hasSelection : 1;
236 bool m_hasContents : 1;
237 friend class QQuickTextNode;
238
239};
240
241QT_END_NAMESPACE
242
243#endif // QQUICKTEXTNODEENGINE_P_H
244

source code of qtdeclarative/src/quick/items/qquicktextnodeengine_p.h