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

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