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) 2015 The Qt Company Ltd.-
4** Contact: http://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL21$-
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 http://www.qt.io/terms-conditions. For further-
15** information use the contact form at http://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 2.1 or version 3 as published by the Free-
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and-
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the-
22** following information to ensure the GNU Lesser General Public License-
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and-
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.-
25**-
26** As a special exception, The Qt Company gives you certain additional-
27** rights. These rights are described in The Qt Company LGPL Exception-
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.-
29**-
30** $QT_END_LICENSE$-
31**-
32****************************************************************************/-
33-
34#include "qtextlayout.h"-
35#include "qtextengine_p.h"-
36-
37#include <qthread.h>-
38#include <qfont.h>-
39#include <qmath.h>-
40#include <qpainter.h>-
41#include <qvarlengtharray.h>-
42#include <qtextformat.h>-
43#include <qabstracttextdocumentlayout.h>-
44#include "qtextdocument_p.h"-
45#include "qtextformat_p.h"-
46#include "qpainterpath.h"-
47#include "qglyphrun.h"-
48#include "qglyphrun_p.h"-
49#include "qrawfont.h"-
50#include "qrawfont_p.h"-
51#include <limits.h>-
52-
53#include <qdebug.h>-
54-
55#include "qfontengine_p.h"-
56#include <private/qpainter_p.h>-
57-
58QT_BEGIN_NAMESPACE-
59-
60#define ObjectSelectionBrush (QTextFormat::ForegroundBrush + 1)-
61#define SuppressText 0x5012-
62#define SuppressBackground 0x513-
63-
64/*!-
65 \class QTextLayout::FormatRange-
66 \reentrant-
67-
68 \brief The QTextLayout::FormatRange structure is used to apply extra formatting information-
69 for a specified area in the text layout's content.-
70 \inmodule QtGui-
71-
72 \sa QTextLayout::setFormats(), QTextLayout::draw()-
73*/-
74-
75/*!-
76 \variable QTextLayout::FormatRange::start-
77 Specifies the beginning of the format range within the text layout's text.-
78*/-
79-
80/*!-
81 \variable QTextLayout::FormatRange::length-
82 Specifies the numer of characters the format range spans.-
83*/-
84-
85/*!-
86 \variable QTextLayout::FormatRange::format-
87 Specifies the format to apply.-
88*/-
89-
90/*! \fn bool operator==(const FormatRange &lhs, const FormatRange &rhs)-
91 \relates QTextLayout::FormatRange-
92-
93 Returns true if the \c {start}, \c {length}, and \c {format} fields-
94 in \a lhs and \a rhs contain the same values respectively.-
95 */-
96-
97/*! \fn bool operator!=(const FormatRange &lhs, const FormatRange &rhs)-
98 \relates QTextLayout::FormatRange-
99-
100 Returns true if any of the \c {start}, \c {length}, or \c {format} fields-
101 in \a lhs and \a rhs contain different values respectively.-
102 */-
103-
104/*!-
105 \class QTextInlineObject-
106 \reentrant-
107-
108 \brief The QTextInlineObject class represents an inline object in-
109 a QAbstractTextDocumentLayout and its implementations.-
110 \inmodule QtGui-
111-
112 \ingroup richtext-processing-
113-
114 Normally, you do not need to create a QTextInlineObject. It is-
115 used by QAbstractTextDocumentLayout to handle inline objects when-
116 implementing a custom layout.-
117-
118 The inline object has various attributes that can be set, for-
119 example using, setWidth(), setAscent(), and setDescent(). The-
120 rectangle it occupies is given by rect(), and its direction by-
121 textDirection(). Its position in the text layout is given by-
122 textPosition(), and its format is given by format().-
123*/-
124-
125/*!-
126 \fn QTextInlineObject::QTextInlineObject(int i, QTextEngine *e)-
127 \internal-
128-
129 Creates a new inline object for the item at position \a i in the-
130 text engine \a e.-
131*/-
132-
133/*!-
134 \fn QTextInlineObject::QTextInlineObject()-
135-
136 \internal-
137*/-
138-
139/*!-
140 \fn bool QTextInlineObject::isValid() const-
141-
142 Returns \c true if this inline object is valid; otherwise returns-
143 false.-
144*/-
145-
146/*!-
147 Returns the inline object's rectangle.-
148-
149 \sa ascent(), descent(), width()-
150*/-
151QRectF QTextInlineObject::rect() const-
152{-
153 QScriptItem& si = eng->layoutData->items[itm];-
154 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
155}-
156-
157/*!-
158 Returns the inline object's width.-
159-
160 \sa ascent(), descent(), rect()-
161*/-
162qreal QTextInlineObject::width() const-
163{-
164 return eng->layoutData->items[itm].width.toReal();
never executed: return eng->layoutData->items[itm].width.toReal();
0
165}-
166-
167/*!-
168 Returns the inline object's ascent.-
169-
170 \sa descent(), width(), rect()-
171*/-
172qreal QTextInlineObject::ascent() const-
173{-
174 return eng->layoutData->items[itm].ascent.toReal();
never executed: return eng->layoutData->items[itm].ascent.toReal();
0
175}-
176-
177/*!-
178 Returns the inline object's descent.-
179-
180 \sa ascent(), width(), rect()-
181*/-
182qreal QTextInlineObject::descent() const-
183{-
184 return eng->layoutData->items[itm].descent.toReal();
never executed: return eng->layoutData->items[itm].descent.toReal();
0
185}-
186-
187/*!-
188 Returns the inline object's total height. This is equal to-
189 ascent() + descent() + 1.-
190-
191 \sa ascent(), descent(), width(), rect()-
192*/-
193qreal QTextInlineObject::height() const-
194{-
195 return eng->layoutData->items[itm].height().toReal();
never executed: return eng->layoutData->items[itm].height().toReal();
0
196}-
197-
198/*!-
199 Sets the inline object's width to \a w.-
200-
201 \sa width(), ascent(), descent(), rect()-
202*/-
203void QTextInlineObject::setWidth(qreal w)-
204{-
205 eng->layoutData->items[itm].width = QFixed::fromReal(w);-
206}
never executed: end of block
0
207-
208/*!-
209 Sets the inline object's ascent to \a a.-
210-
211 \sa ascent(), setDescent(), width(), rect()-
212*/-
213void QTextInlineObject::setAscent(qreal a)-
214{-
215 eng->layoutData->items[itm].ascent = QFixed::fromReal(a);-
216}
never executed: end of block
0
217-
218/*!-
219 Sets the inline object's descent to \a d.-
220-
221 \sa descent(), setAscent(), width(), rect()-
222*/-
223void QTextInlineObject::setDescent(qreal d)-
224{-
225 eng->layoutData->items[itm].descent = QFixed::fromReal(d);-
226}
never executed: end of block
0
227-
228/*!-
229 The position of the inline object within the text layout.-
230*/-
231int QTextInlineObject::textPosition() const-
232{-
233 return eng->layoutData->items[itm].position;
never executed: return eng->layoutData->items[itm].position;
0
234}-
235-
236/*!-
237 Returns an integer describing the format of the inline object-
238 within the text layout.-
239*/-
240int QTextInlineObject::formatIndex() const-
241{-
242 return eng->formatIndex(&eng->layoutData->items[itm]);
never executed: return eng->formatIndex(&eng->layoutData->items[itm]);
0
243}-
244-
245/*!-
246 Returns format of the inline object within the text layout.-
247*/-
248QTextFormat QTextInlineObject::format() const-
249{-
250 return eng->format(&eng->layoutData->items[itm]);
never executed: return eng->format(&eng->layoutData->items[itm]);
0
251}-
252-
253/*!-
254 Returns if the object should be laid out right-to-left or left-to-right.-
255*/-
256Qt::LayoutDirection QTextInlineObject::textDirection() const-
257{-
258 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);
eng->layoutDat....bidiLevel % 2Description
TRUEnever evaluated
FALSEnever evaluated
0
259}-
260-
261/*!-
262 \class QTextLayout-
263 \reentrant-
264-
265 \brief The QTextLayout class is used to lay out and render text.-
266 \inmodule QtGui-
267-
268 \ingroup richtext-processing-
269-
270 It offers many features expected from a modern text layout-
271 engine, including Unicode compliant rendering, line breaking and-
272 handling of cursor positioning. It can also produce and render-
273 device independent layout, something that is important for WYSIWYG-
274 applications.-
275-
276 The class has a rather low level API and unless you intend to-
277 implement your own text rendering for some specialized widget, you-
278 probably won't need to use it directly.-
279-
280 QTextLayout can be used with both plain and rich text.-
281-
282 QTextLayout can be used to create a sequence of QTextLine-
283 instances with given widths and can position them independently-
284 on the screen. Once the layout is done, these lines can be drawn-
285 on a paint device.-
286-
287 The text to be laid out can be provided in the constructor or set with-
288 setText().-
289-
290 The layout can be seen as a sequence of QTextLine objects; use createLine()-
291 to create a QTextLine instance, and lineAt() or lineForTextPosition() to retrieve-
292 created lines.-
293-
294 Here is a code snippet that demonstrates the layout phase:-
295 \snippet code/src_gui_text_qtextlayout.cpp 0-
296-
297 The text can then be rendered by calling the layout's draw() function:-
298 \snippet code/src_gui_text_qtextlayout.cpp 1-
299-
300 For a given position in the text you can find a valid cursor position with-
301 isValidCursorPosition(), nextCursorPosition(), and previousCursorPosition().-
302-
303 The QTextLayout itself can be positioned with setPosition(); it has a-
304 boundingRect(), and a minimumWidth() and a maximumWidth().-
305-
306 \sa QStaticText-
307*/-
308-
309/*!-
310 \enum QTextLayout::CursorMode-
311-
312 \value SkipCharacters-
313 \value SkipWords-
314*/-
315-
316/*!-
317 \fn QTextEngine *QTextLayout::engine() const-
318 \internal-
319-
320 Returns the text engine used to render the text layout.-
321*/-
322-
323/*!-
324 Constructs an empty text layout.-
325-
326 \sa setText()-
327*/-
328QTextLayout::QTextLayout()-
329{
never executed: end of block
d = new QTextEngine(); }
never executed: end of block
0
330-
331/*!-
332 Constructs a text layout to lay out the given \a text.-
333*/-
334QTextLayout::QTextLayout(const QString& text)-
335{-
336 d = new QTextEngine();-
337 d->text = text;-
338}
never executed: end of block
0
339-
340/*!-
341 Constructs a text layout to lay out the given \a text with the specified-
342 \a font.-
343-
344 All the metric and layout calculations will be done in terms of-
345 the paint device, \a paintdevice. If \a paintdevice is 0 the-
346 calculations will be done in screen metrics.-
347*/-
348QTextLayout::QTextLayout(const QString& text, const QFont &font, QPaintDevice *paintdevice)-
349{-
350 QFont f(font);-
351 if (paintdevice)
paintdeviceDescription
TRUEnever evaluated
FALSEnever evaluated
0
352 f = QFont(font, paintdevice);
never executed: f = QFont(font, paintdevice);
0
353 d = new QTextEngine((text.isNull() ? (const QString&)QString::fromLatin1("") : text), f);-
354}
never executed: end of block
0
355-
356/*!-
357 \internal-
358 Constructs a text layout to lay out the given \a block.-
359*/-
360QTextLayout::QTextLayout(const QTextBlock &block)-
361{-
362 d = new QTextEngine();-
363 d->block = block;-
364}
never executed: end of block
0
365-
366/*!-
367 Destructs the layout.-
368*/-
369QTextLayout::~QTextLayout()-
370{-
371 if (!d->stackEngine)
!d->stackEngineDescription
TRUEnever evaluated
FALSEnever evaluated
0
372 delete d;
never executed: delete d;
0
373}
never executed: end of block
0
374-
375#ifndef QT_NO_RAWFONT-
376/*!-
377 \internal-
378 Sets a raw font, to be used with QTextLayout::glyphRuns.-
379 Note that this only supports the needs of WebKit.-
380 Use of this function with e.g. QTextLayout::draw will result-
381 in undefined behaviour.-
382*/-
383void QTextLayout::setRawFont(const QRawFont &rawFont)-
384{-
385 d->rawFont = rawFont;-
386 d->useRawFont = true;-
387 d->resetFontEngineCache();-
388}
never executed: end of block
0
389#endif-
390-
391/*!-
392 Sets the layout's font to the given \a font. The layout is-
393 invalidated and must be laid out again.-
394-
395 \sa font()-
396*/-
397void QTextLayout::setFont(const QFont &font)-
398{-
399 d->fnt = font;-
400#ifndef QT_NO_RAWFONT-
401 d->useRawFont = false;-
402#endif-
403 d->resetFontEngineCache();-
404}
never executed: end of block
0
405-
406/*!-
407 Returns the current font that is used for the layout, or a default-
408 font if none is set.-
409-
410 \sa setFont()-
411*/-
412QFont QTextLayout::font() const-
413{-
414 return d->font();
never executed: return d->font();
0
415}-
416-
417/*!-
418 Sets the layout's text to the given \a string. The layout is-
419 invalidated and must be laid out again.-
420-
421 Notice that when using this QTextLayout as part of a QTextDocument this-
422 method will have no effect.-
423-
424 \sa text()-
425*/-
426void QTextLayout::setText(const QString& string)-
427{-
428 d->invalidate();-
429 d->clearLineData();-
430 d->text = string;-
431}
never executed: end of block
0
432-
433/*!-
434 Returns the layout's text.-
435-
436 \sa setText()-
437*/-
438QString QTextLayout::text() const-
439{-
440 return d->text;
never executed: return d->text;
0
441}-
442-
443/*!-
444 Sets the text option structure that controls the layout process to the-
445 given \a option.-
446-
447 \sa textOption()-
448*/-
449void QTextLayout::setTextOption(const QTextOption &option)-
450{-
451 d->option = option;-
452}
never executed: end of block
0
453-
454/*!-
455 Returns the current text option used to control the layout process.-
456-
457 \sa setTextOption()-
458*/-
459const QTextOption &QTextLayout::textOption() const-
460{-
461 return d->option;
never executed: return d->option;
0
462}-
463-
464/*!-
465 Sets the \a position and \a text of the area in the layout that is-
466 processed before editing occurs. The layout is-
467 invalidated and must be laid out again.-
468-
469 \sa preeditAreaPosition(), preeditAreaText()-
470*/-
471void QTextLayout::setPreeditArea(int position, const QString &text)-
472{-
473 if (d->preeditAreaPosition() == position && d->preeditAreaText() == text)
d->preeditArea...() == positionDescription
TRUEnever evaluated
FALSEnever evaluated
d->preeditAreaText() == textDescription
TRUEnever evaluated
FALSEnever evaluated
0
474 return;
never executed: return;
0
475 d->setPreeditArea(position, text);-
476-
477 if (d->block.docHandle())
d->block.docHandle()Description
TRUEnever evaluated
FALSEnever evaluated
0
478 d->block.docHandle()->documentChange(d->block.position(), d->block.length());
never executed: d->block.docHandle()->documentChange(d->block.position(), d->block.length());
0
479}
never executed: end of block
0
480-
481/*!-
482 Returns the position of the area in the text layout that will be-
483 processed before editing occurs.-
484-
485 \sa preeditAreaText()-
486*/-
487int QTextLayout::preeditAreaPosition() const-
488{-
489 return d->preeditAreaPosition();
never executed: return d->preeditAreaPosition();
0
490}-
491-
492/*!-
493 Returns the text that is inserted in the layout before editing occurs.-
494-
495 \sa preeditAreaPosition()-
496*/-
497QString QTextLayout::preeditAreaText() const-
498{-
499 return d->preeditAreaText();
never executed: return d->preeditAreaText();
0
500}-
501-
502#if QT_DEPRECATED_SINCE(5, 6)-
503/*!-
504 \obsolete Use setFormats() instead.-
505*/-
506void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList)-
507{-
508 setFormats(formatList.toVector());-
509}
never executed: end of block
0
510#endif // deprecated since 5.6-
511-
512/*!-
513 \since 5.6-
514-
515 Sets the additional formats supported by the text layout to \a formats.-
516 The formats are applied with preedit area text in place.-
517-
518 \sa formats(), clearFormats()-
519*/-
520void QTextLayout::setFormats(const QVector<FormatRange> &formats)-
521{-
522 d->setFormats(formats);-
523-
524 if (d->block.docHandle())
d->block.docHandle()Description
TRUEnever evaluated
FALSEnever evaluated
0
525 d->block.docHandle()->documentChange(d->block.position(), d->block.length());
never executed: d->block.docHandle()->documentChange(d->block.position(), d->block.length());
0
526}
never executed: end of block
0
527-
528#if QT_DEPRECATED_SINCE(5, 6)-
529/*!-
530 \obsolete Use formats() instead.-
531-
532 \sa setAdditionalFormats(), clearAdditionalFormats()-
533*/-
534QList<QTextLayout::FormatRange> QTextLayout::additionalFormats() const-
535{-
536 return formats().toList();
never executed: return formats().toList();
0
537}-
538#endif // deprecated since 5.6-
539-
540/*!-
541 \since 5.6-
542-
543 Returns the list of additional formats supported by the text layout.-
544-
545 \sa setFormats(), clearFormats()-
546*/-
547QVector<QTextLayout::FormatRange> QTextLayout::formats() const-
548{-
549 return d->formats();
never executed: return d->formats();
0
550}-
551-
552#if QT_DEPRECATED_SINCE(5, 6)-
553/*!-
554 \obsolete Use clearFormats() instead.-
555*/-
556void QTextLayout::clearAdditionalFormats()-
557{-
558 clearFormats();-
559}
never executed: end of block
0
560#endif // deprecated since 5.6-
561-
562/*!-
563 \since 5.6-
564-
565 Clears the list of additional formats supported by the text layout.-
566-
567 \sa formats(), setFormats()-
568*/-
569void QTextLayout::clearFormats()-
570{-
571 setFormats(QVector<FormatRange>());-
572}
never executed: end of block
0
573-
574/*!-
575 Enables caching of the complete layout information if \a enable is-
576 true; otherwise disables layout caching. Usually-
577 QTextLayout throws most of the layouting information away after a-
578 call to endLayout() to reduce memory consumption. If you however-
579 want to draw the laid out text directly afterwards enabling caching-
580 might speed up drawing significantly.-
581-
582 \sa cacheEnabled()-
583*/-
584void QTextLayout::setCacheEnabled(bool enable)-
585{-
586 d->cacheGlyphs = enable;-
587}
never executed: end of block
0
588-
589/*!-
590 Returns \c true if the complete layout information is cached; otherwise-
591 returns \c false.-
592-
593 \sa setCacheEnabled()-
594*/-
595bool QTextLayout::cacheEnabled() const-
596{-
597 return d->cacheGlyphs;
never executed: return d->cacheGlyphs;
0
598}-
599-
600/*!-
601 Sets the visual cursor movement style to the given \a style. If the-
602 QTextLayout is backed by a document, you can ignore this and use the option-
603 in QTextDocument, this option is for widgets like QLineEdit or custom-
604 widgets without a QTextDocument. Default value is Qt::LogicalMoveStyle.-
605-
606 \sa cursorMoveStyle()-
607*/-
608void QTextLayout::setCursorMoveStyle(Qt::CursorMoveStyle style)-
609{-
610 d->visualMovement = style == Qt::VisualMoveStyle;-
611}
never executed: end of block
0
612-
613/*!-
614 The cursor movement style of this QTextLayout. The default is-
615 Qt::LogicalMoveStyle.-
616-
617 \sa setCursorMoveStyle()-
618*/-
619Qt::CursorMoveStyle QTextLayout::cursorMoveStyle() const-
620{-
621 return d->visualMovement ? Qt::VisualMoveStyle : Qt::LogicalMoveStyle;
never executed: return d->visualMovement ? Qt::VisualMoveStyle : Qt::LogicalMoveStyle;
d->visualMovementDescription
TRUEnever evaluated
FALSEnever evaluated
0
622}-
623-
624/*!-
625 Begins the layout process.-
626-
627 \sa endLayout()-
628*/-
629void QTextLayout::beginLayout()-
630{-
631#ifndef QT_NO_DEBUG-
632 if (d->layoutData && d->layoutData->layoutState == QTextEngine::InLayout) {
d->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
d->layoutData-...gine::InLayoutDescription
TRUEnever evaluated
FALSEnever evaluated
0
633 qWarning("QTextLayout::beginLayout: Called while already doing layout");-
634 return;
never executed: return;
0
635 }-
636#endif-
637 d->invalidate();-
638 d->clearLineData();-
639 d->itemize();-
640 d->layoutData->layoutState = QTextEngine::InLayout;-
641}
never executed: end of block
0
642-
643/*!-
644 Ends the layout process.-
645-
646 \sa beginLayout()-
647*/-
648void QTextLayout::endLayout()-
649{-
650#ifndef QT_NO_DEBUG-
651 if (!d->layoutData || d->layoutData->layoutState == QTextEngine::LayoutEmpty) {
!d->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
d->layoutData-...e::LayoutEmptyDescription
TRUEnever evaluated
FALSEnever evaluated
0
652 qWarning("QTextLayout::endLayout: Called without beginLayout()");-
653 return;
never executed: return;
0
654 }-
655#endif-
656 int l = d->lines.size();-
657 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
658 QTextLine(l-1, d).setNumColumns(INT_MAX);-
659 }
never executed: end of block
0
660 d->layoutData->layoutState = QTextEngine::LayoutEmpty;-
661 if (!d->cacheGlyphs)
!d->cacheGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
662 d->freeMemory();
never executed: d->freeMemory();
0
663}
never executed: end of block
0
664-
665/*!-
666 \since 4.4-
667-
668 Clears the line information in the layout. After having called-
669 this function, lineCount() returns 0.-
670*/-
671void QTextLayout::clearLayout()-
672{-
673 d->clearLineData();-
674}
never executed: end of block
0
675-
676/*!-
677 Returns the next valid cursor position after \a oldPos that-
678 respects the given cursor \a mode.-
679 Returns value of \a oldPos, if \a oldPos is not a valid cursor position.-
680-
681 \sa isValidCursorPosition(), previousCursorPosition()-
682*/-
683int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const-
684{-
685 const QCharAttributes *attributes = d->attributes();-
686 int len = d->block.isValid() ? d->block.length() - 1
d->block.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
687 : d->layoutData->string.length();-
688 Q_ASSERT(len <= d->layoutData->string.length());-
689 if (!attributes || oldPos < 0 || oldPos >= len)
!attributesDescription
TRUEnever evaluated
FALSEnever evaluated
oldPos < 0Description
TRUEnever evaluated
FALSEnever evaluated
oldPos >= lenDescription
TRUEnever evaluated
FALSEnever evaluated
0
690 return oldPos;
never executed: return oldPos;
0
691-
692 if (mode == SkipCharacters) {
mode == SkipCharactersDescription
TRUEnever evaluated
FALSEnever evaluated
0
693 oldPos++;-
694 while (oldPos < len && !attributes[oldPos].graphemeBoundary)
oldPos < lenDescription
TRUEnever evaluated
FALSEnever evaluated
!attributes[ol...aphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
695 oldPos++;
never executed: oldPos++;
0
696 } else {
never executed: end of block
0
697 if (oldPos < len && d->atWordSeparator(oldPos)) {
oldPos < lenDescription
TRUEnever evaluated
FALSEnever evaluated
d->atWordSeparator(oldPos)Description
TRUEnever evaluated
FALSEnever evaluated
0
698 oldPos++;-
699 while (oldPos < len && d->atWordSeparator(oldPos))
oldPos < lenDescription
TRUEnever evaluated
FALSEnever evaluated
d->atWordSeparator(oldPos)Description
TRUEnever evaluated
FALSEnever evaluated
0
700 oldPos++;
never executed: oldPos++;
0
701 } else {
never executed: end of block
0
702 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
703 oldPos++;
never executed: oldPos++;
0
704 }
never executed: end of block
0
705 while (oldPos < len && attributes[oldPos].whiteSpace)
oldPos < lenDescription
TRUEnever evaluated
FALSEnever evaluated
attributes[oldPos].whiteSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
706 oldPos++;
never executed: oldPos++;
0
707 }
never executed: end of block
0
708-
709 return oldPos;
never executed: return oldPos;
0
710}-
711-
712/*!-
713 Returns the first valid cursor position before \a oldPos that-
714 respects the given cursor \a mode.-
715 Returns value of \a oldPos, if \a oldPos is not a valid cursor position.-
716-
717 \sa isValidCursorPosition(), nextCursorPosition()-
718*/-
719int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const-
720{-
721 const QCharAttributes *attributes = d->attributes();-
722 int len = d->block.isValid() ? d->block.length() - 1
d->block.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
723 : d->layoutData->string.length();-
724 Q_ASSERT(len <= d->layoutData->string.length());-
725 if (!attributes || oldPos <= 0 || oldPos > len)
!attributesDescription
TRUEnever evaluated
FALSEnever evaluated
oldPos <= 0Description
TRUEnever evaluated
FALSEnever evaluated
oldPos > lenDescription
TRUEnever evaluated
FALSEnever evaluated
0
726 return oldPos;
never executed: return oldPos;
0
727-
728 if (mode == SkipCharacters) {
mode == SkipCharactersDescription
TRUEnever evaluated
FALSEnever evaluated
0
729 oldPos--;-
730 while (oldPos && !attributes[oldPos].graphemeBoundary)
oldPosDescription
TRUEnever evaluated
FALSEnever evaluated
!attributes[ol...aphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
731 oldPos--;
never executed: oldPos--;
0
732 } else {
never executed: end of block
0
733 while (oldPos > 0 && attributes[oldPos - 1].whiteSpace)
oldPos > 0Description
TRUEnever evaluated
FALSEnever evaluated
attributes[old... 1].whiteSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
734 oldPos--;
never executed: oldPos--;
0
735-
736 if (oldPos && d->atWordSeparator(oldPos-1)) {
oldPosDescription
TRUEnever evaluated
FALSEnever evaluated
d->atWordSeparator(oldPos-1)Description
TRUEnever evaluated
FALSEnever evaluated
0
737 oldPos--;-
738 while (oldPos && d->atWordSeparator(oldPos-1))
oldPosDescription
TRUEnever evaluated
FALSEnever evaluated
d->atWordSeparator(oldPos-1)Description
TRUEnever evaluated
FALSEnever evaluated
0
739 oldPos--;
never executed: oldPos--;
0
740 } else {
never executed: end of block
0
741 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
742 oldPos--;
never executed: oldPos--;
0
743 }
never executed: end of block
0
744 }-
745-
746 return oldPos;
never executed: return oldPos;
0
747}-
748-
749/*!-
750 Returns the cursor position to the right of \a oldPos, next to it.-
751 It's dependent on the visual position of characters, after bi-directional-
752 reordering.-
753-
754 \sa leftCursorPosition(), nextCursorPosition()-
755*/-
756int QTextLayout::rightCursorPosition(int oldPos) const-
757{-
758 int newPos = d->positionAfterVisualMovement(oldPos, QTextCursor::Right);-
759// qDebug("%d -> %d", oldPos, newPos);-
760 return newPos;
never executed: return newPos;
0
761}-
762-
763/*!-
764 Returns the cursor position to the left of \a oldPos, next to it.-
765 It's dependent on the visual position of characters, after bi-directional-
766 reordering.-
767-
768 \sa rightCursorPosition(), previousCursorPosition()-
769*/-
770int QTextLayout::leftCursorPosition(int oldPos) const-
771{-
772 int newPos = d->positionAfterVisualMovement(oldPos, QTextCursor::Left);-
773// qDebug("%d -> %d", oldPos, newPos);-
774 return newPos;
never executed: return newPos;
0
775}-
776-
777/*!/-
778 Returns \c true if position \a pos is a valid cursor position.-
779-
780 In a Unicode context some positions in the text are not valid-
781 cursor positions, because the position is inside a Unicode-
782 surrogate or a grapheme cluster.-
783-
784 A grapheme cluster is a sequence of two or more Unicode characters-
785 that form one indivisible entity on the screen. For example the-
786 latin character `\unicode{0xC4}' can be represented in Unicode by two-
787 characters, `A' (0x41), and the combining diaresis (0x308). A text-
788 cursor can only validly be positioned before or after these two-
789 characters, never between them since that wouldn't make sense. In-
790 indic languages every syllable forms a grapheme cluster.-
791*/-
792bool QTextLayout::isValidCursorPosition(int pos) const-
793{-
794 const QCharAttributes *attributes = d->attributes();-
795 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
796 return false;
never executed: return false;
0
797 return attributes[pos].graphemeBoundary;
never executed: return attributes[pos].graphemeBoundary;
0
798}-
799-
800/*!-
801 Returns a new text line to be laid out if there is text to be-
802 inserted into the layout; otherwise returns an invalid text line.-
803-
804 The text layout creates a new line object that starts after the-
805 last line in the layout, or at the beginning if the layout is empty.-
806 The layout maintains an internal cursor, and each line is filled-
807 with text from the cursor position onwards when the-
808 QTextLine::setLineWidth() function is called.-
809-
810 Once QTextLine::setLineWidth() is called, a new line can be created and-
811 filled with text. Repeating this process will lay out the whole block-
812 of text contained in the QTextLayout. If there is no text left to be-
813 inserted into the layout, the QTextLine returned will not be valid-
814 (isValid() will return false).-
815*/-
816QTextLine QTextLayout::createLine()-
817{-
818#ifndef QT_NO_DEBUG-
819 if (!d->layoutData || d->layoutData->layoutState == QTextEngine::LayoutEmpty) {
!d->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
d->layoutData-...e::LayoutEmptyDescription
TRUEnever evaluated
FALSEnever evaluated
0
820 qWarning("QTextLayout::createLine: Called without layouting");-
821 return QTextLine();
never executed: return QTextLine();
0
822 }-
823#endif-
824 if (d->layoutData->layoutState == QTextEngine::LayoutFailed)
d->layoutData-...::LayoutFailedDescription
TRUEnever evaluated
FALSEnever evaluated
0
825 return QTextLine();
never executed: return QTextLine();
0
826-
827 int l = d->lines.size();-
828 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
829 QTextLine(l-1, d).setNumColumns(INT_MAX);-
830 }
never executed: end of block
0
831 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
832 int strlen = d->layoutData->string.length();-
833 if (l && from >= strlen) {
lDescription
TRUEnever evaluated
FALSEnever evaluated
from >= strlenDescription
TRUEnever evaluated
FALSEnever evaluated
0
834 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
835 return QTextLine();
never executed: return QTextLine();
0
836 }
never executed: end of block
0
837-
838 QScriptLine line;-
839 line.from = from;-
840 line.length = -1;-
841 line.justified = false;-
842 line.gridfitted = false;-
843-
844 d->lines.append(line);-
845 return QTextLine(l, d);
never executed: return QTextLine(l, d);
0
846}-
847-
848/*!-
849 Returns the number of lines in this text layout.-
850-
851 \sa lineAt()-
852*/-
853int QTextLayout::lineCount() const-
854{-
855 return d->lines.size();
never executed: return d->lines.size();
0
856}-
857-
858/*!-
859 Returns the \a{i}-th line of text in this text layout.-
860-
861 \sa lineCount(), lineForTextPosition()-
862*/-
863QTextLine QTextLayout::lineAt(int i) const-
864{-
865 return i < lineCount() ? QTextLine(i, d) : QTextLine();
never executed: return i < lineCount() ? QTextLine(i, d) : QTextLine();
i < lineCount()Description
TRUEnever evaluated
FALSEnever evaluated
0
866}-
867-
868/*!-
869 Returns the line that contains the cursor position specified by \a pos.-
870-
871 \sa isValidCursorPosition(), lineAt()-
872*/-
873QTextLine QTextLayout::lineForTextPosition(int pos) const-
874{-
875 int lineNum = d->lineNumberForTextPosition(pos);-
876 return lineNum >= 0 ? lineAt(lineNum) : QTextLine();
never executed: return lineNum >= 0 ? lineAt(lineNum) : QTextLine();
lineNum >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
877}-
878-
879/*!-
880 \since 4.2-
881-
882 The global position of the layout. This is independent of the-
883 bounding rectangle and of the layout process.-
884-
885 \sa setPosition()-
886*/-
887QPointF QTextLayout::position() const-
888{-
889 return d->position;
never executed: return d->position;
0
890}-
891-
892/*!-
893 Moves the text layout to point \a p.-
894-
895 \sa position()-
896*/-
897void QTextLayout::setPosition(const QPointF &p)-
898{-
899 d->position = p;-
900}
never executed: end of block
0
901-
902/*!-
903 The smallest rectangle that contains all the lines in the layout.-
904*/-
905QRectF QTextLayout::boundingRect() const-
906{-
907 if (d->lines.isEmpty())
d->lines.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
908 return QRectF();
never executed: return QRectF();
0
909-
910 QFixed xmax, ymax;-
911 QFixed xmin = d->lines.at(0).x;-
912 QFixed ymin = d->lines.at(0).y;-
913-
914 for (int i = 0; i < d->lines.size(); ++i) {
i < d->lines.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
915 const QScriptLine &si = d->lines[i];-
916 xmin = qMin(xmin, si.x);-
917 ymin = qMin(ymin, si.y);-
918 QFixed lineWidth = si.width < QFIXED_MAX ? qMax(si.width, si.textWidth) : si.textWidth;
si.width < (2147483647/256)Description
TRUEnever evaluated
FALSEnever evaluated
0
919 xmax = qMax(xmax, si.x+lineWidth);-
920 // ### shouldn't the ascent be used in ymin???-
921 ymax = qMax(ymax, si.y+si.height().ceil());-
922 }
never executed: end of block
0
923 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
924}-
925-
926/*!-
927 The minimum width the layout needs. This is the width of the-
928 layout's smallest non-breakable substring.-
929-
930 \warning This function only returns a valid value after the layout-
931 has been done.-
932-
933 \sa maximumWidth()-
934*/-
935qreal QTextLayout::minimumWidth() const-
936{-
937 return d->minWidth.toReal();
never executed: return d->minWidth.toReal();
0
938}-
939-
940/*!-
941 The maximum width the layout could expand to; this is essentially-
942 the width of the entire text.-
943-
944 \warning This function only returns a valid value after the layout-
945 has been done.-
946-
947 \sa minimumWidth()-
948*/-
949qreal QTextLayout::maximumWidth() const-
950{-
951 return d->maxWidth.toReal();
never executed: return d->maxWidth.toReal();
0
952}-
953-
954-
955/*!-
956 \internal-
957*/-
958void QTextLayout::setFlags(int flags)-
959{-
960 if (flags & Qt::TextJustificationForced) {
flags & Qt::Te...ficationForcedDescription
TRUEnever evaluated
FALSEnever evaluated
0
961 d->option.setAlignment(Qt::AlignJustify);-
962 d->forceJustification = true;-
963 }
never executed: end of block
0
964-
965 if (flags & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
flags & (Qt::T...ceRightToLeft)Description
TRUEnever evaluated
FALSEnever evaluated
0
966 d->ignoreBidi = true;-
967 d->option.setTextDirection((flags & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);-
968 }
never executed: end of block
0
969}
never executed: end of block
0
970-
971static void addSelectedRegionsToPath(QTextEngine *eng, int lineNumber, const QPointF &pos, QTextLayout::FormatRange *selection,-
972 QPainterPath *region, QRectF boundingRect)-
973{-
974 const QScriptLine &line = eng->lines[lineNumber];-
975-
976 QTextLineItemIterator iterator(eng, lineNumber, pos, selection);-
977-
978-
979-
980 const qreal selectionY = pos.y() + line.y.toReal();-
981 const qreal lineHeight = line.height().toReal();-
982-
983 QFixed lastSelectionX = iterator.x;-
984 QFixed lastSelectionWidth;-
985-
986 while (!iterator.atEnd()) {
!iterator.atEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
987 iterator.next();-
988-
989 QFixed selectionX, selectionWidth;-
990 if (iterator.getSelectionBounds(&selectionX, &selectionWidth)) {
iterator.getSe...electionWidth)Description
TRUEnever evaluated
FALSEnever evaluated
0
991 if (selectionX == lastSelectionX + lastSelectionWidth) {
selectionX == ...SelectionWidthDescription
TRUEnever evaluated
FALSEnever evaluated
0
992 lastSelectionWidth += selectionWidth;-
993 continue;
never executed: continue;
0
994 }-
995-
996 if (lastSelectionWidth > 0) {
lastSelectionWidth > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
997 QRectF rect = boundingRect & QRectF(lastSelectionX.toReal(), selectionY, lastSelectionWidth.toReal(), lineHeight);-
998 rect.moveLeft(qFloor(rect.left()));-
999 rect.moveTop(qFloor(rect.top()));-
1000 region->addRect(rect);-
1001 }
never executed: end of block
0
1002-
1003 lastSelectionX = selectionX;-
1004 lastSelectionWidth = selectionWidth;-
1005 }
never executed: end of block
0
1006 }
never executed: end of block
0
1007 if (lastSelectionWidth > 0) {
lastSelectionWidth > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1008 QRectF rect = boundingRect & QRectF(lastSelectionX.toReal(), selectionY, lastSelectionWidth.toReal(), lineHeight);-
1009 rect.moveLeft(qFloor(rect.left()));-
1010 rect.moveTop(qFloor(rect.top()));-
1011 region->addRect(rect);-
1012 }
never executed: end of block
0
1013}
never executed: end of block
0
1014-
1015static inline QRectF clipIfValid(const QRectF &rect, const QRectF &clip)-
1016{-
1017 return clip.isValid() ? (rect & clip) : rect;
never executed: return clip.isValid() ? (rect & clip) : rect;
clip.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
1018}-
1019-
1020-
1021/*!-
1022 Returns the glyph indexes and positions for all glyphs corresponding to the \a length characters-
1023 starting at the position \a from in this QTextLayout. This is an expensive function, and should-
1024 not be called in a time sensitive context.-
1025-
1026 If \a from is less than zero, then the glyph run will begin at the first character in the-
1027 layout. If \a length is less than zero, it will span the entire string from the start position.-
1028-
1029 \since 4.8-
1030-
1031 \sa draw(), QPainter::drawGlyphRun()-
1032*/-
1033#if !defined(QT_NO_RAWFONT)-
1034QList<QGlyphRun> QTextLayout::glyphRuns(int from, int length) const-
1035{-
1036 if (from < 0)
from < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1037 from = 0;
never executed: from = 0;
0
1038 if (length < 0)
length < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1039 length = text().length();
never executed: length = text().length();
0
1040-
1041 QHash<QPair<QFontEngine *, int>, QGlyphRun> glyphRunHash;-
1042 for (int i=0; i<d->lines.size(); ++i) {
i<d->lines.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1043 if (d->lines[i].from > from + length)
d->lines[i].fr... from + lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1044 break;
never executed: break;
0
1045 else if (d->lines[i].from + d->lines[i].length >= from) {
d->lines[i].fr...length >= fromDescription
TRUEnever evaluated
FALSEnever evaluated
0
1046 QList<QGlyphRun> glyphRuns = QTextLine(i, d).glyphRuns(from, length);-
1047-
1048 for (int j = 0; j < glyphRuns.size(); j++) {
j < glyphRuns.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1049 const QGlyphRun &glyphRun = glyphRuns.at(j);-
1050 QRawFont rawFont = glyphRun.rawFont();-
1051-
1052 QFontEngine *fontEngine = rawFont.d->fontEngine;-
1053 QGlyphRun::GlyphRunFlags flags = glyphRun.flags();-
1054 QPair<QFontEngine *, int> key(fontEngine, int(flags));-
1055 // merge the glyph runs using the same font-
1056 if (glyphRunHash.contains(key)) {
glyphRunHash.contains(key)Description
TRUEnever evaluated
FALSEnever evaluated
0
1057 QGlyphRun &oldGlyphRun = glyphRunHash[key];-
1058-
1059 QVector<quint32> indexes = oldGlyphRun.glyphIndexes();-
1060 QVector<QPointF> positions = oldGlyphRun.positions();-
1061 QRectF boundingRect = oldGlyphRun.boundingRect();-
1062-
1063 indexes += glyphRun.glyphIndexes();-
1064 positions += glyphRun.positions();-
1065 boundingRect = boundingRect.united(glyphRun.boundingRect());-
1066-
1067 oldGlyphRun.setGlyphIndexes(indexes);-
1068 oldGlyphRun.setPositions(positions);-
1069 oldGlyphRun.setBoundingRect(boundingRect);-
1070 } else {
never executed: end of block
0
1071 glyphRunHash[key] = glyphRun;-
1072 }
never executed: end of block
0
1073 }-
1074 }
never executed: end of block
0
1075 }
never executed: end of block
0
1076-
1077 return glyphRunHash.values();
never executed: return glyphRunHash.values();
0
1078}-
1079#endif // QT_NO_RAWFONT-
1080-
1081/*!-
1082 Draws the whole layout on the painter \a p at the position specified by \a pos.-
1083 The rendered layout includes the given \a selections and is clipped within-
1084 the rectangle specified by \a clip.-
1085*/-
1086void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRange> &selections, const QRectF &clip) const-
1087{-
1088 if (d->lines.isEmpty())
d->lines.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1089 return;
never executed: return;
0
1090-
1091 if (!d->layoutData)
!d->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
1092 d->itemize();
never executed: d->itemize();
0
1093-
1094 QPointF position = pos + d->position;-
1095-
1096 QFixed clipy = (INT_MIN/256);-
1097 QFixed clipe = (INT_MAX/256);-
1098 if (clip.isValid()) {
clip.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
1099 clipy = QFixed::fromReal(clip.y() - position.y());-
1100 clipe = clipy + QFixed::fromReal(clip.height());-
1101 }
never executed: end of block
0
1102-
1103 int firstLine = 0;-
1104 int lastLine = d->lines.size();-
1105 for (int i = 0; i < d->lines.size(); ++i) {
i < d->lines.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1106 QTextLine l(i, d);-
1107 const QScriptLine &sl = d->lines[i];-
1108-
1109 if (sl.y > clipe) {
sl.y > clipeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1110 lastLine = i;-
1111 break;
never executed: break;
0
1112 }-
1113 if ((sl.y + sl.height()) < clipy) {
(sl.y + sl.height()) < clipyDescription
TRUEnever evaluated
FALSEnever evaluated
0
1114 firstLine = i;-
1115 continue;
never executed: continue;
0
1116 }-
1117 }
never executed: end of block
0
1118-
1119 QPainterPath excludedRegion;-
1120 QPainterPath textDoneRegion;-
1121 for (int i = 0; i < selections.size(); ++i) {
i < selections.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1122 FormatRange selection = selections.at(i);-
1123 const QBrush bg = selection.format.background();-
1124-
1125 QPainterPath region;-
1126 region.setFillRule(Qt::WindingFill);-
1127-
1128 for (int line = firstLine; line < lastLine; ++line) {
line < lastLineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1129 const QScriptLine &sl = d->lines[line];-
1130 QTextLine tl(line, d);-
1131-
1132 QRectF lineRect(tl.naturalTextRect());-
1133 lineRect.translate(position);-
1134 lineRect.adjust(0, 0, d->leadingSpaceWidth(sl).toReal(), 0);-
1135-
1136 bool isLastLineInBlock = (line == d->lines.size()-1);-
1137 int sl_length = sl.length + (isLastLineInBlock? 1 : 0); // the infamous newline
isLastLineInBlockDescription
TRUEnever evaluated
FALSEnever evaluated
0
1138-
1139-
1140 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
1141 continue; // no actual intersection
never executed: continue;
0
1142-
1143 const bool selectionStartInLine = sl.from <= selection.start;-
1144 const bool selectionEndInLine = selection.start + selection.length < sl.from + sl_length;-
1145-
1146 if (sl.length && (selectionStartInLine || selectionEndInLine)) {
sl.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
selectionStartInLineDescription
TRUEnever evaluated
FALSEnever evaluated
selectionEndInLineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1147 addSelectedRegionsToPath(d, line, position, &selection, &region, clipIfValid(lineRect, clip));-
1148 } else {
never executed: end of block
0
1149 region.addRect(clipIfValid(lineRect, clip));-
1150 }
never executed: end of block
0
1151-
1152 if (selection.format.boolProperty(QTextFormat::FullWidthSelection)) {
selection.form...idthSelection)Description
TRUEnever evaluated
FALSEnever evaluated
0
1153 QRectF fullLineRect(tl.rect());-
1154 fullLineRect.translate(position);-
1155 fullLineRect.setRight(QFIXED_MAX);-
1156 if (!selectionEndInLine)
!selectionEndInLineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1157 region.addRect(clipIfValid(QRectF(lineRect.topRight(), fullLineRect.bottomRight()), clip));
never executed: region.addRect(clipIfValid(QRectF(lineRect.topRight(), fullLineRect.bottomRight()), clip));
0
1158 if (!selectionStartInLine)
!selectionStartInLineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1159 region.addRect(clipIfValid(QRectF(fullLineRect.topLeft(), lineRect.bottomLeft()), clip));
never executed: region.addRect(clipIfValid(QRectF(fullLineRect.topLeft(), lineRect.bottomLeft()), clip));
0
1160 } else if (!selectionEndInLine
never executed: end of block
!selectionEndInLineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1161 && isLastLineInBlock
isLastLineInBlockDescription
TRUEnever evaluated
FALSEnever evaluated
0
1162 &&!(d->option.flags() & QTextOption::ShowLineAndParagraphSeparators)) {
!(d->option.fl...aphSeparators)Description
TRUEnever evaluated
FALSEnever evaluated
0
1163 region.addRect(clipIfValid(QRectF(lineRect.right(), lineRect.top(),-
1164 lineRect.height()/4, lineRect.height()), clip));-
1165 }
never executed: end of block
0
1166-
1167 }
never executed: end of block
0
1168 {-
1169 const QPen oldPen = p->pen();-
1170 const QBrush oldBrush = p->brush();-
1171-
1172 p->setPen(selection.format.penProperty(QTextFormat::OutlinePen));-
1173 p->setBrush(selection.format.brushProperty(QTextFormat::BackgroundBrush));-
1174 p->drawPath(region);-
1175-
1176 p->setPen(oldPen);-
1177 p->setBrush(oldBrush);-
1178 }-
1179-
1180-
1181-
1182 bool hasText = (selection.format.foreground().style() != Qt::NoBrush);-
1183 bool hasBackground= (selection.format.background().style() != Qt::NoBrush);-
1184-
1185 if (hasBackground) {
hasBackgroundDescription
TRUEnever evaluated
FALSEnever evaluated
0
1186 selection.format.setProperty(ObjectSelectionBrush, selection.format.property(QTextFormat::BackgroundBrush));-
1187 // don't just clear the property, set an empty brush that overrides a potential-
1188 // background brush specified in the text-
1189 selection.format.setProperty(QTextFormat::BackgroundBrush, QBrush());-
1190 selection.format.clearProperty(QTextFormat::OutlinePen);-
1191 }
never executed: end of block
0
1192-
1193 selection.format.setProperty(SuppressText, !hasText);-
1194-
1195 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
1196 continue;
never executed: continue;
0
1197-
1198 p->save();-
1199 p->setClipPath(region, Qt::IntersectClip);-
1200-
1201 for (int line = firstLine; line < lastLine; ++line) {
line < lastLineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1202 QTextLine l(line, d);-
1203 l.draw(p, position, &selection);-
1204 }
never executed: end of block
0
1205 p->restore();-
1206-
1207 if (hasText) {
hasTextDescription
TRUEnever evaluated
FALSEnever evaluated
0
1208 textDoneRegion += region;-
1209 } else {
never executed: end of block
0
1210 if (hasBackground)
hasBackgroundDescription
TRUEnever evaluated
FALSEnever evaluated
0
1211 textDoneRegion -= region;
never executed: textDoneRegion -= region;
0
1212 }
never executed: end of block
0
1213-
1214 excludedRegion += region;-
1215 }
never executed: end of block
0
1216-
1217 QPainterPath needsTextButNoBackground = excludedRegion - textDoneRegion;-
1218 if (!needsTextButNoBackground.isEmpty()){
!needsTextButN...ound.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1219 p->save();-
1220 p->setClipPath(needsTextButNoBackground, Qt::IntersectClip);-
1221 FormatRange selection;-
1222 selection.start = 0;-
1223 selection.length = INT_MAX;-
1224 selection.format.setProperty(SuppressBackground, true);-
1225 for (int line = firstLine; line < lastLine; ++line) {
line < lastLineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1226 QTextLine l(line, d);-
1227 l.draw(p, position, &selection);-
1228 }
never executed: end of block
0
1229 p->restore();-
1230 }
never executed: end of block
0
1231-
1232 if (!excludedRegion.isEmpty()) {
!excludedRegion.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1233 p->save();-
1234 QPainterPath path;-
1235 QRectF br = boundingRect().translated(position);-
1236 br.setRight(QFIXED_MAX);-
1237 if (!clip.isNull())
!clip.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
1238 br = br.intersected(clip);
never executed: br = br.intersected(clip);
0
1239 path.addRect(br);-
1240 path -= excludedRegion;-
1241 p->setClipPath(path, Qt::IntersectClip);-
1242 }
never executed: end of block
0
1243-
1244 for (int i = firstLine; i < lastLine; ++i) {
i < lastLineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1245 QTextLine l(i, d);-
1246 l.draw(p, position);-
1247 }
never executed: end of block
0
1248 if (!excludedRegion.isEmpty())
!excludedRegion.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1249 p->restore();
never executed: p->restore();
0
1250-
1251-
1252 if (!d->cacheGlyphs)
!d->cacheGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1253 d->freeMemory();
never executed: d->freeMemory();
0
1254}
never executed: end of block
0
1255-
1256/*!-
1257 \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition) const-
1258 \overload-
1259-
1260 Draws a text cursor with the current pen at the given \a position using the-
1261 \a painter specified.-
1262 The corresponding position within the text is specified by \a cursorPosition.-
1263*/-
1264void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition) const-
1265{-
1266 drawCursor(p, pos, cursorPosition, 1);-
1267}
never executed: end of block
0
1268-
1269/*!-
1270 \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition, int width) const-
1271-
1272 Draws a text cursor with the current pen and the specified \a width at the given \a position using the-
1273 \a painter specified.-
1274 The corresponding position within the text is specified by \a cursorPosition.-
1275*/-
1276void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition, int width) const-
1277{-
1278 if (d->lines.isEmpty())
d->lines.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1279 return;
never executed: return;
0
1280-
1281 if (!d->layoutData)
!d->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
1282 d->itemize();
never executed: d->itemize();
0
1283-
1284 QPointF position = pos + d->position;-
1285-
1286 cursorPosition = qBound(0, cursorPosition, d->layoutData->string.length());-
1287 int line = d->lineNumberForTextPosition(cursorPosition);-
1288 if (line < 0)
line < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1289 line = 0;
never executed: line = 0;
0
1290 if (line >= d->lines.size())
line >= d->lines.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1291 return;
never executed: return;
0
1292-
1293 QTextLine l(line, d);-
1294 const QScriptLine &sl = d->lines[line];-
1295-
1296 qreal x = position.x() + l.cursorToX(cursorPosition);-
1297-
1298 int itm;-
1299-
1300 if (d->visualCursorMovement()) {
d->visualCursorMovement()Description
TRUEnever evaluated
FALSEnever evaluated
0
1301 if (cursorPosition == sl.from + sl.length)
cursorPosition...om + sl.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1302 cursorPosition--;
never executed: cursorPosition--;
0
1303 itm = d->findItem(cursorPosition);-
1304 } else
never executed: end of block
0
1305 itm = d->findItem(cursorPosition - 1);
never executed: itm = d->findItem(cursorPosition - 1);
0
1306-
1307 QFixed base = sl.base();-
1308 QFixed descent = sl.descent;-
1309 bool rightToLeft = d->isRightToLeft();-
1310 if (itm >= 0) {
itm >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1311 const QScriptItem &si = d->layoutData->items.at(itm);-
1312 if (si.ascent > 0)
si.ascent > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1313 base = si.ascent;
never executed: base = si.ascent;
0
1314 if (si.descent > 0)
si.descent > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1315 descent = si.descent;
never executed: descent = si.descent;
0
1316 rightToLeft = si.analysis.bidiLevel % 2;-
1317 }
never executed: end of block
0
1318 qreal y = position.y() + (sl.y + sl.base() - base).toReal();-
1319 bool toggleAntialiasing = !(p->renderHints() & QPainter::Antialiasing)
!(p->renderHin...:Antialiasing)Description
TRUEnever evaluated
FALSEnever evaluated
0
1320 && (p->transform().type() > QTransform::TxTranslate);
(p->transform(...::TxTranslate)Description
TRUEnever evaluated
FALSEnever evaluated
0
1321 if (toggleAntialiasing)
toggleAntialiasingDescription
TRUEnever evaluated
FALSEnever evaluated
0
1322 p->setRenderHint(QPainter::Antialiasing);
never executed: p->setRenderHint(QPainter::Antialiasing);
0
1323 p->fillRect(QRectF(x, y, qreal(width), (base + descent).toReal()), p->pen().brush());-
1324 if (toggleAntialiasing)
toggleAntialiasingDescription
TRUEnever evaluated
FALSEnever evaluated
0
1325 p->setRenderHint(QPainter::Antialiasing, false);
never executed: p->setRenderHint(QPainter::Antialiasing, false);
0
1326 if (d->layoutData->hasBidi) {
d->layoutData->hasBidiDescription
TRUEnever evaluated
FALSEnever evaluated
0
1327 const int arrow_extent = 4;-
1328 int sign = rightToLeft ? -1 : 1;
rightToLeftDescription
TRUEnever evaluated
FALSEnever evaluated
0
1329 p->drawLine(QLineF(x, y, x + (sign * arrow_extent/2), y + arrow_extent/2));-
1330 p->drawLine(QLineF(x, y+arrow_extent, x + (sign * arrow_extent/2), y + arrow_extent/2));-
1331 }
never executed: end of block
0
1332 return;
never executed: return;
0
1333}-
1334-
1335/*!-
1336 \class QTextLine-
1337 \reentrant-
1338-
1339 \brief The QTextLine class represents a line of text inside a QTextLayout.-
1340 \inmodule QtGui-
1341-
1342 \ingroup richtext-processing-
1343-
1344 A text line is usually created by QTextLayout::createLine().-
1345-
1346 After being created, the line can be filled using the setLineWidth()-
1347 or setNumColumns() functions. A line has a number of attributes including the-
1348 rectangle it occupies, rect(), its coordinates, x() and y(), its-
1349 textLength(), width() and naturalTextWidth(), and its ascent() and descent()-
1350 relative to the text. The position of the cursor in terms of the-
1351 line is available from cursorToX() and its inverse from-
1352 xToCursor(). A line can be moved with setPosition().-
1353*/-
1354-
1355/*!-
1356 \enum QTextLine::Edge-
1357-
1358 \value Leading-
1359 \value Trailing-
1360*/-
1361-
1362/*!-
1363 \enum QTextLine::CursorPosition-
1364-
1365 \value CursorBetweenCharacters-
1366 \value CursorOnCharacter-
1367*/-
1368-
1369/*!-
1370 \fn QTextLine::QTextLine(int line, QTextEngine *e)-
1371 \internal-
1372-
1373 Constructs a new text line using the line at position \a line in-
1374 the text engine \a e.-
1375*/-
1376-
1377/*!-
1378 \fn QTextLine::QTextLine()-
1379-
1380 Creates an invalid line.-
1381*/-
1382-
1383/*!-
1384 \fn bool QTextLine::isValid() const-
1385-
1386 Returns \c true if this text line is valid; otherwise returns \c false.-
1387*/-
1388-
1389/*!-
1390 \fn int QTextLine::lineNumber() const-
1391-
1392 Returns the position of the line in the text engine.-
1393*/-
1394-
1395-
1396/*!-
1397 Returns the line's bounding rectangle.-
1398-
1399 \sa x(), y(), textLength(), width()-
1400*/-
1401QRectF QTextLine::rect() const-
1402{-
1403 const QScriptLine& sl = eng->lines[index];-
1404 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
1405}-
1406-
1407/*!-
1408 Returns the rectangle covered by the line.-
1409*/-
1410QRectF QTextLine::naturalTextRect() const-
1411{-
1412 const QScriptLine& sl = eng->lines[index];-
1413 QFixed x = sl.x + eng->alignLine(sl);-
1414-
1415 QFixed width = sl.textWidth;-
1416 if (sl.justified)
sl.justifiedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1417 width = sl.width;
never executed: width = sl.width;
0
1418-
1419 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
1420}-
1421-
1422/*!-
1423 Returns the line's x position.-
1424-
1425 \sa rect(), y(), textLength(), width()-
1426*/-
1427qreal QTextLine::x() const-
1428{-
1429 return eng->lines[index].x.toReal();
never executed: return eng->lines[index].x.toReal();
0
1430}-
1431-
1432/*!-
1433 Returns the line's y position.-
1434-
1435 \sa x(), rect(), textLength(), width()-
1436*/-
1437qreal QTextLine::y() const-
1438{-
1439 return eng->lines[index].y.toReal();
never executed: return eng->lines[index].y.toReal();
0
1440}-
1441-
1442/*!-
1443 Returns the line's width as specified by the layout() function.-
1444-
1445 \sa naturalTextWidth(), x(), y(), textLength(), rect()-
1446*/-
1447qreal QTextLine::width() const-
1448{-
1449 return eng->lines[index].width.toReal();
never executed: return eng->lines[index].width.toReal();
0
1450}-
1451-
1452-
1453/*!-
1454 Returns the line's ascent.-
1455-
1456 \sa descent(), height()-
1457*/-
1458qreal QTextLine::ascent() const-
1459{-
1460 return eng->lines[index].ascent.toReal();
never executed: return eng->lines[index].ascent.toReal();
0
1461}-
1462-
1463/*!-
1464 Returns the line's descent.-
1465-
1466 \sa ascent(), height()-
1467*/-
1468qreal QTextLine::descent() const-
1469{-
1470 return eng->lines[index].descent.toReal();
never executed: return eng->lines[index].descent.toReal();
0
1471}-
1472-
1473/*!-
1474 Returns the line's height. This is equal to ascent() + descent()-
1475 if leading is not included. If leading is included, this equals to-
1476 ascent() + descent() + leading().-
1477-
1478 \sa ascent(), descent(), leading(), setLeadingIncluded()-
1479*/-
1480qreal QTextLine::height() const-
1481{-
1482 return eng->lines[index].height().ceil().toReal();
never executed: return eng->lines[index].height().ceil().toReal();
0
1483}-
1484-
1485/*!-
1486 \since 4.6-
1487-
1488 Returns the line's leading.-
1489-
1490 \sa ascent(), descent(), height()-
1491*/-
1492qreal QTextLine::leading() const-
1493{-
1494 return eng->lines[index].leading.toReal();
never executed: return eng->lines[index].leading.toReal();
0
1495}-
1496-
1497/*!-
1498 \since 4.6-
1499-
1500 Includes positive leading into the line's height if \a included is true;-
1501 otherwise does not include leading.-
1502-
1503 By default, leading is not included.-
1504-
1505 Note that negative leading is ignored, it must be handled-
1506 in the code using the text lines by letting the lines overlap.-
1507-
1508 \sa leadingIncluded()-
1509-
1510*/-
1511void QTextLine::setLeadingIncluded(bool included)-
1512{-
1513 eng->lines[index].leadingIncluded= included;-
1514-
1515}
never executed: end of block
0
1516-
1517/*!-
1518 \since 4.6-
1519-
1520 Returns \c true if positive leading is included into the line's height;-
1521 otherwise returns \c false.-
1522-
1523 By default, leading is not included.-
1524-
1525 \sa setLeadingIncluded()-
1526*/-
1527bool QTextLine::leadingIncluded() const-
1528{-
1529 return eng->lines[index].leadingIncluded;
never executed: return eng->lines[index].leadingIncluded;
0
1530}-
1531-
1532/*!-
1533 Returns the width of the line that is occupied by text. This is-
1534 always \<= to width(), and is the minimum width that could be used-
1535 by layout() without changing the line break position.-
1536*/-
1537qreal QTextLine::naturalTextWidth() const-
1538{-
1539 return eng->lines[index].textWidth.toReal();
never executed: return eng->lines[index].textWidth.toReal();
0
1540}-
1541-
1542/*!-
1543 \since 4.7-
1544 Returns the horizontal advance of the text. The advance of the text-
1545 is the distance from its position to the next position at which-
1546 text would naturally be drawn.-
1547-
1548 By adding the advance to the position of the text line and using this-
1549 as the position of a second text line, you will be able to position-
1550 the two lines side-by-side without gaps in-between.-
1551*/-
1552qreal QTextLine::horizontalAdvance() const-
1553{-
1554 return eng->lines[index].textAdvance.toReal();
never executed: return eng->lines[index].textAdvance.toReal();
0
1555}-
1556-
1557/*!-
1558 Lays out the line with the given \a width. The line is filled from-
1559 its starting position with as many characters as will fit into-
1560 the line. In case the text cannot be split at the end of the line,-
1561 it will be filled with additional characters to the next whitespace-
1562 or end of the text.-
1563*/-
1564void QTextLine::setLineWidth(qreal width)-
1565{-
1566 QScriptLine &line = eng->lines[index];-
1567 if (!eng->layoutData) {
!eng->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
1568 qWarning("QTextLine: Can't set a line width while not layouting.");-
1569 return;
never executed: return;
0
1570 }-
1571-
1572 if (width > QFIXED_MAX)
width > (2147483647/256)Description
TRUEnever evaluated
FALSEnever evaluated
0
1573 width = QFIXED_MAX;
never executed: width = (2147483647/256);
0
1574-
1575 line.width = QFixed::fromReal(width);-
1576 if (line.length
line.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1577 && line.textWidth <= line.width
line.textWidth <= line.widthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1578 && line.from + line.length == eng->layoutData->string.length())
line.from + li...tring.length()Description
TRUEnever evaluated
FALSEnever evaluated
0
1579 // no need to do anything if the line is already layouted and the last one. This optimization helps-
1580 // when using things in a single line layout.-
1581 return;
never executed: return;
0
1582 line.length = 0;-
1583 line.textWidth = 0;-
1584-
1585 layout_helper(INT_MAX);-
1586}
never executed: end of block
0
1587-
1588/*!-
1589 Lays out the line. The line is filled from its starting position-
1590 with as many characters as are specified by \a numColumns. In case-
1591 the text cannot be split until \a numColumns characters, the line-
1592 will be filled with as many characters to the next whitespace or-
1593 end of the text.-
1594*/-
1595void QTextLine::setNumColumns(int numColumns)-
1596{-
1597 QScriptLine &line = eng->lines[index];-
1598 line.width = QFIXED_MAX;-
1599 line.length = 0;-
1600 line.textWidth = 0;-
1601 layout_helper(numColumns);-
1602}
never executed: end of block
0
1603-
1604/*!-
1605 Lays out the line. The line is filled from its starting position-
1606 with as many characters as are specified by \a numColumns. In case-
1607 the text cannot be split until \a numColumns characters, the line-
1608 will be filled with as many characters to the next whitespace or-
1609 end of the text. The provided \a alignmentWidth is used as reference-
1610 width for alignment.-
1611*/-
1612void QTextLine::setNumColumns(int numColumns, qreal alignmentWidth)-
1613{-
1614 QScriptLine &line = eng->lines[index];-
1615 line.width = QFixed::fromReal(alignmentWidth);-
1616 line.length = 0;-
1617 line.textWidth = 0;-
1618 layout_helper(numColumns);-
1619}
never executed: end of block
0
1620-
1621#if 0-
1622#define LB_DEBUG qDebug-
1623#else-
1624#define LB_DEBUG if (0) qDebug-
1625#endif-
1626-
1627namespace {-
1628-
1629 struct LineBreakHelper-
1630 {-
1631 LineBreakHelper()-
1632 : glyphCount(0), maxGlyphs(0), currentPosition(0), fontEngine(0), logClusters(0),-
1633 manualWrap(false), whiteSpaceOrObject(true)-
1634 {-
1635 }
never executed: end of block
0
1636-
1637-
1638 QScriptLine tmpData;-
1639 QScriptLine spaceData;-
1640-
1641 QGlyphLayout glyphs;-
1642-
1643 int glyphCount;-
1644 int maxGlyphs;-
1645 int currentPosition;-
1646 glyph_t previousGlyph;-
1647-
1648 QFixed minw;-
1649 QFixed softHyphenWidth;-
1650 QFixed rightBearing;-
1651 QFixed minimumRightBearing;-
1652-
1653 QFontEngine *fontEngine;-
1654 const unsigned short *logClusters;-
1655-
1656 bool manualWrap;-
1657 bool whiteSpaceOrObject;-
1658-
1659 bool checkFullOtherwiseExtend(QScriptLine &line);-
1660-
1661 QFixed calculateNewWidth(const QScriptLine &line) const {-
1662 return line.textWidth + tmpData.textWidth + spaceData.textWidth
never executed: return line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth + negativeRightBearing();
0
1663 + softHyphenWidth + negativeRightBearing();
never executed: return line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth + negativeRightBearing();
0
1664 }-
1665-
1666 inline glyph_t currentGlyph() const-
1667 {-
1668 Q_ASSERT(currentPosition > 0);-
1669 Q_ASSERT(logClusters[currentPosition - 1] < glyphs.numGlyphs);-
1670-
1671 return glyphs.glyphs[logClusters[currentPosition - 1]];
never executed: return glyphs.glyphs[logClusters[currentPosition - 1]];
0
1672 }-
1673-
1674 inline void saveCurrentGlyph()-
1675 {-
1676 previousGlyph = 0;-
1677 if (currentPosition > 0 &&
currentPosition > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1678 logClusters[currentPosition - 1] < glyphs.numGlyphs) {
logClusters[cu...yphs.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1679 previousGlyph = currentGlyph(); // needed to calculate right bearing later-
1680 }
never executed: end of block
0
1681 }
never executed: end of block
0
1682-
1683 inline void calculateRightBearing(glyph_t glyph)-
1684 {-
1685 qreal rb;-
1686 fontEngine->getGlyphBearings(glyph, 0, &rb);-
1687-
1688 // We only care about negative right bearings, so we limit the range-
1689 // of the bearing here so that we can assume it's negative in the rest-
1690 // of the code, as well ase use QFixed(1) as a sentinel to represent-
1691 // the state where we have yet to compute the right bearing.-
1692 rightBearing = qMin(QFixed::fromReal(rb), QFixed(0));-
1693 }
never executed: end of block
0
1694-
1695 inline void calculateRightBearing()-
1696 {-
1697 if (currentPosition <= 0)
currentPosition <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1698 return;
never executed: return;
0
1699 calculateRightBearing(currentGlyph());-
1700 }
never executed: end of block
0
1701-
1702 inline void calculateRightBearingForPreviousGlyph()-
1703 {-
1704 if (previousGlyph > 0)
previousGlyph > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1705 calculateRightBearing(previousGlyph);
never executed: calculateRightBearing(previousGlyph);
0
1706 }
never executed: end of block
0
1707-
1708 static const QFixed RightBearingNotCalculated;-
1709-
1710 inline void resetRightBearing()-
1711 {-
1712 rightBearing = RightBearingNotCalculated;-
1713 }
never executed: end of block
0
1714-
1715 // We express the negative right bearing as an absolute number-
1716 // so that it can be applied to the width using addition.-
1717 inline QFixed negativeRightBearing() const-
1718 {-
1719 if (rightBearing == RightBearingNotCalculated)
rightBearing =...gNotCalculatedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1720 return QFixed(0);
never executed: return QFixed(0);
0
1721-
1722 return qAbs(rightBearing);
never executed: return qAbs(rightBearing);
0
1723 }-
1724 };-
1725-
1726const QFixed LineBreakHelper::RightBearingNotCalculated = QFixed(1);-
1727-
1728inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line)-
1729{-
1730 LB_DEBUG("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal());
dead code: QMessageLogger(__FILE__, 1730, __PRETTY_FUNCTION__).debug("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal());
-
1731-
1732 QFixed newWidth = calculateNewWidth(line);-
1733 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
1734 return true;
never executed: return true;
0
1735-
1736 minw = qMax(minw, tmpData.textWidth);-
1737 line += tmpData;-
1738 line.textWidth += spaceData.textWidth;-
1739-
1740 line.length += spaceData.length;-
1741 tmpData.textWidth = 0;-
1742 tmpData.length = 0;-
1743 spaceData.textWidth = 0;-
1744 spaceData.length = 0;-
1745-
1746 return false;
never executed: return false;
0
1747}-
1748-
1749} // anonymous namespace-
1750-
1751-
1752static inline void addNextCluster(int &pos, int end, QScriptLine &line, int &glyphCount,-
1753 const QScriptItem &current, const unsigned short *logClusters,-
1754 const QGlyphLayout &glyphs)-
1755{-
1756 int glyphPosition = logClusters[pos];-
1757 do { // got to the first next cluster-
1758 ++pos;-
1759 ++line.length;-
1760 } 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
1761 do { // calculate the textWidth for the rest of the current cluster.-
1762 if (!glyphs.attributes[glyphPosition].dontPrint)
!glyphs.attrib...ion].dontPrintDescription
TRUEnever evaluated
FALSEnever evaluated
0
1763 line.textWidth += glyphs.advances[glyphPosition];
never executed: line.textWidth += glyphs.advances[glyphPosition];
0
1764 ++glyphPosition;-
1765 } 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
1766-
1767 Q_ASSERT((pos == end && glyphPosition == current.num_glyphs) || logClusters[pos] == glyphPosition);-
1768-
1769 ++glyphCount;-
1770}
never executed: end of block
0
1771-
1772-
1773// fill QScriptLine-
1774void QTextLine::layout_helper(int maxGlyphs)-
1775{-
1776 QScriptLine &line = eng->lines[index];-
1777 line.length = 0;-
1778 line.trailingSpaces = 0;-
1779 line.textWidth = 0;-
1780 line.hasTrailingSpaces = false;-
1781-
1782 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
1783 line.setDefaultHeight(eng);-
1784 return;
never executed: return;
0
1785 }-
1786-
1787 Q_ASSERT(line.from < eng->layoutData->string.length());-
1788-
1789 LineBreakHelper lbh;-
1790-
1791 lbh.maxGlyphs = maxGlyphs;-
1792-
1793 QTextOption::WrapMode wrapMode = eng->option.wrapMode();-
1794 bool breakany = (wrapMode == QTextOption::WrapAnywhere);-
1795 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
1796-
1797 int item = -1;-
1798 int newItem = eng->findItem(line.from);-
1799 Q_ASSERT(newItem >= 0);-
1800-
1801 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__, 1801, __PRETTY_FUNCTION__).debug("from: %d: item=%d, total %d, width available %f", line.from, newItem, eng->layoutData->items.size(), line.width.toReal());
-
1802-
1803 Qt::Alignment alignment = eng->option.alignment();-
1804-
1805 const QCharAttributes *attributes = eng->attributes();-
1806 if (!attributes)
!attributesDescription
TRUEnever evaluated
FALSEnever evaluated
0
1807 return;
never executed: return;
0
1808 lbh.currentPosition = line.from;-
1809 int end = 0;-
1810 lbh.logClusters = eng->layoutData->logClustersPtr;-
1811 lbh.previousGlyph = 0;-
1812-
1813 while (newItem < eng->layoutData->items.size()) {
newItem < eng-...->items.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1814 lbh.resetRightBearing();-
1815 lbh.softHyphenWidth = 0;-
1816 if (newItem != item) {
newItem != itemDescription
TRUEnever evaluated
FALSEnever evaluated
0
1817 item = newItem;-
1818 const QScriptItem &current = eng->layoutData->items[item];-
1819 if (!current.num_glyphs) {
!current.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1820 eng->shape(item);-
1821 attributes = eng->attributes();-
1822 if (!attributes)
!attributesDescription
TRUEnever evaluated
FALSEnever evaluated
0
1823 return;
never executed: return;
0
1824 lbh.logClusters = eng->layoutData->logClustersPtr;-
1825 }
never executed: end of block
0
1826 lbh.currentPosition = qMax(line.from, current.position);-
1827 end = current.position + eng->length(item);-
1828 lbh.glyphs = eng->shapedGlyphs(&current);-
1829 QFontEngine *fontEngine = eng->fontEngine(current);-
1830 if (lbh.fontEngine != fontEngine) {
lbh.fontEngine != fontEngineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1831 lbh.fontEngine = fontEngine;-
1832 lbh.minimumRightBearing = qMin(QFixed(),-
1833 QFixed::fromReal(fontEngine->minRightBearing()));-
1834 }
never executed: end of block
0
1835 }
never executed: end of block
0
1836 const QScriptItem &current = eng->layoutData->items[item];-
1837-
1838 lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent,-
1839 current.leading + current.ascent) - qMax(lbh.tmpData.ascent,-
1840 current.ascent);-
1841 lbh.tmpData.ascent = qMax(lbh.tmpData.ascent, current.ascent);-
1842 lbh.tmpData.descent = qMax(lbh.tmpData.descent, current.descent);-
1843-
1844 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
1845 lbh.whiteSpaceOrObject = true;-
1846 if (lbh.checkFullOtherwiseExtend(line))
lbh.checkFullO...seExtend(line)Description
TRUEnever evaluated
FALSEnever evaluated
0
1847 goto found;
never executed: goto found;
0
1848-
1849 QFixed x = line.x + line.textWidth + lbh.tmpData.textWidth + lbh.spaceData.textWidth;-
1850 QFixed tabWidth = eng->calculateTabWidth(item, x);-
1851 attributes = eng->attributes();-
1852 if (!attributes)
!attributesDescription
TRUEnever evaluated
FALSEnever evaluated
0
1853 return;
never executed: return;
0
1854 lbh.logClusters = eng->layoutData->logClustersPtr;-
1855 lbh.glyphs = eng->shapedGlyphs(&current);-
1856-
1857 lbh.spaceData.textWidth += tabWidth;-
1858 lbh.spaceData.length++;-
1859 newItem = item + 1;-
1860-
1861 QFixed averageCharWidth = eng->fontEngine(current)->averageCharWidth();-
1862 lbh.glyphCount += qRound(tabWidth / averageCharWidth);-
1863-
1864 if (lbh.checkFullOtherwiseExtend(line))
lbh.checkFullO...seExtend(line)Description
TRUEnever evaluated
FALSEnever evaluated
0
1865 goto found;
never executed: goto found;
0
1866 } else if (current.analysis.flags == QScriptAnalysis::LineOrParagraphSeparator) {
never executed: end of block
current.analys...graphSeparatorDescription
TRUEnever evaluated
FALSEnever evaluated
0
1867 lbh.whiteSpaceOrObject = true;-
1868 // if the line consists only of the line separator make sure-
1869 // we have a sane height-
1870 if (!line.length && !lbh.tmpData.length)
!line.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
!lbh.tmpData.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1871 line.setDefaultHeight(eng);
never executed: line.setDefaultHeight(eng);
0
1872 if (eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators) {
eng->option.fl...raphSeparatorsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1873 if (lbh.checkFullOtherwiseExtend(line))
lbh.checkFullO...seExtend(line)Description
TRUEnever evaluated
FALSEnever evaluated
0
1874 goto found;
never executed: goto found;
0
1875-
1876 addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount,-
1877 current, lbh.logClusters, lbh.glyphs);-
1878 } else {
never executed: end of block
0
1879 lbh.tmpData.length++;-
1880 lbh.calculateRightBearingForPreviousGlyph();-
1881 }
never executed: end of block
0
1882 line += lbh.tmpData;-
1883 goto found;
never executed: goto found;
0
1884 } else if (current.analysis.flags == QScriptAnalysis::Object) {
current.analys...alysis::ObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
1885 lbh.whiteSpaceOrObject = true;-
1886 lbh.tmpData.length++;-
1887-
1888 if (eng->block.docHandle()) {
eng->block.docHandle()Description
TRUEnever evaluated
FALSEnever evaluated
0
1889 QTextInlineObject inlineObject(item, eng);-
1890 eng->docLayout()->positionInlineObject(inlineObject, eng->block.position() + current.position, inlineObject.format());-
1891 }
never executed: end of block
0
1892-
1893 lbh.tmpData.textWidth += current.width;-
1894-
1895 newItem = item + 1;-
1896 ++lbh.glyphCount;-
1897 if (lbh.checkFullOtherwiseExtend(line))
lbh.checkFullO...seExtend(line)Description
TRUEnever evaluated
FALSEnever evaluated
0
1898 goto found;
never executed: goto found;
0
1899 } else if (attributes[lbh.currentPosition].whiteSpace
never executed: end of block
attributes[lbh...on].whiteSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1900 && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak) {
eng->layoutDat...QChar::NoBreakDescription
TRUEnever evaluated
FALSEnever evaluated
0
1901 lbh.whiteSpaceOrObject = true;-
1902 while (lbh.currentPosition < end
lbh.currentPosition < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1903 && attributes[lbh.currentPosition].whiteSpace
attributes[lbh...on].whiteSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1904 && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak) {
eng->layoutDat...QChar::NoBreakDescription
TRUEnever evaluated
FALSEnever evaluated
0
1905 addNextCluster(lbh.currentPosition, end, lbh.spaceData, lbh.glyphCount,-
1906 current, lbh.logClusters, lbh.glyphs);-
1907 }
never executed: end of block
0
1908-
1909 if (!lbh.manualWrap && lbh.spaceData.textWidth > line.width) {
!lbh.manualWrapDescription
TRUEnever evaluated
FALSEnever evaluated
lbh.spaceData....h > line.widthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1910 lbh.spaceData.textWidth = line.width; // ignore spaces that fall out of the line.-
1911 goto found;
never executed: goto found;
0
1912 }-
1913 } else {
never executed: end of block
0
1914 lbh.whiteSpaceOrObject = false;-
1915 bool sb_or_ws = false;-
1916 lbh.saveCurrentGlyph();-
1917 do {-
1918 addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount,-
1919 current, lbh.logClusters, lbh.glyphs);-
1920-
1921 // This is a hack to fix a regression caused by the introduction of the-
1922 // whitespace flag to non-breakable spaces and will cause the non-breakable-
1923 // spaces to behave as in previous Qt versions in the line breaking algorithm.-
1924 // The line breaks do not currently follow the Unicode specs, but fixing this would-
1925 // require refactoring the code and would cause behavioral regressions.-
1926 bool isBreakableSpace = lbh.currentPosition < eng->layoutData->string.length()
lbh.currentPos...tring.length()Description
TRUEnever evaluated
FALSEnever evaluated
0
1927 && attributes[lbh.currentPosition].whiteSpace
attributes[lbh...on].whiteSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1928 && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak;
eng->layoutDat...QChar::NoBreakDescription
TRUEnever evaluated
FALSEnever evaluated
0
1929-
1930 if (lbh.currentPosition >= eng->layoutData->string.length()
lbh.currentPos...tring.length()Description
TRUEnever evaluated
FALSEnever evaluated
0
1931 || isBreakableSpace
isBreakableSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1932 || attributes[lbh.currentPosition].lineBreak) {
attributes[lbh...ion].lineBreakDescription
TRUEnever evaluated
FALSEnever evaluated
0
1933 sb_or_ws = true;-
1934 break;
never executed: break;
0
1935 } else if (breakany && attributes[lbh.currentPosition].graphemeBoundary) {
breakanyDescription
TRUEnever evaluated
FALSEnever evaluated
attributes[lbh...aphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
1936 break;
never executed: break;
0
1937 }-
1938 } while (lbh.currentPosition < end);
never executed: end of block
lbh.currentPosition < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1939 lbh.minw = qMax(lbh.tmpData.textWidth, lbh.minw);-
1940-
1941 if (lbh.currentPosition > 0 && lbh.currentPosition < end
lbh.currentPosition > 0Description
TRUEnever evaluated
FALSEnever evaluated
lbh.currentPosition < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1942 && attributes[lbh.currentPosition].lineBreak
attributes[lbh...ion].lineBreakDescription
TRUEnever evaluated
FALSEnever evaluated
0
1943 && eng->layoutData->string.at(lbh.currentPosition - 1).unicode() == QChar::SoftHyphen) {
eng->layoutDat...ar::SoftHyphenDescription
TRUEnever evaluated
FALSEnever evaluated
0
1944 // if we are splitting up a word because of-
1945 // a soft hyphen then we ...-
1946 //-
1947 // a) have to take the width of the soft hyphen into-
1948 // account to see if the first syllable(s) /and/-
1949 // the soft hyphen fit into the line-
1950 //-
1951 // b) if we are so short of available width that the-
1952 // soft hyphen is the first breakable position, then-
1953 // we don't want to show it. However we initially-
1954 // have to take the width for it into account so that-
1955 // the text document layout sees the overflow and-
1956 // switch to break-anywhere mode, in which we-
1957 // want the soft-hyphen to slip into the next line-
1958 // and thus become invisible again.-
1959 //-
1960 if (line.length)
line.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1961 lbh.softHyphenWidth = lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]];
never executed: lbh.softHyphenWidth = lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]];
0
1962 else if (breakany)
breakanyDescription
TRUEnever evaluated
FALSEnever evaluated
0
1963 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
1964 }
never executed: end of block
0
1965-
1966 if (sb_or_ws|breakany) {
sb_or_ws|breakanyDescription
TRUEnever evaluated
FALSEnever evaluated
0
1967 // To compute the final width of the text we need to take negative right bearing-
1968 // into account (negative right bearing means the glyph has pixel data past the-
1969 // advance length). Note that the negative right bearing is an absolute number,-
1970 // so that we can apply it to the width using straight forward addition.-
1971-
1972 // Store previous right bearing (for the already accepted glyph) in case we-
1973 // end up breaking due to the current glyph being too wide.-
1974 QFixed previousRightBearing = lbh.rightBearing;-
1975-
1976 // We skip calculating the right bearing if the minimum negative bearing is too-
1977 // small to possibly expand the text beyond the edge. Note that this optimization-
1978 // will in some cases fail, as the minimum right bearing reported by the font-
1979 // engine may not cover all the glyphs in the font. The result is that we think-
1980 // we don't need to break at the current glyph (because the right bearing is 0),-
1981 // and when we then end up breaking on the next glyph we compute the right bearing-
1982 // and end up with a line width that is slightly larger width than what was requested.-
1983 // Unfortunately we can't remove this optimization as it will slow down text-
1984 // layouting significantly, so we accept the slight correctnes issue.-
1985 if ((lbh.calculateNewWidth(line) + qAbs(lbh.minimumRightBearing)) > line.width)
(lbh.calculate...) > line.widthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1986 lbh.calculateRightBearing();
never executed: lbh.calculateRightBearing();
0
1987-
1988 if (lbh.checkFullOtherwiseExtend(line)) {
lbh.checkFullO...seExtend(line)Description
TRUEnever evaluated
FALSEnever evaluated
0
1989 // We are too wide to accept the next glyph with its bearing, so we restore the-
1990 // right bearing to that of the previous glyph (the one that was already accepted),-
1991 // so that the bearing can be be applied to the final width of the text below.-
1992 if (previousRightBearing != LineBreakHelper::RightBearingNotCalculated)
previousRightB...gNotCalculatedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1993 lbh.rightBearing = previousRightBearing;
never executed: lbh.rightBearing = previousRightBearing;
0
1994 else-
1995 lbh.calculateRightBearingForPreviousGlyph();
never executed: lbh.calculateRightBearingForPreviousGlyph();
0
1996-
1997 if (!breakany) {
!breakanyDescription
TRUEnever evaluated
FALSEnever evaluated
0
1998 line.textWidth += lbh.softHyphenWidth;-
1999 }
never executed: end of block
0
2000-
2001 goto found;
never executed: goto found;
0
2002 }-
2003 }
never executed: end of block
0
2004 lbh.saveCurrentGlyph();-
2005 }
never executed: end of block
0
2006 if (lbh.currentPosition == end)
lbh.currentPosition == endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2007 newItem = item + 1;
never executed: newItem = item + 1;
0
2008 }
never executed: end of block
0
2009 LB_DEBUG("reached end of line");
dead code: QMessageLogger(__FILE__, 2009, __PRETTY_FUNCTION__).debug("reached end of line");
-
2010 lbh.checkFullOtherwiseExtend(line);-
2011found:
code before this statement never executed: found:
0
2012 line.textAdvance = line.textWidth;-
2013-
2014 // If right bearing has not been calculated yet, do that now-
2015 if (lbh.rightBearing == LineBreakHelper::RightBearingNotCalculated && !lbh.whiteSpaceOrObject)
lbh.rightBeari...gNotCalculatedDescription
TRUEnever evaluated
FALSEnever evaluated
!lbh.whiteSpaceOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
2016 lbh.calculateRightBearing();
never executed: lbh.calculateRightBearing();
0
2017-
2018 // Then apply any negative right bearing-
2019 line.textWidth += lbh.negativeRightBearing();-
2020-
2021 if (line.length == 0) {
line.length == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2022 LB_DEBUG("no break available in line, adding temp: length %d, width %f, space: length %d, width %f",
dead code: QMessageLogger(__FILE__, 2022, __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());
-
2023 lbh.tmpData.length, lbh.tmpData.textWidth.toReal(),
dead code: QMessageLogger(__FILE__, 2022, __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());
-
2024 lbh.spaceData.length, lbh.spaceData.textWidth.toReal());
dead code: QMessageLogger(__FILE__, 2022, __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());
-
2025 line += lbh.tmpData;-
2026 }
never executed: end of block
0
2027-
2028 LB_DEBUG("line length = %d, ascent=%f, descent=%f, textWidth=%f (spacew=%f)", line.length, line.ascent.toReal(),
dead code: QMessageLogger(__FILE__, 2028, __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());
-
2029 line.descent.toReal(), line.textWidth.toReal(), lbh.spaceData.width.toReal());
dead code: QMessageLogger(__FILE__, 2028, __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());
-
2030 LB_DEBUG(" : '%s'", eng->layoutData->string.mid(line.from, line.length).toUtf8().data());
dead code: QMessageLogger(__FILE__, 2030, __PRETTY_FUNCTION__).debug(" : '%s'", eng->layoutData->string.mid(line.from, line.length).toUtf8().data());
-
2031-
2032 if (lbh.manualWrap) {
lbh.manualWrapDescription
TRUEnever evaluated
FALSEnever evaluated
0
2033 eng->minWidth = qMax(eng->minWidth, line.textWidth);-
2034 eng->maxWidth = qMax(eng->maxWidth, line.textWidth);-
2035 } else {
never executed: end of block
0
2036 eng->minWidth = qMax(eng->minWidth, lbh.minw);-
2037 eng->maxWidth += line.textWidth;-
2038 }
never executed: end of block
0
2039-
2040 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
2041 eng->maxWidth += lbh.spaceData.textWidth;
never executed: eng->maxWidth += lbh.spaceData.textWidth;
0
2042 if (eng->option.flags() & QTextOption::IncludeTrailingSpaces)
eng->option.fl...TrailingSpacesDescription
TRUEnever evaluated
FALSEnever evaluated
0
2043 line.textWidth += lbh.spaceData.textWidth;
never executed: line.textWidth += lbh.spaceData.textWidth;
0
2044 if (lbh.spaceData.length) {
lbh.spaceData.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2045 line.trailingSpaces = lbh.spaceData.length;-
2046 line.hasTrailingSpaces = true;-
2047 }
never executed: end of block
0
2048-
2049 line.justified = false;-
2050 line.gridfitted = false;-
2051-
2052 if (eng->option.wrapMode() == QTextOption::WrapAtWordBoundaryOrAnywhere) {
eng->option.wr...daryOrAnywhereDescription
TRUEnever evaluated
FALSEnever evaluated
0
2053 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
2054 || (lbh.maxGlyphs == INT_MAX && line.textWidth > line.width)) {
lbh.maxGlyphs == 2147483647Description
TRUEnever evaluated
FALSEnever evaluated
line.textWidth > line.widthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2055-
2056 eng->option.setWrapMode(QTextOption::WrapAnywhere);-
2057 line.length = 0;-
2058 line.textWidth = 0;-
2059 layout_helper(lbh.maxGlyphs);-
2060 eng->option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);-
2061 }
never executed: end of block
0
2062 }
never executed: end of block
0
2063}
never executed: end of block
0
2064-
2065/*!-
2066 Moves the line to position \a pos.-
2067*/-
2068void QTextLine::setPosition(const QPointF &pos)-
2069{-
2070 eng->lines[index].x = QFixed::fromReal(pos.x());-
2071 eng->lines[index].y = QFixed::fromReal(pos.y());-
2072}
never executed: end of block
0
2073-
2074/*!-
2075 Returns the line's position relative to the text layout's position.-
2076*/-
2077QPointF QTextLine::position() const-
2078{-
2079 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
2080}-
2081-
2082// ### DOC: I have no idea what this means/does.-
2083// You create a text layout with a string of text. Once you laid-
2084// it out, it contains a number of QTextLines. from() returns the position-
2085// inside the text string where this line starts. If you e.g. has a-
2086// text of "This is a string", laid out into two lines (the second-
2087// starting at the word 'a'), layout.lineAt(0).from() == 0 and-
2088// layout.lineAt(1).from() == 8.-
2089/*!-
2090 Returns the start of the line from the beginning of the string-
2091 passed to the QTextLayout.-
2092*/-
2093int QTextLine::textStart() const-
2094{-
2095 return eng->lines[index].from;
never executed: return eng->lines[index].from;
0
2096}-
2097-
2098/*!-
2099 Returns the length of the text in the line.-
2100-
2101 \sa naturalTextWidth()-
2102*/-
2103int QTextLine::textLength() const-
2104{-
2105 if (eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators
eng->option.fl...raphSeparatorsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2106 && 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
2107 return eng->lines[index].length - 1;
never executed: return eng->lines[index].length - 1;
0
2108 }-
2109 return eng->lines[index].length + eng->lines[index].trailingSpaces;
never executed: return eng->lines[index].length + eng->lines[index].trailingSpaces;
0
2110}-
2111-
2112static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const QTextCharFormat &chf, const QRectF &r)-
2113{-
2114 QBrush c = chf.foreground();-
2115 if (c.style() == Qt::NoBrush) {
c.style() == Qt::NoBrushDescription
TRUEnever evaluated
FALSEnever evaluated
0
2116 p->setPen(defaultPen);-
2117 }
never executed: end of block
0
2118-
2119 QBrush bg = chf.background();-
2120 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
2121 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
2122 if (c.style() != Qt::NoBrush) {
c.style() != Qt::NoBrushDescription
TRUEnever evaluated
FALSEnever evaluated
0
2123 p->setPen(QPen(c, 0));-
2124 }
never executed: end of block
0
2125-
2126}
never executed: end of block
0
2127-
2128#if !defined(QT_NO_RAWFONT)-
2129static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine,-
2130 const QGlyphLayout &glyphLayout,-
2131 const QPointF &pos,-
2132 const QGlyphRun::GlyphRunFlags &flags,-
2133 const QFixed &selectionX,-
2134 const QFixed &selectionWidth,-
2135 int glyphsStart,-
2136 int glyphsEnd,-
2137 unsigned short *logClusters,-
2138 int textPosition,-
2139 int textLength)-
2140{-
2141 Q_ASSERT(logClusters != 0);-
2142-
2143 QGlyphRun glyphRun;-
2144-
2145 QGlyphRunPrivate *d = QGlyphRunPrivate::get(glyphRun);-
2146-
2147 int rangeStart = textPosition;-
2148 while (*logClusters != glyphsStart && rangeStart < textPosition + textLength) {
*logClusters != glyphsStartDescription
TRUEnever evaluated
FALSEnever evaluated
rangeStart < t...n + textLengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2149 ++logClusters;-
2150 ++rangeStart;-
2151 }
never executed: end of block
0
2152-
2153 int rangeEnd = rangeStart;-
2154 while (*logClusters != glyphsEnd && rangeEnd < textPosition + textLength) {
*logClusters != glyphsEndDescription
TRUEnever evaluated
FALSEnever evaluated
rangeEnd < tex...n + textLengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2155 ++logClusters;-
2156 ++rangeEnd;-
2157 }
never executed: end of block
0
2158-
2159 d->textRangeStart = rangeStart;-
2160 d->textRangeEnd = rangeEnd;-
2161-
2162 // Make a font for this particular engine-
2163 QRawFont font;-
2164 QRawFontPrivate *fontD = QRawFontPrivate::get(font);-
2165 fontD->setFontEngine(fontEngine);-
2166-
2167 QVarLengthArray<glyph_t> glyphsArray;-
2168 QVarLengthArray<QFixedPoint> positionsArray;-
2169-
2170 QTextItem::RenderFlags renderFlags;-
2171 if (flags.testFlag(QGlyphRun::Overline))
flags.testFlag...Run::Overline)Description
TRUEnever evaluated
FALSEnever evaluated
0
2172 renderFlags |= QTextItem::Overline;
never executed: renderFlags |= QTextItem::Overline;
0
2173 if (flags.testFlag(QGlyphRun::Underline))
flags.testFlag...un::Underline)Description
TRUEnever evaluated
FALSEnever evaluated
0
2174 renderFlags |= QTextItem::Underline;
never executed: renderFlags |= QTextItem::Underline;
0
2175 if (flags.testFlag(QGlyphRun::StrikeOut))
flags.testFlag...un::StrikeOut)Description
TRUEnever evaluated
FALSEnever evaluated
0
2176 renderFlags |= QTextItem::StrikeOut;
never executed: renderFlags |= QTextItem::StrikeOut;
0
2177 if (flags.testFlag(QGlyphRun::RightToLeft))
flags.testFlag...::RightToLeft)Description
TRUEnever evaluated
FALSEnever evaluated
0
2178 renderFlags |= QTextItem::RightToLeft;
never executed: renderFlags |= QTextItem::RightToLeft;
0
2179-
2180 fontEngine->getGlyphPositions(glyphLayout, QTransform(), renderFlags, glyphsArray,-
2181 positionsArray);-
2182 Q_ASSERT(glyphsArray.size() == positionsArray.size());-
2183-
2184 qreal fontHeight = font.ascent() + font.descent();-
2185 qreal minY = 0;-
2186 qreal maxY = 0;-
2187 QVector<quint32> glyphs;-
2188 glyphs.reserve(glyphsArray.size());-
2189 QVector<QPointF> positions;-
2190 positions.reserve(glyphsArray.size());-
2191 for (int i=0; i<glyphsArray.size(); ++i) {
i<glyphsArray.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
2192 glyphs.append(glyphsArray.at(i) & 0xffffff);-
2193-
2194 QPointF position = positionsArray.at(i).toPointF() + pos;-
2195 positions.append(position);-
2196-
2197 if (i == 0) {
i == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2198 maxY = minY = position.y();-
2199 } else {
never executed: end of block
0
2200 minY = qMin(minY, position.y());-
2201 maxY = qMax(maxY, position.y());-
2202 }
never executed: end of block
0
2203 }-
2204-
2205 qreal height = maxY + fontHeight - minY;-
2206-
2207 glyphRun.setGlyphIndexes(glyphs);-
2208 glyphRun.setPositions(positions);-
2209 glyphRun.setFlags(flags);-
2210 glyphRun.setRawFont(font);-
2211-
2212 glyphRun.setBoundingRect(QRectF(selectionX.toReal(), minY - font.ascent(),-
2213 selectionWidth.toReal(), height));-
2214-
2215 return glyphRun;
never executed: return glyphRun;
0
2216}-
2217-
2218/*!-
2219 Returns the glyph indexes and positions for all glyphs in this QTextLine for characters-
2220 in the range defined by \a from and \a length. The \a from index is relative to the beginning-
2221 of the text in the containing QTextLayout, and the range must be within the range of QTextLine-
2222 as given by functions textStart() and textLength().-
2223-
2224 If \a from is negative, it will default to textStart(), and if \a length is negative it will-
2225 default to the return value of textLength().-
2226-
2227 \since 5.0-
2228-
2229 \sa QTextLayout::glyphRuns()-
2230*/-
2231QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const-
2232{-
2233 const QScriptLine &line = eng->lines[index];-
2234-
2235 if (line.length == 0)
line.length == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2236 return QList<QGlyphRun>();
never executed: return QList<QGlyphRun>();
0
2237-
2238 if (from < 0)
from < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2239 from = textStart();
never executed: from = textStart();
0
2240-
2241 if (length < 0)
length < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2242 length = textLength();
never executed: length = textLength();
0
2243-
2244 if (length == 0)
length == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2245 return QList<QGlyphRun>();
never executed: return QList<QGlyphRun>();
0
2246-
2247 QTextLayout::FormatRange selection;-
2248 selection.start = from;-
2249 selection.length = length;-
2250-
2251 QTextLineItemIterator iterator(eng, index, QPointF(), &selection);-
2252 qreal y = line.y.toReal() + line.base().toReal();-
2253 QList<QGlyphRun> glyphRuns;-
2254 while (!iterator.atEnd()) {
!iterator.atEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
2255 QScriptItem &si = iterator.next();-
2256 if (si.analysis.flags >= QScriptAnalysis::TabOrObject)
si.analysis.fl...s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
2257 continue;
never executed: continue;
0
2258-
2259 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
2260 continue;
never executed: continue;
0
2261-
2262 QPointF pos(iterator.x.toReal(), y);-
2263-
2264 QFont font;-
2265 QGlyphRun::GlyphRunFlags flags;-
2266 if (!eng->useRawFont) {
!eng->useRawFontDescription
TRUEnever evaluated
FALSEnever evaluated
0
2267 font = eng->font(si);-
2268 if (font.overline())
font.overline()Description
TRUEnever evaluated
FALSEnever evaluated
0
2269 flags |= QGlyphRun::Overline;
never executed: flags |= QGlyphRun::Overline;
0
2270 if (font.underline())
font.underline()Description
TRUEnever evaluated
FALSEnever evaluated
0
2271 flags |= QGlyphRun::Underline;
never executed: flags |= QGlyphRun::Underline;
0
2272 if (font.strikeOut())
font.strikeOut()Description
TRUEnever evaluated
FALSEnever evaluated
0
2273 flags |= QGlyphRun::StrikeOut;
never executed: flags |= QGlyphRun::StrikeOut;
0
2274 }
never executed: end of block
0
2275-
2276 bool rtl = false;-
2277 if (si.analysis.bidiLevel % 2) {
si.analysis.bidiLevel % 2Description
TRUEnever evaluated
FALSEnever evaluated
0
2278 flags |= QGlyphRun::RightToLeft;-
2279 rtl = true;-
2280 }
never executed: end of block
0
2281-
2282 int relativeFrom = qMax(iterator.itemStart, from) - si.position;-
2283 int relativeTo = qMin(iterator.itemEnd, from + length) - 1 - si.position;-
2284-
2285 unsigned short *logClusters = eng->logClusters(&si);-
2286 int glyphsStart = logClusters[relativeFrom];-
2287 int glyphsEnd = (relativeTo == iterator.itemLength) ? si.num_glyphs - 1 : logClusters[relativeTo];
(relativeTo ==...or.itemLength)Description
TRUEnever evaluated
FALSEnever evaluated
0
2288 // the glyph index right next to the requested range-
2289 int nextGlyphIndex = (relativeTo < iterator.itemLength - 1) ? logClusters[relativeTo + 1] : si.num_glyphs;
(relativeTo < ...temLength - 1)Description
TRUEnever evaluated
FALSEnever evaluated
0
2290 if (nextGlyphIndex - 1 > glyphsEnd)
nextGlyphIndex - 1 > glyphsEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2291 glyphsEnd = nextGlyphIndex - 1;
never executed: glyphsEnd = nextGlyphIndex - 1;
0
2292 bool startsInsideLigature = relativeFrom > 0 && logClusters[relativeFrom - 1] == glyphsStart;
relativeFrom > 0Description
TRUEnever evaluated
FALSEnever evaluated
logClusters[re...== glyphsStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
2293 bool endsInsideLigature = nextGlyphIndex == glyphsEnd;-
2294-
2295 int itemGlyphsStart = logClusters[iterator.itemStart - si.position];-
2296 int itemGlyphsEnd = logClusters[iterator.itemEnd - 1 - si.position];-
2297-
2298 QGlyphLayout glyphLayout = eng->shapedGlyphs(&si);-
2299-
2300 // Calculate new x position of glyph layout for a subset. This becomes somewhat complex-
2301 // when we're breaking a RTL script item, since the expected position passed into-
2302 // getGlyphPositions() is the left-most edge of the left-most glyph in an RTL run.-
2303 if (relativeFrom != (iterator.itemStart - si.position) && !rtl) {
relativeFrom !...- si.position)Description
TRUEnever evaluated
FALSEnever evaluated
!rtlDescription
TRUEnever evaluated
FALSEnever evaluated
0
2304 for (int i=itemGlyphsStart; i<glyphsStart; ++i) {
i<glyphsStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
2305 QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6);-
2306 pos.rx() += (glyphLayout.advances[i] + justification).toReal();-
2307 }
never executed: end of block
0
2308 } 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
2309 for (int i=itemGlyphsEnd; i>glyphsEnd; --i) {
i>glyphsEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2310 QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6);-
2311 pos.rx() += (glyphLayout.advances[i] + justification).toReal();-
2312 }
never executed: end of block
0
2313 }
never executed: end of block
0
2314-
2315 glyphLayout = glyphLayout.mid(glyphsStart, glyphsEnd - glyphsStart + 1);-
2316-
2317 QFixed x;-
2318 QFixed width;-
2319 iterator.getSelectionBounds(&x, &width);-
2320-
2321 if (glyphLayout.numGlyphs > 0) {
glyphLayout.numGlyphs > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2322 QFontEngine *mainFontEngine;-
2323#ifndef QT_NO_RAWFONT-
2324 if (eng->useRawFont && eng->rawFont.isValid())
eng->useRawFontDescription
TRUEnever evaluated
FALSEnever evaluated
eng->rawFont.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
2325 mainFontEngine= eng->fontEngine(si);
never executed: mainFontEngine= eng->fontEngine(si);
0
2326 else-
2327#endif-
2328 mainFontEngine = font.d->engineForScript(si.analysis.script);
never executed: mainFontEngine = font.d->engineForScript(si.analysis.script);
0
2329-
2330 if (mainFontEngine->type() == QFontEngine::Multi) {
mainFontEngine...tEngine::MultiDescription
TRUEnever evaluated
FALSEnever evaluated
0
2331 QFontEngineMulti *multiFontEngine = static_cast<QFontEngineMulti *>(mainFontEngine);-
2332 int start = rtl ? glyphLayout.numGlyphs : 0;
rtlDescription
TRUEnever evaluated
FALSEnever evaluated
0
2333 int end = start - 1;-
2334 int which = glyphLayout.glyphs[rtl ? start - 1 : end + 1] >> 24;-
2335 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
2336 rtl ? --start : ++end) {-
2337 const int e = glyphLayout.glyphs[rtl ? start - 1 : end + 1] >> 24;-
2338 if (e == which)
e == whichDescription
TRUEnever evaluated
FALSEnever evaluated
0
2339 continue;
never executed: continue;
0
2340-
2341 QGlyphLayout subLayout = glyphLayout.mid(start, end - start + 1);-
2342 multiFontEngine->ensureEngineAt(which);-
2343-
2344 QGlyphRun::GlyphRunFlags subFlags = flags;-
2345 if (start == 0 && startsInsideLigature)
start == 0Description
TRUEnever evaluated
FALSEnever evaluated
startsInsideLigatureDescription
TRUEnever evaluated
FALSEnever evaluated
0
2346 subFlags |= QGlyphRun::SplitLigature;
never executed: subFlags |= QGlyphRun::SplitLigature;
0
2347-
2348 glyphRuns.append(glyphRunWithInfo(multiFontEngine->engine(which),-
2349 subLayout,-
2350 pos,-
2351 subFlags,-
2352 x,-
2353 width,-
2354 glyphsStart + start,-
2355 glyphsStart + end,-
2356 logClusters + relativeFrom,-
2357 relativeFrom + si.position,-
2358 relativeTo - relativeFrom + 1));-
2359 for (int i = 0; i < subLayout.numGlyphs; ++i) {
i < subLayout.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2360 QFixed justification = QFixed::fromFixed(subLayout.justifications[i].space_18d6);-
2361 pos.rx() += (subLayout.advances[i] + justification).toReal();-
2362 }
never executed: end of block
0
2363-
2364 if (rtl)
rtlDescription
TRUEnever evaluated
FALSEnever evaluated
0
2365 end = start - 1;
never executed: end = start - 1;
0
2366 else-
2367 start = end + 1;
never executed: start = end + 1;
0
2368 which = e;-
2369 }
never executed: end of block
0
2370-
2371 QGlyphLayout subLayout = glyphLayout.mid(start, end - start + 1);-
2372 multiFontEngine->ensureEngineAt(which);-
2373-
2374 QGlyphRun::GlyphRunFlags subFlags = flags;-
2375 if ((start == 0 && startsInsideLigature) || endsInsideLigature)
start == 0Description
TRUEnever evaluated
FALSEnever evaluated
startsInsideLigatureDescription
TRUEnever evaluated
FALSEnever evaluated
endsInsideLigatureDescription
TRUEnever evaluated
FALSEnever evaluated
0
2376 subFlags |= QGlyphRun::SplitLigature;
never executed: subFlags |= QGlyphRun::SplitLigature;
0
2377-
2378 QGlyphRun glyphRun = glyphRunWithInfo(multiFontEngine->engine(which),-
2379 subLayout,-
2380 pos,-
2381 subFlags,-
2382 x,-
2383 width,-
2384 glyphsStart + start,-
2385 glyphsStart + end,-
2386 logClusters + relativeFrom,-
2387 relativeFrom + si.position,-
2388 relativeTo - relativeFrom + 1);-
2389 if (!glyphRun.isEmpty())
!glyphRun.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
2390 glyphRuns.append(glyphRun);
never executed: glyphRuns.append(glyphRun);
0
2391 } else {
never executed: end of block
0
2392 if (startsInsideLigature || endsInsideLigature)
startsInsideLigatureDescription
TRUEnever evaluated
FALSEnever evaluated
endsInsideLigatureDescription
TRUEnever evaluated
FALSEnever evaluated
0
2393 flags |= QGlyphRun::SplitLigature;
never executed: flags |= QGlyphRun::SplitLigature;
0
2394 QGlyphRun glyphRun = glyphRunWithInfo(mainFontEngine,-
2395 glyphLayout,-
2396 pos,-
2397 flags,-
2398 x,-
2399 width,-
2400 glyphsStart,-
2401 glyphsEnd,-
2402 logClusters + relativeFrom,-
2403 relativeFrom + si.position,-
2404 relativeTo - relativeFrom + 1);-
2405 if (!glyphRun.isEmpty())
!glyphRun.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
2406 glyphRuns.append(glyphRun);
never executed: glyphRuns.append(glyphRun);
0
2407 }
never executed: end of block
0
2408 }-
2409 }
never executed: end of block
0
2410-
2411 return glyphRuns;
never executed: return glyphRuns;
0
2412}-
2413#endif // QT_NO_RAWFONT-
2414-
2415/*!-
2416 \fn void QTextLine::draw(QPainter *painter, const QPointF &position, const QTextLayout::FormatRange *selection) const-
2417-
2418 Draws a line on the given \a painter at the specified \a position.-
2419 The \a selection is reserved for internal use.-
2420*/-
2421void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatRange *selection) const-
2422{-
2423#ifndef QT_NO_RAWFONT-
2424 // Not intended to work with rawfont-
2425 Q_ASSERT(!eng->useRawFont);-
2426#endif-
2427 const QScriptLine &line = eng->lines[index];-
2428 QPen pen = p->pen();-
2429-
2430 bool noText = (selection && selection->format.property(SuppressText).toBool());
selectionDescription
TRUEnever evaluated
FALSEnever evaluated
selection->for...5012).toBool()Description
TRUEnever evaluated
FALSEnever evaluated
0
2431-
2432 if (!line.length) {
!line.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2433 if (selection
selectionDescription
TRUEnever evaluated
FALSEnever evaluated
0
2434 && selection->start <= line.from
selection->start <= line.fromDescription
TRUEnever evaluated
FALSEnever evaluated
0
2435 && selection->start + selection->length > line.from) {
selection->sta...th > line.fromDescription
TRUEnever evaluated
FALSEnever evaluated
0
2436-
2437 const qreal lineHeight = line.height().toReal();-
2438 QRectF r(pos.x() + line.x.toReal(), pos.y() + line.y.toReal(),-
2439 lineHeight / 2, QFontMetrics(eng->font()).width(QLatin1Char(' ')));-
2440 setPenAndDrawBackground(p, QPen(), selection->format, r);-
2441 p->setPen(pen);-
2442 }
never executed: end of block
0
2443 return;
never executed: return;
0
2444 }-
2445-
2446-
2447 QTextLineItemIterator iterator(eng, index, pos, selection);-
2448 QFixed lineBase = line.base();-
2449 eng->clearDecorations();-
2450 eng->enableDelayDecorations();-
2451-
2452 const QFixed y = QFixed::fromReal(pos.y()) + line.y + lineBase;-
2453-
2454 bool suppressColors = (eng->option.flags() & QTextOption::SuppressColors);-
2455 while (!iterator.atEnd()) {
!iterator.atEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
2456 QScriptItem &si = iterator.next();-
2457-
2458 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
2459 continue;
never executed: continue;
0
2460-
2461 if (si.analysis.flags == QScriptAnalysis::LineOrParagraphSeparator
si.analysis.fl...graphSeparatorDescription
TRUEnever evaluated
FALSEnever evaluated
0
2462 && !(eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators))
!(eng->option....aphSeparators)Description
TRUEnever evaluated
FALSEnever evaluated
0
2463 continue;
never executed: continue;
0
2464-
2465 QFixed itemBaseLine = y;-
2466 QFont f = eng->font(si);-
2467 QTextCharFormat format;-
2468-
2469 if (eng->hasFormats() || selection) {
eng->hasFormats()Description
TRUEnever evaluated
FALSEnever evaluated
selectionDescription
TRUEnever evaluated
FALSEnever evaluated
0
2470 format = eng->format(&si);-
2471 if (suppressColors) {
suppressColorsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2472 format.clearForeground();-
2473 format.clearBackground();-
2474 format.clearProperty(QTextFormat::TextUnderlineColor);-
2475 }
never executed: end of block
0
2476 if (selection)
selectionDescription
TRUEnever evaluated
FALSEnever evaluated
0
2477 format.merge(selection->format);
never executed: format.merge(selection->format);
0
2478-
2479 setPenAndDrawBackground(p, pen, format, QRectF(iterator.x.toReal(), (y - lineBase).toReal(),-
2480 iterator.itemWidth.toReal(), line.height().toReal()));-
2481-
2482 QTextCharFormat::VerticalAlignment valign = format.verticalAlignment();-
2483 if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) {
valign == QTex...ignSuperScriptDescription
TRUEnever evaluated
FALSEnever evaluated
valign == QTex...AlignSubScriptDescription
TRUEnever evaluated
FALSEnever evaluated
0
2484 QFontEngine *fe = f.d->engineForScript(si.analysis.script);-
2485 QFixed height = fe->ascent() + fe->descent();-
2486 if (valign == QTextCharFormat::AlignSubScript)
valign == QTex...AlignSubScriptDescription
TRUEnever evaluated
FALSEnever evaluated
0
2487 itemBaseLine += height / 6;
never executed: itemBaseLine += height / 6;
0
2488 else if (valign == QTextCharFormat::AlignSuperScript)
valign == QTex...ignSuperScriptDescription
TRUEnever evaluated
FALSEnever evaluated
0
2489 itemBaseLine -= height / 2;
never executed: itemBaseLine -= height / 2;
0
2490 }
never executed: end of block
0
2491 }
never executed: end of block
0
2492-
2493 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
si.analysis.fl...s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
2494-
2495 if (eng->hasFormats()) {
eng->hasFormats()Description
TRUEnever evaluated
FALSEnever evaluated
0
2496 p->save();-
2497 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
2498 QFixed itemY = y - si.ascent;-
2499 if (format.verticalAlignment() == QTextCharFormat::AlignTop) {
format.vertica...rmat::AlignTopDescription
TRUEnever evaluated
FALSEnever evaluated
0
2500 itemY = y - lineBase;-
2501 }
never executed: end of block
0
2502-
2503 QRectF itemRect(iterator.x.toReal(), itemY.toReal(), iterator.itemWidth.toReal(), si.height().toReal());-
2504-
2505 eng->docLayout()->drawInlineObject(p, itemRect,-
2506 QTextInlineObject(iterator.item, eng),-
2507 si.position + eng->block.position(),-
2508 format);-
2509 if (selection) {
selectionDescription
TRUEnever evaluated
FALSEnever evaluated
0
2510 QBrush bg = format.brushProperty(ObjectSelectionBrush);-
2511 if (bg.style() != Qt::NoBrush) {
bg.style() != Qt::NoBrushDescription
TRUEnever evaluated
FALSEnever evaluated
0
2512 QColor c = bg.color();-
2513 c.setAlpha(128);-
2514 p->fillRect(itemRect, c);-
2515 }
never executed: end of block
0
2516 }
never executed: end of block
0
2517 } else { // si.isTab
never executed: end of block
0
2518 QFont f = eng->font(si);-
2519 QTextItemInt gf(si, &f, format);-
2520 gf.chars = 0;-
2521 gf.num_chars = 0;-
2522 gf.width = iterator.itemWidth;-
2523 QPainterPrivate::get(p)->drawTextItem(QPointF(iterator.x.toReal(), y.toReal()), gf, eng);-
2524 if (eng->option.flags() & QTextOption::ShowTabsAndSpaces) {
eng->option.fl...wTabsAndSpacesDescription
TRUEnever evaluated
FALSEnever evaluated
0
2525 QChar visualTab(0x2192);-
2526 int w = QFontMetrics(f).width(visualTab);-
2527 qreal x = iterator.itemWidth.toReal() - w; // Right-aligned-
2528 if (x < 0)
x < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2529 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
2530 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
2531 Qt::IntersectClip);
never executed: p->setClipRect(QRectF(iterator.x.toReal(), line.y.toReal(), iterator.itemWidth.toReal(), line.height().toReal()), Qt::IntersectClip);
0
2532 else-
2533 x /= 2; // Centered
never executed: x /= 2;
0
2534 p->drawText(QPointF(iterator.x.toReal() + x,-
2535 y.toReal()), visualTab);-
2536 }
never executed: end of block
0
2537-
2538 }
never executed: end of block
0
2539 p->restore();-
2540 }
never executed: end of block
0
2541-
2542 continue;
never executed: continue;
0
2543 }-
2544-
2545 unsigned short *logClusters = eng->logClusters(&si);-
2546 QGlyphLayout glyphs = eng->shapedGlyphs(&si);-
2547-
2548 QTextItemInt gf(glyphs.mid(iterator.glyphsStart, iterator.glyphsEnd - iterator.glyphsStart),-
2549 &f, eng->layoutData->string.unicode() + iterator.itemStart,-
2550 iterator.itemEnd - iterator.itemStart, eng->fontEngine(si), format);-
2551 gf.logClusters = logClusters + iterator.itemStart - si.position;-
2552 gf.width = iterator.itemWidth;-
2553 gf.justified = line.justified;-
2554 gf.initWithScriptItem(si);-
2555-
2556 Q_ASSERT(gf.fontEngine);-
2557-
2558 QPointF pos(iterator.x.toReal(), itemBaseLine.toReal());-
2559 if (format.penProperty(QTextFormat::TextOutline).style() != Qt::NoPen) {
format.penProp...) != Qt::NoPenDescription
TRUEnever evaluated
FALSEnever evaluated
0
2560 QPainterPath path;-
2561 path.setFillRule(Qt::WindingFill);-
2562-
2563 if (gf.glyphs.numGlyphs)
gf.glyphs.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2564 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
2565 if (gf.flags) {
gf.flagsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2566 const QFontEngine *fe = gf.fontEngine;-
2567 const qreal lw = fe->lineThickness().toReal();-
2568 if (gf.flags & QTextItem::Underline) {
gf.flags & QTe...tem::UnderlineDescription
TRUEnever evaluated
FALSEnever evaluated
0
2569 qreal offs = fe->underlinePosition().toReal();-
2570 path.addRect(pos.x(), pos.y() + offs, gf.width.toReal(), lw);-
2571 }
never executed: end of block
0
2572 if (gf.flags & QTextItem::Overline) {
gf.flags & QTextItem::OverlineDescription
TRUEnever evaluated
FALSEnever evaluated
0
2573 qreal offs = fe->ascent().toReal() + 1;-
2574 path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);-
2575 }
never executed: end of block
0
2576 if (gf.flags & QTextItem::StrikeOut) {
gf.flags & QTe...tem::StrikeOutDescription
TRUEnever evaluated
FALSEnever evaluated
0
2577 qreal offs = fe->ascent().toReal() / 3;-
2578 path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);-
2579 }
never executed: end of block
0
2580 }
never executed: end of block
0
2581-
2582 p->save();-
2583 p->setRenderHint(QPainter::Antialiasing);-
2584 //Currently QPen with a Qt::NoPen style still returns a default-
2585 //QBrush which != Qt::NoBrush so we need this specialcase to reset it-
2586 if (p->pen().style() == Qt::NoPen)
p->pen().style() == Qt::NoPenDescription
TRUEnever evaluated
FALSEnever evaluated
0
2587 p->setBrush(Qt::NoBrush);
never executed: p->setBrush(Qt::NoBrush);
0
2588 else-
2589 p->setBrush(p->pen().brush());
never executed: p->setBrush(p->pen().brush());
0
2590-
2591 p->setPen(format.textOutline());-
2592 p->drawPath(path);-
2593 p->restore();-
2594 } else {
never executed: end of block
0
2595 if (noText)
noTextDescription
TRUEnever evaluated
FALSEnever evaluated
0
2596 gf.glyphs.numGlyphs = 0; // slightly less elegant than it should be
never executed: gf.glyphs.numGlyphs = 0;
0
2597 QPainterPrivate::get(p)->drawTextItem(pos, gf, eng);-
2598 }
never executed: end of block
0
2599-
2600 if (si.analysis.flags == QScriptAnalysis::Space
si.analysis.fl...nalysis::SpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
2601 && (eng->option.flags() & QTextOption::ShowTabsAndSpaces)) {
(eng->option.f...TabsAndSpaces)Description
TRUEnever evaluated
FALSEnever evaluated
0
2602 QBrush c = format.foreground();-
2603 if (c.style() != Qt::NoBrush)
c.style() != Qt::NoBrushDescription
TRUEnever evaluated
FALSEnever evaluated
0
2604 p->setPen(c.color());
never executed: p->setPen(c.color());
0
2605 QChar visualSpace((ushort)0xb7);-
2606 p->drawText(QPointF(iterator.x.toReal(), itemBaseLine.toReal()), visualSpace);-
2607 p->setPen(pen);-
2608 }
never executed: end of block
0
2609 }
never executed: end of block
0
2610 eng->drawDecorations(p);-
2611-
2612 if (eng->hasFormats())
eng->hasFormats()Description
TRUEnever evaluated
FALSEnever evaluated
0
2613 p->setPen(pen);
never executed: p->setPen(pen);
0
2614}
never executed: end of block
0
2615-
2616/*!-
2617 \fn int QTextLine::cursorToX(int cursorPos, Edge edge) const-
2618-
2619 \overload-
2620*/-
2621-
2622/*!-
2623 Converts the cursor position \a cursorPos to the corresponding x position-
2624 inside the line, taking account of the \a edge.-
2625-
2626 If \a cursorPos is not a valid cursor position, the nearest valid-
2627 cursor position will be used instead, and \a cursorPos will be modified to-
2628 point to this valid cursor position.-
2629-
2630 \sa xToCursor()-
2631*/-
2632qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const-
2633{-
2634 const QScriptLine &line = eng->lines[index];-
2635 bool lastLine = index >= eng->lines.size() - 1;-
2636-
2637 QFixed x = line.x + eng->alignLine(line) - eng->leadingSpaceWidth(line);-
2638-
2639 if (!eng->layoutData)
!eng->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
2640 eng->itemize();
never executed: eng->itemize();
0
2641 if (!eng->layoutData->items.size()) {
!eng->layoutData->items.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
2642 *cursorPos = line.from;-
2643 return x.toReal();
never executed: return x.toReal();
0
2644 }-
2645-
2646 int lineEnd = line.from + line.length + line.trailingSpaces;-
2647 int pos = qBound(line.from, *cursorPos, lineEnd);-
2648 int itm;-
2649 const QCharAttributes *attributes = eng->attributes();-
2650 if (!attributes) {
!attributesDescription
TRUEnever evaluated
FALSEnever evaluated
0
2651 *cursorPos = line.from;-
2652 return x.toReal();
never executed: return x.toReal();
0
2653 }-
2654 while (pos < lineEnd && !attributes[pos].graphemeBoundary)
pos < lineEndDescription
TRUEnever evaluated
FALSEnever evaluated
!attributes[po...aphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
2655 pos++;
never executed: pos++;
0
2656 if (pos == lineEnd) {
pos == lineEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2657 // end of line ensure we have the last item on the line-
2658 itm = eng->findItem(pos-1);-
2659 }
never executed: end of block
0
2660 else-
2661 itm = eng->findItem(pos);
never executed: itm = eng->findItem(pos);
0
2662 if (itm < 0) {
itm < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2663 *cursorPos = line.from;-
2664 return x.toReal();
never executed: return x.toReal();
0
2665 }-
2666 eng->shapeLine(line);-
2667-
2668 const QScriptItem *si = &eng->layoutData->items[itm];-
2669 if (!si->num_glyphs)
!si->num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2670 eng->shape(itm);
never executed: eng->shape(itm);
0
2671-
2672 const int l = eng->length(itm);-
2673 pos = qBound(0, pos - si->position, l);-
2674-
2675 QGlyphLayout glyphs = eng->shapedGlyphs(si);-
2676 unsigned short *logClusters = eng->logClusters(si);-
2677 Q_ASSERT(logClusters);-
2678-
2679 int glyph_pos = pos == l ? si->num_glyphs : logClusters[pos];
pos == lDescription
TRUEnever evaluated
FALSEnever evaluated
0
2680 if (edge == Trailing && glyph_pos < si->num_glyphs) {
edge == TrailingDescription
TRUEnever evaluated
FALSEnever evaluated
glyph_pos < si->num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2681 // trailing edge is leading edge of next cluster-
2682 glyph_pos++;-
2683 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
2684 glyph_pos++;
never executed: glyph_pos++;
0
2685 }
never executed: end of block
0
2686-
2687 bool reverse = si->analysis.bidiLevel % 2;-
2688-
2689-
2690 // add the items left of the cursor-
2691-
2692 int firstItem = eng->findItem(line.from);-
2693 int lastItem = eng->findItem(lineEnd - 1, itm);-
2694 int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
firstItem >= 0Description
TRUEnever evaluated
FALSEnever evaluated
lastItem >= firstItemDescription
TRUEnever evaluated
FALSEnever evaluated
0
2695-
2696 QVarLengthArray<int> visualOrder(nItems);-
2697 QVarLengthArray<uchar> levels(nItems);-
2698 for (int i = 0; i < nItems; ++i)
i < nItemsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2699 levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
never executed: levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
0
2700 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());-
2701-
2702 for (int i = 0; i < nItems; ++i) {
i < nItemsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2703 int item = visualOrder[i]+firstItem;-
2704 if (item == itm)
item == itmDescription
TRUEnever evaluated
FALSEnever evaluated
0
2705 break;
never executed: break;
0
2706 QScriptItem &si = eng->layoutData->items[item];-
2707 if (!si.num_glyphs)
!si.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2708 eng->shape(item);
never executed: eng->shape(item);
0
2709-
2710 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
si.analysis.fl...s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
2711 x += si.width;-
2712 continue;
never executed: continue;
0
2713 }-
2714-
2715 const int itemLength = eng->length(item);-
2716 int start = qMax(line.from, si.position);-
2717 int end = qMin(lineEnd, si.position + itemLength);-
2718-
2719 logClusters = eng->logClusters(&si);-
2720-
2721 int gs = logClusters[start-si.position];-
2722 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
2723-
2724 QGlyphLayout glyphs = eng->shapedGlyphs(&si);-
2725-
2726 while (gs <= ge) {
gs <= geDescription
TRUEnever evaluated
FALSEnever evaluated
0
2727 x += glyphs.effectiveAdvance(gs);-
2728 ++gs;-
2729 }
never executed: end of block
0
2730 }
never executed: end of block
0
2731-
2732 logClusters = eng->logClusters(si);-
2733 glyphs = eng->shapedGlyphs(si);-
2734 if (si->analysis.flags >= QScriptAnalysis::TabOrObject) {
si->analysis.f...s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
2735 if (pos == (reverse ? 0 : l))
pos == (reverse ? 0 : l)Description
TRUEnever evaluated
FALSEnever evaluated
reverseDescription
TRUEnever evaluated
FALSEnever evaluated
0
2736 x += si->width;
never executed: x += si->width;
0
2737 } else {
never executed: end of block
0
2738 bool rtl = eng->isRightToLeft();-
2739 bool visual = eng->visualCursorMovement();-
2740 int end = qMin(lineEnd, si->position + l) - si->position;-
2741 if (reverse) {
reverseDescription
TRUEnever evaluated
FALSEnever evaluated
0
2742 int glyph_end = end == l ? si->num_glyphs : logClusters[end];
end == lDescription
TRUEnever evaluated
FALSEnever evaluated
0
2743 int glyph_start = glyph_pos;-
2744 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
2745 glyph_start++;
never executed: glyph_start++;
0
2746 for (int i = glyph_end - 1; i >= glyph_start; i--)
i >= glyph_startDescription
TRUEnever evaluated
FALSEnever evaluated
0
2747 x += glyphs.effectiveAdvance(i);
never executed: x += glyphs.effectiveAdvance(i);
0
2748 } else {
never executed: end of block
0
2749 int start = qMax(line.from - si->position, 0);-
2750 int glyph_start = logClusters[start];-
2751 int glyph_end = glyph_pos;-
2752 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
2753 glyph_end--;
never executed: glyph_end--;
0
2754 for (int i = glyph_start; i <= glyph_end; i++)
i <= glyph_endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2755 x += glyphs.effectiveAdvance(i);
never executed: x += glyphs.effectiveAdvance(i);
0
2756 }
never executed: end of block
0
2757 x += eng->offsetInLigature(si, pos, end, glyph_pos);-
2758 }
never executed: end of block
0
2759-
2760 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
2761 x = line.x + line.width;
never executed: x = line.x + line.width;
0
2762 if (eng->option.wrapMode() != QTextOption::NoWrap && x < 0)
eng->option.wr...Option::NoWrapDescription
TRUEnever evaluated
FALSEnever evaluated
x < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2763 x = 0;
never executed: x = 0;
0
2764-
2765 *cursorPos = pos + si->position;-
2766 return x.toReal();
never executed: return x.toReal();
0
2767}-
2768-
2769/*!-
2770 \fn int QTextLine::xToCursor(qreal x, CursorPosition cpos) const-
2771-
2772 Converts the x-coordinate \a x, to the nearest matching cursor-
2773 position, depending on the cursor position type, \a cpos.-
2774 Note that result cursor position includes possible preedit area text.-
2775-
2776 \sa cursorToX()-
2777*/-
2778int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const-
2779{-
2780 QFixed x = QFixed::fromReal(_x);-
2781 const QScriptLine &line = eng->lines[index];-
2782 bool lastLine = index >= eng->lines.size() - 1;-
2783 int lineNum = index;-
2784-
2785 if (!eng->layoutData)
!eng->layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
2786 eng->itemize();
never executed: eng->itemize();
0
2787-
2788 int line_length = textLength();-
2789-
2790 if (!line_length)
!line_lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2791 return line.from;
never executed: return line.from;
0
2792-
2793 int firstItem = eng->findItem(line.from);-
2794 int lastItem = eng->findItem(line.from + line_length - 1, firstItem);-
2795 int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
firstItem >= 0Description
TRUEnever evaluated
FALSEnever evaluated
lastItem >= firstItemDescription
TRUEnever evaluated
FALSEnever evaluated
0
2796-
2797 if (!nItems)
!nItemsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2798 return 0;
never executed: return 0;
0
2799-
2800 x -= line.x;-
2801 x -= eng->alignLine(line);-
2802// qDebug("xToCursor: x=%f, cpos=%d", x.toReal(), cpos);-
2803-
2804 QVarLengthArray<int> visualOrder(nItems);-
2805 QVarLengthArray<unsigned char> levels(nItems);-
2806 for (int i = 0; i < nItems; ++i)
i < nItemsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2807 levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
never executed: levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
0
2808 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());-
2809-
2810 bool visual = eng->visualCursorMovement();-
2811 if (x <= 0) {
x <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2812 // left of first item-
2813 int item = visualOrder[0]+firstItem;-
2814 QScriptItem &si = eng->layoutData->items[item];-
2815 if (!si.num_glyphs)
!si.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2816 eng->shape(item);
never executed: eng->shape(item);
0
2817 int pos = si.position;-
2818 if (si.analysis.bidiLevel % 2)
si.analysis.bidiLevel % 2Description
TRUEnever evaluated
FALSEnever evaluated
0
2819 pos += eng->length(item);
never executed: pos += eng->length(item);
0
2820 pos = qMax(line.from, pos);-
2821 pos = qMin(line.from + line_length, pos);-
2822 return pos;
never executed: return pos;
0
2823 } else if (x < line.textWidth
x < line.textWidthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2824 || (line.justified && x < line.width)) {
line.justifiedDescription
TRUEnever evaluated
FALSEnever evaluated
x < line.widthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2825 // has to be in one of the runs-
2826 QFixed pos;-
2827 bool rtl = eng->isRightToLeft();-
2828-
2829 eng->shapeLine(line);-
2830 QVector<int> insertionPoints;-
2831 if (visual && rtl)
visualDescription
TRUEnever evaluated
FALSEnever evaluated
rtlDescription
TRUEnever evaluated
FALSEnever evaluated
0
2832 eng->insertionPointsForLine(lineNum, insertionPoints);
never executed: eng->insertionPointsForLine(lineNum, insertionPoints);
0
2833 int nchars = 0;-
2834 for (int i = 0; i < nItems; ++i) {
i < nItemsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2835 int item = visualOrder[i]+firstItem;-
2836 QScriptItem &si = eng->layoutData->items[item];-
2837 int item_length = eng->length(item);-
2838// qDebug(" item %d, visual %d x_remain=%f", i, item, x.toReal());-
2839-
2840 int start = qMax(line.from - si.position, 0);-
2841 int end = qMin(line.from + line_length - si.position, item_length);-
2842-
2843 unsigned short *logClusters = eng->logClusters(&si);-
2844-
2845 int gs = logClusters[start];-
2846 int ge = (end == item_length ? si.num_glyphs : logClusters[end]) - 1;
end == item_lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2847 QGlyphLayout glyphs = eng->shapedGlyphs(&si);-
2848-
2849 QFixed item_width = 0;-
2850 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
si.analysis.fl...s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
2851 item_width = si.width;-
2852 } else {
never executed: end of block
0
2853 int g = gs;-
2854 while (g <= ge) {
g <= geDescription
TRUEnever evaluated
FALSEnever evaluated
0
2855 item_width += glyphs.effectiveAdvance(g);-
2856 ++g;-
2857 }
never executed: end of block
0
2858 }
never executed: end of block
0
2859// qDebug(" start=%d, end=%d, gs=%d, ge=%d item_width=%f", start, end, gs, ge, item_width.toReal());-
2860-
2861 if (pos + item_width < x) {
pos + item_width < xDescription
TRUEnever evaluated
FALSEnever evaluated
0
2862 pos += item_width;-
2863 nchars += end;-
2864 continue;
never executed: continue;
0
2865 }-
2866// qDebug(" inside run");-
2867 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
si.analysis.fl...s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
2868 if (cpos == QTextLine::CursorOnCharacter)
cpos == QTextL...sorOnCharacterDescription
TRUEnever evaluated
FALSEnever evaluated
0
2869 return si.position;
never executed: return si.position;
0
2870 bool left_half = (x - pos) < item_width/2;-
2871-
2872 if (bool(si.analysis.bidiLevel % 2) != left_half)
bool(si.analys...) != left_halfDescription
TRUEnever evaluated
FALSEnever evaluated
0
2873 return si.position;
never executed: return si.position;
0
2874 return si.position + 1;
never executed: return si.position + 1;
0
2875 }-
2876-
2877 int glyph_pos = -1;-
2878 QFixed edge;-
2879 // has to be inside run-
2880 if (cpos == QTextLine::CursorOnCharacter) {
cpos == QTextL...sorOnCharacterDescription
TRUEnever evaluated
FALSEnever evaluated
0
2881 if (si.analysis.bidiLevel % 2) {
si.analysis.bidiLevel % 2Description
TRUEnever evaluated
FALSEnever evaluated
0
2882 pos += item_width;-
2883 glyph_pos = gs;-
2884 while (gs <= ge) {
gs <= geDescription
TRUEnever evaluated
FALSEnever evaluated
0
2885 if (glyphs.attributes[gs].clusterStart) {
glyphs.attribu...].clusterStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
2886 if (pos < x)
pos < xDescription
TRUEnever evaluated
FALSEnever evaluated
0
2887 break;
never executed: break;
0
2888 glyph_pos = gs;-
2889 edge = pos;-
2890 }
never executed: end of block
0
2891 pos -= glyphs.effectiveAdvance(gs);-
2892 ++gs;-
2893 }
never executed: end of block
0
2894 } else {
never executed: end of block
0
2895 glyph_pos = gs;-
2896 while (gs <= ge) {
gs <= geDescription
TRUEnever evaluated
FALSEnever evaluated
0
2897 if (glyphs.attributes[gs].clusterStart) {
glyphs.attribu...].clusterStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
2898 if (pos > x)
pos > xDescription
TRUEnever evaluated
FALSEnever evaluated
0
2899 break;
never executed: break;
0
2900 glyph_pos = gs;-
2901 edge = pos;-
2902 }
never executed: end of block
0
2903 pos += glyphs.effectiveAdvance(gs);-
2904 ++gs;-
2905 }
never executed: end of block
0
2906 }
never executed: end of block
0
2907 } else {-
2908 QFixed dist = INT_MAX/256;-
2909 if (si.analysis.bidiLevel % 2) {
si.analysis.bidiLevel % 2Description
TRUEnever evaluated
FALSEnever evaluated
0
2910 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
2911 pos += item_width;-
2912 while (gs <= ge) {
gs <= geDescription
TRUEnever evaluated
FALSEnever evaluated
0
2913 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
2914 glyph_pos = gs;-
2915 edge = pos;-
2916 dist = qAbs(x-pos);-
2917 }
never executed: end of block
0
2918 pos -= glyphs.effectiveAdvance(gs);-
2919 ++gs;-
2920 }
never executed: end of block
0
2921 } else {
never executed: end of block
0
2922 while (ge >= gs) {
ge >= gsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2923 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
2924 glyph_pos = ge;-
2925 edge = pos;-
2926 dist = qAbs(x-pos);-
2927 }
never executed: end of block
0
2928 pos += glyphs.effectiveAdvance(ge);-
2929 --ge;-
2930 }
never executed: end of block
0
2931 }
never executed: end of block
0
2932 } else {-
2933 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
2934 while (gs <= ge) {
gs <= geDescription
TRUEnever evaluated
FALSEnever evaluated
0
2935 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
2936 glyph_pos = gs;-
2937 edge = pos;-
2938 dist = qAbs(x-pos);-
2939 }
never executed: end of block
0
2940 pos += glyphs.effectiveAdvance(gs);-
2941 ++gs;-
2942 }
never executed: end of block
0
2943 } else {
never executed: end of block
0
2944 QFixed oldPos = pos;-
2945 while (gs <= ge) {
gs <= geDescription
TRUEnever evaluated
FALSEnever evaluated
0
2946 pos += glyphs.effectiveAdvance(gs);-
2947 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
2948 glyph_pos = gs;-
2949 edge = pos;-
2950 dist = qAbs(x-pos);-
2951 }
never executed: end of block
0
2952 ++gs;-
2953 }
never executed: end of block
0
2954 pos = oldPos;-
2955 }
never executed: end of block
0
2956 }-
2957 if (qAbs(x-pos) < dist) {
qAbs(x-pos) < distDescription
TRUEnever evaluated
FALSEnever evaluated
0
2958 if (visual) {
visualDescription
TRUEnever evaluated
FALSEnever evaluated
0
2959 if (!rtl && i < nItems - 1) {
!rtlDescription
TRUEnever evaluated
FALSEnever evaluated
i < nItems - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
2960 nchars += end;-
2961 continue;
never executed: continue;
0
2962 }-
2963 if (rtl && nchars > 0)
rtlDescription
TRUEnever evaluated
FALSEnever evaluated
nchars > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2964 return insertionPoints[lastLine ? nchars : nchars - 1];
never executed: return insertionPoints[lastLine ? nchars : nchars - 1];
0
2965 }
never executed: end of block
0
2966 return eng->positionInLigature(&si, end, x, pos, -1,
never executed: return eng->positionInLigature(&si, end, x, pos, -1, cpos == QTextLine::CursorOnCharacter);
0
2967 cpos == QTextLine::CursorOnCharacter);
never executed: return eng->positionInLigature(&si, end, x, pos, -1, cpos == QTextLine::CursorOnCharacter);
0
2968 }-
2969 }
never executed: end of block
0
2970 Q_ASSERT(glyph_pos != -1);-
2971 return eng->positionInLigature(&si, end, x, edge, glyph_pos,
never executed: return eng->positionInLigature(&si, end, x, edge, glyph_pos, cpos == QTextLine::CursorOnCharacter);
0
2972 cpos == QTextLine::CursorOnCharacter);
never executed: return eng->positionInLigature(&si, end, x, edge, glyph_pos, cpos == QTextLine::CursorOnCharacter);
0
2973 }-
2974 }
never executed: end of block
0
2975 // right of last item-
2976// qDebug() << "right of last";-
2977 int item = visualOrder[nItems-1]+firstItem;-
2978 QScriptItem &si = eng->layoutData->items[item];-
2979 if (!si.num_glyphs)
!si.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2980 eng->shape(item);
never executed: eng->shape(item);
0
2981 int pos = si.position;-
2982 if (!(si.analysis.bidiLevel % 2))
!(si.analysis.bidiLevel % 2)Description
TRUEnever evaluated
FALSEnever evaluated
0
2983 pos += eng->length(item);
never executed: pos += eng->length(item);
0
2984 pos = qMax(line.from, pos);-
2985-
2986 int maxPos = line.from + line_length;-
2987-
2988 // except for the last line we assume that the-
2989 // character between lines is a space and we want-
2990 // to position the cursor to the left of that-
2991 // character.-
2992 // ###### breaks with japanese for example-
2993 if (this->index < eng->lines.count() - 1)
this->index < ...es.count() - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
2994 --maxPos;
never executed: --maxPos;
0
2995-
2996 pos = qMin(pos, maxPos);-
2997 return pos;
never executed: return pos;
0
2998}-
2999-
3000QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

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