OpenCoverage

qtextlayout.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/text/qtextlayout.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
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-
64QT_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*/-
157QRectF 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*/-
168qreal 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*/-
178qreal 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*/-
188qreal 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*/-
199qreal 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*/-
209void 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*/-
219void 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*/-
229void 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*/-
237int 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*/-
246int 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*/-
254QTextFormat 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*/-
262Qt::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*/-
334QTextLayout::QTextLayout()-
335{
never executed: end of block
d = new QTextEngine(); }
never executed: end of block
0
336-
337/*!-
338 Constructs a text layout to lay out the given \a text.-
339*/-
340QTextLayout::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*/-
354QTextLayout::QTextLayout(const QString& text, const QFont &font, QPaintDevice *paintdevice)-
355{-
356 QFont f(font);-
357 if (paintdevice)
paintdeviceDescription
TRUEnever evaluated
FALSEnever evaluated
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*/-
366QTextLayout::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*/-
375QTextLayout::~QTextLayout()-
376{-
377 if (!d->stackEngine)
!d->stackEngineDescription
TRUEnever evaluated
FALSEnever evaluated
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*/-
389void 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*/-
403void 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*/-
418QFont 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*/-
432void 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*/-
444QString 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*/-
455void 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*/-
465const 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*/-
477void QTextLayout::setPreeditArea(int position, const QString &text)-
478{-
479 if (d->preeditAreaPosition() == position && d->preeditAreaText() == text)
d->preeditArea...() == positionDescription
TRUEnever evaluated
FALSEnever evaluated
d->preeditAreaText() == textDescription
TRUEnever evaluated
FALSEnever evaluated
0
480 return;
never executed: return;
0
481 d->setPreeditArea(position, text);-
482-
483 if (d->block.docHandle())
d->block.docHandle()Description
TRUEnever evaluated
FALSEnever evaluated
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*/-
493int 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*/-
503QString 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*/-
512void 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*/-
526void QTextLayout::setFormats(const QVector<FormatRange> &formats)-
527{-
528 d->setFormats(formats);-
529-
530 if (d->block.docHandle())
d->block.docHandle()Description
TRUEnever evaluated
FALSEnever evaluated
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*/-
540QList<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*/-
553QVector<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*/-
562void 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*/-
575void 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*/-
590void 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*/-
601bool 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*/-
614void 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*/-
625Qt::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*/-
635void QTextLayout::beginLayout()-
636{-
637#ifndef QT_NO_DEBUG-
638 if (d->layoutData && d->layoutData->layoutState == QTextEngine::InLayout) {
d->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
d->layoutData-...gine::InLayoutDescription
TRUEnever evaluated
FALSEnever evaluated
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*/-
654void QTextLayout::endLayout()-
655{-
656#ifndef QT_NO_DEBUG-
657 if (!d->layoutData || d->layoutData->layoutState == QTextEngine::LayoutEmpty) {
!d->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
d->layoutData-...e::LayoutEmptyDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
lDescription
TRUEnever evaluated
FALSEnever evaluated
d->lines.at(l-1).length < 0Description
TRUEnever evaluated
FALSEnever evaluated
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)
!d->cacheGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
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*/-
677void 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*/-
689int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const-
690{-
691 const QCharAttributes *attributes = d->attributes();-
692 int len = d->block.isValid() ? d->block.length() - 1
d->block.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
693 : d->layoutData->string.length();-
694 Q_ASSERT(len <= d->layoutData->string.length());-
695 if (!attributes || oldPos < 0 || oldPos >= len)
!attributesDescription
TRUEnever evaluated
FALSEnever evaluated
oldPos < 0Description
TRUEnever evaluated
FALSEnever evaluated
oldPos >= lenDescription
TRUEnever evaluated
FALSEnever evaluated
0
696 return oldPos;
never executed: return oldPos;
0
697-
698 if (mode == SkipCharacters) {
mode == SkipCharactersDescription
TRUEnever evaluated
FALSEnever evaluated
0
699 oldPos++;-
700 while (oldPos < len && !attributes[oldPos].graphemeBoundary)
oldPos < lenDescription
TRUEnever evaluated
FALSEnever evaluated
!attributes[ol...aphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
701 oldPos++;
never executed: oldPos++;
0
702 } else {
never executed: end of block
0
703 if (oldPos < len && d->atWordSeparator(oldPos)) {
oldPos < lenDescription
TRUEnever evaluated
FALSEnever evaluated
d->atWordSeparator(oldPos)Description
TRUEnever evaluated
FALSEnever evaluated
0
704 oldPos++;-
705 while (oldPos < len && d->atWordSeparator(oldPos))
oldPos < lenDescription
TRUEnever evaluated
FALSEnever evaluated
d->atWordSeparator(oldPos)Description
TRUEnever evaluated
FALSEnever evaluated
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))
oldPos < lenDescription
TRUEnever evaluated
FALSEnever evaluated
!attributes[oldPos].whiteSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
!d->atWordSeparator(oldPos)Description
TRUEnever evaluated
FALSEnever evaluated
0
709 oldPos++;
never executed: oldPos++;
0
710 }
never executed: end of block
0
711 while (oldPos < len && attributes[oldPos].whiteSpace)
oldPos < lenDescription
TRUEnever evaluated
FALSEnever evaluated
attributes[oldPos].whiteSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
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*/-
725int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const-
726{-
727 const QCharAttributes *attributes = d->attributes();-
728 int len = d->block.isValid() ? d->block.length() - 1
d->block.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
729 : d->layoutData->string.length();-
730 Q_ASSERT(len <= d->layoutData->string.length());-
731 if (!attributes || oldPos <= 0 || oldPos > len)
!attributesDescription
TRUEnever evaluated
FALSEnever evaluated
oldPos <= 0Description
TRUEnever evaluated
FALSEnever evaluated
oldPos > lenDescription
TRUEnever evaluated
FALSEnever evaluated
0
732 return oldPos;
never executed: return oldPos;
0
733-
734 if (mode == SkipCharacters) {
mode == SkipCharactersDescription
TRUEnever evaluated
FALSEnever evaluated
0
735 oldPos--;-
736 while (oldPos && !attributes[oldPos].graphemeBoundary)
oldPosDescription
TRUEnever evaluated
FALSEnever evaluated
!attributes[ol...aphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
737 oldPos--;
never executed: oldPos--;
0
738 } else {
never executed: end of block
0
739 while (oldPos > 0 && attributes[oldPos - 1].whiteSpace)
oldPos > 0Description
TRUEnever evaluated
FALSEnever evaluated
attributes[old... 1].whiteSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
740 oldPos--;
never executed: oldPos--;
0
741-
742 if (oldPos && d->atWordSeparator(oldPos-1)) {
oldPosDescription
TRUEnever evaluated
FALSEnever evaluated
d->atWordSeparator(oldPos-1)Description
TRUEnever evaluated
FALSEnever evaluated
0
743 oldPos--;-
744 while (oldPos && d->atWordSeparator(oldPos-1))
oldPosDescription
TRUEnever evaluated
FALSEnever evaluated
d->atWordSeparator(oldPos-1)Description
TRUEnever evaluated
FALSEnever evaluated
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))
oldPos > 0Description
TRUEnever evaluated
FALSEnever evaluated
!attributes[ol... 1].whiteSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
!d->atWordSeparator(oldPos-1)Description
TRUEnever evaluated
FALSEnever evaluated
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*/-
762int 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*/-
776int 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*/-
798bool QTextLayout::isValidCursorPosition(int pos) const-
799{-
800 const QCharAttributes *attributes = d->attributes();-
801 if (!attributes || pos < 0 || pos > (int)d->layoutData->string.length())
!attributesDescription
TRUEnever evaluated
FALSEnever evaluated
pos < 0Description
TRUEnever evaluated
FALSEnever evaluated
pos > (int)d->...tring.length()Description
TRUEnever evaluated
FALSEnever evaluated
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*/-
822QTextLine QTextLayout::createLine()-
823{-
824#ifndef QT_NO_DEBUG-
825 if (!d->layoutData || d->layoutData->layoutState == QTextEngine::LayoutEmpty) {
!d->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
d->layoutData-...e::LayoutEmptyDescription
TRUEnever evaluated
FALSEnever evaluated
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)
d->layoutData-...::LayoutFailedDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
lDescription
TRUEnever evaluated
FALSEnever evaluated
d->lines.at(l-1).length < 0Description
TRUEnever evaluated
FALSEnever evaluated
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;
l > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
838 int strlen = d->layoutData->string.length();-
839 if (l && from >= strlen) {
lDescription
TRUEnever evaluated
FALSEnever evaluated
from >= strlenDescription
TRUEnever evaluated
FALSEnever evaluated
0
840 if (!d->lines.at(l-1).length || d->layoutData->string.at(strlen - 1) != QChar::LineSeparator)
!d->lines.at(l-1).lengthDescription
TRUEnever evaluated
FALSEnever evaluated
d->layoutData-...:LineSeparatorDescription
TRUEnever evaluated
FALSEnever evaluated
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*/-
859int 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*/-
869QTextLine 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*/-
879QTextLine 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*/-
893QPointF 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*/-
903void 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*/-
911QRectF QTextLayout::boundingRect() const-
912{-
913 if (d->lines.isEmpty())
d->lines.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
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) {
i < d->lines.size()Description
TRUEnever evaluated
FALSEnever evaluated
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;
si.width < (2147483647/256)Description
TRUEnever evaluated
FALSEnever evaluated
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*/-
941qreal 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*/-
955qreal QTextLayout::maximumWidth() const-
956{-
957 return d->maxWidth.toReal();
never executed: return d->maxWidth.toReal();
0
958}-
959-
960-
961/*!-
962 \internal-
963*/-
964void QTextLayout::setFlags(int flags)-
965{-
966 if (flags & Qt::TextJustificationForced) {
flags & Qt::Te...ficationForcedDescription
TRUEnever evaluated
FALSEnever evaluated
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)) {
flags & (Qt::T...ceRightToLeft)Description
TRUEnever evaluated
FALSEnever evaluated
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-
977static 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()) {
!iterator.atEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
993 iterator.next();-
994-
995 QFixed selectionX, selectionWidth;-
996 if (iterator.getSelectionBounds(&selectionX, &selectionWidth)) {
iterator.getSe...electionWidth)Description
TRUEnever evaluated
FALSEnever evaluated
0
997 if (selectionX == lastSelectionX + lastSelectionWidth) {
selectionX == ...SelectionWidthDescription
TRUEnever evaluated
FALSEnever evaluated
0
998 lastSelectionWidth += selectionWidth;-
999 continue;
never executed: continue;
0
1000 }-
1001-
1002 if (lastSelectionWidth > 0) {
lastSelectionWidth > 0Description
TRUEnever evaluated
FALSEnever evaluated
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) {
lastSelectionWidth > 0Description
TRUEnever evaluated
FALSEnever evaluated
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-
1021static 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)-
1040QList<QGlyphRun> QTextLayout::glyphRuns(int from, int length) const-
1041{-
1042 if (from < 0)
from < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1043 from = 0;
never executed: from = 0;
0
1044 if (length < 0)
length < 0Description
TRUEnever evaluated
FALSEnever evaluated
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) {
i<d->lines.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1049 if (d->lines[i].from > from + length)
d->lines[i].fr... from + lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1050 break;
never executed: break;
0
1051 else if (d->lines[i].from + d->lines[i].length >= from) {
d->lines[i].fr...length >= fromDescription
TRUEnever evaluated
FALSEnever evaluated
0
1052 QList<QGlyphRun> glyphRuns = QTextLine(i, d).glyphRuns(from, length);-
1053-
1054 for (int j = 0; j < glyphRuns.size(); j++) {
j < glyphRuns.size()Description
TRUEnever evaluated
FALSEnever evaluated
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)) {
glyphRunHash.contains(key)Description
TRUEnever evaluated
FALSEnever evaluated
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*/-
1092void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRange> &selections, const QRectF &clip) const-
1093{-
1094 if (d->lines.isEmpty())
d->lines.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1095 return;
never executed: return;
0
1096-
1097 if (!d->layoutData)
!d->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
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()) {
clip.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
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) {
i < d->lines.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1112 QTextLine l(i, d);-
1113 const QScriptLine &sl = d->lines[i];-
1114-
1115 if (sl.y > clipe) {
sl.y > clipeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1116 lastLine = i;-
1117 break;
never executed: break;
0
1118 }-
1119 if ((sl.y + sl.height()) < clipy) {
(sl.y + sl.height()) < clipyDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
i < selections.size()Description
TRUEnever evaluated
FALSEnever evaluated
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) {
line < lastLineDescription
TRUEnever evaluated
FALSEnever evaluated
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
isLastLineInBlockDescription
TRUEnever evaluated
FALSEnever evaluated
0
1144-
1145-
1146 if (sl.from > selection.start + selection.length || sl.from + sl_length <= selection.start)
sl.from > sele...lection.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
sl.from + sl_l...election.startDescription
TRUEnever evaluated
FALSEnever evaluated
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)) {
sl.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
selectionStartInLineDescription
TRUEnever evaluated
FALSEnever evaluated
selectionEndInLineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1153 addSelectedRegionsToPath(d, line, position, &selection, &region, 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)) {
selection.form...idthSelection)Description
TRUEnever evaluated
FALSEnever evaluated
0
1159 QRectF fullLineRect(tl.rect());-
1160 fullLineRect.translate(position);-
1161 fullLineRect.setRight(QFIXED_MAX);-
1162 if (!selectionEndInLine)
!selectionEndInLineDescription
TRUEnever evaluated
FALSEnever evaluated
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)
!selectionStartInLineDescription
TRUEnever evaluated
FALSEnever evaluated
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
!selectionEndInLineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1167 && isLastLineInBlock
isLastLineInBlockDescription
TRUEnever evaluated
FALSEnever evaluated
0
1168 &&!(d->option.flags() & QTextOption::ShowLineAndParagraphSeparators)) {
!(d->option.fl...aphSeparators)Description
TRUEnever evaluated
FALSEnever evaluated
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) {
hasBackgroundDescription
TRUEnever evaluated
FALSEnever evaluated
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())
hasTextDescription
TRUEnever evaluated
FALSEnever evaluated
!hasBackgroundDescription
TRUEnever evaluated
FALSEnever evaluated
!(textDoneRegi...ion).isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
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) {
line < lastLineDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
hasTextDescription
TRUEnever evaluated
FALSEnever evaluated
0
1214 textDoneRegion += region;-
1215 } else {
never executed: end of block
0
1216 if (hasBackground)
hasBackgroundDescription
TRUEnever evaluated
FALSEnever evaluated
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()){
!needsTextButN...ound.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
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) {
line < lastLineDescription
TRUEnever evaluated
FALSEnever evaluated
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()) {
!excludedRegion.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1239 p->save();-
1240 QPainterPath path;-
1241 QRectF br = boundingRect().translated(position);-
1242 br.setRight(QFIXED_MAX);-
1243 if (!clip.isNull())
!clip.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
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) {
i < lastLineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1251 QTextLine l(i, d);-
1252 l.draw(p, position);-
1253 }
never executed: end of block
0
1254 if (!excludedRegion.isEmpty())
!excludedRegion.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1255 p->restore();
never executed: p->restore();
0
1256-
1257-
1258 if (!d->cacheGlyphs)
!d->cacheGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
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*/-
1270void 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*/-
1282void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition, int width) const-
1283{-
1284 if (d->lines.isEmpty())
d->lines.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1285 return;
never executed: return;
0
1286-
1287 if (!d->layoutData)
!d->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
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)
line < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1295 line = 0;
never executed: line = 0;
0
1296 if (line >= d->lines.size())
line >= d->lines.size()Description
TRUEnever evaluated
FALSEnever evaluated
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()) {
d->visualCursorMovement()Description
TRUEnever evaluated
FALSEnever evaluated
0
1307 if (cursorPosition == sl.from + sl.length)
cursorPosition...om + sl.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
itm >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1317 const QScriptItem &si = d->layoutData->items.at(itm);-
1318 if (si.ascent > 0)
si.ascent > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1319 base = si.ascent;
never executed: base = si.ascent;
0
1320 if (si.descent > 0)
si.descent > 0Description
TRUEnever evaluated
FALSEnever evaluated
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)
!(p->renderHin...:Antialiasing)Description
TRUEnever evaluated
FALSEnever evaluated
0
1326 && (p->transform().type() > QTransform::TxTranslate);
(p->transform(...::TxTranslate)Description
TRUEnever evaluated
FALSEnever evaluated
0
1327 if (toggleAntialiasing)
toggleAntialiasingDescription
TRUEnever evaluated
FALSEnever evaluated
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)
toggleAntialiasingDescription
TRUEnever evaluated
FALSEnever evaluated
0
1331 p->setRenderHint(QPainter::Antialiasing, false);
never executed: p->setRenderHint(QPainter::Antialiasing, false);
0
1332 if (d->layoutData->hasBidi) {
d->layoutData->hasBidiDescription
TRUEnever evaluated
FALSEnever evaluated
0
1333 const int arrow_extent = 4;-
1334 int sign = rightToLeft ? -1 : 1;
rightToLeftDescription
TRUEnever evaluated
FALSEnever evaluated
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*/-
1407QRectF 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*/-
1416QRectF 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)
sl.justifiedDescription
TRUEnever evaluated
FALSEnever evaluated
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*/-
1433qreal 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*/-
1443qreal 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*/-
1453qreal 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*/-
1464qreal 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*/-
1474qreal 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*/-
1486qreal 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*/-
1498qreal 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*/-
1517void 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*/-
1533bool 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*/-
1543qreal 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*/-
1558qreal 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*/-
1570void QTextLine::setLineWidth(qreal width)-
1571{-
1572 QScriptLine &line = eng->lines[index];-
1573 if (!eng->layoutData) {
!eng->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
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)
width > (2147483647/256)Description
TRUEnever evaluated
FALSEnever evaluated
0
1579 width = QFIXED_MAX;
never executed: width = (2147483647/256);
0
1580-
1581 line.width = QFixed::fromReal(width);-
1582 if (line.length
line.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1583 && line.textWidth <= line.width
line.textWidth <= line.widthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1584 && line.from + line.length == eng->layoutData->string.length())
line.from + li...tring.length()Description
TRUEnever evaluated
FALSEnever evaluated
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*/-
1601void 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*/-
1618void 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-
1633namespace {-
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 &&
currentPosition > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1684 logClusters[currentPosition - 1] < glyphs.numGlyphs) {
logClusters[cu...yphs.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
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)
currentPosition <= 0Description
TRUEnever evaluated
FALSEnever evaluated
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)
previousGlyph > 0Description
TRUEnever evaluated
FALSEnever evaluated
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)
rightBearing =...gNotCalculatedDescription
TRUEnever evaluated
FALSEnever evaluated
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-
1732const QFixed LineBreakHelper::RightBearingNotCalculated = QFixed(1);-
1733-
1734inline 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))
line.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
!manualWrapDescription
TRUEnever evaluated
FALSEnever evaluated
newWidth > line.widthDescription
TRUEnever evaluated
FALSEnever evaluated
glyphCount > maxGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
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-
1758static inline void addNextCluster(int &pos, int end, QScriptLine &line, int &glyphCount,-
1759 const QScriptItem &current, 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
pos < endDescription
TRUEnever evaluated
FALSEnever evaluated
logClusters[po... glyphPositionDescription
TRUEnever evaluated
FALSEnever evaluated
0
1767 do { // calculate the textWidth for the rest of the current cluster.-
1768 if (!glyphs.attributes[glyphPosition].dontPrint)
!glyphs.attrib...ion].dontPrintDescription
TRUEnever evaluated
FALSEnever evaluated
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
glyphPosition ...ent.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
!glyphs.attrib...].clusterStartDescription
TRUEnever evaluated
FALSEnever evaluated
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-
1780void 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()) {
!eng->layoutData->items.size()Description
TRUEnever evaluated
FALSEnever evaluated
line.from >= e...tring.length()Description
TRUEnever evaluated
FALSEnever evaluated
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);
wrapMode == QT...on::ManualWrapDescription
TRUEnever evaluated
FALSEnever evaluated
wrapMode == QT...Option::NoWrapDescription
TRUEnever evaluated
FALSEnever evaluated
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)
!attributesDescription
TRUEnever evaluated
FALSEnever evaluated
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()) {
newItem < eng-...->items.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1820 lbh.resetRightBearing();-
1821 lbh.softHyphenWidth = 0;-
1822 if (newItem != item) {
newItem != itemDescription
TRUEnever evaluated
FALSEnever evaluated
0
1823 item = newItem;-
1824 const QScriptItem &current = eng->layoutData->items[item];-
1825 if (!current.num_glyphs) {
!current.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1826 eng->shape(item);-
1827 attributes = eng->attributes();-
1828 if (!attributes)
!attributesDescription
TRUEnever evaluated
FALSEnever evaluated
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(&current);-
1835 QFontEngine *fontEngine = eng->fontEngine(current);-
1836 if (lbh.fontEngine != fontEngine) {
lbh.fontEngine != fontEngineDescription
TRUEnever evaluated
FALSEnever evaluated
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 &current = 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))) {
current.analys...tAnalysis::TabDescription
TRUEnever evaluated
FALSEnever evaluated
(alignment & (...AlignJustify))Description
TRUEnever evaluated
FALSEnever evaluated
0
1851 lbh.whiteSpaceOrObject = true;-
1852 if (lbh.checkFullOtherwiseExtend(line))
lbh.checkFullO...seExtend(line)Description
TRUEnever evaluated
FALSEnever evaluated
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)
!attributesDescription
TRUEnever evaluated
FALSEnever evaluated
0
1859 return;
never executed: return;
0
1860 lbh.logClusters = eng->layoutData->logClustersPtr;-
1861 lbh.glyphs = eng->shapedGlyphs(&current);-
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))
lbh.checkFullO...seExtend(line)Description
TRUEnever evaluated
FALSEnever evaluated
0
1871 goto found;
never executed: goto found;
0
1872 } else if (current.analysis.flags == QScriptAnalysis::LineOrParagraphSeparator) {
never executed: end of block
current.analys...graphSeparatorDescription
TRUEnever evaluated
FALSEnever evaluated
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)
!line.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
!lbh.tmpData.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1877 line.setDefaultHeight(eng);
never executed: line.setDefaultHeight(eng);
0
1878 if (eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators) {
eng->option.fl...raphSeparatorsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1879 if (lbh.checkFullOtherwiseExtend(line))
lbh.checkFullO...seExtend(line)Description
TRUEnever evaluated
FALSEnever evaluated
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) {
current.analys...alysis::ObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
1891 lbh.whiteSpaceOrObject = true;-
1892 lbh.tmpData.length++;-
1893-
1894 if (eng->block.docHandle()) {
eng->block.docHandle()Description
TRUEnever evaluated
FALSEnever evaluated
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))
lbh.checkFullO...seExtend(line)Description
TRUEnever evaluated
FALSEnever evaluated
0
1904 goto found;
never executed: goto found;
0
1905 } else if (attributes[lbh.currentPosition].whiteSpace
never executed: end of block
attributes[lbh...on].whiteSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1906 && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak) {
eng->layoutDat...QChar::NoBreakDescription
TRUEnever evaluated
FALSEnever evaluated
0
1907 lbh.whiteSpaceOrObject = true;-
1908 while (lbh.currentPosition < end
lbh.currentPosition < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1909 && attributes[lbh.currentPosition].whiteSpace
attributes[lbh...on].whiteSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1910 && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak) {
eng->layoutDat...QChar::NoBreakDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
!lbh.manualWrapDescription
TRUEnever evaluated
FALSEnever evaluated
lbh.spaceData....h > line.widthDescription
TRUEnever evaluated
FALSEnever evaluated
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()
lbh.currentPos...tring.length()Description
TRUEnever evaluated
FALSEnever evaluated
0
1933 && attributes[lbh.currentPosition].whiteSpace
attributes[lbh...on].whiteSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1934 && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak;
eng->layoutDat...QChar::NoBreakDescription
TRUEnever evaluated
FALSEnever evaluated
0
1935-
1936 if (lbh.currentPosition >= eng->layoutData->string.length()
lbh.currentPos...tring.length()Description
TRUEnever evaluated
FALSEnever evaluated
0
1937 || isBreakableSpace
isBreakableSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1938 || attributes[lbh.currentPosition].lineBreak) {
attributes[lbh...ion].lineBreakDescription
TRUEnever evaluated
FALSEnever evaluated
0
1939 sb_or_ws = true;-
1940 break;
never executed: break;
0
1941 } else if (breakany && attributes[lbh.currentPosition].graphemeBoundary) {
breakanyDescription
TRUEnever evaluated
FALSEnever evaluated
attributes[lbh...aphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
1942 break;
never executed: break;
0
1943 }-
1944 } while (lbh.currentPosition < end);
never executed: end of block
lbh.currentPosition < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1945 lbh.minw = qMax(lbh.tmpData.textWidth, lbh.minw);-
1946-
1947 if (lbh.currentPosition > 0 && lbh.currentPosition < end
lbh.currentPosition > 0Description
TRUEnever evaluated
FALSEnever evaluated
lbh.currentPosition < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1948 && attributes[lbh.currentPosition].lineBreak
attributes[lbh...ion].lineBreakDescription
TRUEnever evaluated
FALSEnever evaluated
0
1949 && eng->layoutData->string.at(lbh.currentPosition - 1).unicode() == QChar::SoftHyphen) {
eng->layoutDat...ar::SoftHyphenDescription
TRUEnever evaluated
FALSEnever evaluated
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)
line.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
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)
breakanyDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
sb_or_ws|breakanyDescription
TRUEnever evaluated
FALSEnever evaluated
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)
(lbh.calculate...) > line.widthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1992 lbh.calculateRightBearing();
never executed: lbh.calculateRightBearing();
0
1993-
1994 if (lbh.checkFullOtherwiseExtend(line)) {
lbh.checkFullO...seExtend(line)Description
TRUEnever evaluated
FALSEnever evaluated
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)
previousRightB...gNotCalculatedDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
!breakanyDescription
TRUEnever evaluated
FALSEnever evaluated
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)
lbh.currentPosition == endDescription
TRUEnever evaluated
FALSEnever evaluated
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);-
2017found:
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)
lbh.rightBeari...gNotCalculatedDescription
TRUEnever evaluated
FALSEnever evaluated
!lbh.whiteSpaceOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
line.length == 0Description
TRUEnever evaluated
FALSEnever evaluated
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) {
lbh.manualWrapDescription
TRUEnever evaluated
FALSEnever evaluated
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())
line.textWidth > 0Description
TRUEnever evaluated
FALSEnever evaluated
item < eng->la...->items.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
2047 eng->maxWidth += lbh.spaceData.textWidth;
never executed: eng->maxWidth += lbh.spaceData.textWidth;
0
2048 if (eng->option.flags() & QTextOption::IncludeTrailingSpaces)
eng->option.fl...TrailingSpacesDescription
TRUEnever evaluated
FALSEnever evaluated
0
2049 line.textWidth += lbh.spaceData.textWidth;
never executed: line.textWidth += lbh.spaceData.textWidth;
0
2050 if (lbh.spaceData.length) {
lbh.spaceData.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
eng->option.wr...daryOrAnywhereDescription
TRUEnever evaluated
FALSEnever evaluated
0
2059 if ((lbh.maxGlyphs != INT_MAX && lbh.glyphCount > lbh.maxGlyphs)
lbh.maxGlyphs != 2147483647Description
TRUEnever evaluated
FALSEnever evaluated
lbh.glyphCount > lbh.maxGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2060 || (lbh.maxGlyphs == INT_MAX && line.textWidth > line.width)) {
lbh.maxGlyphs == 2147483647Description
TRUEnever evaluated
FALSEnever evaluated
line.textWidth > line.widthDescription
TRUEnever evaluated
FALSEnever evaluated
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*/-
2074void 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*/-
2083QPointF 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*/-
2099int 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*/-
2109int QTextLine::textLength() const-
2110{-
2111 if (eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators
eng->option.fl...raphSeparatorsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2112 && eng->block.isValid() && index == eng->lines.count()-1) {
eng->block.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
index == eng->lines.count()-1Description
TRUEnever evaluated
FALSEnever evaluated
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-
2118static 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) {
c.style() == Qt::NoBrushDescription
TRUEnever evaluated
FALSEnever evaluated
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())
bg.style() != Qt::NoBrushDescription
TRUEnever evaluated
FALSEnever evaluated
!chf.property(0x513).toBool()Description
TRUEnever evaluated
FALSEnever evaluated
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) {
c.style() != Qt::NoBrushDescription
TRUEnever evaluated
FALSEnever evaluated
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)-
2135static 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) {
*logClusters != glyphsStartDescription
TRUEnever evaluated
FALSEnever evaluated
rangeStart < t...n + textLengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2155 ++logClusters;-
2156 ++rangeStart;-
2157 }
never executed: end of block
0
2158-
2159 int rangeEnd = rangeStart;-
2160 while (*logClusters != glyphsEnd && rangeEnd < textPosition + textLength) {
*logClusters != glyphsEndDescription
TRUEnever evaluated
FALSEnever evaluated
rangeEnd < tex...n + textLengthDescription
TRUEnever evaluated
FALSEnever evaluated
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))
flags.testFlag...Run::Overline)Description
TRUEnever evaluated
FALSEnever evaluated
0
2178 renderFlags |= QTextItem::Overline;
never executed: renderFlags |= QTextItem::Overline;
0
2179 if (flags.testFlag(QGlyphRun::Underline))
flags.testFlag...un::Underline)Description
TRUEnever evaluated
FALSEnever evaluated
0
2180 renderFlags |= QTextItem::Underline;
never executed: renderFlags |= QTextItem::Underline;
0
2181 if (flags.testFlag(QGlyphRun::StrikeOut))
flags.testFlag...un::StrikeOut)Description
TRUEnever evaluated
FALSEnever evaluated
0
2182 renderFlags |= QTextItem::StrikeOut;
never executed: renderFlags |= QTextItem::StrikeOut;
0
2183 if (flags.testFlag(QGlyphRun::RightToLeft))
flags.testFlag...::RightToLeft)Description
TRUEnever evaluated
FALSEnever evaluated
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) {
i<glyphsArray.size()Description
TRUEnever evaluated
FALSEnever evaluated
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) {
i == 0Description
TRUEnever evaluated
FALSEnever evaluated
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*/-
2237QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const-
2238{-
2239 const QScriptLine &line = eng->lines[index];-
2240-
2241 if (line.length == 0)
line.length == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2242 return QList<QGlyphRun>();
never executed: return QList<QGlyphRun>();
0
2243-
2244 if (from < 0)
from < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2245 from = textStart();
never executed: from = textStart();
0
2246-
2247 if (length < 0)
length < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2248 length = textLength();
never executed: length = textLength();
0
2249-
2250 if (length == 0)
length == 0Description
TRUEnever evaluated
FALSEnever evaluated
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()) {
!iterator.atEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
2261 QScriptItem &si = iterator.next();-
2262 if (si.analysis.flags >= QScriptAnalysis::TabOrObject)
si.analysis.fl...s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
2263 continue;
never executed: continue;
0
2264-
2265 if (from >= 0 && length >= 0 && (from >= iterator.itemEnd || from + length <= iterator.itemStart))
from >= 0Description
TRUEnever evaluated
FALSEnever evaluated
length >= 0Description
TRUEnever evaluated
FALSEnever evaluated
from >= iterator.itemEndDescription
TRUEnever evaluated
FALSEnever evaluated
from + length ...ator.itemStartDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
!eng->useRawFontDescription
TRUEnever evaluated
FALSEnever evaluated
0
2273 font = eng->font(si);-
2274 if (font.overline())
font.overline()Description
TRUEnever evaluated
FALSEnever evaluated
0
2275 flags |= QGlyphRun::Overline;
never executed: flags |= QGlyphRun::Overline;
0
2276 if (font.underline())
font.underline()Description
TRUEnever evaluated
FALSEnever evaluated
0
2277 flags |= QGlyphRun::Underline;
never executed: flags |= QGlyphRun::Underline;
0
2278 if (font.strikeOut())
font.strikeOut()Description
TRUEnever evaluated
FALSEnever evaluated
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) {
si.analysis.bidiLevel % 2Description
TRUEnever evaluated
FALSEnever evaluated
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];
(relativeTo ==...or.itemLength)Description
TRUEnever evaluated
FALSEnever evaluated
0
2294 // the glyph index right next to the requested range-
2295 int nextGlyphIndex = (relativeTo < iterator.itemLength - 1) ? logClusters[relativeTo + 1] : si.num_glyphs;
(relativeTo < ...temLength - 1)Description
TRUEnever evaluated
FALSEnever evaluated
0
2296 if (nextGlyphIndex - 1 > glyphsEnd)
nextGlyphIndex - 1 > glyphsEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2297 glyphsEnd = nextGlyphIndex - 1;
never executed: glyphsEnd = nextGlyphIndex - 1;
0
2298 bool startsInsideLigature = relativeFrom > 0 && logClusters[relativeFrom - 1] == glyphsStart;
relativeFrom > 0Description
TRUEnever evaluated
FALSEnever evaluated
logClusters[re...== glyphsStartDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
relativeFrom !...- si.position)Description
TRUEnever evaluated
FALSEnever evaluated
!rtlDescription
TRUEnever evaluated
FALSEnever evaluated
0
2310 for (int i=itemGlyphsStart; i<glyphsStart; ++i) {
i<glyphsStartDescription
TRUEnever evaluated
FALSEnever evaluated
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
relativeTo != ....position - 1)Description
TRUEnever evaluated
FALSEnever evaluated
rtlDescription
TRUEnever evaluated
FALSEnever evaluated
0
2315 for (int i=itemGlyphsEnd; i>glyphsEnd; --i) {
i>glyphsEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2316 QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6);-
2317 pos.rx() += (glyphLayout.advances[i] + justification).toReal();-
2318 }
never executed: end of block
0
2319 }
never executed: end of block
0
2320-
2321 glyphLayout = glyphLayout.mid(glyphsStart, glyphsEnd - glyphsStart + 1);-
2322-
2323 QFixed x;-
2324 QFixed width;-
2325 iterator.getSelectionBounds(&x, &width);-
2326-
2327 if (glyphLayout.numGlyphs > 0) {
glyphLayout.numGlyphs > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2328 QFontEngine *mainFontEngine;-
2329#ifndef QT_NO_RAWFONT-
2330 if (eng->useRawFont && eng->rawFont.isValid())
eng->useRawFontDescription
TRUEnever evaluated
FALSEnever evaluated
eng->rawFont.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
2331 mainFontEngine= eng->fontEngine(si);
never executed: mainFontEngine= eng->fontEngine(si);
0
2332 else-
2333#endif-
2334 mainFontEngine = font.d->engineForScript(si.analysis.script);
never executed: mainFontEngine = font.d->engineForScript(si.analysis.script);
0
2335-
2336 if (mainFontEngine->type() == QFontEngine::Multi) {
mainFontEngine...tEngine::MultiDescription
TRUEnever evaluated
FALSEnever evaluated
0
2337 QFontEngineMulti *multiFontEngine = static_cast<QFontEngineMulti *>(mainFontEngine);-
2338 int start = rtl ? glyphLayout.numGlyphs : 0;
rtlDescription
TRUEnever evaluated
FALSEnever evaluated
0
2339 int end = start - 1;-
2340 int which = glyphLayout.glyphs[rtl ? start - 1 : end + 1] >> 24;-
2341 for (; (rtl && start > 0) || (!rtl && end < glyphLayout.numGlyphs - 1);
rtlDescription
TRUEnever evaluated
FALSEnever evaluated
start > 0Description
TRUEnever evaluated
FALSEnever evaluated
!rtlDescription
TRUEnever evaluated
FALSEnever evaluated
end < glyphLay....numGlyphs - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
2342 rtl ? --start : ++end) {-
2343 const int e = glyphLayout.glyphs[rtl ? start - 1 : end + 1] >> 24;-
2344 if (e == which)
e == whichDescription
TRUEnever evaluated
FALSEnever evaluated
0
2345 continue;
never executed: continue;
0
2346-
2347 QGlyphLayout subLayout = glyphLayout.mid(start, end - start + 1);-
2348 multiFontEngine->ensureEngineAt(which);-
2349-
2350 QGlyphRun::GlyphRunFlags subFlags = flags;-
2351 if (start == 0 && startsInsideLigature)
start == 0Description
TRUEnever evaluated
FALSEnever evaluated
startsInsideLigatureDescription
TRUEnever evaluated
FALSEnever evaluated
0
2352 subFlags |= QGlyphRun::SplitLigature;
never executed: subFlags |= QGlyphRun::SplitLigature;
0
2353-
2354 glyphRuns.append(glyphRunWithInfo(multiFontEngine->engine(which),-
2355 subLayout,-
2356 pos,-
2357 subFlags,-
2358 x,-
2359 width,-
2360 glyphsStart + start,-
2361 glyphsStart + end,-
2362 logClusters + relativeFrom,-
2363 relativeFrom + si.position,-
2364 relativeTo - relativeFrom + 1));-
2365 for (int i = 0; i < subLayout.numGlyphs; ++i) {
i < subLayout.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2366 QFixed justification = QFixed::fromFixed(subLayout.justifications[i].space_18d6);-
2367 pos.rx() += (subLayout.advances[i] + justification).toReal();-
2368 }
never executed: end of block
0
2369-
2370 if (rtl)
rtlDescription
TRUEnever evaluated
FALSEnever evaluated
0
2371 end = start - 1;
never executed: end = start - 1;
0
2372 else-
2373 start = end + 1;
never executed: start = end + 1;
0
2374 which = e;-
2375 }
never executed: end of block
0
2376-
2377 QGlyphLayout subLayout = glyphLayout.mid(start, end - start + 1);-
2378 multiFontEngine->ensureEngineAt(which);-
2379-
2380 QGlyphRun::GlyphRunFlags subFlags = flags;-
2381 if ((start == 0 && startsInsideLigature) || endsInsideLigature)
start == 0Description
TRUEnever evaluated
FALSEnever evaluated
startsInsideLigatureDescription
TRUEnever evaluated
FALSEnever evaluated
endsInsideLigatureDescription
TRUEnever evaluated
FALSEnever evaluated
0
2382 subFlags |= QGlyphRun::SplitLigature;
never executed: subFlags |= QGlyphRun::SplitLigature;
0
2383-
2384 QGlyphRun glyphRun = glyphRunWithInfo(multiFontEngine->engine(which),-
2385 subLayout,-
2386 pos,-
2387 subFlags,-
2388 x,-
2389 width,-
2390 glyphsStart + start,-
2391 glyphsStart + end,-
2392 logClusters + relativeFrom,-
2393 relativeFrom + si.position,-
2394 relativeTo - relativeFrom + 1);-
2395 if (!glyphRun.isEmpty())
!glyphRun.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
2396 glyphRuns.append(glyphRun);
never executed: glyphRuns.append(glyphRun);
0
2397 } else {
never executed: end of block
0
2398 if (startsInsideLigature || endsInsideLigature)
startsInsideLigatureDescription
TRUEnever evaluated
FALSEnever evaluated
endsInsideLigatureDescription
TRUEnever evaluated
FALSEnever evaluated
0
2399 flags |= QGlyphRun::SplitLigature;
never executed: flags |= QGlyphRun::SplitLigature;
0
2400 QGlyphRun glyphRun = glyphRunWithInfo(mainFontEngine,-
2401 glyphLayout,-
2402 pos,-
2403 flags,-
2404 x,-
2405 width,-
2406 glyphsStart,-
2407 glyphsEnd,-
2408 logClusters + relativeFrom,-
2409 relativeFrom + si.position,-
2410 relativeTo - relativeFrom + 1);-
2411 if (!glyphRun.isEmpty())
!glyphRun.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
2412 glyphRuns.append(glyphRun);
never executed: glyphRuns.append(glyphRun);
0
2413 }
never executed: end of block
0
2414 }-
2415 }
never executed: end of block
0
2416-
2417 return glyphRuns;
never executed: return glyphRuns;
0
2418}-
2419#endif // QT_NO_RAWFONT-
2420-
2421/*!-
2422 \fn void QTextLine::draw(QPainter *painter, const QPointF &position, const QTextLayout::FormatRange *selection) const-
2423-
2424 Draws a line on the given \a painter at the specified \a position.-
2425 The \a selection is reserved for internal use.-
2426*/-
2427void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatRange *selection) const-
2428{-
2429#ifndef QT_NO_RAWFONT-
2430 // Not intended to work with rawfont-
2431 Q_ASSERT(!eng->useRawFont);-
2432#endif-
2433 const QScriptLine &line = eng->lines[index];-
2434 QPen pen = p->pen();-
2435-
2436 bool noText = (selection && selection->format.property(SuppressText).toBool());
selectionDescription
TRUEnever evaluated
FALSEnever evaluated
selection->for...5012).toBool()Description
TRUEnever evaluated
FALSEnever evaluated
0
2437-
2438 if (!line.length) {
!line.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2439 if (selection
selectionDescription
TRUEnever evaluated
FALSEnever evaluated
0
2440 && selection->start <= line.from
selection->start <= line.fromDescription
TRUEnever evaluated
FALSEnever evaluated
0
2441 && selection->start + selection->length > line.from) {
selection->sta...th > line.fromDescription
TRUEnever evaluated
FALSEnever evaluated
0
2442-
2443 const qreal lineHeight = line.height().toReal();-
2444 QRectF r(pos.x() + line.x.toReal(), pos.y() + line.y.toReal(),-
2445 lineHeight / 2, QFontMetrics(eng->font()).width(QLatin1Char(' ')));-
2446 setPenAndDrawBackground(p, QPen(), selection->format, r);-
2447 p->setPen(pen);-
2448 }
never executed: end of block
0
2449 return;
never executed: return;
0
2450 }-
2451-
2452-
2453 QTextLineItemIterator iterator(eng, index, pos, selection);-
2454 QFixed lineBase = line.base();-
2455 eng->clearDecorations();-
2456 eng->enableDelayDecorations();-
2457-
2458 const QFixed y = QFixed::fromReal(pos.y()) + line.y + lineBase;-
2459-
2460 bool suppressColors = (eng->option.flags() & QTextOption::SuppressColors);-
2461 while (!iterator.atEnd()) {
!iterator.atEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
2462 QScriptItem &si = iterator.next();-
2463-
2464 if (selection && selection->start >= 0 && iterator.isOutsideSelection())
selectionDescription
TRUEnever evaluated
FALSEnever evaluated
selection->start >= 0Description
TRUEnever evaluated
FALSEnever evaluated
iterator.isOutsideSelection()Description
TRUEnever evaluated
FALSEnever evaluated
0
2465 continue;
never executed: continue;
0
2466-
2467 if (si.analysis.flags == QScriptAnalysis::LineOrParagraphSeparator
si.analysis.fl...graphSeparatorDescription
TRUEnever evaluated
FALSEnever evaluated
0
2468 && !(eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators))
!(eng->option....aphSeparators)Description
TRUEnever evaluated
FALSEnever evaluated
0
2469 continue;
never executed: continue;
0
2470-
2471 QFixed itemBaseLine = y;-
2472 QFont f = eng->font(si);-
2473 QTextCharFormat format;-
2474-
2475 if (eng->hasFormats() || selection) {
eng->hasFormats()Description
TRUEnever evaluated
FALSEnever evaluated
selectionDescription
TRUEnever evaluated
FALSEnever evaluated
0
2476 format = eng->format(&si);-
2477 if (suppressColors) {
suppressColorsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2478 format.clearForeground();-
2479 format.clearBackground();-
2480 format.clearProperty(QTextFormat::TextUnderlineColor);-
2481 }
never executed: end of block
0
2482 if (selection)
selectionDescription
TRUEnever evaluated
FALSEnever evaluated
0
2483 format.merge(selection->format);
never executed: format.merge(selection->format);
0
2484-
2485 setPenAndDrawBackground(p, pen, format, QRectF(iterator.x.toReal(), (y - lineBase).toReal(),-
2486 iterator.itemWidth.toReal(), line.height().toReal()));-
2487-
2488 QTextCharFormat::VerticalAlignment valign = format.verticalAlignment();-
2489 if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) {
valign == QTex...ignSuperScriptDescription
TRUEnever evaluated
FALSEnever evaluated
valign == QTex...AlignSubScriptDescription
TRUEnever evaluated
FALSEnever evaluated
0
2490 QFontEngine *fe = f.d->engineForScript(si.analysis.script);-
2491 QFixed height = fe->ascent() + fe->descent();-
2492 if (valign == QTextCharFormat::AlignSubScript)
valign == QTex...AlignSubScriptDescription
TRUEnever evaluated
FALSEnever evaluated
0
2493 itemBaseLine += height / 6;
never executed: itemBaseLine += height / 6;
0
2494 else if (valign == QTextCharFormat::AlignSuperScript)
valign == QTex...ignSuperScriptDescription
TRUEnever evaluated
FALSEnever evaluated
0
2495 itemBaseLine -= height / 2;
never executed: itemBaseLine -= height / 2;
0
2496 }
never executed: end of block
0
2497 }
never executed: end of block
0
2498-
2499 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
si.analysis.fl...s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
2500-
2501 if (eng->hasFormats()) {
eng->hasFormats()Description
TRUEnever evaluated
FALSEnever evaluated
0
2502 p->save();-
2503 if (si.analysis.flags == QScriptAnalysis::Object && eng->block.docHandle()) {
si.analysis.fl...alysis::ObjectDescription
TRUEnever evaluated
FALSEnever evaluated
eng->block.docHandle()Description
TRUEnever evaluated
FALSEnever evaluated
0
2504 QFixed itemY = y - si.ascent;-
2505 if (format.verticalAlignment() == QTextCharFormat::AlignTop) {
format.vertica...rmat::AlignTopDescription
TRUEnever evaluated
FALSEnever evaluated
0
2506 itemY = y - lineBase;-
2507 }
never executed: end of block
0
2508-
2509 QRectF itemRect(iterator.x.toReal(), itemY.toReal(), iterator.itemWidth.toReal(), si.height().toReal());-
2510-
2511 eng->docLayout()->drawInlineObject(p, itemRect,-
2512 QTextInlineObject(iterator.item, eng),-
2513 si.position + eng->block.position(),-
2514 format);-
2515 if (selection) {
selectionDescription
TRUEnever evaluated
FALSEnever evaluated
0
2516 QBrush bg = format.brushProperty(ObjectSelectionBrush);-
2517 if (bg.style() != Qt::NoBrush) {
bg.style() != Qt::NoBrushDescription
TRUEnever evaluated
FALSEnever evaluated
0
2518 QColor c = bg.color();-
2519 c.setAlpha(128);-
2520 p->fillRect(itemRect, c);-
2521 }
never executed: end of block
0
2522 }
never executed: end of block
0
2523 } else { // si.isTab
never executed: end of block
0
2524 QFont f = eng->font(si);-
2525 QTextItemInt gf(si, &f, format);-
2526 gf.chars = 0;-
2527 gf.num_chars = 0;-
2528 gf.width = iterator.itemWidth;-
2529 QPainterPrivate::get(p)->drawTextItem(QPointF(iterator.x.toReal(), y.toReal()), gf, eng);-
2530 if (eng->option.flags() & QTextOption::ShowTabsAndSpaces) {
eng->option.fl...wTabsAndSpacesDescription
TRUEnever evaluated
FALSEnever evaluated
0
2531 QChar visualTab(0x2192);-
2532 int w = QFontMetrics(f).width(visualTab);-
2533 qreal x = iterator.itemWidth.toReal() - w; // Right-aligned-
2534 if (x < 0)
x < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2535 p->setClipRect(QRectF(iterator.x.toReal(), line.y.toReal(),
never executed: p->setClipRect(QRectF(iterator.x.toReal(), line.y.toReal(), iterator.itemWidth.toReal(), line.height().toReal()), Qt::IntersectClip);
0
2536 iterator.itemWidth.toReal(), line.height().toReal()),
never executed: p->setClipRect(QRectF(iterator.x.toReal(), line.y.toReal(), iterator.itemWidth.toReal(), line.height().toReal()), Qt::IntersectClip);
0
2537 Qt::IntersectClip);
never executed: p->setClipRect(QRectF(iterator.x.toReal(), line.y.toReal(), iterator.itemWidth.toReal(), line.height().toReal()), Qt::IntersectClip);
0
2538 else-
2539 x /= 2; // Centered
never executed: x /= 2;
0
2540 p->drawText(QPointF(iterator.x.toReal() + x,-
2541 y.toReal()), visualTab);-
2542 }
never executed: end of block
0
2543-
2544 }
never executed: end of block
0
2545 p->restore();-
2546 }
never executed: end of block
0
2547-
2548 continue;
never executed: continue;
0
2549 }-
2550-
2551 unsigned short *logClusters = eng->logClusters(&si);-
2552 QGlyphLayout glyphs = eng->shapedGlyphs(&si);-
2553-
2554 QTextItemInt gf(glyphs.mid(iterator.glyphsStart, iterator.glyphsEnd - iterator.glyphsStart),-
2555 &f, eng->layoutData->string.unicode() + iterator.itemStart,-
2556 iterator.itemEnd - iterator.itemStart, eng->fontEngine(si), format);-
2557 gf.logClusters = logClusters + iterator.itemStart - si.position;-
2558 gf.width = iterator.itemWidth;-
2559 gf.justified = line.justified;-
2560 gf.initWithScriptItem(si);-
2561-
2562 Q_ASSERT(gf.fontEngine);-
2563-
2564 QPointF pos(iterator.x.toReal(), itemBaseLine.toReal());-
2565 if (format.penProperty(QTextFormat::TextOutline).style() != Qt::NoPen) {
format.penProp...) != Qt::NoPenDescription
TRUEnever evaluated
FALSEnever evaluated
0
2566 QPainterPath path;-
2567 path.setFillRule(Qt::WindingFill);-
2568-
2569 if (gf.glyphs.numGlyphs)
gf.glyphs.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2570 gf.fontEngine->addOutlineToPath(pos.x(), pos.y(), gf.glyphs, &path, gf.flags);
never executed: gf.fontEngine->addOutlineToPath(pos.x(), pos.y(), gf.glyphs, &path, gf.flags);
0
2571 if (gf.flags) {
gf.flagsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2572 const QFontEngine *fe = gf.fontEngine;-
2573 const qreal lw = fe->lineThickness().toReal();-
2574 if (gf.flags & QTextItem::Underline) {
gf.flags & QTe...tem::UnderlineDescription
TRUEnever evaluated
FALSEnever evaluated
0
2575 qreal offs = fe->underlinePosition().toReal();-
2576 path.addRect(pos.x(), pos.y() + offs, gf.width.toReal(), lw);-
2577 }
never executed: end of block
0
2578 if (gf.flags & QTextItem::Overline) {
gf.flags & QTextItem::OverlineDescription
TRUEnever evaluated
FALSEnever evaluated
0
2579 qreal offs = fe->ascent().toReal() + 1;-
2580 path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);-
2581 }
never executed: end of block
0
2582 if (gf.flags & QTextItem::StrikeOut) {
gf.flags & QTe...tem::StrikeOutDescription
TRUEnever evaluated
FALSEnever evaluated
0
2583 qreal offs = fe->ascent().toReal() / 3;-
2584 path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);-
2585 }
never executed: end of block
0
2586 }
never executed: end of block
0
2587-
2588 p->save();-
2589 p->setRenderHint(QPainter::Antialiasing);-
2590 //Currently QPen with a Qt::NoPen style still returns a default-
2591 //QBrush which != Qt::NoBrush so we need this specialcase to reset it-
2592 if (p->pen().style() == Qt::NoPen)
p->pen().style() == Qt::NoPenDescription
TRUEnever evaluated
FALSEnever evaluated
0
2593 p->setBrush(Qt::NoBrush);
never executed: p->setBrush(Qt::NoBrush);
0
2594 else-
2595 p->setBrush(p->pen().brush());
never executed: p->setBrush(p->pen().brush());
0
2596-
2597 p->setPen(format.textOutline());-
2598 p->drawPath(path);-
2599 p->restore();-
2600 } else {
never executed: end of block
0
2601 if (noText)
noTextDescription
TRUEnever evaluated
FALSEnever evaluated
0
2602 gf.glyphs.numGlyphs = 0; // slightly less elegant than it should be
never executed: gf.glyphs.numGlyphs = 0;
0
2603 QPainterPrivate::get(p)->drawTextItem(pos, gf, eng);-
2604 }
never executed: end of block
0
2605-
2606 if (si.analysis.flags == QScriptAnalysis::Space
si.analysis.fl...nalysis::SpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
2607 && (eng->option.flags() & QTextOption::ShowTabsAndSpaces)) {
(eng->option.f...TabsAndSpaces)Description
TRUEnever evaluated
FALSEnever evaluated
0
2608 QBrush c = format.foreground();-
2609 if (c.style() != Qt::NoBrush)
c.style() != Qt::NoBrushDescription
TRUEnever evaluated
FALSEnever evaluated
0
2610 p->setPen(c.color());
never executed: p->setPen(c.color());
0
2611 QChar visualSpace((ushort)0xb7);-
2612 p->drawText(QPointF(iterator.x.toReal(), itemBaseLine.toReal()), visualSpace);-
2613 p->setPen(pen);-
2614 }
never executed: end of block
0
2615 }
never executed: end of block
0
2616 eng->drawDecorations(p);-
2617-
2618 if (eng->hasFormats())
eng->hasFormats()Description
TRUEnever evaluated
FALSEnever evaluated
0
2619 p->setPen(pen);
never executed: p->setPen(pen);
0
2620}
never executed: end of block
0
2621-
2622/*!-
2623 \fn int QTextLine::cursorToX(int cursorPos, Edge edge) const-
2624-
2625 \overload-
2626*/-
2627-
2628/*!-
2629 Converts the cursor position \a cursorPos to the corresponding x position-
2630 inside the line, taking account of the \a edge.-
2631-
2632 If \a cursorPos is not a valid cursor position, the nearest valid-
2633 cursor position will be used instead, and \a cursorPos will be modified to-
2634 point to this valid cursor position.-
2635-
2636 \sa xToCursor()-
2637*/-
2638qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const-
2639{-
2640 const QScriptLine &line = eng->lines[index];-
2641 bool lastLine = index >= eng->lines.size() - 1;-
2642-
2643 QFixed x = line.x + eng->alignLine(line) - eng->leadingSpaceWidth(line);-
2644-
2645 if (!eng->layoutData)
!eng->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
2646 eng->itemize();
never executed: eng->itemize();
0
2647 if (!eng->layoutData->items.size()) {
!eng->layoutData->items.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
2648 *cursorPos = line.from;-
2649 return x.toReal();
never executed: return x.toReal();
0
2650 }-
2651-
2652 int lineEnd = line.from + line.length + line.trailingSpaces;-
2653 int pos = qBound(line.from, *cursorPos, lineEnd);-
2654 int itm;-
2655 const QCharAttributes *attributes = eng->attributes();-
2656 if (!attributes) {
!attributesDescription
TRUEnever evaluated
FALSEnever evaluated
0
2657 *cursorPos = line.from;-
2658 return x.toReal();
never executed: return x.toReal();
0
2659 }-
2660 while (pos < lineEnd && !attributes[pos].graphemeBoundary)
pos < lineEndDescription
TRUEnever evaluated
FALSEnever evaluated
!attributes[po...aphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
2661 pos++;
never executed: pos++;
0
2662 if (pos == lineEnd) {
pos == lineEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2663 // end of line ensure we have the last item on the line-
2664 itm = eng->findItem(pos-1);-
2665 }
never executed: end of block
0
2666 else-
2667 itm = eng->findItem(pos);
never executed: itm = eng->findItem(pos);
0
2668 if (itm < 0) {
itm < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2669 *cursorPos = line.from;-
2670 return x.toReal();
never executed: return x.toReal();
0
2671 }-
2672 eng->shapeLine(line);-
2673-
2674 const QScriptItem *si = &eng->layoutData->items[itm];-
2675 if (!si->num_glyphs)
!si->num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2676 eng->shape(itm);
never executed: eng->shape(itm);
0
2677-
2678 const int l = eng->length(itm);-
2679 pos = qBound(0, pos - si->position, l);-
2680-
2681 QGlyphLayout glyphs = eng->shapedGlyphs(si);-
2682 unsigned short *logClusters = eng->logClusters(si);-
2683 Q_ASSERT(logClusters);-
2684-
2685 int glyph_pos = pos == l ? si->num_glyphs : logClusters[pos];
pos == lDescription
TRUEnever evaluated
FALSEnever evaluated
0
2686 if (edge == Trailing && glyph_pos < si->num_glyphs) {
edge == TrailingDescription
TRUEnever evaluated
FALSEnever evaluated
glyph_pos < si->num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2687 // trailing edge is leading edge of next cluster-
2688 glyph_pos++;-
2689 while (glyph_pos < si->num_glyphs && !glyphs.attributes[glyph_pos].clusterStart)
glyph_pos < si->num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
!glyphs.attrib...].clusterStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
2690 glyph_pos++;
never executed: glyph_pos++;
0
2691 }
never executed: end of block
0
2692-
2693 bool reverse = si->analysis.bidiLevel % 2;-
2694-
2695-
2696 // add the items left of the cursor-
2697-
2698 int firstItem = eng->findItem(line.from);-
2699 int lastItem = eng->findItem(lineEnd - 1, itm);-
2700 int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
firstItem >= 0Description
TRUEnever evaluated
FALSEnever evaluated
lastItem >= firstItemDescription
TRUEnever evaluated
FALSEnever evaluated
0
2701-
2702 QVarLengthArray<int> visualOrder(nItems);-
2703 QVarLengthArray<uchar> levels(nItems);-
2704 for (int i = 0; i < nItems; ++i)
i < nItemsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2705 levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
never executed: levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
0
2706 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());-
2707-
2708 for (int i = 0; i < nItems; ++i) {
i < nItemsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2709 int item = visualOrder[i]+firstItem;-
2710 if (item == itm)
item == itmDescription
TRUEnever evaluated
FALSEnever evaluated
0
2711 break;
never executed: break;
0
2712 QScriptItem &si = eng->layoutData->items[item];-
2713 if (!si.num_glyphs)
!si.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2714 eng->shape(item);
never executed: eng->shape(item);
0
2715-
2716 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
si.analysis.fl...s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
2717 x += si.width;-
2718 continue;
never executed: continue;
0
2719 }-
2720-
2721 const int itemLength = eng->length(item);-
2722 int start = qMax(line.from, si.position);-
2723 int end = qMin(lineEnd, si.position + itemLength);-
2724-
2725 logClusters = eng->logClusters(&si);-
2726-
2727 int gs = logClusters[start-si.position];-
2728 int ge = (end == si.position + itemLength) ? si.num_glyphs-1 : logClusters[end-si.position-1];
(end == si.pos... + itemLength)Description
TRUEnever evaluated
FALSEnever evaluated
0
2729-
2730 QGlyphLayout glyphs = eng->shapedGlyphs(&si);-
2731-
2732 while (gs <= ge) {
gs <= geDescription
TRUEnever evaluated
FALSEnever evaluated
0
2733 x += glyphs.effectiveAdvance(gs);-
2734 ++gs;-
2735 }
never executed: end of block
0
2736 }
never executed: end of block
0
2737-
2738 logClusters = eng->logClusters(si);-
2739 glyphs = eng->shapedGlyphs(si);-
2740 if (si->analysis.flags >= QScriptAnalysis::TabOrObject) {
si->analysis.f...s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
2741 if (pos == (reverse ? 0 : l))
pos == (reverse ? 0 : l)Description
TRUEnever evaluated
FALSEnever evaluated
reverseDescription
TRUEnever evaluated
FALSEnever evaluated
0
2742 x += si->width;
never executed: x += si->width;
0
2743 } else {
never executed: end of block
0
2744 bool rtl = eng->isRightToLeft();-
2745 bool visual = eng->visualCursorMovement();-
2746 int end = qMin(lineEnd, si->position + l) - si->position;-
2747 if (reverse) {
reverseDescription
TRUEnever evaluated
FALSEnever evaluated
0
2748 int glyph_end = end == l ? si->num_glyphs : logClusters[end];
end == lDescription
TRUEnever evaluated
FALSEnever evaluated
0
2749 int glyph_start = glyph_pos;-
2750 if (visual && !rtl && !(lastLine && itm == (visualOrder[nItems - 1] + firstItem)))
visualDescription
TRUEnever evaluated
FALSEnever evaluated
!rtlDescription
TRUEnever evaluated
FALSEnever evaluated
lastLineDescription
TRUEnever evaluated
FALSEnever evaluated
itm == (visual...] + firstItem)Description
TRUEnever evaluated
FALSEnever evaluated
0
2751 glyph_start++;
never executed: glyph_start++;
0
2752 for (int i = glyph_end - 1; i >= glyph_start; i--)
i >= glyph_startDescription
TRUEnever evaluated
FALSEnever evaluated
0
2753 x += glyphs.effectiveAdvance(i);
never executed: x += glyphs.effectiveAdvance(i);
0
2754 } else {
never executed: end of block
0
2755 int start = qMax(line.from - si->position, 0);-
2756 int glyph_start = logClusters[start];-
2757 int glyph_end = glyph_pos;-
2758 if (!visual || !rtl || (lastLine && itm == visualOrder[0] + firstItem))
!visualDescription
TRUEnever evaluated
FALSEnever evaluated
!rtlDescription
TRUEnever evaluated
FALSEnever evaluated
lastLineDescription
TRUEnever evaluated
FALSEnever evaluated
itm == visualO...0] + firstItemDescription
TRUEnever evaluated
FALSEnever evaluated
0
2759 glyph_end--;
never executed: glyph_end--;
0
2760 for (int i = glyph_start; i <= glyph_end; i++)
i <= glyph_endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2761 x += glyphs.effectiveAdvance(i);
never executed: x += glyphs.effectiveAdvance(i);
0
2762 }
never executed: end of block
0
2763 x += eng->offsetInLigature(si, pos, end, glyph_pos);-
2764 }
never executed: end of block
0
2765-
2766 if (eng->option.wrapMode() != QTextOption::NoWrap && x > line.x + line.width)
eng->option.wr...Option::NoWrapDescription
TRUEnever evaluated
FALSEnever evaluated
x > line.x + line.widthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2767 x = line.x + line.width;
never executed: x = line.x + line.width;
0
2768 if (eng->option.wrapMode() != QTextOption::NoWrap && x < 0)
eng->option.wr...Option::NoWrapDescription
TRUEnever evaluated
FALSEnever evaluated
x < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2769 x = 0;
never executed: x = 0;
0
2770-
2771 *cursorPos = pos + si->position;-
2772 return x.toReal();
never executed: return x.toReal();
0
2773}-
2774-
2775/*!-
2776 \fn int QTextLine::xToCursor(qreal x, CursorPosition cpos) const-
2777-
2778 Converts the x-coordinate \a x, to the nearest matching cursor-
2779 position, depending on the cursor position type, \a cpos.-
2780 Note that result cursor position includes possible preedit area text.-
2781-
2782 \sa cursorToX()-
2783*/-
2784int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const-
2785{-
2786 QFixed x = QFixed::fromReal(_x);-
2787 const QScriptLine &line = eng->lines[index];-
2788 bool lastLine = index >= eng->lines.size() - 1;-
2789 int lineNum = index;-
2790-
2791 if (!eng->layoutData)
!eng->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
2792 eng->itemize();
never executed: eng->itemize();
0
2793-
2794 int line_length = textLength();-
2795-
2796 if (!line_length)
!line_lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2797 return line.from;
never executed: return line.from;
0
2798-
2799 int firstItem = eng->findItem(line.from);-
2800 int lastItem = eng->findItem(line.from + line_length - 1, firstItem);-
2801 int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
firstItem >= 0Description
TRUEnever evaluated
FALSEnever evaluated
lastItem >= firstItemDescription
TRUEnever evaluated
FALSEnever evaluated
0
2802-
2803 if (!nItems)
!nItemsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2804 return 0;
never executed: return 0;
0
2805-
2806 x -= line.x;-
2807 x -= eng->alignLine(line);-
2808// qDebug("xToCursor: x=%f, cpos=%d", x.toReal(), cpos);-
2809-
2810 QVarLengthArray<int> visualOrder(nItems);-
2811 QVarLengthArray<unsigned char> levels(nItems);-
2812 for (int i = 0; i < nItems; ++i)
i < nItemsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2813 levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
never executed: levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
0
2814 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());-
2815-
2816 bool visual = eng->visualCursorMovement();-
2817 if (x <= 0) {
x <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2818 // left of first item-
2819 int item = visualOrder[0]+firstItem;-
2820 QScriptItem &si = eng->layoutData->items[item];-
2821 if (!si.num_glyphs)
!si.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2822 eng->shape(item);
never executed: eng->shape(item);
0
2823 int pos = si.position;-
2824 if (si.analysis.bidiLevel % 2)
si.analysis.bidiLevel % 2Description
TRUEnever evaluated
FALSEnever evaluated
0
2825 pos += eng->length(item);
never executed: pos += eng->length(item);
0
2826 pos = qMax(line.from, pos);-
2827 pos = qMin(line.from + line_length, pos);-
2828 return pos;
never executed: return pos;
0
2829 } else if (x < line.textWidth
x < line.textWidthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2830 || (line.justified && x < line.width)) {
line.justifiedDescription
TRUEnever evaluated
FALSEnever evaluated
x < line.widthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2831 // has to be in one of the runs-
2832 QFixed pos;-
2833 bool rtl = eng->isRightToLeft();-
2834-
2835 eng->shapeLine(line);-
2836 QVector<int> insertionPoints;-
2837 if (visual && rtl)
visualDescription
TRUEnever evaluated
FALSEnever evaluated
rtlDescription
TRUEnever evaluated
FALSEnever evaluated
0
2838 eng->insertionPointsForLine(lineNum, insertionPoints);
never executed: eng->insertionPointsForLine(lineNum, insertionPoints);
0
2839 int nchars = 0;-
2840 for (int i = 0; i < nItems; ++i) {
i < nItemsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2841 int item = visualOrder[i]+firstItem;-
2842 QScriptItem &si = eng->layoutData->items[item];-
2843 int item_length = eng->length(item);-
2844// qDebug(" item %d, visual %d x_remain=%f", i, item, x.toReal());-
2845-
2846 int start = qMax(line.from - si.position, 0);-
2847 int end = qMin(line.from + line_length - si.position, item_length);-
2848-
2849 unsigned short *logClusters = eng->logClusters(&si);-
2850-
2851 int gs = logClusters[start];-
2852 int ge = (end == item_length ? si.num_glyphs : logClusters[end]) - 1;
end == item_lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2853 QGlyphLayout glyphs = eng->shapedGlyphs(&si);-
2854-
2855 QFixed item_width = 0;-
2856 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
si.analysis.fl...s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
2857 item_width = si.width;-
2858 } else {
never executed: end of block
0
2859 int g = gs;-
2860 while (g <= ge) {
g <= geDescription
TRUEnever evaluated
FALSEnever evaluated
0
2861 item_width += glyphs.effectiveAdvance(g);-
2862 ++g;-
2863 }
never executed: end of block
0
2864 }
never executed: end of block
0
2865// qDebug(" start=%d, end=%d, gs=%d, ge=%d item_width=%f", start, end, gs, ge, item_width.toReal());-
2866-
2867 if (pos + item_width < x) {
pos + item_width < xDescription
TRUEnever evaluated
FALSEnever evaluated
0
2868 pos += item_width;-
2869 nchars += end;-
2870 continue;
never executed: continue;
0
2871 }-
2872// qDebug(" inside run");-
2873 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
si.analysis.fl...s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
2874 if (cpos == QTextLine::CursorOnCharacter)
cpos == QTextL...sorOnCharacterDescription
TRUEnever evaluated
FALSEnever evaluated
0
2875 return si.position;
never executed: return si.position;
0
2876 bool left_half = (x - pos) < item_width/2;-
2877-
2878 if (bool(si.analysis.bidiLevel % 2) != left_half)
bool(si.analys...) != left_halfDescription
TRUEnever evaluated
FALSEnever evaluated
0
2879 return si.position;
never executed: return si.position;
0
2880 return si.position + 1;
never executed: return si.position + 1;
0
2881 }-
2882-
2883 int glyph_pos = -1;-
2884 QFixed edge;-
2885 // has to be inside run-
2886 if (cpos == QTextLine::CursorOnCharacter) {
cpos == QTextL...sorOnCharacterDescription
TRUEnever evaluated
FALSEnever evaluated
0
2887 if (si.analysis.bidiLevel % 2) {
si.analysis.bidiLevel % 2Description
TRUEnever evaluated
FALSEnever evaluated
0
2888 pos += item_width;-
2889 glyph_pos = gs;-
2890 while (gs <= ge) {
gs <= geDescription
TRUEnever evaluated
FALSEnever evaluated
0
2891 if (glyphs.attributes[gs].clusterStart) {
glyphs.attribu...].clusterStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
2892 if (pos < x)
pos < xDescription
TRUEnever evaluated
FALSEnever evaluated
0
2893 break;
never executed: break;
0
2894 glyph_pos = gs;-
2895 edge = pos;-
2896 }
never executed: end of block
0
2897 pos -= glyphs.effectiveAdvance(gs);-
2898 ++gs;-
2899 }
never executed: end of block
0
2900 } else {
never executed: end of block
0
2901 glyph_pos = gs;-
2902 while (gs <= ge) {
gs <= geDescription
TRUEnever evaluated
FALSEnever evaluated
0
2903 if (glyphs.attributes[gs].clusterStart) {
glyphs.attribu...].clusterStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
2904 if (pos > x)
pos > xDescription
TRUEnever evaluated
FALSEnever evaluated
0
2905 break;
never executed: break;
0
2906 glyph_pos = gs;-
2907 edge = pos;-
2908 }
never executed: end of block
0
2909 pos += glyphs.effectiveAdvance(gs);-
2910 ++gs;-
2911 }
never executed: end of block
0
2912 }
never executed: end of block
0
2913 } else {-
2914 QFixed dist = INT_MAX/256;-
2915 if (si.analysis.bidiLevel % 2) {
si.analysis.bidiLevel % 2Description
TRUEnever evaluated
FALSEnever evaluated
0
2916 if (!visual || rtl || (lastLine && i == nItems - 1)) {
!visualDescription
TRUEnever evaluated
FALSEnever evaluated
rtlDescription
TRUEnever evaluated
FALSEnever evaluated
lastLineDescription
TRUEnever evaluated
FALSEnever evaluated
i == nItems - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
2917 pos += item_width;-
2918 while (gs <= ge) {
gs <= geDescription
TRUEnever evaluated
FALSEnever evaluated
0
2919 if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {
glyphs.attribu...].clusterStartDescription
TRUEnever evaluated
FALSEnever evaluated
qAbs(x-pos) < distDescription
TRUEnever evaluated
FALSEnever evaluated
0
2920 glyph_pos = gs;-
2921 edge = pos;-
2922 dist = qAbs(x-pos);-
2923 }
never executed: end of block
0
2924 pos -= glyphs.effectiveAdvance(gs);-
2925 ++gs;-
2926 }
never executed: end of block
0
2927 } else {
never executed: end of block
0
2928 while (ge >= gs) {
ge >= gsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2929 if (glyphs.attributes[ge].clusterStart && qAbs(x-pos) < dist) {
glyphs.attribu...].clusterStartDescription
TRUEnever evaluated
FALSEnever evaluated
qAbs(x-pos) < distDescription
TRUEnever evaluated
FALSEnever evaluated
0
2930 glyph_pos = ge;-
2931 edge = pos;-
2932 dist = qAbs(x-pos);-
2933 }
never executed: end of block
0
2934 pos += glyphs.effectiveAdvance(ge);-
2935 --ge;-
2936 }
never executed: end of block
0
2937 }
never executed: end of block
0
2938 } else {-
2939 if (!visual || !rtl || (lastLine && i == 0)) {
!visualDescription
TRUEnever evaluated
FALSEnever evaluated
!rtlDescription
TRUEnever evaluated
FALSEnever evaluated
lastLineDescription
TRUEnever evaluated
FALSEnever evaluated
i == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2940 while (gs <= ge) {
gs <= geDescription
TRUEnever evaluated
FALSEnever evaluated
0
2941 if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {
glyphs.attribu...].clusterStartDescription
TRUEnever evaluated
FALSEnever evaluated
qAbs(x-pos) < distDescription
TRUEnever evaluated
FALSEnever evaluated
0
2942 glyph_pos = gs;-
2943 edge = pos;-
2944 dist = qAbs(x-pos);-
2945 }
never executed: end of block
0
2946 pos += glyphs.effectiveAdvance(gs);-
2947 ++gs;-
2948 }
never executed: end of block
0
2949 } else {
never executed: end of block
0
2950 QFixed oldPos = pos;-
2951 while (gs <= ge) {
gs <= geDescription
TRUEnever evaluated
FALSEnever evaluated
0
2952 pos += glyphs.effectiveAdvance(gs);-
2953 if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {
glyphs.attribu...].clusterStartDescription
TRUEnever evaluated
FALSEnever evaluated
qAbs(x-pos) < distDescription
TRUEnever evaluated
FALSEnever evaluated
0
2954 glyph_pos = gs;-
2955 edge = pos;-
2956 dist = qAbs(x-pos);-
2957 }
never executed: end of block
0
2958 ++gs;-
2959 }
never executed: end of block
0
2960 pos = oldPos;-
2961 }
never executed: end of block
0
2962 }-
2963 if (qAbs(x-pos) < dist) {
qAbs(x-pos) < distDescription
TRUEnever evaluated
FALSEnever evaluated
0
2964 if (visual) {
visualDescription
TRUEnever evaluated
FALSEnever evaluated
0
2965 if (!rtl && i < nItems - 1) {
!rtlDescription
TRUEnever evaluated
FALSEnever evaluated
i < nItems - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
2966 nchars += end;-
2967 continue;
never executed: continue;
0
2968 }-
2969 if (rtl && nchars > 0)
rtlDescription
TRUEnever evaluated
FALSEnever evaluated
nchars > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2970 return insertionPoints[lastLine ? nchars : nchars - 1];
never executed: return insertionPoints[lastLine ? nchars : nchars - 1];
0
2971 }
never executed: end of block
0
2972 return eng->positionInLigature(&si, end, x, pos, -1,
never executed: return eng->positionInLigature(&si, end, x, pos, -1, cpos == QTextLine::CursorOnCharacter);
0
2973 cpos == QTextLine::CursorOnCharacter);
never executed: return eng->positionInLigature(&si, end, x, pos, -1, cpos == QTextLine::CursorOnCharacter);
0
2974 }-
2975 }
never executed: end of block
0
2976 Q_ASSERT(glyph_pos != -1);-
2977 return eng->positionInLigature(&si, end, x, edge, glyph_pos,
never executed: return eng->positionInLigature(&si, end, x, edge, glyph_pos, cpos == QTextLine::CursorOnCharacter);
0
2978 cpos == QTextLine::CursorOnCharacter);
never executed: return eng->positionInLigature(&si, end, x, edge, glyph_pos, cpos == QTextLine::CursorOnCharacter);
0
2979 }-
2980 }
never executed: end of block
0
2981 // right of last item-
2982// qDebug("right of last");-
2983 int item = visualOrder[nItems-1]+firstItem;-
2984 QScriptItem &si = eng->layoutData->items[item];-
2985 if (!si.num_glyphs)
!si.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2986 eng->shape(item);
never executed: eng->shape(item);
0
2987 int pos = si.position;-
2988 if (!(si.analysis.bidiLevel % 2))
!(si.analysis.bidiLevel % 2)Description
TRUEnever evaluated
FALSEnever evaluated
0
2989 pos += eng->length(item);
never executed: pos += eng->length(item);
0
2990 pos = qMax(line.from, pos);-
2991-
2992 int maxPos = line.from + line_length;-
2993-
2994 // except for the last line we assume that the-
2995 // character between lines is a space and we want-
2996 // to position the cursor to the left of that-
2997 // character.-
2998 // ###### breaks with japanese for example-
2999 if (this->index < eng->lines.count() - 1)
this->index < ...es.count() - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
3000 --maxPos;
never executed: --maxPos;
0
3001-
3002 pos = qMin(pos, maxPos);-
3003 return pos;
never executed: return pos;
0
3004}-
3005-
3006QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9