Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/gui/text/qtextlayout.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
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 QtGui 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 "qtextlayout.h" | - | ||||||||||||||||||||||||
41 | #include "qtextengine_p.h" | - | ||||||||||||||||||||||||
42 | - | |||||||||||||||||||||||||
43 | #include <qthread.h> | - | ||||||||||||||||||||||||
44 | #include <qfont.h> | - | ||||||||||||||||||||||||
45 | #include <qmath.h> | - | ||||||||||||||||||||||||
46 | #include <qpainter.h> | - | ||||||||||||||||||||||||
47 | #include <qvarlengtharray.h> | - | ||||||||||||||||||||||||
48 | #include <qtextformat.h> | - | ||||||||||||||||||||||||
49 | #include <qabstracttextdocumentlayout.h> | - | ||||||||||||||||||||||||
50 | #include "qtextdocument_p.h" | - | ||||||||||||||||||||||||
51 | #include "qtextformat_p.h" | - | ||||||||||||||||||||||||
52 | #include "qpainterpath.h" | - | ||||||||||||||||||||||||
53 | #include "qglyphrun.h" | - | ||||||||||||||||||||||||
54 | #include "qglyphrun_p.h" | - | ||||||||||||||||||||||||
55 | #include "qrawfont.h" | - | ||||||||||||||||||||||||
56 | #include "qrawfont_p.h" | - | ||||||||||||||||||||||||
57 | #include <limits.h> | - | ||||||||||||||||||||||||
58 | - | |||||||||||||||||||||||||
59 | #include <qdebug.h> | - | ||||||||||||||||||||||||
60 | - | |||||||||||||||||||||||||
61 | #include "qfontengine_p.h" | - | ||||||||||||||||||||||||
62 | #include <private/qpainter_p.h> | - | ||||||||||||||||||||||||
63 | - | |||||||||||||||||||||||||
64 | QT_BEGIN_NAMESPACE | - | ||||||||||||||||||||||||
65 | - | |||||||||||||||||||||||||
66 | #define ObjectSelectionBrush (QTextFormat::ForegroundBrush + 1) | - | ||||||||||||||||||||||||
67 | #define SuppressText 0x5012 | - | ||||||||||||||||||||||||
68 | #define SuppressBackground 0x513 | - | ||||||||||||||||||||||||
69 | - | |||||||||||||||||||||||||
70 | /*! | - | ||||||||||||||||||||||||
71 | \class QTextLayout::FormatRange | - | ||||||||||||||||||||||||
72 | \reentrant | - | ||||||||||||||||||||||||
73 | - | |||||||||||||||||||||||||
74 | \brief The QTextLayout::FormatRange structure is used to apply extra formatting information | - | ||||||||||||||||||||||||
75 | for a specified area in the text layout's content. | - | ||||||||||||||||||||||||
76 | \inmodule QtGui | - | ||||||||||||||||||||||||
77 | - | |||||||||||||||||||||||||
78 | \sa QTextLayout::setFormats(), QTextLayout::draw() | - | ||||||||||||||||||||||||
79 | */ | - | ||||||||||||||||||||||||
80 | - | |||||||||||||||||||||||||
81 | /*! | - | ||||||||||||||||||||||||
82 | \variable QTextLayout::FormatRange::start | - | ||||||||||||||||||||||||
83 | Specifies the beginning of the format range within the text layout's text. | - | ||||||||||||||||||||||||
84 | */ | - | ||||||||||||||||||||||||
85 | - | |||||||||||||||||||||||||
86 | /*! | - | ||||||||||||||||||||||||
87 | \variable QTextLayout::FormatRange::length | - | ||||||||||||||||||||||||
88 | Specifies the numer of characters the format range spans. | - | ||||||||||||||||||||||||
89 | */ | - | ||||||||||||||||||||||||
90 | - | |||||||||||||||||||||||||
91 | /*! | - | ||||||||||||||||||||||||
92 | \variable QTextLayout::FormatRange::format | - | ||||||||||||||||||||||||
93 | Specifies the format to apply. | - | ||||||||||||||||||||||||
94 | */ | - | ||||||||||||||||||||||||
95 | - | |||||||||||||||||||||||||
96 | /*! \fn bool operator==(const FormatRange &lhs, const FormatRange &rhs) | - | ||||||||||||||||||||||||
97 | \relates QTextLayout::FormatRange | - | ||||||||||||||||||||||||
98 | - | |||||||||||||||||||||||||
99 | Returns true if the \c {start}, \c {length}, and \c {format} fields | - | ||||||||||||||||||||||||
100 | in \a lhs and \a rhs contain the same values respectively. | - | ||||||||||||||||||||||||
101 | */ | - | ||||||||||||||||||||||||
102 | - | |||||||||||||||||||||||||
103 | /*! \fn bool operator!=(const FormatRange &lhs, const FormatRange &rhs) | - | ||||||||||||||||||||||||
104 | \relates QTextLayout::FormatRange | - | ||||||||||||||||||||||||
105 | - | |||||||||||||||||||||||||
106 | Returns true if any of the \c {start}, \c {length}, or \c {format} fields | - | ||||||||||||||||||||||||
107 | in \a lhs and \a rhs contain different values respectively. | - | ||||||||||||||||||||||||
108 | */ | - | ||||||||||||||||||||||||
109 | - | |||||||||||||||||||||||||
110 | /*! | - | ||||||||||||||||||||||||
111 | \class QTextInlineObject | - | ||||||||||||||||||||||||
112 | \reentrant | - | ||||||||||||||||||||||||
113 | - | |||||||||||||||||||||||||
114 | \brief The QTextInlineObject class represents an inline object in | - | ||||||||||||||||||||||||
115 | a QAbstractTextDocumentLayout and its implementations. | - | ||||||||||||||||||||||||
116 | \inmodule QtGui | - | ||||||||||||||||||||||||
117 | - | |||||||||||||||||||||||||
118 | \ingroup richtext-processing | - | ||||||||||||||||||||||||
119 | - | |||||||||||||||||||||||||
120 | Normally, you do not need to create a QTextInlineObject. It is | - | ||||||||||||||||||||||||
121 | used by QAbstractTextDocumentLayout to handle inline objects when | - | ||||||||||||||||||||||||
122 | implementing a custom layout. | - | ||||||||||||||||||||||||
123 | - | |||||||||||||||||||||||||
124 | The inline object has various attributes that can be set, for | - | ||||||||||||||||||||||||
125 | example using, setWidth(), setAscent(), and setDescent(). The | - | ||||||||||||||||||||||||
126 | rectangle it occupies is given by rect(), and its direction by | - | ||||||||||||||||||||||||
127 | textDirection(). Its position in the text layout is given by | - | ||||||||||||||||||||||||
128 | textPosition(), and its format is given by format(). | - | ||||||||||||||||||||||||
129 | */ | - | ||||||||||||||||||||||||
130 | - | |||||||||||||||||||||||||
131 | /*! | - | ||||||||||||||||||||||||
132 | \fn QTextInlineObject::QTextInlineObject(int i, QTextEngine *e) | - | ||||||||||||||||||||||||
133 | \internal | - | ||||||||||||||||||||||||
134 | - | |||||||||||||||||||||||||
135 | Creates a new inline object for the item at position \a i in the | - | ||||||||||||||||||||||||
136 | text engine \a e. | - | ||||||||||||||||||||||||
137 | */ | - | ||||||||||||||||||||||||
138 | - | |||||||||||||||||||||||||
139 | /*! | - | ||||||||||||||||||||||||
140 | \fn QTextInlineObject::QTextInlineObject() | - | ||||||||||||||||||||||||
141 | - | |||||||||||||||||||||||||
142 | \internal | - | ||||||||||||||||||||||||
143 | */ | - | ||||||||||||||||||||||||
144 | - | |||||||||||||||||||||||||
145 | /*! | - | ||||||||||||||||||||||||
146 | \fn bool QTextInlineObject::isValid() const | - | ||||||||||||||||||||||||
147 | - | |||||||||||||||||||||||||
148 | Returns \c true if this inline object is valid; otherwise returns | - | ||||||||||||||||||||||||
149 | false. | - | ||||||||||||||||||||||||
150 | */ | - | ||||||||||||||||||||||||
151 | - | |||||||||||||||||||||||||
152 | /*! | - | ||||||||||||||||||||||||
153 | Returns the inline object's rectangle. | - | ||||||||||||||||||||||||
154 | - | |||||||||||||||||||||||||
155 | \sa ascent(), descent(), width() | - | ||||||||||||||||||||||||
156 | */ | - | ||||||||||||||||||||||||
157 | QRectF QTextInlineObject::rect() const | - | ||||||||||||||||||||||||
158 | { | - | ||||||||||||||||||||||||
159 | QScriptItem& si = eng->layoutData->items[itm]; | - | ||||||||||||||||||||||||
160 | return QRectF(0, -si.ascent.toReal(), si.width.toReal(), si.height().toReal()); never executed: return QRectF(0, -si.ascent.toReal(), si.width.toReal(), si.height().toReal()); | 0 | ||||||||||||||||||||||||
161 | } | - | ||||||||||||||||||||||||
162 | - | |||||||||||||||||||||||||
163 | /*! | - | ||||||||||||||||||||||||
164 | Returns the inline object's width. | - | ||||||||||||||||||||||||
165 | - | |||||||||||||||||||||||||
166 | \sa ascent(), descent(), rect() | - | ||||||||||||||||||||||||
167 | */ | - | ||||||||||||||||||||||||
168 | qreal QTextInlineObject::width() const | - | ||||||||||||||||||||||||
169 | { | - | ||||||||||||||||||||||||
170 | return eng->layoutData->items[itm].width.toReal(); never executed: return eng->layoutData->items[itm].width.toReal(); | 0 | ||||||||||||||||||||||||
171 | } | - | ||||||||||||||||||||||||
172 | - | |||||||||||||||||||||||||
173 | /*! | - | ||||||||||||||||||||||||
174 | Returns the inline object's ascent. | - | ||||||||||||||||||||||||
175 | - | |||||||||||||||||||||||||
176 | \sa descent(), width(), rect() | - | ||||||||||||||||||||||||
177 | */ | - | ||||||||||||||||||||||||
178 | qreal QTextInlineObject::ascent() const | - | ||||||||||||||||||||||||
179 | { | - | ||||||||||||||||||||||||
180 | return eng->layoutData->items[itm].ascent.toReal(); never executed: return eng->layoutData->items[itm].ascent.toReal(); | 0 | ||||||||||||||||||||||||
181 | } | - | ||||||||||||||||||||||||
182 | - | |||||||||||||||||||||||||
183 | /*! | - | ||||||||||||||||||||||||
184 | Returns the inline object's descent. | - | ||||||||||||||||||||||||
185 | - | |||||||||||||||||||||||||
186 | \sa ascent(), width(), rect() | - | ||||||||||||||||||||||||
187 | */ | - | ||||||||||||||||||||||||
188 | qreal QTextInlineObject::descent() const | - | ||||||||||||||||||||||||
189 | { | - | ||||||||||||||||||||||||
190 | return eng->layoutData->items[itm].descent.toReal(); never executed: return eng->layoutData->items[itm].descent.toReal(); | 0 | ||||||||||||||||||||||||
191 | } | - | ||||||||||||||||||||||||
192 | - | |||||||||||||||||||||||||
193 | /*! | - | ||||||||||||||||||||||||
194 | Returns the inline object's total height. This is equal to | - | ||||||||||||||||||||||||
195 | ascent() + descent() + 1. | - | ||||||||||||||||||||||||
196 | - | |||||||||||||||||||||||||
197 | \sa ascent(), descent(), width(), rect() | - | ||||||||||||||||||||||||
198 | */ | - | ||||||||||||||||||||||||
199 | qreal QTextInlineObject::height() const | - | ||||||||||||||||||||||||
200 | { | - | ||||||||||||||||||||||||
201 | return eng->layoutData->items[itm].height().toReal(); never executed: return eng->layoutData->items[itm].height().toReal(); | 0 | ||||||||||||||||||||||||
202 | } | - | ||||||||||||||||||||||||
203 | - | |||||||||||||||||||||||||
204 | /*! | - | ||||||||||||||||||||||||
205 | Sets the inline object's width to \a w. | - | ||||||||||||||||||||||||
206 | - | |||||||||||||||||||||||||
207 | \sa width(), ascent(), descent(), rect() | - | ||||||||||||||||||||||||
208 | */ | - | ||||||||||||||||||||||||
209 | void QTextInlineObject::setWidth(qreal w) | - | ||||||||||||||||||||||||
210 | { | - | ||||||||||||||||||||||||
211 | eng->layoutData->items[itm].width = QFixed::fromReal(w); | - | ||||||||||||||||||||||||
212 | } never executed: end of block | 0 | ||||||||||||||||||||||||
213 | - | |||||||||||||||||||||||||
214 | /*! | - | ||||||||||||||||||||||||
215 | Sets the inline object's ascent to \a a. | - | ||||||||||||||||||||||||
216 | - | |||||||||||||||||||||||||
217 | \sa ascent(), setDescent(), width(), rect() | - | ||||||||||||||||||||||||
218 | */ | - | ||||||||||||||||||||||||
219 | void QTextInlineObject::setAscent(qreal a) | - | ||||||||||||||||||||||||
220 | { | - | ||||||||||||||||||||||||
221 | eng->layoutData->items[itm].ascent = QFixed::fromReal(a); | - | ||||||||||||||||||||||||
222 | } never executed: end of block | 0 | ||||||||||||||||||||||||
223 | - | |||||||||||||||||||||||||
224 | /*! | - | ||||||||||||||||||||||||
225 | Sets the inline object's descent to \a d. | - | ||||||||||||||||||||||||
226 | - | |||||||||||||||||||||||||
227 | \sa descent(), setAscent(), width(), rect() | - | ||||||||||||||||||||||||
228 | */ | - | ||||||||||||||||||||||||
229 | void QTextInlineObject::setDescent(qreal d) | - | ||||||||||||||||||||||||
230 | { | - | ||||||||||||||||||||||||
231 | eng->layoutData->items[itm].descent = QFixed::fromReal(d); | - | ||||||||||||||||||||||||
232 | } never executed: end of block | 0 | ||||||||||||||||||||||||
233 | - | |||||||||||||||||||||||||
234 | /*! | - | ||||||||||||||||||||||||
235 | The position of the inline object within the text layout. | - | ||||||||||||||||||||||||
236 | */ | - | ||||||||||||||||||||||||
237 | int QTextInlineObject::textPosition() const | - | ||||||||||||||||||||||||
238 | { | - | ||||||||||||||||||||||||
239 | return eng->layoutData->items[itm].position; never executed: return eng->layoutData->items[itm].position; | 0 | ||||||||||||||||||||||||
240 | } | - | ||||||||||||||||||||||||
241 | - | |||||||||||||||||||||||||
242 | /*! | - | ||||||||||||||||||||||||
243 | Returns an integer describing the format of the inline object | - | ||||||||||||||||||||||||
244 | within the text layout. | - | ||||||||||||||||||||||||
245 | */ | - | ||||||||||||||||||||||||
246 | int QTextInlineObject::formatIndex() const | - | ||||||||||||||||||||||||
247 | { | - | ||||||||||||||||||||||||
248 | return eng->formatIndex(&eng->layoutData->items[itm]); never executed: return eng->formatIndex(&eng->layoutData->items[itm]); | 0 | ||||||||||||||||||||||||
249 | } | - | ||||||||||||||||||||||||
250 | - | |||||||||||||||||||||||||
251 | /*! | - | ||||||||||||||||||||||||
252 | Returns format of the inline object within the text layout. | - | ||||||||||||||||||||||||
253 | */ | - | ||||||||||||||||||||||||
254 | QTextFormat QTextInlineObject::format() const | - | ||||||||||||||||||||||||
255 | { | - | ||||||||||||||||||||||||
256 | return eng->format(&eng->layoutData->items[itm]); never executed: return eng->format(&eng->layoutData->items[itm]); | 0 | ||||||||||||||||||||||||
257 | } | - | ||||||||||||||||||||||||
258 | - | |||||||||||||||||||||||||
259 | /*! | - | ||||||||||||||||||||||||
260 | Returns if the object should be laid out right-to-left or left-to-right. | - | ||||||||||||||||||||||||
261 | */ | - | ||||||||||||||||||||||||
262 | Qt::LayoutDirection QTextInlineObject::textDirection() const | - | ||||||||||||||||||||||||
263 | { | - | ||||||||||||||||||||||||
264 | return (eng->layoutData->items[itm].analysis.bidiLevel % 2 ? Qt::RightToLeft : Qt::LeftToRight); never executed: return (eng->layoutData->items[itm].analysis.bidiLevel % 2 ? Qt::RightToLeft : Qt::LeftToRight); | 0 | ||||||||||||||||||||||||
265 | } | - | ||||||||||||||||||||||||
266 | - | |||||||||||||||||||||||||
267 | /*! | - | ||||||||||||||||||||||||
268 | \class QTextLayout | - | ||||||||||||||||||||||||
269 | \reentrant | - | ||||||||||||||||||||||||
270 | - | |||||||||||||||||||||||||
271 | \brief The QTextLayout class is used to lay out and render text. | - | ||||||||||||||||||||||||
272 | \inmodule QtGui | - | ||||||||||||||||||||||||
273 | - | |||||||||||||||||||||||||
274 | \ingroup richtext-processing | - | ||||||||||||||||||||||||
275 | - | |||||||||||||||||||||||||
276 | It offers many features expected from a modern text layout | - | ||||||||||||||||||||||||
277 | engine, including Unicode compliant rendering, line breaking and | - | ||||||||||||||||||||||||
278 | handling of cursor positioning. It can also produce and render | - | ||||||||||||||||||||||||
279 | device independent layout, something that is important for WYSIWYG | - | ||||||||||||||||||||||||
280 | applications. | - | ||||||||||||||||||||||||
281 | - | |||||||||||||||||||||||||
282 | The class has a rather low level API and unless you intend to | - | ||||||||||||||||||||||||
283 | implement your own text rendering for some specialized widget, you | - | ||||||||||||||||||||||||
284 | probably won't need to use it directly. | - | ||||||||||||||||||||||||
285 | - | |||||||||||||||||||||||||
286 | QTextLayout can be used with both plain and rich text. | - | ||||||||||||||||||||||||
287 | - | |||||||||||||||||||||||||
288 | QTextLayout can be used to create a sequence of QTextLine | - | ||||||||||||||||||||||||
289 | instances with given widths and can position them independently | - | ||||||||||||||||||||||||
290 | on the screen. Once the layout is done, these lines can be drawn | - | ||||||||||||||||||||||||
291 | on a paint device. | - | ||||||||||||||||||||||||
292 | - | |||||||||||||||||||||||||
293 | The text to be laid out can be provided in the constructor or set with | - | ||||||||||||||||||||||||
294 | setText(). | - | ||||||||||||||||||||||||
295 | - | |||||||||||||||||||||||||
296 | The layout can be seen as a sequence of QTextLine objects; use createLine() | - | ||||||||||||||||||||||||
297 | to create a QTextLine instance, and lineAt() or lineForTextPosition() to retrieve | - | ||||||||||||||||||||||||
298 | created lines. | - | ||||||||||||||||||||||||
299 | - | |||||||||||||||||||||||||
300 | Here is a code snippet that demonstrates the layout phase: | - | ||||||||||||||||||||||||
301 | \snippet code/src_gui_text_qtextlayout.cpp 0 | - | ||||||||||||||||||||||||
302 | - | |||||||||||||||||||||||||
303 | The text can then be rendered by calling the layout's draw() function: | - | ||||||||||||||||||||||||
304 | \snippet code/src_gui_text_qtextlayout.cpp 1 | - | ||||||||||||||||||||||||
305 | - | |||||||||||||||||||||||||
306 | For a given position in the text you can find a valid cursor position with | - | ||||||||||||||||||||||||
307 | isValidCursorPosition(), nextCursorPosition(), and previousCursorPosition(). | - | ||||||||||||||||||||||||
308 | - | |||||||||||||||||||||||||
309 | The QTextLayout itself can be positioned with setPosition(); it has a | - | ||||||||||||||||||||||||
310 | boundingRect(), and a minimumWidth() and a maximumWidth(). | - | ||||||||||||||||||||||||
311 | - | |||||||||||||||||||||||||
312 | \sa QStaticText | - | ||||||||||||||||||||||||
313 | */ | - | ||||||||||||||||||||||||
314 | - | |||||||||||||||||||||||||
315 | /*! | - | ||||||||||||||||||||||||
316 | \enum QTextLayout::CursorMode | - | ||||||||||||||||||||||||
317 | - | |||||||||||||||||||||||||
318 | \value SkipCharacters | - | ||||||||||||||||||||||||
319 | \value SkipWords | - | ||||||||||||||||||||||||
320 | */ | - | ||||||||||||||||||||||||
321 | - | |||||||||||||||||||||||||
322 | /*! | - | ||||||||||||||||||||||||
323 | \fn QTextEngine *QTextLayout::engine() const | - | ||||||||||||||||||||||||
324 | \internal | - | ||||||||||||||||||||||||
325 | - | |||||||||||||||||||||||||
326 | Returns the text engine used to render the text layout. | - | ||||||||||||||||||||||||
327 | */ | - | ||||||||||||||||||||||||
328 | - | |||||||||||||||||||||||||
329 | /*! | - | ||||||||||||||||||||||||
330 | Constructs an empty text layout. | - | ||||||||||||||||||||||||
331 | - | |||||||||||||||||||||||||
332 | \sa setText() | - | ||||||||||||||||||||||||
333 | */ | - | ||||||||||||||||||||||||
334 | QTextLayout::QTextLayout() | - | ||||||||||||||||||||||||
335 | { never executed: d = new QTextEngine(); }end of block never executed: end of block | 0 | ||||||||||||||||||||||||
336 | - | |||||||||||||||||||||||||
337 | /*! | - | ||||||||||||||||||||||||
338 | Constructs a text layout to lay out the given \a text. | - | ||||||||||||||||||||||||
339 | */ | - | ||||||||||||||||||||||||
340 | QTextLayout::QTextLayout(const QString& text) | - | ||||||||||||||||||||||||
341 | { | - | ||||||||||||||||||||||||
342 | d = new QTextEngine(); | - | ||||||||||||||||||||||||
343 | d->text = text; | - | ||||||||||||||||||||||||
344 | } never executed: end of block | 0 | ||||||||||||||||||||||||
345 | - | |||||||||||||||||||||||||
346 | /*! | - | ||||||||||||||||||||||||
347 | Constructs a text layout to lay out the given \a text with the specified | - | ||||||||||||||||||||||||
348 | \a font. | - | ||||||||||||||||||||||||
349 | - | |||||||||||||||||||||||||
350 | All the metric and layout calculations will be done in terms of | - | ||||||||||||||||||||||||
351 | the paint device, \a paintdevice. If \a paintdevice is 0 the | - | ||||||||||||||||||||||||
352 | calculations will be done in screen metrics. | - | ||||||||||||||||||||||||
353 | */ | - | ||||||||||||||||||||||||
354 | QTextLayout::QTextLayout(const QString& text, const QFont &font, QPaintDevice *paintdevice) | - | ||||||||||||||||||||||||
355 | { | - | ||||||||||||||||||||||||
356 | QFont f(font); | - | ||||||||||||||||||||||||
357 | if (paintdevice)
| 0 | ||||||||||||||||||||||||
358 | f = QFont(font, paintdevice); never executed: f = QFont(font, paintdevice); | 0 | ||||||||||||||||||||||||
359 | d = new QTextEngine((text.isNull() ? (const QString&)QString::fromLatin1("") : text), f); | - | ||||||||||||||||||||||||
360 | } never executed: end of block | 0 | ||||||||||||||||||||||||
361 | - | |||||||||||||||||||||||||
362 | /*! | - | ||||||||||||||||||||||||
363 | \internal | - | ||||||||||||||||||||||||
364 | Constructs a text layout to lay out the given \a block. | - | ||||||||||||||||||||||||
365 | */ | - | ||||||||||||||||||||||||
366 | QTextLayout::QTextLayout(const QTextBlock &block) | - | ||||||||||||||||||||||||
367 | { | - | ||||||||||||||||||||||||
368 | d = new QTextEngine(); | - | ||||||||||||||||||||||||
369 | d->block = block; | - | ||||||||||||||||||||||||
370 | } never executed: end of block | 0 | ||||||||||||||||||||||||
371 | - | |||||||||||||||||||||||||
372 | /*! | - | ||||||||||||||||||||||||
373 | Destructs the layout. | - | ||||||||||||||||||||||||
374 | */ | - | ||||||||||||||||||||||||
375 | QTextLayout::~QTextLayout() | - | ||||||||||||||||||||||||
376 | { | - | ||||||||||||||||||||||||
377 | if (!d->stackEngine)
| 0 | ||||||||||||||||||||||||
378 | delete d; never executed: delete d; | 0 | ||||||||||||||||||||||||
379 | } never executed: end of block | 0 | ||||||||||||||||||||||||
380 | - | |||||||||||||||||||||||||
381 | #ifndef QT_NO_RAWFONT | - | ||||||||||||||||||||||||
382 | /*! | - | ||||||||||||||||||||||||
383 | \internal | - | ||||||||||||||||||||||||
384 | Sets a raw font, to be used with QTextLayout::glyphRuns. | - | ||||||||||||||||||||||||
385 | Note that this only supports the needs of WebKit. | - | ||||||||||||||||||||||||
386 | Use of this function with e.g. QTextLayout::draw will result | - | ||||||||||||||||||||||||
387 | in undefined behaviour. | - | ||||||||||||||||||||||||
388 | */ | - | ||||||||||||||||||||||||
389 | void QTextLayout::setRawFont(const QRawFont &rawFont) | - | ||||||||||||||||||||||||
390 | { | - | ||||||||||||||||||||||||
391 | d->rawFont = rawFont; | - | ||||||||||||||||||||||||
392 | d->useRawFont = true; | - | ||||||||||||||||||||||||
393 | d->resetFontEngineCache(); | - | ||||||||||||||||||||||||
394 | } never executed: end of block | 0 | ||||||||||||||||||||||||
395 | #endif | - | ||||||||||||||||||||||||
396 | - | |||||||||||||||||||||||||
397 | /*! | - | ||||||||||||||||||||||||
398 | Sets the layout's font to the given \a font. The layout is | - | ||||||||||||||||||||||||
399 | invalidated and must be laid out again. | - | ||||||||||||||||||||||||
400 | - | |||||||||||||||||||||||||
401 | \sa font() | - | ||||||||||||||||||||||||
402 | */ | - | ||||||||||||||||||||||||
403 | void QTextLayout::setFont(const QFont &font) | - | ||||||||||||||||||||||||
404 | { | - | ||||||||||||||||||||||||
405 | d->fnt = font; | - | ||||||||||||||||||||||||
406 | #ifndef QT_NO_RAWFONT | - | ||||||||||||||||||||||||
407 | d->useRawFont = false; | - | ||||||||||||||||||||||||
408 | #endif | - | ||||||||||||||||||||||||
409 | d->resetFontEngineCache(); | - | ||||||||||||||||||||||||
410 | } never executed: end of block | 0 | ||||||||||||||||||||||||
411 | - | |||||||||||||||||||||||||
412 | /*! | - | ||||||||||||||||||||||||
413 | Returns the current font that is used for the layout, or a default | - | ||||||||||||||||||||||||
414 | font if none is set. | - | ||||||||||||||||||||||||
415 | - | |||||||||||||||||||||||||
416 | \sa setFont() | - | ||||||||||||||||||||||||
417 | */ | - | ||||||||||||||||||||||||
418 | QFont QTextLayout::font() const | - | ||||||||||||||||||||||||
419 | { | - | ||||||||||||||||||||||||
420 | return d->font(); never executed: return d->font(); | 0 | ||||||||||||||||||||||||
421 | } | - | ||||||||||||||||||||||||
422 | - | |||||||||||||||||||||||||
423 | /*! | - | ||||||||||||||||||||||||
424 | Sets the layout's text to the given \a string. The layout is | - | ||||||||||||||||||||||||
425 | invalidated and must be laid out again. | - | ||||||||||||||||||||||||
426 | - | |||||||||||||||||||||||||
427 | Notice that when using this QTextLayout as part of a QTextDocument this | - | ||||||||||||||||||||||||
428 | method will have no effect. | - | ||||||||||||||||||||||||
429 | - | |||||||||||||||||||||||||
430 | \sa text() | - | ||||||||||||||||||||||||
431 | */ | - | ||||||||||||||||||||||||
432 | void QTextLayout::setText(const QString& string) | - | ||||||||||||||||||||||||
433 | { | - | ||||||||||||||||||||||||
434 | d->invalidate(); | - | ||||||||||||||||||||||||
435 | d->clearLineData(); | - | ||||||||||||||||||||||||
436 | d->text = string; | - | ||||||||||||||||||||||||
437 | } never executed: end of block | 0 | ||||||||||||||||||||||||
438 | - | |||||||||||||||||||||||||
439 | /*! | - | ||||||||||||||||||||||||
440 | Returns the layout's text. | - | ||||||||||||||||||||||||
441 | - | |||||||||||||||||||||||||
442 | \sa setText() | - | ||||||||||||||||||||||||
443 | */ | - | ||||||||||||||||||||||||
444 | QString QTextLayout::text() const | - | ||||||||||||||||||||||||
445 | { | - | ||||||||||||||||||||||||
446 | return d->text; never executed: return d->text; | 0 | ||||||||||||||||||||||||
447 | } | - | ||||||||||||||||||||||||
448 | - | |||||||||||||||||||||||||
449 | /*! | - | ||||||||||||||||||||||||
450 | Sets the text option structure that controls the layout process to the | - | ||||||||||||||||||||||||
451 | given \a option. | - | ||||||||||||||||||||||||
452 | - | |||||||||||||||||||||||||
453 | \sa textOption() | - | ||||||||||||||||||||||||
454 | */ | - | ||||||||||||||||||||||||
455 | void QTextLayout::setTextOption(const QTextOption &option) | - | ||||||||||||||||||||||||
456 | { | - | ||||||||||||||||||||||||
457 | d->option = option; | - | ||||||||||||||||||||||||
458 | } never executed: end of block | 0 | ||||||||||||||||||||||||
459 | - | |||||||||||||||||||||||||
460 | /*! | - | ||||||||||||||||||||||||
461 | Returns the current text option used to control the layout process. | - | ||||||||||||||||||||||||
462 | - | |||||||||||||||||||||||||
463 | \sa setTextOption() | - | ||||||||||||||||||||||||
464 | */ | - | ||||||||||||||||||||||||
465 | const QTextOption &QTextLayout::textOption() const | - | ||||||||||||||||||||||||
466 | { | - | ||||||||||||||||||||||||
467 | return d->option; never executed: return d->option; | 0 | ||||||||||||||||||||||||
468 | } | - | ||||||||||||||||||||||||
469 | - | |||||||||||||||||||||||||
470 | /*! | - | ||||||||||||||||||||||||
471 | Sets the \a position and \a text of the area in the layout that is | - | ||||||||||||||||||||||||
472 | processed before editing occurs. The layout is | - | ||||||||||||||||||||||||
473 | invalidated and must be laid out again. | - | ||||||||||||||||||||||||
474 | - | |||||||||||||||||||||||||
475 | \sa preeditAreaPosition(), preeditAreaText() | - | ||||||||||||||||||||||||
476 | */ | - | ||||||||||||||||||||||||
477 | void QTextLayout::setPreeditArea(int position, const QString &text) | - | ||||||||||||||||||||||||
478 | { | - | ||||||||||||||||||||||||
479 | if (d->preeditAreaPosition() == position && d->preeditAreaText() == text)
| 0 | ||||||||||||||||||||||||
480 | return; never executed: return; | 0 | ||||||||||||||||||||||||
481 | d->setPreeditArea(position, text); | - | ||||||||||||||||||||||||
482 | - | |||||||||||||||||||||||||
483 | if (d->block.docHandle())
| 0 | ||||||||||||||||||||||||
484 | d->block.docHandle()->documentChange(d->block.position(), d->block.length()); never executed: d->block.docHandle()->documentChange(d->block.position(), d->block.length()); | 0 | ||||||||||||||||||||||||
485 | } never executed: end of block | 0 | ||||||||||||||||||||||||
486 | - | |||||||||||||||||||||||||
487 | /*! | - | ||||||||||||||||||||||||
488 | Returns the position of the area in the text layout that will be | - | ||||||||||||||||||||||||
489 | processed before editing occurs. | - | ||||||||||||||||||||||||
490 | - | |||||||||||||||||||||||||
491 | \sa preeditAreaText() | - | ||||||||||||||||||||||||
492 | */ | - | ||||||||||||||||||||||||
493 | int QTextLayout::preeditAreaPosition() const | - | ||||||||||||||||||||||||
494 | { | - | ||||||||||||||||||||||||
495 | return d->preeditAreaPosition(); never executed: return d->preeditAreaPosition(); | 0 | ||||||||||||||||||||||||
496 | } | - | ||||||||||||||||||||||||
497 | - | |||||||||||||||||||||||||
498 | /*! | - | ||||||||||||||||||||||||
499 | Returns the text that is inserted in the layout before editing occurs. | - | ||||||||||||||||||||||||
500 | - | |||||||||||||||||||||||||
501 | \sa preeditAreaPosition() | - | ||||||||||||||||||||||||
502 | */ | - | ||||||||||||||||||||||||
503 | QString QTextLayout::preeditAreaText() const | - | ||||||||||||||||||||||||
504 | { | - | ||||||||||||||||||||||||
505 | return d->preeditAreaText(); never executed: return d->preeditAreaText(); | 0 | ||||||||||||||||||||||||
506 | } | - | ||||||||||||||||||||||||
507 | - | |||||||||||||||||||||||||
508 | #if QT_DEPRECATED_SINCE(5, 6) | - | ||||||||||||||||||||||||
509 | /*! | - | ||||||||||||||||||||||||
510 | \obsolete Use setFormats() instead. | - | ||||||||||||||||||||||||
511 | */ | - | ||||||||||||||||||||||||
512 | void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList) | - | ||||||||||||||||||||||||
513 | { | - | ||||||||||||||||||||||||
514 | setFormats(formatList.toVector()); | - | ||||||||||||||||||||||||
515 | } never executed: end of block | 0 | ||||||||||||||||||||||||
516 | #endif // deprecated since 5.6 | - | ||||||||||||||||||||||||
517 | - | |||||||||||||||||||||||||
518 | /*! | - | ||||||||||||||||||||||||
519 | \since 5.6 | - | ||||||||||||||||||||||||
520 | - | |||||||||||||||||||||||||
521 | Sets the additional formats supported by the text layout to \a formats. | - | ||||||||||||||||||||||||
522 | The formats are applied with preedit area text in place. | - | ||||||||||||||||||||||||
523 | - | |||||||||||||||||||||||||
524 | \sa formats(), clearFormats() | - | ||||||||||||||||||||||||
525 | */ | - | ||||||||||||||||||||||||
526 | void QTextLayout::setFormats(const QVector<FormatRange> &formats) | - | ||||||||||||||||||||||||
527 | { | - | ||||||||||||||||||||||||
528 | d->setFormats(formats); | - | ||||||||||||||||||||||||
529 | - | |||||||||||||||||||||||||
530 | if (d->block.docHandle())
| 0 | ||||||||||||||||||||||||
531 | d->block.docHandle()->documentChange(d->block.position(), d->block.length()); never executed: d->block.docHandle()->documentChange(d->block.position(), d->block.length()); | 0 | ||||||||||||||||||||||||
532 | } never executed: end of block | 0 | ||||||||||||||||||||||||
533 | - | |||||||||||||||||||||||||
534 | #if QT_DEPRECATED_SINCE(5, 6) | - | ||||||||||||||||||||||||
535 | /*! | - | ||||||||||||||||||||||||
536 | \obsolete Use formats() instead. | - | ||||||||||||||||||||||||
537 | - | |||||||||||||||||||||||||
538 | \sa setAdditionalFormats(), clearAdditionalFormats() | - | ||||||||||||||||||||||||
539 | */ | - | ||||||||||||||||||||||||
540 | QList<QTextLayout::FormatRange> QTextLayout::additionalFormats() const | - | ||||||||||||||||||||||||
541 | { | - | ||||||||||||||||||||||||
542 | return formats().toList(); never executed: return formats().toList(); | 0 | ||||||||||||||||||||||||
543 | } | - | ||||||||||||||||||||||||
544 | #endif // deprecated since 5.6 | - | ||||||||||||||||||||||||
545 | - | |||||||||||||||||||||||||
546 | /*! | - | ||||||||||||||||||||||||
547 | \since 5.6 | - | ||||||||||||||||||||||||
548 | - | |||||||||||||||||||||||||
549 | Returns the list of additional formats supported by the text layout. | - | ||||||||||||||||||||||||
550 | - | |||||||||||||||||||||||||
551 | \sa setFormats(), clearFormats() | - | ||||||||||||||||||||||||
552 | */ | - | ||||||||||||||||||||||||
553 | QVector<QTextLayout::FormatRange> QTextLayout::formats() const | - | ||||||||||||||||||||||||
554 | { | - | ||||||||||||||||||||||||
555 | return d->formats(); never executed: return d->formats(); | 0 | ||||||||||||||||||||||||
556 | } | - | ||||||||||||||||||||||||
557 | - | |||||||||||||||||||||||||
558 | #if QT_DEPRECATED_SINCE(5, 6) | - | ||||||||||||||||||||||||
559 | /*! | - | ||||||||||||||||||||||||
560 | \obsolete Use clearFormats() instead. | - | ||||||||||||||||||||||||
561 | */ | - | ||||||||||||||||||||||||
562 | void QTextLayout::clearAdditionalFormats() | - | ||||||||||||||||||||||||
563 | { | - | ||||||||||||||||||||||||
564 | clearFormats(); | - | ||||||||||||||||||||||||
565 | } never executed: end of block | 0 | ||||||||||||||||||||||||
566 | #endif // deprecated since 5.6 | - | ||||||||||||||||||||||||
567 | - | |||||||||||||||||||||||||
568 | /*! | - | ||||||||||||||||||||||||
569 | \since 5.6 | - | ||||||||||||||||||||||||
570 | - | |||||||||||||||||||||||||
571 | Clears the list of additional formats supported by the text layout. | - | ||||||||||||||||||||||||
572 | - | |||||||||||||||||||||||||
573 | \sa formats(), setFormats() | - | ||||||||||||||||||||||||
574 | */ | - | ||||||||||||||||||||||||
575 | void QTextLayout::clearFormats() | - | ||||||||||||||||||||||||
576 | { | - | ||||||||||||||||||||||||
577 | setFormats(QVector<FormatRange>()); | - | ||||||||||||||||||||||||
578 | } never executed: end of block | 0 | ||||||||||||||||||||||||
579 | - | |||||||||||||||||||||||||
580 | /*! | - | ||||||||||||||||||||||||
581 | Enables caching of the complete layout information if \a enable is | - | ||||||||||||||||||||||||
582 | true; otherwise disables layout caching. Usually | - | ||||||||||||||||||||||||
583 | QTextLayout throws most of the layouting information away after a | - | ||||||||||||||||||||||||
584 | call to endLayout() to reduce memory consumption. If you however | - | ||||||||||||||||||||||||
585 | want to draw the laid out text directly afterwards enabling caching | - | ||||||||||||||||||||||||
586 | might speed up drawing significantly. | - | ||||||||||||||||||||||||
587 | - | |||||||||||||||||||||||||
588 | \sa cacheEnabled() | - | ||||||||||||||||||||||||
589 | */ | - | ||||||||||||||||||||||||
590 | void QTextLayout::setCacheEnabled(bool enable) | - | ||||||||||||||||||||||||
591 | { | - | ||||||||||||||||||||||||
592 | d->cacheGlyphs = enable; | - | ||||||||||||||||||||||||
593 | } never executed: end of block | 0 | ||||||||||||||||||||||||
594 | - | |||||||||||||||||||||||||
595 | /*! | - | ||||||||||||||||||||||||
596 | Returns \c true if the complete layout information is cached; otherwise | - | ||||||||||||||||||||||||
597 | returns \c false. | - | ||||||||||||||||||||||||
598 | - | |||||||||||||||||||||||||
599 | \sa setCacheEnabled() | - | ||||||||||||||||||||||||
600 | */ | - | ||||||||||||||||||||||||
601 | bool QTextLayout::cacheEnabled() const | - | ||||||||||||||||||||||||
602 | { | - | ||||||||||||||||||||||||
603 | return d->cacheGlyphs; never executed: return d->cacheGlyphs; | 0 | ||||||||||||||||||||||||
604 | } | - | ||||||||||||||||||||||||
605 | - | |||||||||||||||||||||||||
606 | /*! | - | ||||||||||||||||||||||||
607 | Sets the visual cursor movement style to the given \a style. If the | - | ||||||||||||||||||||||||
608 | QTextLayout is backed by a document, you can ignore this and use the option | - | ||||||||||||||||||||||||
609 | in QTextDocument, this option is for widgets like QLineEdit or custom | - | ||||||||||||||||||||||||
610 | widgets without a QTextDocument. Default value is Qt::LogicalMoveStyle. | - | ||||||||||||||||||||||||
611 | - | |||||||||||||||||||||||||
612 | \sa cursorMoveStyle() | - | ||||||||||||||||||||||||
613 | */ | - | ||||||||||||||||||||||||
614 | void QTextLayout::setCursorMoveStyle(Qt::CursorMoveStyle style) | - | ||||||||||||||||||||||||
615 | { | - | ||||||||||||||||||||||||
616 | d->visualMovement = style == Qt::VisualMoveStyle; | - | ||||||||||||||||||||||||
617 | } never executed: end of block | 0 | ||||||||||||||||||||||||
618 | - | |||||||||||||||||||||||||
619 | /*! | - | ||||||||||||||||||||||||
620 | The cursor movement style of this QTextLayout. The default is | - | ||||||||||||||||||||||||
621 | Qt::LogicalMoveStyle. | - | ||||||||||||||||||||||||
622 | - | |||||||||||||||||||||||||
623 | \sa setCursorMoveStyle() | - | ||||||||||||||||||||||||
624 | */ | - | ||||||||||||||||||||||||
625 | Qt::CursorMoveStyle QTextLayout::cursorMoveStyle() const | - | ||||||||||||||||||||||||
626 | { | - | ||||||||||||||||||||||||
627 | return d->visualMovement ? Qt::VisualMoveStyle : Qt::LogicalMoveStyle; never executed: return d->visualMovement ? Qt::VisualMoveStyle : Qt::LogicalMoveStyle; | 0 | ||||||||||||||||||||||||
628 | } | - | ||||||||||||||||||||||||
629 | - | |||||||||||||||||||||||||
630 | /*! | - | ||||||||||||||||||||||||
631 | Begins the layout process. | - | ||||||||||||||||||||||||
632 | - | |||||||||||||||||||||||||
633 | \sa endLayout() | - | ||||||||||||||||||||||||
634 | */ | - | ||||||||||||||||||||||||
635 | void QTextLayout::beginLayout() | - | ||||||||||||||||||||||||
636 | { | - | ||||||||||||||||||||||||
637 | #ifndef QT_NO_DEBUG | - | ||||||||||||||||||||||||
638 | if (d->layoutData && d->layoutData->layoutState == QTextEngine::InLayout) {
| 0 | ||||||||||||||||||||||||
639 | qWarning("QTextLayout::beginLayout: Called while already doing layout"); | - | ||||||||||||||||||||||||
640 | return; never executed: return; | 0 | ||||||||||||||||||||||||
641 | } | - | ||||||||||||||||||||||||
642 | #endif | - | ||||||||||||||||||||||||
643 | d->invalidate(); | - | ||||||||||||||||||||||||
644 | d->clearLineData(); | - | ||||||||||||||||||||||||
645 | d->itemize(); | - | ||||||||||||||||||||||||
646 | d->layoutData->layoutState = QTextEngine::InLayout; | - | ||||||||||||||||||||||||
647 | } never executed: end of block | 0 | ||||||||||||||||||||||||
648 | - | |||||||||||||||||||||||||
649 | /*! | - | ||||||||||||||||||||||||
650 | Ends the layout process. | - | ||||||||||||||||||||||||
651 | - | |||||||||||||||||||||||||
652 | \sa beginLayout() | - | ||||||||||||||||||||||||
653 | */ | - | ||||||||||||||||||||||||
654 | void QTextLayout::endLayout() | - | ||||||||||||||||||||||||
655 | { | - | ||||||||||||||||||||||||
656 | #ifndef QT_NO_DEBUG | - | ||||||||||||||||||||||||
657 | if (!d->layoutData || d->layoutData->layoutState == QTextEngine::LayoutEmpty) {
| 0 | ||||||||||||||||||||||||
658 | qWarning("QTextLayout::endLayout: Called without beginLayout()"); | - | ||||||||||||||||||||||||
659 | return; never executed: return; | 0 | ||||||||||||||||||||||||
660 | } | - | ||||||||||||||||||||||||
661 | #endif | - | ||||||||||||||||||||||||
662 | int l = d->lines.size(); | - | ||||||||||||||||||||||||
663 | if (l && d->lines.at(l-1).length < 0) {
| 0 | ||||||||||||||||||||||||
664 | QTextLine(l-1, d).setNumColumns(INT_MAX); | - | ||||||||||||||||||||||||
665 | } never executed: end of block | 0 | ||||||||||||||||||||||||
666 | d->layoutData->layoutState = QTextEngine::LayoutEmpty; | - | ||||||||||||||||||||||||
667 | if (!d->cacheGlyphs)
| 0 | ||||||||||||||||||||||||
668 | d->freeMemory(); never executed: d->freeMemory(); | 0 | ||||||||||||||||||||||||
669 | } never executed: end of block | 0 | ||||||||||||||||||||||||
670 | - | |||||||||||||||||||||||||
671 | /*! | - | ||||||||||||||||||||||||
672 | \since 4.4 | - | ||||||||||||||||||||||||
673 | - | |||||||||||||||||||||||||
674 | Clears the line information in the layout. After having called | - | ||||||||||||||||||||||||
675 | this function, lineCount() returns 0. | - | ||||||||||||||||||||||||
676 | */ | - | ||||||||||||||||||||||||
677 | void QTextLayout::clearLayout() | - | ||||||||||||||||||||||||
678 | { | - | ||||||||||||||||||||||||
679 | d->clearLineData(); | - | ||||||||||||||||||||||||
680 | } never executed: end of block | 0 | ||||||||||||||||||||||||
681 | - | |||||||||||||||||||||||||
682 | /*! | - | ||||||||||||||||||||||||
683 | Returns the next valid cursor position after \a oldPos that | - | ||||||||||||||||||||||||
684 | respects the given cursor \a mode. | - | ||||||||||||||||||||||||
685 | Returns value of \a oldPos, if \a oldPos is not a valid cursor position. | - | ||||||||||||||||||||||||
686 | - | |||||||||||||||||||||||||
687 | \sa isValidCursorPosition(), previousCursorPosition() | - | ||||||||||||||||||||||||
688 | */ | - | ||||||||||||||||||||||||
689 | int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const | - | ||||||||||||||||||||||||
690 | { | - | ||||||||||||||||||||||||
691 | const QCharAttributes *attributes = d->attributes(); | - | ||||||||||||||||||||||||
692 | int len = d->block.isValid() ? d->block.length() - 1
| 0 | ||||||||||||||||||||||||
693 | : d->layoutData->string.length(); | - | ||||||||||||||||||||||||
694 | Q_ASSERT(len <= d->layoutData->string.length()); | - | ||||||||||||||||||||||||
695 | if (!attributes || oldPos < 0 || oldPos >= len)
| 0 | ||||||||||||||||||||||||
696 | return oldPos; never executed: return oldPos; | 0 | ||||||||||||||||||||||||
697 | - | |||||||||||||||||||||||||
698 | if (mode == SkipCharacters) {
| 0 | ||||||||||||||||||||||||
699 | oldPos++; | - | ||||||||||||||||||||||||
700 | while (oldPos < len && !attributes[oldPos].graphemeBoundary)
| 0 | ||||||||||||||||||||||||
701 | oldPos++; never executed: oldPos++; | 0 | ||||||||||||||||||||||||
702 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
703 | if (oldPos < len && d->atWordSeparator(oldPos)) {
| 0 | ||||||||||||||||||||||||
704 | oldPos++; | - | ||||||||||||||||||||||||
705 | while (oldPos < len && d->atWordSeparator(oldPos))
| 0 | ||||||||||||||||||||||||
706 | oldPos++; never executed: oldPos++; | 0 | ||||||||||||||||||||||||
707 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
708 | while (oldPos < len && !attributes[oldPos].whiteSpace && !d->atWordSeparator(oldPos))
| 0 | ||||||||||||||||||||||||
709 | oldPos++; never executed: oldPos++; | 0 | ||||||||||||||||||||||||
710 | } never executed: end of block | 0 | ||||||||||||||||||||||||
711 | while (oldPos < len && attributes[oldPos].whiteSpace)
| 0 | ||||||||||||||||||||||||
712 | oldPos++; never executed: oldPos++; | 0 | ||||||||||||||||||||||||
713 | } never executed: end of block | 0 | ||||||||||||||||||||||||
714 | - | |||||||||||||||||||||||||
715 | return oldPos; never executed: return oldPos; | 0 | ||||||||||||||||||||||||
716 | } | - | ||||||||||||||||||||||||
717 | - | |||||||||||||||||||||||||
718 | /*! | - | ||||||||||||||||||||||||
719 | Returns the first valid cursor position before \a oldPos that | - | ||||||||||||||||||||||||
720 | respects the given cursor \a mode. | - | ||||||||||||||||||||||||
721 | Returns value of \a oldPos, if \a oldPos is not a valid cursor position. | - | ||||||||||||||||||||||||
722 | - | |||||||||||||||||||||||||
723 | \sa isValidCursorPosition(), nextCursorPosition() | - | ||||||||||||||||||||||||
724 | */ | - | ||||||||||||||||||||||||
725 | int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const | - | ||||||||||||||||||||||||
726 | { | - | ||||||||||||||||||||||||
727 | const QCharAttributes *attributes = d->attributes(); | - | ||||||||||||||||||||||||
728 | int len = d->block.isValid() ? d->block.length() - 1
| 0 | ||||||||||||||||||||||||
729 | : d->layoutData->string.length(); | - | ||||||||||||||||||||||||
730 | Q_ASSERT(len <= d->layoutData->string.length()); | - | ||||||||||||||||||||||||
731 | if (!attributes || oldPos <= 0 || oldPos > len)
| 0 | ||||||||||||||||||||||||
732 | return oldPos; never executed: return oldPos; | 0 | ||||||||||||||||||||||||
733 | - | |||||||||||||||||||||||||
734 | if (mode == SkipCharacters) {
| 0 | ||||||||||||||||||||||||
735 | oldPos--; | - | ||||||||||||||||||||||||
736 | while (oldPos && !attributes[oldPos].graphemeBoundary)
| 0 | ||||||||||||||||||||||||
737 | oldPos--; never executed: oldPos--; | 0 | ||||||||||||||||||||||||
738 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
739 | while (oldPos > 0 && attributes[oldPos - 1].whiteSpace)
| 0 | ||||||||||||||||||||||||
740 | oldPos--; never executed: oldPos--; | 0 | ||||||||||||||||||||||||
741 | - | |||||||||||||||||||||||||
742 | if (oldPos && d->atWordSeparator(oldPos-1)) {
| 0 | ||||||||||||||||||||||||
743 | oldPos--; | - | ||||||||||||||||||||||||
744 | while (oldPos && d->atWordSeparator(oldPos-1))
| 0 | ||||||||||||||||||||||||
745 | oldPos--; never executed: oldPos--; | 0 | ||||||||||||||||||||||||
746 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
747 | while (oldPos > 0 && !attributes[oldPos - 1].whiteSpace && !d->atWordSeparator(oldPos-1))
| 0 | ||||||||||||||||||||||||
748 | oldPos--; never executed: oldPos--; | 0 | ||||||||||||||||||||||||
749 | } never executed: end of block | 0 | ||||||||||||||||||||||||
750 | } | - | ||||||||||||||||||||||||
751 | - | |||||||||||||||||||||||||
752 | return oldPos; never executed: return oldPos; | 0 | ||||||||||||||||||||||||
753 | } | - | ||||||||||||||||||||||||
754 | - | |||||||||||||||||||||||||
755 | /*! | - | ||||||||||||||||||||||||
756 | Returns the cursor position to the right of \a oldPos, next to it. | - | ||||||||||||||||||||||||
757 | It's dependent on the visual position of characters, after bi-directional | - | ||||||||||||||||||||||||
758 | reordering. | - | ||||||||||||||||||||||||
759 | - | |||||||||||||||||||||||||
760 | \sa leftCursorPosition(), nextCursorPosition() | - | ||||||||||||||||||||||||
761 | */ | - | ||||||||||||||||||||||||
762 | int QTextLayout::rightCursorPosition(int oldPos) const | - | ||||||||||||||||||||||||
763 | { | - | ||||||||||||||||||||||||
764 | int newPos = d->positionAfterVisualMovement(oldPos, QTextCursor::Right); | - | ||||||||||||||||||||||||
765 | // qDebug("%d -> %d", oldPos, newPos); | - | ||||||||||||||||||||||||
766 | return newPos; never executed: return newPos; | 0 | ||||||||||||||||||||||||
767 | } | - | ||||||||||||||||||||||||
768 | - | |||||||||||||||||||||||||
769 | /*! | - | ||||||||||||||||||||||||
770 | Returns the cursor position to the left of \a oldPos, next to it. | - | ||||||||||||||||||||||||
771 | It's dependent on the visual position of characters, after bi-directional | - | ||||||||||||||||||||||||
772 | reordering. | - | ||||||||||||||||||||||||
773 | - | |||||||||||||||||||||||||
774 | \sa rightCursorPosition(), previousCursorPosition() | - | ||||||||||||||||||||||||
775 | */ | - | ||||||||||||||||||||||||
776 | int QTextLayout::leftCursorPosition(int oldPos) const | - | ||||||||||||||||||||||||
777 | { | - | ||||||||||||||||||||||||
778 | int newPos = d->positionAfterVisualMovement(oldPos, QTextCursor::Left); | - | ||||||||||||||||||||||||
779 | // qDebug("%d -> %d", oldPos, newPos); | - | ||||||||||||||||||||||||
780 | return newPos; never executed: return newPos; | 0 | ||||||||||||||||||||||||
781 | } | - | ||||||||||||||||||||||||
782 | - | |||||||||||||||||||||||||
783 | /*!/ | - | ||||||||||||||||||||||||
784 | Returns \c true if position \a pos is a valid cursor position. | - | ||||||||||||||||||||||||
785 | - | |||||||||||||||||||||||||
786 | In a Unicode context some positions in the text are not valid | - | ||||||||||||||||||||||||
787 | cursor positions, because the position is inside a Unicode | - | ||||||||||||||||||||||||
788 | surrogate or a grapheme cluster. | - | ||||||||||||||||||||||||
789 | - | |||||||||||||||||||||||||
790 | A grapheme cluster is a sequence of two or more Unicode characters | - | ||||||||||||||||||||||||
791 | that form one indivisible entity on the screen. For example the | - | ||||||||||||||||||||||||
792 | latin character `\unicode{0xC4}' can be represented in Unicode by two | - | ||||||||||||||||||||||||
793 | characters, `A' (0x41), and the combining diaresis (0x308). A text | - | ||||||||||||||||||||||||
794 | cursor can only validly be positioned before or after these two | - | ||||||||||||||||||||||||
795 | characters, never between them since that wouldn't make sense. In | - | ||||||||||||||||||||||||
796 | indic languages every syllable forms a grapheme cluster. | - | ||||||||||||||||||||||||
797 | */ | - | ||||||||||||||||||||||||
798 | bool QTextLayout::isValidCursorPosition(int pos) const | - | ||||||||||||||||||||||||
799 | { | - | ||||||||||||||||||||||||
800 | const QCharAttributes *attributes = d->attributes(); | - | ||||||||||||||||||||||||
801 | if (!attributes || pos < 0 || pos > (int)d->layoutData->string.length())
| 0 | ||||||||||||||||||||||||
802 | return false; never executed: return false; | 0 | ||||||||||||||||||||||||
803 | return attributes[pos].graphemeBoundary; never executed: return attributes[pos].graphemeBoundary; | 0 | ||||||||||||||||||||||||
804 | } | - | ||||||||||||||||||||||||
805 | - | |||||||||||||||||||||||||
806 | /*! | - | ||||||||||||||||||||||||
807 | Returns a new text line to be laid out if there is text to be | - | ||||||||||||||||||||||||
808 | inserted into the layout; otherwise returns an invalid text line. | - | ||||||||||||||||||||||||
809 | - | |||||||||||||||||||||||||
810 | The text layout creates a new line object that starts after the | - | ||||||||||||||||||||||||
811 | last line in the layout, or at the beginning if the layout is empty. | - | ||||||||||||||||||||||||
812 | The layout maintains an internal cursor, and each line is filled | - | ||||||||||||||||||||||||
813 | with text from the cursor position onwards when the | - | ||||||||||||||||||||||||
814 | QTextLine::setLineWidth() function is called. | - | ||||||||||||||||||||||||
815 | - | |||||||||||||||||||||||||
816 | Once QTextLine::setLineWidth() is called, a new line can be created and | - | ||||||||||||||||||||||||
817 | filled with text. Repeating this process will lay out the whole block | - | ||||||||||||||||||||||||
818 | of text contained in the QTextLayout. If there is no text left to be | - | ||||||||||||||||||||||||
819 | inserted into the layout, the QTextLine returned will not be valid | - | ||||||||||||||||||||||||
820 | (isValid() will return false). | - | ||||||||||||||||||||||||
821 | */ | - | ||||||||||||||||||||||||
822 | QTextLine QTextLayout::createLine() | - | ||||||||||||||||||||||||
823 | { | - | ||||||||||||||||||||||||
824 | #ifndef QT_NO_DEBUG | - | ||||||||||||||||||||||||
825 | if (!d->layoutData || d->layoutData->layoutState == QTextEngine::LayoutEmpty) {
| 0 | ||||||||||||||||||||||||
826 | qWarning("QTextLayout::createLine: Called without layouting"); | - | ||||||||||||||||||||||||
827 | return QTextLine(); never executed: return QTextLine(); | 0 | ||||||||||||||||||||||||
828 | } | - | ||||||||||||||||||||||||
829 | #endif | - | ||||||||||||||||||||||||
830 | if (d->layoutData->layoutState == QTextEngine::LayoutFailed)
| 0 | ||||||||||||||||||||||||
831 | return QTextLine(); never executed: return QTextLine(); | 0 | ||||||||||||||||||||||||
832 | - | |||||||||||||||||||||||||
833 | int l = d->lines.size(); | - | ||||||||||||||||||||||||
834 | if (l && d->lines.at(l-1).length < 0) {
| 0 | ||||||||||||||||||||||||
835 | QTextLine(l-1, d).setNumColumns(INT_MAX); | - | ||||||||||||||||||||||||
836 | } never executed: end of block | 0 | ||||||||||||||||||||||||
837 | int from = l > 0 ? d->lines.at(l-1).from + d->lines.at(l-1).length + d->lines.at(l-1).trailingSpaces : 0;
| 0 | ||||||||||||||||||||||||
838 | int strlen = d->layoutData->string.length(); | - | ||||||||||||||||||||||||
839 | if (l && from >= strlen) {
| 0 | ||||||||||||||||||||||||
840 | if (!d->lines.at(l-1).length || d->layoutData->string.at(strlen - 1) != QChar::LineSeparator)
| 0 | ||||||||||||||||||||||||
841 | return QTextLine(); never executed: return QTextLine(); | 0 | ||||||||||||||||||||||||
842 | } never executed: end of block | 0 | ||||||||||||||||||||||||
843 | - | |||||||||||||||||||||||||
844 | QScriptLine line; | - | ||||||||||||||||||||||||
845 | line.from = from; | - | ||||||||||||||||||||||||
846 | line.length = -1; | - | ||||||||||||||||||||||||
847 | line.justified = false; | - | ||||||||||||||||||||||||
848 | line.gridfitted = false; | - | ||||||||||||||||||||||||
849 | - | |||||||||||||||||||||||||
850 | d->lines.append(line); | - | ||||||||||||||||||||||||
851 | return QTextLine(l, d); never executed: return QTextLine(l, d); | 0 | ||||||||||||||||||||||||
852 | } | - | ||||||||||||||||||||||||
853 | - | |||||||||||||||||||||||||
854 | /*! | - | ||||||||||||||||||||||||
855 | Returns the number of lines in this text layout. | - | ||||||||||||||||||||||||
856 | - | |||||||||||||||||||||||||
857 | \sa lineAt() | - | ||||||||||||||||||||||||
858 | */ | - | ||||||||||||||||||||||||
859 | int QTextLayout::lineCount() const | - | ||||||||||||||||||||||||
860 | { | - | ||||||||||||||||||||||||
861 | return d->lines.size(); never executed: return d->lines.size(); | 0 | ||||||||||||||||||||||||
862 | } | - | ||||||||||||||||||||||||
863 | - | |||||||||||||||||||||||||
864 | /*! | - | ||||||||||||||||||||||||
865 | Returns the \a{i}-th line of text in this text layout. | - | ||||||||||||||||||||||||
866 | - | |||||||||||||||||||||||||
867 | \sa lineCount(), lineForTextPosition() | - | ||||||||||||||||||||||||
868 | */ | - | ||||||||||||||||||||||||
869 | QTextLine QTextLayout::lineAt(int i) const | - | ||||||||||||||||||||||||
870 | { | - | ||||||||||||||||||||||||
871 | return i < lineCount() ? QTextLine(i, d) : QTextLine(); never executed: return i < lineCount() ? QTextLine(i, d) : QTextLine(); | 0 | ||||||||||||||||||||||||
872 | } | - | ||||||||||||||||||||||||
873 | - | |||||||||||||||||||||||||
874 | /*! | - | ||||||||||||||||||||||||
875 | Returns the line that contains the cursor position specified by \a pos. | - | ||||||||||||||||||||||||
876 | - | |||||||||||||||||||||||||
877 | \sa isValidCursorPosition(), lineAt() | - | ||||||||||||||||||||||||
878 | */ | - | ||||||||||||||||||||||||
879 | QTextLine QTextLayout::lineForTextPosition(int pos) const | - | ||||||||||||||||||||||||
880 | { | - | ||||||||||||||||||||||||
881 | int lineNum = d->lineNumberForTextPosition(pos); | - | ||||||||||||||||||||||||
882 | return lineNum >= 0 ? lineAt(lineNum) : QTextLine(); never executed: return lineNum >= 0 ? lineAt(lineNum) : QTextLine(); | 0 | ||||||||||||||||||||||||
883 | } | - | ||||||||||||||||||||||||
884 | - | |||||||||||||||||||||||||
885 | /*! | - | ||||||||||||||||||||||||
886 | \since 4.2 | - | ||||||||||||||||||||||||
887 | - | |||||||||||||||||||||||||
888 | The global position of the layout. This is independent of the | - | ||||||||||||||||||||||||
889 | bounding rectangle and of the layout process. | - | ||||||||||||||||||||||||
890 | - | |||||||||||||||||||||||||
891 | \sa setPosition() | - | ||||||||||||||||||||||||
892 | */ | - | ||||||||||||||||||||||||
893 | QPointF QTextLayout::position() const | - | ||||||||||||||||||||||||
894 | { | - | ||||||||||||||||||||||||
895 | return d->position; never executed: return d->position; | 0 | ||||||||||||||||||||||||
896 | } | - | ||||||||||||||||||||||||
897 | - | |||||||||||||||||||||||||
898 | /*! | - | ||||||||||||||||||||||||
899 | Moves the text layout to point \a p. | - | ||||||||||||||||||||||||
900 | - | |||||||||||||||||||||||||
901 | \sa position() | - | ||||||||||||||||||||||||
902 | */ | - | ||||||||||||||||||||||||
903 | void QTextLayout::setPosition(const QPointF &p) | - | ||||||||||||||||||||||||
904 | { | - | ||||||||||||||||||||||||
905 | d->position = p; | - | ||||||||||||||||||||||||
906 | } never executed: end of block | 0 | ||||||||||||||||||||||||
907 | - | |||||||||||||||||||||||||
908 | /*! | - | ||||||||||||||||||||||||
909 | The smallest rectangle that contains all the lines in the layout. | - | ||||||||||||||||||||||||
910 | */ | - | ||||||||||||||||||||||||
911 | QRectF QTextLayout::boundingRect() const | - | ||||||||||||||||||||||||
912 | { | - | ||||||||||||||||||||||||
913 | if (d->lines.isEmpty())
| 0 | ||||||||||||||||||||||||
914 | return QRectF(); never executed: return QRectF(); | 0 | ||||||||||||||||||||||||
915 | - | |||||||||||||||||||||||||
916 | QFixed xmax, ymax; | - | ||||||||||||||||||||||||
917 | QFixed xmin = d->lines.at(0).x; | - | ||||||||||||||||||||||||
918 | QFixed ymin = d->lines.at(0).y; | - | ||||||||||||||||||||||||
919 | - | |||||||||||||||||||||||||
920 | for (int i = 0; i < d->lines.size(); ++i) {
| 0 | ||||||||||||||||||||||||
921 | const QScriptLine &si = d->lines[i]; | - | ||||||||||||||||||||||||
922 | xmin = qMin(xmin, si.x); | - | ||||||||||||||||||||||||
923 | ymin = qMin(ymin, si.y); | - | ||||||||||||||||||||||||
924 | QFixed lineWidth = si.width < QFIXED_MAX ? qMax(si.width, si.textWidth) : si.textWidth;
| 0 | ||||||||||||||||||||||||
925 | xmax = qMax(xmax, si.x+lineWidth); | - | ||||||||||||||||||||||||
926 | // ### shouldn't the ascent be used in ymin??? | - | ||||||||||||||||||||||||
927 | ymax = qMax(ymax, si.y+si.height().ceil()); | - | ||||||||||||||||||||||||
928 | } never executed: end of block | 0 | ||||||||||||||||||||||||
929 | return QRectF(xmin.toReal(), ymin.toReal(), (xmax-xmin).toReal(), (ymax-ymin).toReal()); never executed: return QRectF(xmin.toReal(), ymin.toReal(), (xmax-xmin).toReal(), (ymax-ymin).toReal()); | 0 | ||||||||||||||||||||||||
930 | } | - | ||||||||||||||||||||||||
931 | - | |||||||||||||||||||||||||
932 | /*! | - | ||||||||||||||||||||||||
933 | The minimum width the layout needs. This is the width of the | - | ||||||||||||||||||||||||
934 | layout's smallest non-breakable substring. | - | ||||||||||||||||||||||||
935 | - | |||||||||||||||||||||||||
936 | \warning This function only returns a valid value after the layout | - | ||||||||||||||||||||||||
937 | has been done. | - | ||||||||||||||||||||||||
938 | - | |||||||||||||||||||||||||
939 | \sa maximumWidth() | - | ||||||||||||||||||||||||
940 | */ | - | ||||||||||||||||||||||||
941 | qreal QTextLayout::minimumWidth() const | - | ||||||||||||||||||||||||
942 | { | - | ||||||||||||||||||||||||
943 | return d->minWidth.toReal(); never executed: return d->minWidth.toReal(); | 0 | ||||||||||||||||||||||||
944 | } | - | ||||||||||||||||||||||||
945 | - | |||||||||||||||||||||||||
946 | /*! | - | ||||||||||||||||||||||||
947 | The maximum width the layout could expand to; this is essentially | - | ||||||||||||||||||||||||
948 | the width of the entire text. | - | ||||||||||||||||||||||||
949 | - | |||||||||||||||||||||||||
950 | \warning This function only returns a valid value after the layout | - | ||||||||||||||||||||||||
951 | has been done. | - | ||||||||||||||||||||||||
952 | - | |||||||||||||||||||||||||
953 | \sa minimumWidth() | - | ||||||||||||||||||||||||
954 | */ | - | ||||||||||||||||||||||||
955 | qreal QTextLayout::maximumWidth() const | - | ||||||||||||||||||||||||
956 | { | - | ||||||||||||||||||||||||
957 | return d->maxWidth.toReal(); never executed: return d->maxWidth.toReal(); | 0 | ||||||||||||||||||||||||
958 | } | - | ||||||||||||||||||||||||
959 | - | |||||||||||||||||||||||||
960 | - | |||||||||||||||||||||||||
961 | /*! | - | ||||||||||||||||||||||||
962 | \internal | - | ||||||||||||||||||||||||
963 | */ | - | ||||||||||||||||||||||||
964 | void QTextLayout::setFlags(int flags) | - | ||||||||||||||||||||||||
965 | { | - | ||||||||||||||||||||||||
966 | if (flags & Qt::TextJustificationForced) {
| 0 | ||||||||||||||||||||||||
967 | d->option.setAlignment(Qt::AlignJustify); | - | ||||||||||||||||||||||||
968 | d->forceJustification = true; | - | ||||||||||||||||||||||||
969 | } never executed: end of block | 0 | ||||||||||||||||||||||||
970 | - | |||||||||||||||||||||||||
971 | if (flags & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
| 0 | ||||||||||||||||||||||||
972 | d->ignoreBidi = true; | - | ||||||||||||||||||||||||
973 | d->option.setTextDirection((flags & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft); | - | ||||||||||||||||||||||||
974 | } never executed: end of block | 0 | ||||||||||||||||||||||||
975 | } never executed: end of block | 0 | ||||||||||||||||||||||||
976 | - | |||||||||||||||||||||||||
977 | static void addSelectedRegionsToPath(QTextEngine *eng, int lineNumber, const QPointF &pos, QTextLayout::FormatRange *selection, | - | ||||||||||||||||||||||||
978 | QPainterPath *region, QRectF boundingRect) | - | ||||||||||||||||||||||||
979 | { | - | ||||||||||||||||||||||||
980 | const QScriptLine &line = eng->lines[lineNumber]; | - | ||||||||||||||||||||||||
981 | - | |||||||||||||||||||||||||
982 | QTextLineItemIterator iterator(eng, lineNumber, pos, selection); | - | ||||||||||||||||||||||||
983 | - | |||||||||||||||||||||||||
984 | - | |||||||||||||||||||||||||
985 | - | |||||||||||||||||||||||||
986 | const qreal selectionY = pos.y() + line.y.toReal(); | - | ||||||||||||||||||||||||
987 | const qreal lineHeight = line.height().toReal(); | - | ||||||||||||||||||||||||
988 | - | |||||||||||||||||||||||||
989 | QFixed lastSelectionX = iterator.x; | - | ||||||||||||||||||||||||
990 | QFixed lastSelectionWidth; | - | ||||||||||||||||||||||||
991 | - | |||||||||||||||||||||||||
992 | while (!iterator.atEnd()) {
| 0 | ||||||||||||||||||||||||
993 | iterator.next(); | - | ||||||||||||||||||||||||
994 | - | |||||||||||||||||||||||||
995 | QFixed selectionX, selectionWidth; | - | ||||||||||||||||||||||||
996 | if (iterator.getSelectionBounds(&selectionX, &selectionWidth)) {
| 0 | ||||||||||||||||||||||||
997 | if (selectionX == lastSelectionX + lastSelectionWidth) {
| 0 | ||||||||||||||||||||||||
998 | lastSelectionWidth += selectionWidth; | - | ||||||||||||||||||||||||
999 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
1000 | } | - | ||||||||||||||||||||||||
1001 | - | |||||||||||||||||||||||||
1002 | if (lastSelectionWidth > 0) {
| 0 | ||||||||||||||||||||||||
1003 | QRectF rect = boundingRect & QRectF(lastSelectionX.toReal(), selectionY, lastSelectionWidth.toReal(), lineHeight); | - | ||||||||||||||||||||||||
1004 | rect.moveLeft(qFloor(rect.left())); | - | ||||||||||||||||||||||||
1005 | rect.moveTop(qFloor(rect.top())); | - | ||||||||||||||||||||||||
1006 | region->addRect(rect); | - | ||||||||||||||||||||||||
1007 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1008 | - | |||||||||||||||||||||||||
1009 | lastSelectionX = selectionX; | - | ||||||||||||||||||||||||
1010 | lastSelectionWidth = selectionWidth; | - | ||||||||||||||||||||||||
1011 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1012 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1013 | if (lastSelectionWidth > 0) {
| 0 | ||||||||||||||||||||||||
1014 | QRectF rect = boundingRect & QRectF(lastSelectionX.toReal(), selectionY, lastSelectionWidth.toReal(), lineHeight); | - | ||||||||||||||||||||||||
1015 | rect.moveLeft(qFloor(rect.left())); | - | ||||||||||||||||||||||||
1016 | rect.moveTop(qFloor(rect.top())); | - | ||||||||||||||||||||||||
1017 | region->addRect(rect); | - | ||||||||||||||||||||||||
1018 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1019 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1020 | - | |||||||||||||||||||||||||
1021 | static inline QRectF clipIfValid(const QRectF &rect, const QRectF &clip) | - | ||||||||||||||||||||||||
1022 | { | - | ||||||||||||||||||||||||
1023 | return clip.isValid() ? (rect & clip) : rect; never executed: return clip.isValid() ? (rect & clip) : rect; | 0 | ||||||||||||||||||||||||
1024 | } | - | ||||||||||||||||||||||||
1025 | - | |||||||||||||||||||||||||
1026 | - | |||||||||||||||||||||||||
1027 | /*! | - | ||||||||||||||||||||||||
1028 | Returns the glyph indexes and positions for all glyphs corresponding to the \a length characters | - | ||||||||||||||||||||||||
1029 | starting at the position \a from in this QTextLayout. This is an expensive function, and should | - | ||||||||||||||||||||||||
1030 | not be called in a time sensitive context. | - | ||||||||||||||||||||||||
1031 | - | |||||||||||||||||||||||||
1032 | If \a from is less than zero, then the glyph run will begin at the first character in the | - | ||||||||||||||||||||||||
1033 | layout. If \a length is less than zero, it will span the entire string from the start position. | - | ||||||||||||||||||||||||
1034 | - | |||||||||||||||||||||||||
1035 | \since 4.8 | - | ||||||||||||||||||||||||
1036 | - | |||||||||||||||||||||||||
1037 | \sa draw(), QPainter::drawGlyphRun() | - | ||||||||||||||||||||||||
1038 | */ | - | ||||||||||||||||||||||||
1039 | #if !defined(QT_NO_RAWFONT) | - | ||||||||||||||||||||||||
1040 | QList<QGlyphRun> QTextLayout::glyphRuns(int from, int length) const | - | ||||||||||||||||||||||||
1041 | { | - | ||||||||||||||||||||||||
1042 | if (from < 0)
| 0 | ||||||||||||||||||||||||
1043 | from = 0; never executed: from = 0; | 0 | ||||||||||||||||||||||||
1044 | if (length < 0)
| 0 | ||||||||||||||||||||||||
1045 | length = text().length(); never executed: length = text().length(); | 0 | ||||||||||||||||||||||||
1046 | - | |||||||||||||||||||||||||
1047 | QHash<QPair<QFontEngine *, int>, QGlyphRun> glyphRunHash; | - | ||||||||||||||||||||||||
1048 | for (int i=0; i<d->lines.size(); ++i) {
| 0 | ||||||||||||||||||||||||
1049 | if (d->lines[i].from > from + length)
| 0 | ||||||||||||||||||||||||
1050 | break; never executed: break; | 0 | ||||||||||||||||||||||||
1051 | else if (d->lines[i].from + d->lines[i].length >= from) {
| 0 | ||||||||||||||||||||||||
1052 | QList<QGlyphRun> glyphRuns = QTextLine(i, d).glyphRuns(from, length); | - | ||||||||||||||||||||||||
1053 | - | |||||||||||||||||||||||||
1054 | for (int j = 0; j < glyphRuns.size(); j++) {
| 0 | ||||||||||||||||||||||||
1055 | const QGlyphRun &glyphRun = glyphRuns.at(j); | - | ||||||||||||||||||||||||
1056 | QRawFont rawFont = glyphRun.rawFont(); | - | ||||||||||||||||||||||||
1057 | - | |||||||||||||||||||||||||
1058 | QFontEngine *fontEngine = rawFont.d->fontEngine; | - | ||||||||||||||||||||||||
1059 | QGlyphRun::GlyphRunFlags flags = glyphRun.flags(); | - | ||||||||||||||||||||||||
1060 | QPair<QFontEngine *, int> key(fontEngine, int(flags)); | - | ||||||||||||||||||||||||
1061 | // merge the glyph runs using the same font | - | ||||||||||||||||||||||||
1062 | if (glyphRunHash.contains(key)) {
| 0 | ||||||||||||||||||||||||
1063 | QGlyphRun &oldGlyphRun = glyphRunHash[key]; | - | ||||||||||||||||||||||||
1064 | - | |||||||||||||||||||||||||
1065 | QVector<quint32> indexes = oldGlyphRun.glyphIndexes(); | - | ||||||||||||||||||||||||
1066 | QVector<QPointF> positions = oldGlyphRun.positions(); | - | ||||||||||||||||||||||||
1067 | QRectF boundingRect = oldGlyphRun.boundingRect(); | - | ||||||||||||||||||||||||
1068 | - | |||||||||||||||||||||||||
1069 | indexes += glyphRun.glyphIndexes(); | - | ||||||||||||||||||||||||
1070 | positions += glyphRun.positions(); | - | ||||||||||||||||||||||||
1071 | boundingRect = boundingRect.united(glyphRun.boundingRect()); | - | ||||||||||||||||||||||||
1072 | - | |||||||||||||||||||||||||
1073 | oldGlyphRun.setGlyphIndexes(indexes); | - | ||||||||||||||||||||||||
1074 | oldGlyphRun.setPositions(positions); | - | ||||||||||||||||||||||||
1075 | oldGlyphRun.setBoundingRect(boundingRect); | - | ||||||||||||||||||||||||
1076 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
1077 | glyphRunHash[key] = glyphRun; | - | ||||||||||||||||||||||||
1078 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1079 | } | - | ||||||||||||||||||||||||
1080 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1081 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1082 | - | |||||||||||||||||||||||||
1083 | return glyphRunHash.values(); never executed: return glyphRunHash.values(); | 0 | ||||||||||||||||||||||||
1084 | } | - | ||||||||||||||||||||||||
1085 | #endif // QT_NO_RAWFONT | - | ||||||||||||||||||||||||
1086 | - | |||||||||||||||||||||||||
1087 | /*! | - | ||||||||||||||||||||||||
1088 | Draws the whole layout on the painter \a p at the position specified by \a pos. | - | ||||||||||||||||||||||||
1089 | The rendered layout includes the given \a selections and is clipped within | - | ||||||||||||||||||||||||
1090 | the rectangle specified by \a clip. | - | ||||||||||||||||||||||||
1091 | */ | - | ||||||||||||||||||||||||
1092 | void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRange> &selections, const QRectF &clip) const | - | ||||||||||||||||||||||||
1093 | { | - | ||||||||||||||||||||||||
1094 | if (d->lines.isEmpty())
| 0 | ||||||||||||||||||||||||
1095 | return; never executed: return; | 0 | ||||||||||||||||||||||||
1096 | - | |||||||||||||||||||||||||
1097 | if (!d->layoutData)
| 0 | ||||||||||||||||||||||||
1098 | d->itemize(); never executed: d->itemize(); | 0 | ||||||||||||||||||||||||
1099 | - | |||||||||||||||||||||||||
1100 | QPointF position = pos + d->position; | - | ||||||||||||||||||||||||
1101 | - | |||||||||||||||||||||||||
1102 | QFixed clipy = (INT_MIN/256); | - | ||||||||||||||||||||||||
1103 | QFixed clipe = (INT_MAX/256); | - | ||||||||||||||||||||||||
1104 | if (clip.isValid()) {
| 0 | ||||||||||||||||||||||||
1105 | clipy = QFixed::fromReal(clip.y() - position.y()); | - | ||||||||||||||||||||||||
1106 | clipe = clipy + QFixed::fromReal(clip.height()); | - | ||||||||||||||||||||||||
1107 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1108 | - | |||||||||||||||||||||||||
1109 | int firstLine = 0; | - | ||||||||||||||||||||||||
1110 | int lastLine = d->lines.size(); | - | ||||||||||||||||||||||||
1111 | for (int i = 0; i < d->lines.size(); ++i) {
| 0 | ||||||||||||||||||||||||
1112 | QTextLine l(i, d); | - | ||||||||||||||||||||||||
1113 | const QScriptLine &sl = d->lines[i]; | - | ||||||||||||||||||||||||
1114 | - | |||||||||||||||||||||||||
1115 | if (sl.y > clipe) {
| 0 | ||||||||||||||||||||||||
1116 | lastLine = i; | - | ||||||||||||||||||||||||
1117 | break; never executed: break; | 0 | ||||||||||||||||||||||||
1118 | } | - | ||||||||||||||||||||||||
1119 | if ((sl.y + sl.height()) < clipy) {
| 0 | ||||||||||||||||||||||||
1120 | firstLine = i; | - | ||||||||||||||||||||||||
1121 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
1122 | } | - | ||||||||||||||||||||||||
1123 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1124 | - | |||||||||||||||||||||||||
1125 | QPainterPath excludedRegion; | - | ||||||||||||||||||||||||
1126 | QPainterPath textDoneRegion; | - | ||||||||||||||||||||||||
1127 | for (int i = 0; i < selections.size(); ++i) {
| 0 | ||||||||||||||||||||||||
1128 | FormatRange selection = selections.at(i); | - | ||||||||||||||||||||||||
1129 | const QBrush bg = selection.format.background(); | - | ||||||||||||||||||||||||
1130 | - | |||||||||||||||||||||||||
1131 | QPainterPath region; | - | ||||||||||||||||||||||||
1132 | region.setFillRule(Qt::WindingFill); | - | ||||||||||||||||||||||||
1133 | - | |||||||||||||||||||||||||
1134 | for (int line = firstLine; line < lastLine; ++line) {
| 0 | ||||||||||||||||||||||||
1135 | const QScriptLine &sl = d->lines[line]; | - | ||||||||||||||||||||||||
1136 | QTextLine tl(line, d); | - | ||||||||||||||||||||||||
1137 | - | |||||||||||||||||||||||||
1138 | QRectF lineRect(tl.naturalTextRect()); | - | ||||||||||||||||||||||||
1139 | lineRect.translate(position); | - | ||||||||||||||||||||||||
1140 | lineRect.adjust(0, 0, d->leadingSpaceWidth(sl).toReal(), 0); | - | ||||||||||||||||||||||||
1141 | - | |||||||||||||||||||||||||
1142 | bool isLastLineInBlock = (line == d->lines.size()-1); | - | ||||||||||||||||||||||||
1143 | int sl_length = sl.length + (isLastLineInBlock? 1 : 0); // the infamous newline
| 0 | ||||||||||||||||||||||||
1144 | - | |||||||||||||||||||||||||
1145 | - | |||||||||||||||||||||||||
1146 | if (sl.from > selection.start + selection.length || sl.from + sl_length <= selection.start)
| 0 | ||||||||||||||||||||||||
1147 | continue; // no actual intersection never executed: continue; | 0 | ||||||||||||||||||||||||
1148 | - | |||||||||||||||||||||||||
1149 | const bool selectionStartInLine = sl.from <= selection.start; | - | ||||||||||||||||||||||||
1150 | const bool selectionEndInLine = selection.start + selection.length < sl.from + sl_length; | - | ||||||||||||||||||||||||
1151 | - | |||||||||||||||||||||||||
1152 | if (sl.length && (selectionStartInLine || selectionEndInLine)) {
| 0 | ||||||||||||||||||||||||
1153 | addSelectedRegionsToPath(d, line, position, &selection, ®ion, clipIfValid(lineRect, clip)); | - | ||||||||||||||||||||||||
1154 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
1155 | region.addRect(clipIfValid(lineRect, clip)); | - | ||||||||||||||||||||||||
1156 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1157 | - | |||||||||||||||||||||||||
1158 | if (selection.format.boolProperty(QTextFormat::FullWidthSelection)) {
| 0 | ||||||||||||||||||||||||
1159 | QRectF fullLineRect(tl.rect()); | - | ||||||||||||||||||||||||
1160 | fullLineRect.translate(position); | - | ||||||||||||||||||||||||
1161 | fullLineRect.setRight(QFIXED_MAX); | - | ||||||||||||||||||||||||
1162 | if (!selectionEndInLine)
| 0 | ||||||||||||||||||||||||
1163 | region.addRect(clipIfValid(QRectF(lineRect.topRight(), fullLineRect.bottomRight()), clip)); never executed: region.addRect(clipIfValid(QRectF(lineRect.topRight(), fullLineRect.bottomRight()), clip)); | 0 | ||||||||||||||||||||||||
1164 | if (!selectionStartInLine)
| 0 | ||||||||||||||||||||||||
1165 | region.addRect(clipIfValid(QRectF(fullLineRect.topLeft(), lineRect.bottomLeft()), clip)); never executed: region.addRect(clipIfValid(QRectF(fullLineRect.topLeft(), lineRect.bottomLeft()), clip)); | 0 | ||||||||||||||||||||||||
1166 | } else if (!selectionEndInLine never executed: end of block
| 0 | ||||||||||||||||||||||||
1167 | && isLastLineInBlock
| 0 | ||||||||||||||||||||||||
1168 | &&!(d->option.flags() & QTextOption::ShowLineAndParagraphSeparators)) {
| 0 | ||||||||||||||||||||||||
1169 | region.addRect(clipIfValid(QRectF(lineRect.right(), lineRect.top(), | - | ||||||||||||||||||||||||
1170 | lineRect.height()/4, lineRect.height()), clip)); | - | ||||||||||||||||||||||||
1171 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1172 | - | |||||||||||||||||||||||||
1173 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1174 | { | - | ||||||||||||||||||||||||
1175 | const QPen oldPen = p->pen(); | - | ||||||||||||||||||||||||
1176 | const QBrush oldBrush = p->brush(); | - | ||||||||||||||||||||||||
1177 | - | |||||||||||||||||||||||||
1178 | p->setPen(selection.format.penProperty(QTextFormat::OutlinePen)); | - | ||||||||||||||||||||||||
1179 | p->setBrush(selection.format.brushProperty(QTextFormat::BackgroundBrush)); | - | ||||||||||||||||||||||||
1180 | p->drawPath(region); | - | ||||||||||||||||||||||||
1181 | - | |||||||||||||||||||||||||
1182 | p->setPen(oldPen); | - | ||||||||||||||||||||||||
1183 | p->setBrush(oldBrush); | - | ||||||||||||||||||||||||
1184 | } | - | ||||||||||||||||||||||||
1185 | - | |||||||||||||||||||||||||
1186 | - | |||||||||||||||||||||||||
1187 | - | |||||||||||||||||||||||||
1188 | bool hasText = (selection.format.foreground().style() != Qt::NoBrush); | - | ||||||||||||||||||||||||
1189 | bool hasBackground= (selection.format.background().style() != Qt::NoBrush); | - | ||||||||||||||||||||||||
1190 | - | |||||||||||||||||||||||||
1191 | if (hasBackground) {
| 0 | ||||||||||||||||||||||||
1192 | selection.format.setProperty(ObjectSelectionBrush, selection.format.property(QTextFormat::BackgroundBrush)); | - | ||||||||||||||||||||||||
1193 | // don't just clear the property, set an empty brush that overrides a potential | - | ||||||||||||||||||||||||
1194 | // background brush specified in the text | - | ||||||||||||||||||||||||
1195 | selection.format.setProperty(QTextFormat::BackgroundBrush, QBrush()); | - | ||||||||||||||||||||||||
1196 | selection.format.clearProperty(QTextFormat::OutlinePen); | - | ||||||||||||||||||||||||
1197 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1198 | - | |||||||||||||||||||||||||
1199 | selection.format.setProperty(SuppressText, !hasText); | - | ||||||||||||||||||||||||
1200 | - | |||||||||||||||||||||||||
1201 | if (hasText && !hasBackground && !(textDoneRegion & region).isEmpty())
| 0 | ||||||||||||||||||||||||
1202 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
1203 | - | |||||||||||||||||||||||||
1204 | p->save(); | - | ||||||||||||||||||||||||
1205 | p->setClipPath(region, Qt::IntersectClip); | - | ||||||||||||||||||||||||
1206 | - | |||||||||||||||||||||||||
1207 | for (int line = firstLine; line < lastLine; ++line) {
| 0 | ||||||||||||||||||||||||
1208 | QTextLine l(line, d); | - | ||||||||||||||||||||||||
1209 | l.draw(p, position, &selection); | - | ||||||||||||||||||||||||
1210 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1211 | p->restore(); | - | ||||||||||||||||||||||||
1212 | - | |||||||||||||||||||||||||
1213 | if (hasText) {
| 0 | ||||||||||||||||||||||||
1214 | textDoneRegion += region; | - | ||||||||||||||||||||||||
1215 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
1216 | if (hasBackground)
| 0 | ||||||||||||||||||||||||
1217 | textDoneRegion -= region; never executed: textDoneRegion -= region; | 0 | ||||||||||||||||||||||||
1218 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1219 | - | |||||||||||||||||||||||||
1220 | excludedRegion += region; | - | ||||||||||||||||||||||||
1221 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1222 | - | |||||||||||||||||||||||||
1223 | QPainterPath needsTextButNoBackground = excludedRegion - textDoneRegion; | - | ||||||||||||||||||||||||
1224 | if (!needsTextButNoBackground.isEmpty()){
| 0 | ||||||||||||||||||||||||
1225 | p->save(); | - | ||||||||||||||||||||||||
1226 | p->setClipPath(needsTextButNoBackground, Qt::IntersectClip); | - | ||||||||||||||||||||||||
1227 | FormatRange selection; | - | ||||||||||||||||||||||||
1228 | selection.start = 0; | - | ||||||||||||||||||||||||
1229 | selection.length = INT_MAX; | - | ||||||||||||||||||||||||
1230 | selection.format.setProperty(SuppressBackground, true); | - | ||||||||||||||||||||||||
1231 | for (int line = firstLine; line < lastLine; ++line) {
| 0 | ||||||||||||||||||||||||
1232 | QTextLine l(line, d); | - | ||||||||||||||||||||||||
1233 | l.draw(p, position, &selection); | - | ||||||||||||||||||||||||
1234 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1235 | p->restore(); | - | ||||||||||||||||||||||||
1236 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1237 | - | |||||||||||||||||||||||||
1238 | if (!excludedRegion.isEmpty()) {
| 0 | ||||||||||||||||||||||||
1239 | p->save(); | - | ||||||||||||||||||||||||
1240 | QPainterPath path; | - | ||||||||||||||||||||||||
1241 | QRectF br = boundingRect().translated(position); | - | ||||||||||||||||||||||||
1242 | br.setRight(QFIXED_MAX); | - | ||||||||||||||||||||||||
1243 | if (!clip.isNull())
| 0 | ||||||||||||||||||||||||
1244 | br = br.intersected(clip); never executed: br = br.intersected(clip); | 0 | ||||||||||||||||||||||||
1245 | path.addRect(br); | - | ||||||||||||||||||||||||
1246 | path -= excludedRegion; | - | ||||||||||||||||||||||||
1247 | p->setClipPath(path, Qt::IntersectClip); | - | ||||||||||||||||||||||||
1248 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1249 | - | |||||||||||||||||||||||||
1250 | for (int i = firstLine; i < lastLine; ++i) {
| 0 | ||||||||||||||||||||||||
1251 | QTextLine l(i, d); | - | ||||||||||||||||||||||||
1252 | l.draw(p, position); | - | ||||||||||||||||||||||||
1253 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1254 | if (!excludedRegion.isEmpty())
| 0 | ||||||||||||||||||||||||
1255 | p->restore(); never executed: p->restore(); | 0 | ||||||||||||||||||||||||
1256 | - | |||||||||||||||||||||||||
1257 | - | |||||||||||||||||||||||||
1258 | if (!d->cacheGlyphs)
| 0 | ||||||||||||||||||||||||
1259 | d->freeMemory(); never executed: d->freeMemory(); | 0 | ||||||||||||||||||||||||
1260 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1261 | - | |||||||||||||||||||||||||
1262 | /*! | - | ||||||||||||||||||||||||
1263 | \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition) const | - | ||||||||||||||||||||||||
1264 | \overload | - | ||||||||||||||||||||||||
1265 | - | |||||||||||||||||||||||||
1266 | Draws a text cursor with the current pen at the given \a position using the | - | ||||||||||||||||||||||||
1267 | \a painter specified. | - | ||||||||||||||||||||||||
1268 | The corresponding position within the text is specified by \a cursorPosition. | - | ||||||||||||||||||||||||
1269 | */ | - | ||||||||||||||||||||||||
1270 | void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition) const | - | ||||||||||||||||||||||||
1271 | { | - | ||||||||||||||||||||||||
1272 | drawCursor(p, pos, cursorPosition, 1); | - | ||||||||||||||||||||||||
1273 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1274 | - | |||||||||||||||||||||||||
1275 | /*! | - | ||||||||||||||||||||||||
1276 | \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition, int width) const | - | ||||||||||||||||||||||||
1277 | - | |||||||||||||||||||||||||
1278 | Draws a text cursor with the current pen and the specified \a width at the given \a position using the | - | ||||||||||||||||||||||||
1279 | \a painter specified. | - | ||||||||||||||||||||||||
1280 | The corresponding position within the text is specified by \a cursorPosition. | - | ||||||||||||||||||||||||
1281 | */ | - | ||||||||||||||||||||||||
1282 | void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition, int width) const | - | ||||||||||||||||||||||||
1283 | { | - | ||||||||||||||||||||||||
1284 | if (d->lines.isEmpty())
| 0 | ||||||||||||||||||||||||
1285 | return; never executed: return; | 0 | ||||||||||||||||||||||||
1286 | - | |||||||||||||||||||||||||
1287 | if (!d->layoutData)
| 0 | ||||||||||||||||||||||||
1288 | d->itemize(); never executed: d->itemize(); | 0 | ||||||||||||||||||||||||
1289 | - | |||||||||||||||||||||||||
1290 | QPointF position = pos + d->position; | - | ||||||||||||||||||||||||
1291 | - | |||||||||||||||||||||||||
1292 | cursorPosition = qBound(0, cursorPosition, d->layoutData->string.length()); | - | ||||||||||||||||||||||||
1293 | int line = d->lineNumberForTextPosition(cursorPosition); | - | ||||||||||||||||||||||||
1294 | if (line < 0)
| 0 | ||||||||||||||||||||||||
1295 | line = 0; never executed: line = 0; | 0 | ||||||||||||||||||||||||
1296 | if (line >= d->lines.size())
| 0 | ||||||||||||||||||||||||
1297 | return; never executed: return; | 0 | ||||||||||||||||||||||||
1298 | - | |||||||||||||||||||||||||
1299 | QTextLine l(line, d); | - | ||||||||||||||||||||||||
1300 | const QScriptLine &sl = d->lines[line]; | - | ||||||||||||||||||||||||
1301 | - | |||||||||||||||||||||||||
1302 | qreal x = position.x() + l.cursorToX(cursorPosition); | - | ||||||||||||||||||||||||
1303 | - | |||||||||||||||||||||||||
1304 | int itm; | - | ||||||||||||||||||||||||
1305 | - | |||||||||||||||||||||||||
1306 | if (d->visualCursorMovement()) {
| 0 | ||||||||||||||||||||||||
1307 | if (cursorPosition == sl.from + sl.length)
| 0 | ||||||||||||||||||||||||
1308 | cursorPosition--; never executed: cursorPosition--; | 0 | ||||||||||||||||||||||||
1309 | itm = d->findItem(cursorPosition); | - | ||||||||||||||||||||||||
1310 | } else never executed: end of block | 0 | ||||||||||||||||||||||||
1311 | itm = d->findItem(cursorPosition - 1); never executed: itm = d->findItem(cursorPosition - 1); | 0 | ||||||||||||||||||||||||
1312 | - | |||||||||||||||||||||||||
1313 | QFixed base = sl.base(); | - | ||||||||||||||||||||||||
1314 | QFixed descent = sl.descent; | - | ||||||||||||||||||||||||
1315 | bool rightToLeft = d->isRightToLeft(); | - | ||||||||||||||||||||||||
1316 | if (itm >= 0) {
| 0 | ||||||||||||||||||||||||
1317 | const QScriptItem &si = d->layoutData->items.at(itm); | - | ||||||||||||||||||||||||
1318 | if (si.ascent > 0)
| 0 | ||||||||||||||||||||||||
1319 | base = si.ascent; never executed: base = si.ascent; | 0 | ||||||||||||||||||||||||
1320 | if (si.descent > 0)
| 0 | ||||||||||||||||||||||||
1321 | descent = si.descent; never executed: descent = si.descent; | 0 | ||||||||||||||||||||||||
1322 | rightToLeft = si.analysis.bidiLevel % 2; | - | ||||||||||||||||||||||||
1323 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1324 | qreal y = position.y() + (sl.y + sl.base() - base).toReal(); | - | ||||||||||||||||||||||||
1325 | bool toggleAntialiasing = !(p->renderHints() & QPainter::Antialiasing)
| 0 | ||||||||||||||||||||||||
1326 | && (p->transform().type() > QTransform::TxTranslate);
| 0 | ||||||||||||||||||||||||
1327 | if (toggleAntialiasing)
| 0 | ||||||||||||||||||||||||
1328 | p->setRenderHint(QPainter::Antialiasing); never executed: p->setRenderHint(QPainter::Antialiasing); | 0 | ||||||||||||||||||||||||
1329 | p->fillRect(QRectF(x, y, qreal(width), (base + descent).toReal()), p->pen().brush()); | - | ||||||||||||||||||||||||
1330 | if (toggleAntialiasing)
| 0 | ||||||||||||||||||||||||
1331 | p->setRenderHint(QPainter::Antialiasing, false); never executed: p->setRenderHint(QPainter::Antialiasing, false); | 0 | ||||||||||||||||||||||||
1332 | if (d->layoutData->hasBidi) {
| 0 | ||||||||||||||||||||||||
1333 | const int arrow_extent = 4; | - | ||||||||||||||||||||||||
1334 | int sign = rightToLeft ? -1 : 1;
| 0 | ||||||||||||||||||||||||
1335 | p->drawLine(QLineF(x, y, x + (sign * arrow_extent/2), y + arrow_extent/2)); | - | ||||||||||||||||||||||||
1336 | p->drawLine(QLineF(x, y+arrow_extent, x + (sign * arrow_extent/2), y + arrow_extent/2)); | - | ||||||||||||||||||||||||
1337 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1338 | return; never executed: return; | 0 | ||||||||||||||||||||||||
1339 | } | - | ||||||||||||||||||||||||
1340 | - | |||||||||||||||||||||||||
1341 | /*! | - | ||||||||||||||||||||||||
1342 | \class QTextLine | - | ||||||||||||||||||||||||
1343 | \reentrant | - | ||||||||||||||||||||||||
1344 | - | |||||||||||||||||||||||||
1345 | \brief The QTextLine class represents a line of text inside a QTextLayout. | - | ||||||||||||||||||||||||
1346 | \inmodule QtGui | - | ||||||||||||||||||||||||
1347 | - | |||||||||||||||||||||||||
1348 | \ingroup richtext-processing | - | ||||||||||||||||||||||||
1349 | - | |||||||||||||||||||||||||
1350 | A text line is usually created by QTextLayout::createLine(). | - | ||||||||||||||||||||||||
1351 | - | |||||||||||||||||||||||||
1352 | After being created, the line can be filled using the setLineWidth() | - | ||||||||||||||||||||||||
1353 | or setNumColumns() functions. A line has a number of attributes including the | - | ||||||||||||||||||||||||
1354 | rectangle it occupies, rect(), its coordinates, x() and y(), its | - | ||||||||||||||||||||||||
1355 | textLength(), width() and naturalTextWidth(), and its ascent() and descent() | - | ||||||||||||||||||||||||
1356 | relative to the text. The position of the cursor in terms of the | - | ||||||||||||||||||||||||
1357 | line is available from cursorToX() and its inverse from | - | ||||||||||||||||||||||||
1358 | xToCursor(). A line can be moved with setPosition(). | - | ||||||||||||||||||||||||
1359 | */ | - | ||||||||||||||||||||||||
1360 | - | |||||||||||||||||||||||||
1361 | /*! | - | ||||||||||||||||||||||||
1362 | \enum QTextLine::Edge | - | ||||||||||||||||||||||||
1363 | - | |||||||||||||||||||||||||
1364 | \value Leading | - | ||||||||||||||||||||||||
1365 | \value Trailing | - | ||||||||||||||||||||||||
1366 | */ | - | ||||||||||||||||||||||||
1367 | - | |||||||||||||||||||||||||
1368 | /*! | - | ||||||||||||||||||||||||
1369 | \enum QTextLine::CursorPosition | - | ||||||||||||||||||||||||
1370 | - | |||||||||||||||||||||||||
1371 | \value CursorBetweenCharacters | - | ||||||||||||||||||||||||
1372 | \value CursorOnCharacter | - | ||||||||||||||||||||||||
1373 | */ | - | ||||||||||||||||||||||||
1374 | - | |||||||||||||||||||||||||
1375 | /*! | - | ||||||||||||||||||||||||
1376 | \fn QTextLine::QTextLine(int line, QTextEngine *e) | - | ||||||||||||||||||||||||
1377 | \internal | - | ||||||||||||||||||||||||
1378 | - | |||||||||||||||||||||||||
1379 | Constructs a new text line using the line at position \a line in | - | ||||||||||||||||||||||||
1380 | the text engine \a e. | - | ||||||||||||||||||||||||
1381 | */ | - | ||||||||||||||||||||||||
1382 | - | |||||||||||||||||||||||||
1383 | /*! | - | ||||||||||||||||||||||||
1384 | \fn QTextLine::QTextLine() | - | ||||||||||||||||||||||||
1385 | - | |||||||||||||||||||||||||
1386 | Creates an invalid line. | - | ||||||||||||||||||||||||
1387 | */ | - | ||||||||||||||||||||||||
1388 | - | |||||||||||||||||||||||||
1389 | /*! | - | ||||||||||||||||||||||||
1390 | \fn bool QTextLine::isValid() const | - | ||||||||||||||||||||||||
1391 | - | |||||||||||||||||||||||||
1392 | Returns \c true if this text line is valid; otherwise returns \c false. | - | ||||||||||||||||||||||||
1393 | */ | - | ||||||||||||||||||||||||
1394 | - | |||||||||||||||||||||||||
1395 | /*! | - | ||||||||||||||||||||||||
1396 | \fn int QTextLine::lineNumber() const | - | ||||||||||||||||||||||||
1397 | - | |||||||||||||||||||||||||
1398 | Returns the position of the line in the text engine. | - | ||||||||||||||||||||||||
1399 | */ | - | ||||||||||||||||||||||||
1400 | - | |||||||||||||||||||||||||
1401 | - | |||||||||||||||||||||||||
1402 | /*! | - | ||||||||||||||||||||||||
1403 | Returns the line's bounding rectangle. | - | ||||||||||||||||||||||||
1404 | - | |||||||||||||||||||||||||
1405 | \sa x(), y(), textLength(), width() | - | ||||||||||||||||||||||||
1406 | */ | - | ||||||||||||||||||||||||
1407 | QRectF QTextLine::rect() const | - | ||||||||||||||||||||||||
1408 | { | - | ||||||||||||||||||||||||
1409 | const QScriptLine& sl = eng->lines[index]; | - | ||||||||||||||||||||||||
1410 | return QRectF(sl.x.toReal(), sl.y.toReal(), sl.width.toReal(), sl.height().toReal()); never executed: return QRectF(sl.x.toReal(), sl.y.toReal(), sl.width.toReal(), sl.height().toReal()); | 0 | ||||||||||||||||||||||||
1411 | } | - | ||||||||||||||||||||||||
1412 | - | |||||||||||||||||||||||||
1413 | /*! | - | ||||||||||||||||||||||||
1414 | Returns the rectangle covered by the line. | - | ||||||||||||||||||||||||
1415 | */ | - | ||||||||||||||||||||||||
1416 | QRectF QTextLine::naturalTextRect() const | - | ||||||||||||||||||||||||
1417 | { | - | ||||||||||||||||||||||||
1418 | const QScriptLine& sl = eng->lines[index]; | - | ||||||||||||||||||||||||
1419 | QFixed x = sl.x + eng->alignLine(sl); | - | ||||||||||||||||||||||||
1420 | - | |||||||||||||||||||||||||
1421 | QFixed width = sl.textWidth; | - | ||||||||||||||||||||||||
1422 | if (sl.justified)
| 0 | ||||||||||||||||||||||||
1423 | width = sl.width; never executed: width = sl.width; | 0 | ||||||||||||||||||||||||
1424 | - | |||||||||||||||||||||||||
1425 | return QRectF(x.toReal(), sl.y.toReal(), width.toReal(), sl.height().toReal()); never executed: return QRectF(x.toReal(), sl.y.toReal(), width.toReal(), sl.height().toReal()); | 0 | ||||||||||||||||||||||||
1426 | } | - | ||||||||||||||||||||||||
1427 | - | |||||||||||||||||||||||||
1428 | /*! | - | ||||||||||||||||||||||||
1429 | Returns the line's x position. | - | ||||||||||||||||||||||||
1430 | - | |||||||||||||||||||||||||
1431 | \sa rect(), y(), textLength(), width() | - | ||||||||||||||||||||||||
1432 | */ | - | ||||||||||||||||||||||||
1433 | qreal QTextLine::x() const | - | ||||||||||||||||||||||||
1434 | { | - | ||||||||||||||||||||||||
1435 | return eng->lines[index].x.toReal(); never executed: return eng->lines[index].x.toReal(); | 0 | ||||||||||||||||||||||||
1436 | } | - | ||||||||||||||||||||||||
1437 | - | |||||||||||||||||||||||||
1438 | /*! | - | ||||||||||||||||||||||||
1439 | Returns the line's y position. | - | ||||||||||||||||||||||||
1440 | - | |||||||||||||||||||||||||
1441 | \sa x(), rect(), textLength(), width() | - | ||||||||||||||||||||||||
1442 | */ | - | ||||||||||||||||||||||||
1443 | qreal QTextLine::y() const | - | ||||||||||||||||||||||||
1444 | { | - | ||||||||||||||||||||||||
1445 | return eng->lines[index].y.toReal(); never executed: return eng->lines[index].y.toReal(); | 0 | ||||||||||||||||||||||||
1446 | } | - | ||||||||||||||||||||||||
1447 | - | |||||||||||||||||||||||||
1448 | /*! | - | ||||||||||||||||||||||||
1449 | Returns the line's width as specified by the layout() function. | - | ||||||||||||||||||||||||
1450 | - | |||||||||||||||||||||||||
1451 | \sa naturalTextWidth(), x(), y(), textLength(), rect() | - | ||||||||||||||||||||||||
1452 | */ | - | ||||||||||||||||||||||||
1453 | qreal QTextLine::width() const | - | ||||||||||||||||||||||||
1454 | { | - | ||||||||||||||||||||||||
1455 | return eng->lines[index].width.toReal(); never executed: return eng->lines[index].width.toReal(); | 0 | ||||||||||||||||||||||||
1456 | } | - | ||||||||||||||||||||||||
1457 | - | |||||||||||||||||||||||||
1458 | - | |||||||||||||||||||||||||
1459 | /*! | - | ||||||||||||||||||||||||
1460 | Returns the line's ascent. | - | ||||||||||||||||||||||||
1461 | - | |||||||||||||||||||||||||
1462 | \sa descent(), height() | - | ||||||||||||||||||||||||
1463 | */ | - | ||||||||||||||||||||||||
1464 | qreal QTextLine::ascent() const | - | ||||||||||||||||||||||||
1465 | { | - | ||||||||||||||||||||||||
1466 | return eng->lines[index].ascent.toReal(); never executed: return eng->lines[index].ascent.toReal(); | 0 | ||||||||||||||||||||||||
1467 | } | - | ||||||||||||||||||||||||
1468 | - | |||||||||||||||||||||||||
1469 | /*! | - | ||||||||||||||||||||||||
1470 | Returns the line's descent. | - | ||||||||||||||||||||||||
1471 | - | |||||||||||||||||||||||||
1472 | \sa ascent(), height() | - | ||||||||||||||||||||||||
1473 | */ | - | ||||||||||||||||||||||||
1474 | qreal QTextLine::descent() const | - | ||||||||||||||||||||||||
1475 | { | - | ||||||||||||||||||||||||
1476 | return eng->lines[index].descent.toReal(); never executed: return eng->lines[index].descent.toReal(); | 0 | ||||||||||||||||||||||||
1477 | } | - | ||||||||||||||||||||||||
1478 | - | |||||||||||||||||||||||||
1479 | /*! | - | ||||||||||||||||||||||||
1480 | Returns the line's height. This is equal to ascent() + descent() | - | ||||||||||||||||||||||||
1481 | if leading is not included. If leading is included, this equals to | - | ||||||||||||||||||||||||
1482 | ascent() + descent() + leading(). | - | ||||||||||||||||||||||||
1483 | - | |||||||||||||||||||||||||
1484 | \sa ascent(), descent(), leading(), setLeadingIncluded() | - | ||||||||||||||||||||||||
1485 | */ | - | ||||||||||||||||||||||||
1486 | qreal QTextLine::height() const | - | ||||||||||||||||||||||||
1487 | { | - | ||||||||||||||||||||||||
1488 | return eng->lines[index].height().ceil().toReal(); never executed: return eng->lines[index].height().ceil().toReal(); | 0 | ||||||||||||||||||||||||
1489 | } | - | ||||||||||||||||||||||||
1490 | - | |||||||||||||||||||||||||
1491 | /*! | - | ||||||||||||||||||||||||
1492 | \since 4.6 | - | ||||||||||||||||||||||||
1493 | - | |||||||||||||||||||||||||
1494 | Returns the line's leading. | - | ||||||||||||||||||||||||
1495 | - | |||||||||||||||||||||||||
1496 | \sa ascent(), descent(), height() | - | ||||||||||||||||||||||||
1497 | */ | - | ||||||||||||||||||||||||
1498 | qreal QTextLine::leading() const | - | ||||||||||||||||||||||||
1499 | { | - | ||||||||||||||||||||||||
1500 | return eng->lines[index].leading.toReal(); never executed: return eng->lines[index].leading.toReal(); | 0 | ||||||||||||||||||||||||
1501 | } | - | ||||||||||||||||||||||||
1502 | - | |||||||||||||||||||||||||
1503 | /*! | - | ||||||||||||||||||||||||
1504 | \since 4.6 | - | ||||||||||||||||||||||||
1505 | - | |||||||||||||||||||||||||
1506 | Includes positive leading into the line's height if \a included is true; | - | ||||||||||||||||||||||||
1507 | otherwise does not include leading. | - | ||||||||||||||||||||||||
1508 | - | |||||||||||||||||||||||||
1509 | By default, leading is not included. | - | ||||||||||||||||||||||||
1510 | - | |||||||||||||||||||||||||
1511 | Note that negative leading is ignored, it must be handled | - | ||||||||||||||||||||||||
1512 | in the code using the text lines by letting the lines overlap. | - | ||||||||||||||||||||||||
1513 | - | |||||||||||||||||||||||||
1514 | \sa leadingIncluded() | - | ||||||||||||||||||||||||
1515 | - | |||||||||||||||||||||||||
1516 | */ | - | ||||||||||||||||||||||||
1517 | void QTextLine::setLeadingIncluded(bool included) | - | ||||||||||||||||||||||||
1518 | { | - | ||||||||||||||||||||||||
1519 | eng->lines[index].leadingIncluded= included; | - | ||||||||||||||||||||||||
1520 | - | |||||||||||||||||||||||||
1521 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1522 | - | |||||||||||||||||||||||||
1523 | /*! | - | ||||||||||||||||||||||||
1524 | \since 4.6 | - | ||||||||||||||||||||||||
1525 | - | |||||||||||||||||||||||||
1526 | Returns \c true if positive leading is included into the line's height; | - | ||||||||||||||||||||||||
1527 | otherwise returns \c false. | - | ||||||||||||||||||||||||
1528 | - | |||||||||||||||||||||||||
1529 | By default, leading is not included. | - | ||||||||||||||||||||||||
1530 | - | |||||||||||||||||||||||||
1531 | \sa setLeadingIncluded() | - | ||||||||||||||||||||||||
1532 | */ | - | ||||||||||||||||||||||||
1533 | bool QTextLine::leadingIncluded() const | - | ||||||||||||||||||||||||
1534 | { | - | ||||||||||||||||||||||||
1535 | return eng->lines[index].leadingIncluded; never executed: return eng->lines[index].leadingIncluded; | 0 | ||||||||||||||||||||||||
1536 | } | - | ||||||||||||||||||||||||
1537 | - | |||||||||||||||||||||||||
1538 | /*! | - | ||||||||||||||||||||||||
1539 | Returns the width of the line that is occupied by text. This is | - | ||||||||||||||||||||||||
1540 | always \<= to width(), and is the minimum width that could be used | - | ||||||||||||||||||||||||
1541 | by layout() without changing the line break position. | - | ||||||||||||||||||||||||
1542 | */ | - | ||||||||||||||||||||||||
1543 | qreal QTextLine::naturalTextWidth() const | - | ||||||||||||||||||||||||
1544 | { | - | ||||||||||||||||||||||||
1545 | return eng->lines[index].textWidth.toReal(); never executed: return eng->lines[index].textWidth.toReal(); | 0 | ||||||||||||||||||||||||
1546 | } | - | ||||||||||||||||||||||||
1547 | - | |||||||||||||||||||||||||
1548 | /*! | - | ||||||||||||||||||||||||
1549 | \since 4.7 | - | ||||||||||||||||||||||||
1550 | Returns the horizontal advance of the text. The advance of the text | - | ||||||||||||||||||||||||
1551 | is the distance from its position to the next position at which | - | ||||||||||||||||||||||||
1552 | text would naturally be drawn. | - | ||||||||||||||||||||||||
1553 | - | |||||||||||||||||||||||||
1554 | By adding the advance to the position of the text line and using this | - | ||||||||||||||||||||||||
1555 | as the position of a second text line, you will be able to position | - | ||||||||||||||||||||||||
1556 | the two lines side-by-side without gaps in-between. | - | ||||||||||||||||||||||||
1557 | */ | - | ||||||||||||||||||||||||
1558 | qreal QTextLine::horizontalAdvance() const | - | ||||||||||||||||||||||||
1559 | { | - | ||||||||||||||||||||||||
1560 | return eng->lines[index].textAdvance.toReal(); never executed: return eng->lines[index].textAdvance.toReal(); | 0 | ||||||||||||||||||||||||
1561 | } | - | ||||||||||||||||||||||||
1562 | - | |||||||||||||||||||||||||
1563 | /*! | - | ||||||||||||||||||||||||
1564 | Lays out the line with the given \a width. The line is filled from | - | ||||||||||||||||||||||||
1565 | its starting position with as many characters as will fit into | - | ||||||||||||||||||||||||
1566 | the line. In case the text cannot be split at the end of the line, | - | ||||||||||||||||||||||||
1567 | it will be filled with additional characters to the next whitespace | - | ||||||||||||||||||||||||
1568 | or end of the text. | - | ||||||||||||||||||||||||
1569 | */ | - | ||||||||||||||||||||||||
1570 | void QTextLine::setLineWidth(qreal width) | - | ||||||||||||||||||||||||
1571 | { | - | ||||||||||||||||||||||||
1572 | QScriptLine &line = eng->lines[index]; | - | ||||||||||||||||||||||||
1573 | if (!eng->layoutData) {
| 0 | ||||||||||||||||||||||||
1574 | qWarning("QTextLine: Can't set a line width while not layouting."); | - | ||||||||||||||||||||||||
1575 | return; never executed: return; | 0 | ||||||||||||||||||||||||
1576 | } | - | ||||||||||||||||||||||||
1577 | - | |||||||||||||||||||||||||
1578 | if (width > QFIXED_MAX)
| 0 | ||||||||||||||||||||||||
1579 | width = QFIXED_MAX; never executed: width = (2147483647/256); | 0 | ||||||||||||||||||||||||
1580 | - | |||||||||||||||||||||||||
1581 | line.width = QFixed::fromReal(width); | - | ||||||||||||||||||||||||
1582 | if (line.length
| 0 | ||||||||||||||||||||||||
1583 | && line.textWidth <= line.width
| 0 | ||||||||||||||||||||||||
1584 | && line.from + line.length == eng->layoutData->string.length())
| 0 | ||||||||||||||||||||||||
1585 | // no need to do anything if the line is already layouted and the last one. This optimization helps | - | ||||||||||||||||||||||||
1586 | // when using things in a single line layout. | - | ||||||||||||||||||||||||
1587 | return; never executed: return; | 0 | ||||||||||||||||||||||||
1588 | line.length = 0; | - | ||||||||||||||||||||||||
1589 | line.textWidth = 0; | - | ||||||||||||||||||||||||
1590 | - | |||||||||||||||||||||||||
1591 | layout_helper(INT_MAX); | - | ||||||||||||||||||||||||
1592 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1593 | - | |||||||||||||||||||||||||
1594 | /*! | - | ||||||||||||||||||||||||
1595 | Lays out the line. The line is filled from its starting position | - | ||||||||||||||||||||||||
1596 | with as many characters as are specified by \a numColumns. In case | - | ||||||||||||||||||||||||
1597 | the text cannot be split until \a numColumns characters, the line | - | ||||||||||||||||||||||||
1598 | will be filled with as many characters to the next whitespace or | - | ||||||||||||||||||||||||
1599 | end of the text. | - | ||||||||||||||||||||||||
1600 | */ | - | ||||||||||||||||||||||||
1601 | void QTextLine::setNumColumns(int numColumns) | - | ||||||||||||||||||||||||
1602 | { | - | ||||||||||||||||||||||||
1603 | QScriptLine &line = eng->lines[index]; | - | ||||||||||||||||||||||||
1604 | line.width = QFIXED_MAX; | - | ||||||||||||||||||||||||
1605 | line.length = 0; | - | ||||||||||||||||||||||||
1606 | line.textWidth = 0; | - | ||||||||||||||||||||||||
1607 | layout_helper(numColumns); | - | ||||||||||||||||||||||||
1608 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1609 | - | |||||||||||||||||||||||||
1610 | /*! | - | ||||||||||||||||||||||||
1611 | Lays out the line. The line is filled from its starting position | - | ||||||||||||||||||||||||
1612 | with as many characters as are specified by \a numColumns. In case | - | ||||||||||||||||||||||||
1613 | the text cannot be split until \a numColumns characters, the line | - | ||||||||||||||||||||||||
1614 | will be filled with as many characters to the next whitespace or | - | ||||||||||||||||||||||||
1615 | end of the text. The provided \a alignmentWidth is used as reference | - | ||||||||||||||||||||||||
1616 | width for alignment. | - | ||||||||||||||||||||||||
1617 | */ | - | ||||||||||||||||||||||||
1618 | void QTextLine::setNumColumns(int numColumns, qreal alignmentWidth) | - | ||||||||||||||||||||||||
1619 | { | - | ||||||||||||||||||||||||
1620 | QScriptLine &line = eng->lines[index]; | - | ||||||||||||||||||||||||
1621 | line.width = QFixed::fromReal(alignmentWidth); | - | ||||||||||||||||||||||||
1622 | line.length = 0; | - | ||||||||||||||||||||||||
1623 | line.textWidth = 0; | - | ||||||||||||||||||||||||
1624 | layout_helper(numColumns); | - | ||||||||||||||||||||||||
1625 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1626 | - | |||||||||||||||||||||||||
1627 | #if 0 | - | ||||||||||||||||||||||||
1628 | #define LB_DEBUG qDebug | - | ||||||||||||||||||||||||
1629 | #else | - | ||||||||||||||||||||||||
1630 | #define LB_DEBUG if (0) qDebug | - | ||||||||||||||||||||||||
1631 | #endif | - | ||||||||||||||||||||||||
1632 | - | |||||||||||||||||||||||||
1633 | namespace { | - | ||||||||||||||||||||||||
1634 | - | |||||||||||||||||||||||||
1635 | struct LineBreakHelper | - | ||||||||||||||||||||||||
1636 | { | - | ||||||||||||||||||||||||
1637 | LineBreakHelper() | - | ||||||||||||||||||||||||
1638 | : glyphCount(0), maxGlyphs(0), currentPosition(0), fontEngine(0), logClusters(0), | - | ||||||||||||||||||||||||
1639 | manualWrap(false), whiteSpaceOrObject(true) | - | ||||||||||||||||||||||||
1640 | { | - | ||||||||||||||||||||||||
1641 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1642 | - | |||||||||||||||||||||||||
1643 | - | |||||||||||||||||||||||||
1644 | QScriptLine tmpData; | - | ||||||||||||||||||||||||
1645 | QScriptLine spaceData; | - | ||||||||||||||||||||||||
1646 | - | |||||||||||||||||||||||||
1647 | QGlyphLayout glyphs; | - | ||||||||||||||||||||||||
1648 | - | |||||||||||||||||||||||||
1649 | int glyphCount; | - | ||||||||||||||||||||||||
1650 | int maxGlyphs; | - | ||||||||||||||||||||||||
1651 | int currentPosition; | - | ||||||||||||||||||||||||
1652 | glyph_t previousGlyph; | - | ||||||||||||||||||||||||
1653 | - | |||||||||||||||||||||||||
1654 | QFixed minw; | - | ||||||||||||||||||||||||
1655 | QFixed softHyphenWidth; | - | ||||||||||||||||||||||||
1656 | QFixed rightBearing; | - | ||||||||||||||||||||||||
1657 | QFixed minimumRightBearing; | - | ||||||||||||||||||||||||
1658 | - | |||||||||||||||||||||||||
1659 | QFontEngine *fontEngine; | - | ||||||||||||||||||||||||
1660 | const unsigned short *logClusters; | - | ||||||||||||||||||||||||
1661 | - | |||||||||||||||||||||||||
1662 | bool manualWrap; | - | ||||||||||||||||||||||||
1663 | bool whiteSpaceOrObject; | - | ||||||||||||||||||||||||
1664 | - | |||||||||||||||||||||||||
1665 | bool checkFullOtherwiseExtend(QScriptLine &line); | - | ||||||||||||||||||||||||
1666 | - | |||||||||||||||||||||||||
1667 | QFixed calculateNewWidth(const QScriptLine &line) const { | - | ||||||||||||||||||||||||
1668 | return line.textWidth + tmpData.textWidth + spaceData.textWidth never executed: return line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth + negativeRightBearing(); | 0 | ||||||||||||||||||||||||
1669 | + softHyphenWidth + negativeRightBearing(); never executed: return line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth + negativeRightBearing(); | 0 | ||||||||||||||||||||||||
1670 | } | - | ||||||||||||||||||||||||
1671 | - | |||||||||||||||||||||||||
1672 | inline glyph_t currentGlyph() const | - | ||||||||||||||||||||||||
1673 | { | - | ||||||||||||||||||||||||
1674 | Q_ASSERT(currentPosition > 0); | - | ||||||||||||||||||||||||
1675 | Q_ASSERT(logClusters[currentPosition - 1] < glyphs.numGlyphs); | - | ||||||||||||||||||||||||
1676 | - | |||||||||||||||||||||||||
1677 | return glyphs.glyphs[logClusters[currentPosition - 1]]; never executed: return glyphs.glyphs[logClusters[currentPosition - 1]]; | 0 | ||||||||||||||||||||||||
1678 | } | - | ||||||||||||||||||||||||
1679 | - | |||||||||||||||||||||||||
1680 | inline void saveCurrentGlyph() | - | ||||||||||||||||||||||||
1681 | { | - | ||||||||||||||||||||||||
1682 | previousGlyph = 0; | - | ||||||||||||||||||||||||
1683 | if (currentPosition > 0 &&
| 0 | ||||||||||||||||||||||||
1684 | logClusters[currentPosition - 1] < glyphs.numGlyphs) {
| 0 | ||||||||||||||||||||||||
1685 | previousGlyph = currentGlyph(); // needed to calculate right bearing later | - | ||||||||||||||||||||||||
1686 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1687 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1688 | - | |||||||||||||||||||||||||
1689 | inline void calculateRightBearing(glyph_t glyph) | - | ||||||||||||||||||||||||
1690 | { | - | ||||||||||||||||||||||||
1691 | qreal rb; | - | ||||||||||||||||||||||||
1692 | fontEngine->getGlyphBearings(glyph, 0, &rb); | - | ||||||||||||||||||||||||
1693 | - | |||||||||||||||||||||||||
1694 | // We only care about negative right bearings, so we limit the range | - | ||||||||||||||||||||||||
1695 | // of the bearing here so that we can assume it's negative in the rest | - | ||||||||||||||||||||||||
1696 | // of the code, as well ase use QFixed(1) as a sentinel to represent | - | ||||||||||||||||||||||||
1697 | // the state where we have yet to compute the right bearing. | - | ||||||||||||||||||||||||
1698 | rightBearing = qMin(QFixed::fromReal(rb), QFixed(0)); | - | ||||||||||||||||||||||||
1699 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1700 | - | |||||||||||||||||||||||||
1701 | inline void calculateRightBearing() | - | ||||||||||||||||||||||||
1702 | { | - | ||||||||||||||||||||||||
1703 | if (currentPosition <= 0)
| 0 | ||||||||||||||||||||||||
1704 | return; never executed: return; | 0 | ||||||||||||||||||||||||
1705 | calculateRightBearing(currentGlyph()); | - | ||||||||||||||||||||||||
1706 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1707 | - | |||||||||||||||||||||||||
1708 | inline void calculateRightBearingForPreviousGlyph() | - | ||||||||||||||||||||||||
1709 | { | - | ||||||||||||||||||||||||
1710 | if (previousGlyph > 0)
| 0 | ||||||||||||||||||||||||
1711 | calculateRightBearing(previousGlyph); never executed: calculateRightBearing(previousGlyph); | 0 | ||||||||||||||||||||||||
1712 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1713 | - | |||||||||||||||||||||||||
1714 | static const QFixed RightBearingNotCalculated; | - | ||||||||||||||||||||||||
1715 | - | |||||||||||||||||||||||||
1716 | inline void resetRightBearing() | - | ||||||||||||||||||||||||
1717 | { | - | ||||||||||||||||||||||||
1718 | rightBearing = RightBearingNotCalculated; | - | ||||||||||||||||||||||||
1719 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1720 | - | |||||||||||||||||||||||||
1721 | // We express the negative right bearing as an absolute number | - | ||||||||||||||||||||||||
1722 | // so that it can be applied to the width using addition. | - | ||||||||||||||||||||||||
1723 | inline QFixed negativeRightBearing() const | - | ||||||||||||||||||||||||
1724 | { | - | ||||||||||||||||||||||||
1725 | if (rightBearing == RightBearingNotCalculated)
| 0 | ||||||||||||||||||||||||
1726 | return QFixed(0); never executed: return QFixed(0); | 0 | ||||||||||||||||||||||||
1727 | - | |||||||||||||||||||||||||
1728 | return qAbs(rightBearing); never executed: return qAbs(rightBearing); | 0 | ||||||||||||||||||||||||
1729 | } | - | ||||||||||||||||||||||||
1730 | }; | - | ||||||||||||||||||||||||
1731 | - | |||||||||||||||||||||||||
1732 | const QFixed LineBreakHelper::RightBearingNotCalculated = QFixed(1); | - | ||||||||||||||||||||||||
1733 | - | |||||||||||||||||||||||||
1734 | inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line) | - | ||||||||||||||||||||||||
1735 | { | - | ||||||||||||||||||||||||
1736 | LB_DEBUG("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal()); dead code: QMessageLogger(__FILE__, 1736, __PRETTY_FUNCTION__).debug("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal()); | - | ||||||||||||||||||||||||
1737 | - | |||||||||||||||||||||||||
1738 | QFixed newWidth = calculateNewWidth(line); | - | ||||||||||||||||||||||||
1739 | if (line.length && !manualWrap && (newWidth > line.width || glyphCount > maxGlyphs))
| 0 | ||||||||||||||||||||||||
1740 | return true; never executed: return true; | 0 | ||||||||||||||||||||||||
1741 | - | |||||||||||||||||||||||||
1742 | minw = qMax(minw, tmpData.textWidth); | - | ||||||||||||||||||||||||
1743 | line += tmpData; | - | ||||||||||||||||||||||||
1744 | line.textWidth += spaceData.textWidth; | - | ||||||||||||||||||||||||
1745 | - | |||||||||||||||||||||||||
1746 | line.length += spaceData.length; | - | ||||||||||||||||||||||||
1747 | tmpData.textWidth = 0; | - | ||||||||||||||||||||||||
1748 | tmpData.length = 0; | - | ||||||||||||||||||||||||
1749 | spaceData.textWidth = 0; | - | ||||||||||||||||||||||||
1750 | spaceData.length = 0; | - | ||||||||||||||||||||||||
1751 | - | |||||||||||||||||||||||||
1752 | return false; never executed: return false; | 0 | ||||||||||||||||||||||||
1753 | } | - | ||||||||||||||||||||||||
1754 | - | |||||||||||||||||||||||||
1755 | } // anonymous namespace | - | ||||||||||||||||||||||||
1756 | - | |||||||||||||||||||||||||
1757 | - | |||||||||||||||||||||||||
1758 | static inline void addNextCluster(int &pos, int end, QScriptLine &line, int &glyphCount, | - | ||||||||||||||||||||||||
1759 | const QScriptItem ¤t, const unsigned short *logClusters, | - | ||||||||||||||||||||||||
1760 | const QGlyphLayout &glyphs) | - | ||||||||||||||||||||||||
1761 | { | - | ||||||||||||||||||||||||
1762 | int glyphPosition = logClusters[pos]; | - | ||||||||||||||||||||||||
1763 | do { // got to the first next cluster | - | ||||||||||||||||||||||||
1764 | ++pos; | - | ||||||||||||||||||||||||
1765 | ++line.length; | - | ||||||||||||||||||||||||
1766 | } while (pos < end && logClusters[pos] == glyphPosition); never executed: end of block
| 0 | ||||||||||||||||||||||||
1767 | do { // calculate the textWidth for the rest of the current cluster. | - | ||||||||||||||||||||||||
1768 | if (!glyphs.attributes[glyphPosition].dontPrint)
| 0 | ||||||||||||||||||||||||
1769 | line.textWidth += glyphs.advances[glyphPosition]; never executed: line.textWidth += glyphs.advances[glyphPosition]; | 0 | ||||||||||||||||||||||||
1770 | ++glyphPosition; | - | ||||||||||||||||||||||||
1771 | } while (glyphPosition < current.num_glyphs && !glyphs.attributes[glyphPosition].clusterStart); never executed: end of block
| 0 | ||||||||||||||||||||||||
1772 | - | |||||||||||||||||||||||||
1773 | Q_ASSERT((pos == end && glyphPosition == current.num_glyphs) || logClusters[pos] == glyphPosition); | - | ||||||||||||||||||||||||
1774 | - | |||||||||||||||||||||||||
1775 | ++glyphCount; | - | ||||||||||||||||||||||||
1776 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1777 | - | |||||||||||||||||||||||||
1778 | - | |||||||||||||||||||||||||
1779 | // fill QScriptLine | - | ||||||||||||||||||||||||
1780 | void QTextLine::layout_helper(int maxGlyphs) | - | ||||||||||||||||||||||||
1781 | { | - | ||||||||||||||||||||||||
1782 | QScriptLine &line = eng->lines[index]; | - | ||||||||||||||||||||||||
1783 | line.length = 0; | - | ||||||||||||||||||||||||
1784 | line.trailingSpaces = 0; | - | ||||||||||||||||||||||||
1785 | line.textWidth = 0; | - | ||||||||||||||||||||||||
1786 | line.hasTrailingSpaces = false; | - | ||||||||||||||||||||||||
1787 | - | |||||||||||||||||||||||||
1788 | if (!eng->layoutData->items.size() || line.from >= eng->layoutData->string.length()) {
| 0 | ||||||||||||||||||||||||
1789 | line.setDefaultHeight(eng); | - | ||||||||||||||||||||||||
1790 | return; never executed: return; | 0 | ||||||||||||||||||||||||
1791 | } | - | ||||||||||||||||||||||||
1792 | - | |||||||||||||||||||||||||
1793 | Q_ASSERT(line.from < eng->layoutData->string.length()); | - | ||||||||||||||||||||||||
1794 | - | |||||||||||||||||||||||||
1795 | LineBreakHelper lbh; | - | ||||||||||||||||||||||||
1796 | - | |||||||||||||||||||||||||
1797 | lbh.maxGlyphs = maxGlyphs; | - | ||||||||||||||||||||||||
1798 | - | |||||||||||||||||||||||||
1799 | QTextOption::WrapMode wrapMode = eng->option.wrapMode(); | - | ||||||||||||||||||||||||
1800 | bool breakany = (wrapMode == QTextOption::WrapAnywhere); | - | ||||||||||||||||||||||||
1801 | lbh.manualWrap = (wrapMode == QTextOption::ManualWrap || wrapMode == QTextOption::NoWrap);
| 0 | ||||||||||||||||||||||||
1802 | - | |||||||||||||||||||||||||
1803 | int item = -1; | - | ||||||||||||||||||||||||
1804 | int newItem = eng->findItem(line.from); | - | ||||||||||||||||||||||||
1805 | Q_ASSERT(newItem >= 0); | - | ||||||||||||||||||||||||
1806 | - | |||||||||||||||||||||||||
1807 | LB_DEBUG("from: %d: item=%d, total %d, width available %f", line.from, newItem, eng->layoutData->items.size(), line.width.toReal()); dead code: QMessageLogger(__FILE__, 1807, __PRETTY_FUNCTION__).debug("from: %d: item=%d, total %d, width available %f", line.from, newItem, eng->layoutData->items.size(), line.width.toReal()); | - | ||||||||||||||||||||||||
1808 | - | |||||||||||||||||||||||||
1809 | Qt::Alignment alignment = eng->option.alignment(); | - | ||||||||||||||||||||||||
1810 | - | |||||||||||||||||||||||||
1811 | const QCharAttributes *attributes = eng->attributes(); | - | ||||||||||||||||||||||||
1812 | if (!attributes)
| 0 | ||||||||||||||||||||||||
1813 | return; never executed: return; | 0 | ||||||||||||||||||||||||
1814 | lbh.currentPosition = line.from; | - | ||||||||||||||||||||||||
1815 | int end = 0; | - | ||||||||||||||||||||||||
1816 | lbh.logClusters = eng->layoutData->logClustersPtr; | - | ||||||||||||||||||||||||
1817 | lbh.previousGlyph = 0; | - | ||||||||||||||||||||||||
1818 | - | |||||||||||||||||||||||||
1819 | while (newItem < eng->layoutData->items.size()) {
| 0 | ||||||||||||||||||||||||
1820 | lbh.resetRightBearing(); | - | ||||||||||||||||||||||||
1821 | lbh.softHyphenWidth = 0; | - | ||||||||||||||||||||||||
1822 | if (newItem != item) {
| 0 | ||||||||||||||||||||||||
1823 | item = newItem; | - | ||||||||||||||||||||||||
1824 | const QScriptItem ¤t = eng->layoutData->items[item]; | - | ||||||||||||||||||||||||
1825 | if (!current.num_glyphs) {
| 0 | ||||||||||||||||||||||||
1826 | eng->shape(item); | - | ||||||||||||||||||||||||
1827 | attributes = eng->attributes(); | - | ||||||||||||||||||||||||
1828 | if (!attributes)
| 0 | ||||||||||||||||||||||||
1829 | return; never executed: return; | 0 | ||||||||||||||||||||||||
1830 | lbh.logClusters = eng->layoutData->logClustersPtr; | - | ||||||||||||||||||||||||
1831 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1832 | lbh.currentPosition = qMax(line.from, current.position); | - | ||||||||||||||||||||||||
1833 | end = current.position + eng->length(item); | - | ||||||||||||||||||||||||
1834 | lbh.glyphs = eng->shapedGlyphs(¤t); | - | ||||||||||||||||||||||||
1835 | QFontEngine *fontEngine = eng->fontEngine(current); | - | ||||||||||||||||||||||||
1836 | if (lbh.fontEngine != fontEngine) {
| 0 | ||||||||||||||||||||||||
1837 | lbh.fontEngine = fontEngine; | - | ||||||||||||||||||||||||
1838 | lbh.minimumRightBearing = qMin(QFixed(), | - | ||||||||||||||||||||||||
1839 | QFixed::fromReal(fontEngine->minRightBearing())); | - | ||||||||||||||||||||||||
1840 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1841 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1842 | const QScriptItem ¤t = eng->layoutData->items[item]; | - | ||||||||||||||||||||||||
1843 | - | |||||||||||||||||||||||||
1844 | lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent, | - | ||||||||||||||||||||||||
1845 | current.leading + current.ascent) - qMax(lbh.tmpData.ascent, | - | ||||||||||||||||||||||||
1846 | current.ascent); | - | ||||||||||||||||||||||||
1847 | lbh.tmpData.ascent = qMax(lbh.tmpData.ascent, current.ascent); | - | ||||||||||||||||||||||||
1848 | lbh.tmpData.descent = qMax(lbh.tmpData.descent, current.descent); | - | ||||||||||||||||||||||||
1849 | - | |||||||||||||||||||||||||
1850 | if (current.analysis.flags == QScriptAnalysis::Tab && (alignment & (Qt::AlignLeft | Qt::AlignRight | Qt::AlignCenter | Qt::AlignJustify))) {
| 0 | ||||||||||||||||||||||||
1851 | lbh.whiteSpaceOrObject = true; | - | ||||||||||||||||||||||||
1852 | if (lbh.checkFullOtherwiseExtend(line))
| 0 | ||||||||||||||||||||||||
1853 | goto found; never executed: goto found; | 0 | ||||||||||||||||||||||||
1854 | - | |||||||||||||||||||||||||
1855 | QFixed x = line.x + line.textWidth + lbh.tmpData.textWidth + lbh.spaceData.textWidth; | - | ||||||||||||||||||||||||
1856 | QFixed tabWidth = eng->calculateTabWidth(item, x); | - | ||||||||||||||||||||||||
1857 | attributes = eng->attributes(); | - | ||||||||||||||||||||||||
1858 | if (!attributes)
| 0 | ||||||||||||||||||||||||
1859 | return; never executed: return; | 0 | ||||||||||||||||||||||||
1860 | lbh.logClusters = eng->layoutData->logClustersPtr; | - | ||||||||||||||||||||||||
1861 | lbh.glyphs = eng->shapedGlyphs(¤t); | - | ||||||||||||||||||||||||
1862 | - | |||||||||||||||||||||||||
1863 | lbh.spaceData.textWidth += tabWidth; | - | ||||||||||||||||||||||||
1864 | lbh.spaceData.length++; | - | ||||||||||||||||||||||||
1865 | newItem = item + 1; | - | ||||||||||||||||||||||||
1866 | - | |||||||||||||||||||||||||
1867 | QFixed averageCharWidth = eng->fontEngine(current)->averageCharWidth(); | - | ||||||||||||||||||||||||
1868 | lbh.glyphCount += qRound(tabWidth / averageCharWidth); | - | ||||||||||||||||||||||||
1869 | - | |||||||||||||||||||||||||
1870 | if (lbh.checkFullOtherwiseExtend(line))
| 0 | ||||||||||||||||||||||||
1871 | goto found; never executed: goto found; | 0 | ||||||||||||||||||||||||
1872 | } else if (current.analysis.flags == QScriptAnalysis::LineOrParagraphSeparator) { never executed: end of block
| 0 | ||||||||||||||||||||||||
1873 | lbh.whiteSpaceOrObject = true; | - | ||||||||||||||||||||||||
1874 | // if the line consists only of the line separator make sure | - | ||||||||||||||||||||||||
1875 | // we have a sane height | - | ||||||||||||||||||||||||
1876 | if (!line.length && !lbh.tmpData.length)
| 0 | ||||||||||||||||||||||||
1877 | line.setDefaultHeight(eng); never executed: line.setDefaultHeight(eng); | 0 | ||||||||||||||||||||||||
1878 | if (eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators) {
| 0 | ||||||||||||||||||||||||
1879 | if (lbh.checkFullOtherwiseExtend(line))
| 0 | ||||||||||||||||||||||||
1880 | goto found; never executed: goto found; | 0 | ||||||||||||||||||||||||
1881 | - | |||||||||||||||||||||||||
1882 | addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount, | - | ||||||||||||||||||||||||
1883 | current, lbh.logClusters, lbh.glyphs); | - | ||||||||||||||||||||||||
1884 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
1885 | lbh.tmpData.length++; | - | ||||||||||||||||||||||||
1886 | lbh.calculateRightBearingForPreviousGlyph(); | - | ||||||||||||||||||||||||
1887 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1888 | line += lbh.tmpData; | - | ||||||||||||||||||||||||
1889 | goto found; never executed: goto found; | 0 | ||||||||||||||||||||||||
1890 | } else if (current.analysis.flags == QScriptAnalysis::Object) {
| 0 | ||||||||||||||||||||||||
1891 | lbh.whiteSpaceOrObject = true; | - | ||||||||||||||||||||||||
1892 | lbh.tmpData.length++; | - | ||||||||||||||||||||||||
1893 | - | |||||||||||||||||||||||||
1894 | if (eng->block.docHandle()) {
| 0 | ||||||||||||||||||||||||
1895 | QTextInlineObject inlineObject(item, eng); | - | ||||||||||||||||||||||||
1896 | eng->docLayout()->positionInlineObject(inlineObject, eng->block.position() + current.position, inlineObject.format()); | - | ||||||||||||||||||||||||
1897 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1898 | - | |||||||||||||||||||||||||
1899 | lbh.tmpData.textWidth += current.width; | - | ||||||||||||||||||||||||
1900 | - | |||||||||||||||||||||||||
1901 | newItem = item + 1; | - | ||||||||||||||||||||||||
1902 | ++lbh.glyphCount; | - | ||||||||||||||||||||||||
1903 | if (lbh.checkFullOtherwiseExtend(line))
| 0 | ||||||||||||||||||||||||
1904 | goto found; never executed: goto found; | 0 | ||||||||||||||||||||||||
1905 | } else if (attributes[lbh.currentPosition].whiteSpace never executed: end of block
| 0 | ||||||||||||||||||||||||
1906 | && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak) {
| 0 | ||||||||||||||||||||||||
1907 | lbh.whiteSpaceOrObject = true; | - | ||||||||||||||||||||||||
1908 | while (lbh.currentPosition < end
| 0 | ||||||||||||||||||||||||
1909 | && attributes[lbh.currentPosition].whiteSpace
| 0 | ||||||||||||||||||||||||
1910 | && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak) {
| 0 | ||||||||||||||||||||||||
1911 | addNextCluster(lbh.currentPosition, end, lbh.spaceData, lbh.glyphCount, | - | ||||||||||||||||||||||||
1912 | current, lbh.logClusters, lbh.glyphs); | - | ||||||||||||||||||||||||
1913 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1914 | - | |||||||||||||||||||||||||
1915 | if (!lbh.manualWrap && lbh.spaceData.textWidth > line.width) {
| 0 | ||||||||||||||||||||||||
1916 | lbh.spaceData.textWidth = line.width; // ignore spaces that fall out of the line. | - | ||||||||||||||||||||||||
1917 | goto found; never executed: goto found; | 0 | ||||||||||||||||||||||||
1918 | } | - | ||||||||||||||||||||||||
1919 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
1920 | lbh.whiteSpaceOrObject = false; | - | ||||||||||||||||||||||||
1921 | bool sb_or_ws = false; | - | ||||||||||||||||||||||||
1922 | lbh.saveCurrentGlyph(); | - | ||||||||||||||||||||||||
1923 | do { | - | ||||||||||||||||||||||||
1924 | addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount, | - | ||||||||||||||||||||||||
1925 | current, lbh.logClusters, lbh.glyphs); | - | ||||||||||||||||||||||||
1926 | - | |||||||||||||||||||||||||
1927 | // This is a hack to fix a regression caused by the introduction of the | - | ||||||||||||||||||||||||
1928 | // whitespace flag to non-breakable spaces and will cause the non-breakable | - | ||||||||||||||||||||||||
1929 | // spaces to behave as in previous Qt versions in the line breaking algorithm. | - | ||||||||||||||||||||||||
1930 | // The line breaks do not currently follow the Unicode specs, but fixing this would | - | ||||||||||||||||||||||||
1931 | // require refactoring the code and would cause behavioral regressions. | - | ||||||||||||||||||||||||
1932 | bool isBreakableSpace = lbh.currentPosition < eng->layoutData->string.length()
| 0 | ||||||||||||||||||||||||
1933 | && attributes[lbh.currentPosition].whiteSpace
| 0 | ||||||||||||||||||||||||
1934 | && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak;
| 0 | ||||||||||||||||||||||||
1935 | - | |||||||||||||||||||||||||
1936 | if (lbh.currentPosition >= eng->layoutData->string.length()
| 0 | ||||||||||||||||||||||||
1937 | || isBreakableSpace
| 0 | ||||||||||||||||||||||||
1938 | || attributes[lbh.currentPosition].lineBreak) {
| 0 | ||||||||||||||||||||||||
1939 | sb_or_ws = true; | - | ||||||||||||||||||||||||
1940 | break; never executed: break; | 0 | ||||||||||||||||||||||||
1941 | } else if (breakany && attributes[lbh.currentPosition].graphemeBoundary) {
| 0 | ||||||||||||||||||||||||
1942 | break; never executed: break; | 0 | ||||||||||||||||||||||||
1943 | } | - | ||||||||||||||||||||||||
1944 | } while (lbh.currentPosition < end); never executed: end of block
| 0 | ||||||||||||||||||||||||
1945 | lbh.minw = qMax(lbh.tmpData.textWidth, lbh.minw); | - | ||||||||||||||||||||||||
1946 | - | |||||||||||||||||||||||||
1947 | if (lbh.currentPosition > 0 && lbh.currentPosition < end
| 0 | ||||||||||||||||||||||||
1948 | && attributes[lbh.currentPosition].lineBreak
| 0 | ||||||||||||||||||||||||
1949 | && eng->layoutData->string.at(lbh.currentPosition - 1).unicode() == QChar::SoftHyphen) {
| 0 | ||||||||||||||||||||||||
1950 | // if we are splitting up a word because of | - | ||||||||||||||||||||||||
1951 | // a soft hyphen then we ... | - | ||||||||||||||||||||||||
1952 | // | - | ||||||||||||||||||||||||
1953 | // a) have to take the width of the soft hyphen into | - | ||||||||||||||||||||||||
1954 | // account to see if the first syllable(s) /and/ | - | ||||||||||||||||||||||||
1955 | // the soft hyphen fit into the line | - | ||||||||||||||||||||||||
1956 | // | - | ||||||||||||||||||||||||
1957 | // b) if we are so short of available width that the | - | ||||||||||||||||||||||||
1958 | // soft hyphen is the first breakable position, then | - | ||||||||||||||||||||||||
1959 | // we don't want to show it. However we initially | - | ||||||||||||||||||||||||
1960 | // have to take the width for it into account so that | - | ||||||||||||||||||||||||
1961 | // the text document layout sees the overflow and | - | ||||||||||||||||||||||||
1962 | // switch to break-anywhere mode, in which we | - | ||||||||||||||||||||||||
1963 | // want the soft-hyphen to slip into the next line | - | ||||||||||||||||||||||||
1964 | // and thus become invisible again. | - | ||||||||||||||||||||||||
1965 | // | - | ||||||||||||||||||||||||
1966 | if (line.length)
| 0 | ||||||||||||||||||||||||
1967 | lbh.softHyphenWidth = lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]]; never executed: lbh.softHyphenWidth = lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]]; | 0 | ||||||||||||||||||||||||
1968 | else if (breakany)
| 0 | ||||||||||||||||||||||||
1969 | lbh.tmpData.textWidth += lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]]; never executed: lbh.tmpData.textWidth += lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]]; | 0 | ||||||||||||||||||||||||
1970 | } never executed: end of block | 0 | ||||||||||||||||||||||||
1971 | - | |||||||||||||||||||||||||
1972 | if (sb_or_ws|breakany) {
| 0 | ||||||||||||||||||||||||
1973 | // To compute the final width of the text we need to take negative right bearing | - | ||||||||||||||||||||||||
1974 | // into account (negative right bearing means the glyph has pixel data past the | - | ||||||||||||||||||||||||
1975 | // advance length). Note that the negative right bearing is an absolute number, | - | ||||||||||||||||||||||||
1976 | // so that we can apply it to the width using straight forward addition. | - | ||||||||||||||||||||||||
1977 | - | |||||||||||||||||||||||||
1978 | // Store previous right bearing (for the already accepted glyph) in case we | - | ||||||||||||||||||||||||
1979 | // end up breaking due to the current glyph being too wide. | - | ||||||||||||||||||||||||
1980 | QFixed previousRightBearing = lbh.rightBearing; | - | ||||||||||||||||||||||||
1981 | - | |||||||||||||||||||||||||
1982 | // We skip calculating the right bearing if the minimum negative bearing is too | - | ||||||||||||||||||||||||
1983 | // small to possibly expand the text beyond the edge. Note that this optimization | - | ||||||||||||||||||||||||
1984 | // will in some cases fail, as the minimum right bearing reported by the font | - | ||||||||||||||||||||||||
1985 | // engine may not cover all the glyphs in the font. The result is that we think | - | ||||||||||||||||||||||||
1986 | // we don't need to break at the current glyph (because the right bearing is 0), | - | ||||||||||||||||||||||||
1987 | // and when we then end up breaking on the next glyph we compute the right bearing | - | ||||||||||||||||||||||||
1988 | // and end up with a line width that is slightly larger width than what was requested. | - | ||||||||||||||||||||||||
1989 | // Unfortunately we can't remove this optimization as it will slow down text | - | ||||||||||||||||||||||||
1990 | // layouting significantly, so we accept the slight correctnes issue. | - | ||||||||||||||||||||||||
1991 | if ((lbh.calculateNewWidth(line) + qAbs(lbh.minimumRightBearing)) > line.width)
| 0 | ||||||||||||||||||||||||
1992 | lbh.calculateRightBearing(); never executed: lbh.calculateRightBearing(); | 0 | ||||||||||||||||||||||||
1993 | - | |||||||||||||||||||||||||
1994 | if (lbh.checkFullOtherwiseExtend(line)) {
| 0 | ||||||||||||||||||||||||
1995 | // We are too wide to accept the next glyph with its bearing, so we restore the | - | ||||||||||||||||||||||||
1996 | // right bearing to that of the previous glyph (the one that was already accepted), | - | ||||||||||||||||||||||||
1997 | // so that the bearing can be be applied to the final width of the text below. | - | ||||||||||||||||||||||||
1998 | if (previousRightBearing != LineBreakHelper::RightBearingNotCalculated)
| 0 | ||||||||||||||||||||||||
1999 | lbh.rightBearing = previousRightBearing; never executed: lbh.rightBearing = previousRightBearing; | 0 | ||||||||||||||||||||||||
2000 | else | - | ||||||||||||||||||||||||
2001 | lbh.calculateRightBearingForPreviousGlyph(); never executed: lbh.calculateRightBearingForPreviousGlyph(); | 0 | ||||||||||||||||||||||||
2002 | - | |||||||||||||||||||||||||
2003 | if (!breakany) {
| 0 | ||||||||||||||||||||||||
2004 | line.textWidth += lbh.softHyphenWidth; | - | ||||||||||||||||||||||||
2005 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2006 | - | |||||||||||||||||||||||||
2007 | goto found; never executed: goto found; | 0 | ||||||||||||||||||||||||
2008 | } | - | ||||||||||||||||||||||||
2009 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2010 | lbh.saveCurrentGlyph(); | - | ||||||||||||||||||||||||
2011 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2012 | if (lbh.currentPosition == end)
| 0 | ||||||||||||||||||||||||
2013 | newItem = item + 1; never executed: newItem = item + 1; | 0 | ||||||||||||||||||||||||
2014 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2015 | LB_DEBUG("reached end of line"); dead code: QMessageLogger(__FILE__, 2015, __PRETTY_FUNCTION__).debug("reached end of line"); | - | ||||||||||||||||||||||||
2016 | lbh.checkFullOtherwiseExtend(line); | - | ||||||||||||||||||||||||
2017 | found: code before this statement never executed: found: | 0 | ||||||||||||||||||||||||
2018 | line.textAdvance = line.textWidth; | - | ||||||||||||||||||||||||
2019 | - | |||||||||||||||||||||||||
2020 | // If right bearing has not been calculated yet, do that now | - | ||||||||||||||||||||||||
2021 | if (lbh.rightBearing == LineBreakHelper::RightBearingNotCalculated && !lbh.whiteSpaceOrObject)
| 0 | ||||||||||||||||||||||||
2022 | lbh.calculateRightBearing(); never executed: lbh.calculateRightBearing(); | 0 | ||||||||||||||||||||||||
2023 | - | |||||||||||||||||||||||||
2024 | // Then apply any negative right bearing | - | ||||||||||||||||||||||||
2025 | line.textWidth += lbh.negativeRightBearing(); | - | ||||||||||||||||||||||||
2026 | - | |||||||||||||||||||||||||
2027 | if (line.length == 0) {
| 0 | ||||||||||||||||||||||||
2028 | LB_DEBUG("no break available in line, adding temp: length %d, width %f, space: length %d, width %f", dead code: QMessageLogger(__FILE__, 2028, __PRETTY_FUNCTION__).debug("no break available in line, adding temp: length %d, width %f, space: length %d, width %f", lbh.tmpData.length, lbh.tmpData.textWidth.toReal(), lbh.spaceData.length, lbh.spaceData.textWidth.toReal()); | - | ||||||||||||||||||||||||
2029 | lbh.tmpData.length, lbh.tmpData.textWidth.toReal(), dead code: QMessageLogger(__FILE__, 2028, __PRETTY_FUNCTION__).debug("no break available in line, adding temp: length %d, width %f, space: length %d, width %f", lbh.tmpData.length, lbh.tmpData.textWidth.toReal(), lbh.spaceData.length, lbh.spaceData.textWidth.toReal()); | - | ||||||||||||||||||||||||
2030 | lbh.spaceData.length, lbh.spaceData.textWidth.toReal()); dead code: QMessageLogger(__FILE__, 2028, __PRETTY_FUNCTION__).debug("no break available in line, adding temp: length %d, width %f, space: length %d, width %f", lbh.tmpData.length, lbh.tmpData.textWidth.toReal(), lbh.spaceData.length, lbh.spaceData.textWidth.toReal()); | - | ||||||||||||||||||||||||
2031 | line += lbh.tmpData; | - | ||||||||||||||||||||||||
2032 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2033 | - | |||||||||||||||||||||||||
2034 | LB_DEBUG("line length = %d, ascent=%f, descent=%f, textWidth=%f (spacew=%f)", line.length, line.ascent.toReal(), dead code: QMessageLogger(__FILE__, 2034, __PRETTY_FUNCTION__).debug("line length = %d, ascent=%f, descent=%f, textWidth=%f (spacew=%f)", line.length, line.ascent.toReal(), line.descent.toReal(), line.textWidth.toReal(), lbh.spaceData.width.toReal()); | - | ||||||||||||||||||||||||
2035 | line.descent.toReal(), line.textWidth.toReal(), lbh.spaceData.width.toReal()); dead code: QMessageLogger(__FILE__, 2034, __PRETTY_FUNCTION__).debug("line length = %d, ascent=%f, descent=%f, textWidth=%f (spacew=%f)", line.length, line.ascent.toReal(), line.descent.toReal(), line.textWidth.toReal(), lbh.spaceData.width.toReal()); | - | ||||||||||||||||||||||||
2036 | LB_DEBUG(" : '%s'", eng->layoutData->string.mid(line.from, line.length).toUtf8().data()); dead code: QMessageLogger(__FILE__, 2036, __PRETTY_FUNCTION__).debug(" : '%s'", eng->layoutData->string.mid(line.from, line.length).toUtf8().data()); | - | ||||||||||||||||||||||||
2037 | - | |||||||||||||||||||||||||
2038 | if (lbh.manualWrap) {
| 0 | ||||||||||||||||||||||||
2039 | eng->minWidth = qMax(eng->minWidth, line.textWidth); | - | ||||||||||||||||||||||||
2040 | eng->maxWidth = qMax(eng->maxWidth, line.textWidth); | - | ||||||||||||||||||||||||
2041 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
2042 | eng->minWidth = qMax(eng->minWidth, lbh.minw); | - | ||||||||||||||||||||||||
2043 | eng->maxWidth += line.textWidth; | - | ||||||||||||||||||||||||
2044 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2045 | - | |||||||||||||||||||||||||
2046 | if (line.textWidth > 0 && item < eng->layoutData->items.size())
| 0 | ||||||||||||||||||||||||
2047 | eng->maxWidth += lbh.spaceData.textWidth; never executed: eng->maxWidth += lbh.spaceData.textWidth; | 0 | ||||||||||||||||||||||||
2048 | if (eng->option.flags() & QTextOption::IncludeTrailingSpaces)
| 0 | ||||||||||||||||||||||||
2049 | line.textWidth += lbh.spaceData.textWidth; never executed: line.textWidth += lbh.spaceData.textWidth; | 0 | ||||||||||||||||||||||||
2050 | if (lbh.spaceData.length) {
| 0 | ||||||||||||||||||||||||
2051 | line.trailingSpaces = lbh.spaceData.length; | - | ||||||||||||||||||||||||
2052 | line.hasTrailingSpaces = true; | - | ||||||||||||||||||||||||
2053 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2054 | - | |||||||||||||||||||||||||
2055 | line.justified = false; | - | ||||||||||||||||||||||||
2056 | line.gridfitted = false; | - | ||||||||||||||||||||||||
2057 | - | |||||||||||||||||||||||||
2058 | if (eng->option.wrapMode() == QTextOption::WrapAtWordBoundaryOrAnywhere) {
| 0 | ||||||||||||||||||||||||
2059 | if ((lbh.maxGlyphs != INT_MAX && lbh.glyphCount > lbh.maxGlyphs)
| 0 | ||||||||||||||||||||||||
2060 | || (lbh.maxGlyphs == INT_MAX && line.textWidth > line.width)) {
| 0 | ||||||||||||||||||||||||
2061 | - | |||||||||||||||||||||||||
2062 | eng->option.setWrapMode(QTextOption::WrapAnywhere); | - | ||||||||||||||||||||||||
2063 | line.length = 0; | - | ||||||||||||||||||||||||
2064 | line.textWidth = 0; | - | ||||||||||||||||||||||||
2065 | layout_helper(lbh.maxGlyphs); | - | ||||||||||||||||||||||||
2066 | eng->option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); | - | ||||||||||||||||||||||||
2067 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2068 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2069 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2070 | - | |||||||||||||||||||||||||
2071 | /*! | - | ||||||||||||||||||||||||
2072 | Moves the line to position \a pos. | - | ||||||||||||||||||||||||
2073 | */ | - | ||||||||||||||||||||||||
2074 | void QTextLine::setPosition(const QPointF &pos) | - | ||||||||||||||||||||||||
2075 | { | - | ||||||||||||||||||||||||
2076 | eng->lines[index].x = QFixed::fromReal(pos.x()); | - | ||||||||||||||||||||||||
2077 | eng->lines[index].y = QFixed::fromReal(pos.y()); | - | ||||||||||||||||||||||||
2078 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2079 | - | |||||||||||||||||||||||||
2080 | /*! | - | ||||||||||||||||||||||||
2081 | Returns the line's position relative to the text layout's position. | - | ||||||||||||||||||||||||
2082 | */ | - | ||||||||||||||||||||||||
2083 | QPointF QTextLine::position() const | - | ||||||||||||||||||||||||
2084 | { | - | ||||||||||||||||||||||||
2085 | return QPointF(eng->lines[index].x.toReal(), eng->lines[index].y.toReal()); never executed: return QPointF(eng->lines[index].x.toReal(), eng->lines[index].y.toReal()); | 0 | ||||||||||||||||||||||||
2086 | } | - | ||||||||||||||||||||||||
2087 | - | |||||||||||||||||||||||||
2088 | // ### DOC: I have no idea what this means/does. | - | ||||||||||||||||||||||||
2089 | // You create a text layout with a string of text. Once you laid | - | ||||||||||||||||||||||||
2090 | // it out, it contains a number of QTextLines. from() returns the position | - | ||||||||||||||||||||||||
2091 | // inside the text string where this line starts. If you e.g. has a | - | ||||||||||||||||||||||||
2092 | // text of "This is a string", laid out into two lines (the second | - | ||||||||||||||||||||||||
2093 | // starting at the word 'a'), layout.lineAt(0).from() == 0 and | - | ||||||||||||||||||||||||
2094 | // layout.lineAt(1).from() == 8. | - | ||||||||||||||||||||||||
2095 | /*! | - | ||||||||||||||||||||||||
2096 | Returns the start of the line from the beginning of the string | - | ||||||||||||||||||||||||
2097 | passed to the QTextLayout. | - | ||||||||||||||||||||||||
2098 | */ | - | ||||||||||||||||||||||||
2099 | int QTextLine::textStart() const | - | ||||||||||||||||||||||||
2100 | { | - | ||||||||||||||||||||||||
2101 | return eng->lines[index].from; never executed: return eng->lines[index].from; | 0 | ||||||||||||||||||||||||
2102 | } | - | ||||||||||||||||||||||||
2103 | - | |||||||||||||||||||||||||
2104 | /*! | - | ||||||||||||||||||||||||
2105 | Returns the length of the text in the line. | - | ||||||||||||||||||||||||
2106 | - | |||||||||||||||||||||||||
2107 | \sa naturalTextWidth() | - | ||||||||||||||||||||||||
2108 | */ | - | ||||||||||||||||||||||||
2109 | int QTextLine::textLength() const | - | ||||||||||||||||||||||||
2110 | { | - | ||||||||||||||||||||||||
2111 | if (eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators
| 0 | ||||||||||||||||||||||||
2112 | && eng->block.isValid() && index == eng->lines.count()-1) {
| 0 | ||||||||||||||||||||||||
2113 | return eng->lines[index].length - 1; never executed: return eng->lines[index].length - 1; | 0 | ||||||||||||||||||||||||
2114 | } | - | ||||||||||||||||||||||||
2115 | return eng->lines[index].length + eng->lines[index].trailingSpaces; never executed: return eng->lines[index].length + eng->lines[index].trailingSpaces; | 0 | ||||||||||||||||||||||||
2116 | } | - | ||||||||||||||||||||||||
2117 | - | |||||||||||||||||||||||||
2118 | static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const QTextCharFormat &chf, const QRectF &r) | - | ||||||||||||||||||||||||
2119 | { | - | ||||||||||||||||||||||||
2120 | QBrush c = chf.foreground(); | - | ||||||||||||||||||||||||
2121 | if (c.style() == Qt::NoBrush) {
| 0 | ||||||||||||||||||||||||
2122 | p->setPen(defaultPen); | - | ||||||||||||||||||||||||
2123 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2124 | - | |||||||||||||||||||||||||
2125 | QBrush bg = chf.background(); | - | ||||||||||||||||||||||||
2126 | if (bg.style() != Qt::NoBrush && !chf.property(SuppressBackground).toBool())
| 0 | ||||||||||||||||||||||||
2127 | p->fillRect(QRectF(qFloor(r.x()), qFloor(r.y()), r.width(), r.height()), bg); never executed: p->fillRect(QRectF(qFloor(r.x()), qFloor(r.y()), r.width(), r.height()), bg); | 0 | ||||||||||||||||||||||||
2128 | if (c.style() != Qt::NoBrush) {
| 0 | ||||||||||||||||||||||||
2129 | p->setPen(QPen(c, 0)); | - | ||||||||||||||||||||||||
2130 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2131 | - | |||||||||||||||||||||||||
2132 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2133 | - | |||||||||||||||||||||||||
2134 | #if !defined(QT_NO_RAWFONT) | - | ||||||||||||||||||||||||
2135 | static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, | - | ||||||||||||||||||||||||
2136 | const QGlyphLayout &glyphLayout, | - | ||||||||||||||||||||||||
2137 | const QPointF &pos, | - | ||||||||||||||||||||||||
2138 | const QGlyphRun::GlyphRunFlags &flags, | - | ||||||||||||||||||||||||
2139 | const QFixed &selectionX, | - | ||||||||||||||||||||||||
2140 | const QFixed &selectionWidth, | - | ||||||||||||||||||||||||
2141 | int glyphsStart, | - | ||||||||||||||||||||||||
2142 | int glyphsEnd, | - | ||||||||||||||||||||||||
2143 | unsigned short *logClusters, | - | ||||||||||||||||||||||||
2144 | int textPosition, | - | ||||||||||||||||||||||||
2145 | int textLength) | - | ||||||||||||||||||||||||
2146 | { | - | ||||||||||||||||||||||||
2147 | Q_ASSERT(logClusters != 0); | - | ||||||||||||||||||||||||
2148 | - | |||||||||||||||||||||||||
2149 | QGlyphRun glyphRun; | - | ||||||||||||||||||||||||
2150 | - | |||||||||||||||||||||||||
2151 | QGlyphRunPrivate *d = QGlyphRunPrivate::get(glyphRun); | - | ||||||||||||||||||||||||
2152 | - | |||||||||||||||||||||||||
2153 | int rangeStart = textPosition; | - | ||||||||||||||||||||||||
2154 | while (*logClusters != glyphsStart && rangeStart < textPosition + textLength) {
| 0 | ||||||||||||||||||||||||
2155 | ++logClusters; | - | ||||||||||||||||||||||||
2156 | ++rangeStart; | - | ||||||||||||||||||||||||
2157 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2158 | - | |||||||||||||||||||||||||
2159 | int rangeEnd = rangeStart; | - | ||||||||||||||||||||||||
2160 | while (*logClusters != glyphsEnd && rangeEnd < textPosition + textLength) {
| 0 | ||||||||||||||||||||||||
2161 | ++logClusters; | - | ||||||||||||||||||||||||
2162 | ++rangeEnd; | - | ||||||||||||||||||||||||
2163 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2164 | - | |||||||||||||||||||||||||
2165 | d->textRangeStart = rangeStart; | - | ||||||||||||||||||||||||
2166 | d->textRangeEnd = rangeEnd; | - | ||||||||||||||||||||||||
2167 | - | |||||||||||||||||||||||||
2168 | // Make a font for this particular engine | - | ||||||||||||||||||||||||
2169 | QRawFont font; | - | ||||||||||||||||||||||||
2170 | QRawFontPrivate *fontD = QRawFontPrivate::get(font); | - | ||||||||||||||||||||||||
2171 | fontD->setFontEngine(fontEngine); | - | ||||||||||||||||||||||||
2172 | - | |||||||||||||||||||||||||
2173 | QVarLengthArray<glyph_t> glyphsArray; | - | ||||||||||||||||||||||||
2174 | QVarLengthArray<QFixedPoint> positionsArray; | - | ||||||||||||||||||||||||
2175 | - | |||||||||||||||||||||||||
2176 | QTextItem::RenderFlags renderFlags; | - | ||||||||||||||||||||||||
2177 | if (flags.testFlag(QGlyphRun::Overline))
| 0 | ||||||||||||||||||||||||
2178 | renderFlags |= QTextItem::Overline; never executed: renderFlags |= QTextItem::Overline; | 0 | ||||||||||||||||||||||||
2179 | if (flags.testFlag(QGlyphRun::Underline))
| 0 | ||||||||||||||||||||||||
2180 | renderFlags |= QTextItem::Underline; never executed: renderFlags |= QTextItem::Underline; | 0 | ||||||||||||||||||||||||
2181 | if (flags.testFlag(QGlyphRun::StrikeOut))
| 0 | ||||||||||||||||||||||||
2182 | renderFlags |= QTextItem::StrikeOut; never executed: renderFlags |= QTextItem::StrikeOut; | 0 | ||||||||||||||||||||||||
2183 | if (flags.testFlag(QGlyphRun::RightToLeft))
| 0 | ||||||||||||||||||||||||
2184 | renderFlags |= QTextItem::RightToLeft; never executed: renderFlags |= QTextItem::RightToLeft; | 0 | ||||||||||||||||||||||||
2185 | - | |||||||||||||||||||||||||
2186 | fontEngine->getGlyphPositions(glyphLayout, QTransform(), renderFlags, glyphsArray, | - | ||||||||||||||||||||||||
2187 | positionsArray); | - | ||||||||||||||||||||||||
2188 | Q_ASSERT(glyphsArray.size() == positionsArray.size()); | - | ||||||||||||||||||||||||
2189 | - | |||||||||||||||||||||||||
2190 | qreal fontHeight = font.ascent() + font.descent(); | - | ||||||||||||||||||||||||
2191 | qreal minY = 0; | - | ||||||||||||||||||||||||
2192 | qreal maxY = 0; | - | ||||||||||||||||||||||||
2193 | QVector<quint32> glyphs; | - | ||||||||||||||||||||||||
2194 | glyphs.reserve(glyphsArray.size()); | - | ||||||||||||||||||||||||
2195 | QVector<QPointF> positions; | - | ||||||||||||||||||||||||
2196 | positions.reserve(glyphsArray.size()); | - | ||||||||||||||||||||||||
2197 | for (int i=0; i<glyphsArray.size(); ++i) {
| 0 | ||||||||||||||||||||||||
2198 | glyphs.append(glyphsArray.at(i) & 0xffffff); | - | ||||||||||||||||||||||||
2199 | - | |||||||||||||||||||||||||
2200 | QPointF position = positionsArray.at(i).toPointF() + pos; | - | ||||||||||||||||||||||||
2201 | positions.append(position); | - | ||||||||||||||||||||||||
2202 | - | |||||||||||||||||||||||||
2203 | if (i == 0) {
| 0 | ||||||||||||||||||||||||
2204 | maxY = minY = position.y(); | - | ||||||||||||||||||||||||
2205 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
2206 | minY = qMin(minY, position.y()); | - | ||||||||||||||||||||||||
2207 | maxY = qMax(maxY, position.y()); | - | ||||||||||||||||||||||||
2208 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2209 | } | - | ||||||||||||||||||||||||
2210 | - | |||||||||||||||||||||||||
2211 | qreal height = maxY + fontHeight - minY; | - | ||||||||||||||||||||||||
2212 | - | |||||||||||||||||||||||||
2213 | glyphRun.setGlyphIndexes(glyphs); | - | ||||||||||||||||||||||||
2214 | glyphRun.setPositions(positions); | - | ||||||||||||||||||||||||
2215 | glyphRun.setFlags(flags); | - | ||||||||||||||||||||||||
2216 | glyphRun.setRawFont(font); | - | ||||||||||||||||||||||||
2217 | - | |||||||||||||||||||||||||
2218 | glyphRun.setBoundingRect(QRectF(selectionX.toReal(), minY - font.ascent(), | - | ||||||||||||||||||||||||
2219 | selectionWidth.toReal(), height)); | - | ||||||||||||||||||||||||
2220 | - | |||||||||||||||||||||||||
2221 | return glyphRun; never executed: return glyphRun; | 0 | ||||||||||||||||||||||||
2222 | } | - | ||||||||||||||||||||||||
2223 | - | |||||||||||||||||||||||||
2224 | /*! | - | ||||||||||||||||||||||||
2225 | Returns the glyph indexes and positions for all glyphs in this QTextLine for characters | - | ||||||||||||||||||||||||
2226 | in the range defined by \a from and \a length. The \a from index is relative to the beginning | - | ||||||||||||||||||||||||
2227 | of the text in the containing QTextLayout, and the range must be within the range of QTextLine | - | ||||||||||||||||||||||||
2228 | as given by functions textStart() and textLength(). | - | ||||||||||||||||||||||||
2229 | - | |||||||||||||||||||||||||
2230 | If \a from is negative, it will default to textStart(), and if \a length is negative it will | - | ||||||||||||||||||||||||
2231 | default to the return value of textLength(). | - | ||||||||||||||||||||||||
2232 | - | |||||||||||||||||||||||||
2233 | \since 5.0 | - | ||||||||||||||||||||||||
2234 | - | |||||||||||||||||||||||||
2235 | \sa QTextLayout::glyphRuns() | - | ||||||||||||||||||||||||
2236 | */ | - | ||||||||||||||||||||||||
2237 | QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const | - | ||||||||||||||||||||||||
2238 | { | - | ||||||||||||||||||||||||
2239 | const QScriptLine &line = eng->lines[index]; | - | ||||||||||||||||||||||||
2240 | - | |||||||||||||||||||||||||
2241 | if (line.length == 0)
| 0 | ||||||||||||||||||||||||
2242 | return QList<QGlyphRun>(); never executed: return QList<QGlyphRun>(); | 0 | ||||||||||||||||||||||||
2243 | - | |||||||||||||||||||||||||
2244 | if (from < 0)
| 0 | ||||||||||||||||||||||||
2245 | from = textStart(); never executed: from = textStart(); | 0 | ||||||||||||||||||||||||
2246 | - | |||||||||||||||||||||||||
2247 | if (length < 0)
| 0 | ||||||||||||||||||||||||
2248 | length = textLength(); never executed: length = textLength(); | 0 | ||||||||||||||||||||||||
2249 | - | |||||||||||||||||||||||||
2250 | if (length == 0)
| 0 | ||||||||||||||||||||||||
2251 | return QList<QGlyphRun>(); never executed: return QList<QGlyphRun>(); | 0 | ||||||||||||||||||||||||
2252 | - | |||||||||||||||||||||||||
2253 | QTextLayout::FormatRange selection; | - | ||||||||||||||||||||||||
2254 | selection.start = from; | - | ||||||||||||||||||||||||
2255 | selection.length = length; | - | ||||||||||||||||||||||||
2256 | - | |||||||||||||||||||||||||
2257 | QTextLineItemIterator iterator(eng, index, QPointF(), &selection); | - | ||||||||||||||||||||||||
2258 | qreal y = line.y.toReal() + line.base().toReal(); | - | ||||||||||||||||||||||||
2259 | QList<QGlyphRun> glyphRuns; | - | ||||||||||||||||||||||||
2260 | while (!iterator.atEnd()) {
| 0 | ||||||||||||||||||||||||
2261 | QScriptItem &si = iterator.next(); | - | ||||||||||||||||||||||||
2262 | if (si.analysis.flags >= QScriptAnalysis::TabOrObject)
| 0 | ||||||||||||||||||||||||
2263 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
2264 | - | |||||||||||||||||||||||||
2265 | if (from >= 0 && length >= 0 && (from >= iterator.itemEnd || from + length <= iterator.itemStart))
| 0 | ||||||||||||||||||||||||
2266 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
2267 | - | |||||||||||||||||||||||||
2268 | QPointF pos(iterator.x.toReal(), y); | - | ||||||||||||||||||||||||
2269 | - | |||||||||||||||||||||||||
2270 | QFont font; | - | ||||||||||||||||||||||||
2271 | QGlyphRun::GlyphRunFlags flags; | - | ||||||||||||||||||||||||
2272 | if (!eng->useRawFont) {
| 0 | ||||||||||||||||||||||||
2273 | font = eng->font(si); | - | ||||||||||||||||||||||||
2274 | if (font.overline())
| 0 | ||||||||||||||||||||||||
2275 | flags |= QGlyphRun::Overline; never executed: flags |= QGlyphRun::Overline; | 0 | ||||||||||||||||||||||||
2276 | if (font.underline())
| 0 | ||||||||||||||||||||||||
2277 | flags |= QGlyphRun::Underline; never executed: flags |= QGlyphRun::Underline; | 0 | ||||||||||||||||||||||||
2278 | if (font.strikeOut())
| 0 | ||||||||||||||||||||||||
2279 | flags |= QGlyphRun::StrikeOut; never executed: flags |= QGlyphRun::StrikeOut; | 0 | ||||||||||||||||||||||||
2280 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2281 | - | |||||||||||||||||||||||||
2282 | bool rtl = false; | - | ||||||||||||||||||||||||
2283 | if (si.analysis.bidiLevel % 2) {
| 0 | ||||||||||||||||||||||||
2284 | flags |= QGlyphRun::RightToLeft; | - | ||||||||||||||||||||||||
2285 | rtl = true; | - | ||||||||||||||||||||||||
2286 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2287 | - | |||||||||||||||||||||||||
2288 | int relativeFrom = qMax(iterator.itemStart, from) - si.position; | - | ||||||||||||||||||||||||
2289 | int relativeTo = qMin(iterator.itemEnd, from + length) - 1 - si.position; | - | ||||||||||||||||||||||||
2290 | - | |||||||||||||||||||||||||
2291 | unsigned short *logClusters = eng->logClusters(&si); | - | ||||||||||||||||||||||||
2292 | int glyphsStart = logClusters[relativeFrom]; | - | ||||||||||||||||||||||||
2293 | int glyphsEnd = (relativeTo == iterator.itemLength) ? si.num_glyphs - 1 : logClusters[relativeTo];
| 0 | ||||||||||||||||||||||||
2294 | // the glyph index right next to the requested range | - | ||||||||||||||||||||||||
2295 | int nextGlyphIndex = (relativeTo < iterator.itemLength - 1) ? logClusters[relativeTo + 1] : si.num_glyphs;
| 0 | ||||||||||||||||||||||||
2296 | if (nextGlyphIndex - 1 > glyphsEnd)
| 0 | ||||||||||||||||||||||||
2297 | glyphsEnd = nextGlyphIndex - 1; never executed: glyphsEnd = nextGlyphIndex - 1; | 0 | ||||||||||||||||||||||||
2298 | bool startsInsideLigature = relativeFrom > 0 && logClusters[relativeFrom - 1] == glyphsStart;
| 0 | ||||||||||||||||||||||||
2299 | bool endsInsideLigature = nextGlyphIndex == glyphsEnd; | - | ||||||||||||||||||||||||
2300 | - | |||||||||||||||||||||||||
2301 | int itemGlyphsStart = logClusters[iterator.itemStart - si.position]; | - | ||||||||||||||||||||||||
2302 | int itemGlyphsEnd = logClusters[iterator.itemEnd - 1 - si.position]; | - | ||||||||||||||||||||||||
2303 | - | |||||||||||||||||||||||||
2304 | QGlyphLayout glyphLayout = eng->shapedGlyphs(&si); | - | ||||||||||||||||||||||||
2305 | - | |||||||||||||||||||||||||
2306 | // Calculate new x position of glyph layout for a subset. This becomes somewhat complex | - | ||||||||||||||||||||||||
2307 | // when we're breaking a RTL script item, since the expected position passed into | - | ||||||||||||||||||||||||
2308 | // getGlyphPositions() is the left-most edge of the left-most glyph in an RTL run. | - | ||||||||||||||||||||||||
2309 | if (relativeFrom != (iterator.itemStart - si.position) && !rtl) {
| 0 | ||||||||||||||||||||||||
2310 | for (int i=itemGlyphsStart; i<glyphsStart; ++i) {
| 0 | ||||||||||||||||||||||||
2311 | QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6); | - | ||||||||||||||||||||||||
2312 | pos.rx() += (glyphLayout.advances[i] + justification).toReal(); | - | ||||||||||||||||||||||||
2313 | } never executed: end of block | 0 | ||||||||||||||||||||||||
2314 | } else if (relativeTo != (iterator.itemEnd - si.position - 1) && rtl) { never executed: end of block
|