qtextlayout.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/text/qtextlayout.cpp
Switch to Source codePreprocessed file
LineSourceCount
1-
2-
3-
4-
5-
6-
7-
8QRectF QTextInlineObject::rect() const-
9{-
10 QScriptItem& si = eng->layoutData->items[itm];-
11 return QRectF(0, -si.ascent.toReal(), si.width.toReal(), si.height().toReal());-
12}-
13-
14-
15-
16-
17-
18-
19qreal QTextInlineObject::width() const-
20{-
21 return eng->layoutData->items[itm].width.toReal();-
22}-
23-
24-
25-
26-
27-
28-
29qreal QTextInlineObject::ascent() const-
30{-
31 return eng->layoutData->items[itm].ascent.toReal();-
32}-
33-
34-
35-
36-
37-
38-
39qreal QTextInlineObject::descent() const-
40{-
41 return eng->layoutData->items[itm].descent.toReal();-
42}-
43-
44-
45-
46-
47-
48-
49-
50qreal QTextInlineObject::height() const-
51{-
52 return eng->layoutData->items[itm].height().toReal();-
53}-
54-
55-
56-
57-
58-
59-
60void QTextInlineObject::setWidth(qreal w)-
61{-
62 eng->layoutData->items[itm].width = QFixed::fromReal(w);-
63}-
64-
65-
66-
67-
68-
69-
70void QTextInlineObject::setAscent(qreal a)-
71{-
72 eng->layoutData->items[itm].ascent = QFixed::fromReal(a);-
73}-
74-
75-
76-
77-
78-
79-
80void QTextInlineObject::setDescent(qreal d)-
81{-
82 eng->layoutData->items[itm].descent = QFixed::fromReal(d);-
83}-
84-
85-
86-
87-
88int QTextInlineObject::textPosition() const-
89{-
90 return eng->layoutData->items[itm].position;-
91}-
92-
93-
94-
95-
96-
97int QTextInlineObject::formatIndex() const-
98{-
99 return eng->formatIndex(&eng->layoutData->items[itm]);-
100}-
101-
102-
103-
104-
105QTextFormat QTextInlineObject::format() const-
106{-
107 return eng->format(&eng->layoutData->items[itm]);-
108}-
109-
110-
111-
112-
113Qt::LayoutDirection QTextInlineObject::textDirection() const-
114{-
115 return (eng->layoutData->items[itm].analysis.bidiLevel % 2 ? Qt::RightToLeft : Qt::LeftToRight);-
116}-
117QTextLayout::QTextLayout()-
118{ d = new QTextEngine(); }-
119-
120-
121-
122-
123QTextLayout::QTextLayout(const QString& text)-
124{-
125 d = new QTextEngine();-
126 d->text = text;-
127}-
128QTextLayout::QTextLayout(const QString& text, const QFont &font, QPaintDevice *paintdevice)-
129{-
130 QFont f(font);-
131 if (paintdevice)-
132 f = QFont(font, paintdevice);-
133 d = new QTextEngine((text.isNull() ? (const QString&)QString::fromLatin1("") : text), f);-
134}-
135-
136-
137-
138-
139-
140QTextLayout::QTextLayout(const QTextBlock &block)-
141{-
142 d = new QTextEngine();-
143 d->block = block;-
144}-
145-
146-
147-
148-
149QTextLayout::~QTextLayout()-
150{-
151 if (!d->stackEngine)-
152 delete d;-
153}-
154void QTextLayout::setRawFont(const QRawFont &rawFont)-
155{-
156 d->rawFont = rawFont;-
157 d->useRawFont = true;-
158 d->resetFontEngineCache();-
159}-
160void QTextLayout::setFont(const QFont &font)-
161{-
162 d->fnt = font;-
163-
164 d->useRawFont = false;-
165-
166 d->resetFontEngineCache();-
167}-
168-
169-
170-
171-
172-
173-
174-
175QFont QTextLayout::font() const-
176{-
177 return d->font();-
178}-
179void QTextLayout::setText(const QString& string)-
180{-
181 d->invalidate();-
182 d->clearLineData();-
183 d->text = string;-
184}-
185-
186-
187-
188-
189-
190-
191QString QTextLayout::text() const-
192{-
193 return d->text;-
194}-
195-
196-
197-
198-
199-
200-
201-
202void QTextLayout::setTextOption(const QTextOption &option)-
203{-
204 d->option = option;-
205}-
206-
207-
208-
209-
210-
211-
212const QTextOption &QTextLayout::textOption() const-
213{-
214 return d->option;-
215}-
216void QTextLayout::setPreeditArea(int position, const QString &text)-
217{-
218 if (d->preeditAreaPosition() == position && d->preeditAreaText() == text)-
219 return;-
220 d->setPreeditArea(position, text);-
221-
222 if (d->block.docHandle())-
223 d->block.docHandle()->documentChange(d->block.position(), d->block.length());-
224}-
225-
226-
227-
228-
229-
230-
231-
232int QTextLayout::preeditAreaPosition() const-
233{-
234 return d->preeditAreaPosition();-
235}-
236-
237-
238-
239-
240-
241-
242QString QTextLayout::preeditAreaText() const-
243{-
244 return d->preeditAreaText();-
245}-
246-
247-
248-
249-
250-
251void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList)-
252{-
253 setFormats(formatList.toVector());-
254}-
255void QTextLayout::setFormats(const QVector<FormatRange> &formats)-
256{-
257 d->setFormats(formats);-
258-
259 if (d->block.docHandle())-
260 d->block.docHandle()->documentChange(d->block.position(), d->block.length());-
261}-
262-
263-
264-
265-
266-
267-
268-
269QList<QTextLayout::FormatRange> QTextLayout::additionalFormats() const-
270{-
271 return formats().toList();-
272}-
273QVector<QTextLayout::FormatRange> QTextLayout::formats() const-
274{-
275 return d->formats();-
276}-
277-
278-
279-
280-
281-
282void QTextLayout::clearAdditionalFormats()-
283{-
284 clearFormats();-
285}-
286void QTextLayout::clearFormats()-
287{-
288 setFormats(QVector<FormatRange>());-
289}-
290void QTextLayout::setCacheEnabled(bool enable)-
291{-
292 d->cacheGlyphs = enable;-
293}-
294-
295-
296-
297-
298-
299-
300-
301bool QTextLayout::cacheEnabled() const-
302{-
303 return d->cacheGlyphs;-
304}-
305void QTextLayout::setCursorMoveStyle(Qt::CursorMoveStyle style)-
306{-
307 d->visualMovement = style == Qt::VisualMoveStyle;-
308}-
309-
310-
311-
312-
313-
314-
315-
316Qt::CursorMoveStyle QTextLayout::cursorMoveStyle() const-
317{-
318 return d->visualMovement ? Qt::VisualMoveStyle : Qt::LogicalMoveStyle;-
319}-
320-
321-
322-
323-
324-
325-
326void QTextLayout::beginLayout()-
327{-
328-
329 if (d->layoutData && d->layoutData->layoutState == QTextEngine::InLayout) {-
330 QMessageLogger(__FILE__, 633639, __PRETTY_FUNCTION__).warning("QTextLayout::beginLayout: Called while already doing layout");-
331 return;-
332 }-
333-
334 d->invalidate();-
335 d->clearLineData();-
336 d->itemize();-
337 d->layoutData->layoutState = QTextEngine::InLayout;-
338}-
339-
340-
341-
342-
343-
344-
345void QTextLayout::endLayout()-
346{-
347-
348 if (!d->layoutData || d->layoutData->layoutState == QTextEngine::LayoutEmpty) {-
349 QMessageLogger(__FILE__, 652658, __PRETTY_FUNCTION__).warning("QTextLayout::endLayout: Called without beginLayout()");-
350 return;-
351 }-
352-
353 int l = d->lines.size();-
354 if (l && d->lines.at(l-1).length < 0) {-
355 QTextLine(l-1, d).setNumColumns(2147483647);-
356 }-
357 d->layoutData->layoutState = QTextEngine::LayoutEmpty;-
358 if (!d->cacheGlyphs)-
359 d->freeMemory();-
360}-
361-
362-
363-
364-
365-
366-
367-
368void QTextLayout::clearLayout()-
369{-
370 d->clearLineData();-
371}-
372int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const-
373{-
374 const QCharAttributes *attributes = d->attributes();-
375 int len = d->block.isValid() ? d->block.length() - 1-
376 : d->layoutData->string.length();-
377 ((!(len <= d->layoutData->string.length())) ? qt_assert("len <= d->layoutData->string.length()",__FILE__,688694) : qt_noop());-
378 if (!attributes || oldPos < 0 || oldPos >= len)-
379 return oldPos;-
380-
381 if (mode == SkipCharacters) {-
382 oldPos++;-
383 while (oldPos < len && !attributes[oldPos].graphemeBoundary)-
384 oldPos++;-
385 } else {-
386 if (oldPos < len && d->atWordSeparator(oldPos)) {-
387 oldPos++;-
388 while (oldPos < len && d->atWordSeparator(oldPos))-
389 oldPos++;-
390 } else {-
391 while (oldPos < len && !attributes[oldPos].whiteSpace && !d->atWordSeparator(oldPos))-
392 oldPos++;-
393 }-
394 while (oldPos < len && attributes[oldPos].whiteSpace)-
395 oldPos++;-
396 }-
397-
398 return oldPos;-
399}-
400int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const-
401{-
402 const QCharAttributes *attributes = d->attributes();-
403 int len = d->block.isValid() ? d->block.length() - 1-
404 : d->layoutData->string.length();-
405 ((!(len <= d->layoutData->string.length())) ? qt_assert("len <= d->layoutData->string.length()",__FILE__,724730) : qt_noop());-
406 if (!attributes || oldPos <= 0 || oldPos > len)-
407 return oldPos;-
408-
409 if (mode == SkipCharacters) {-
410 oldPos--;-
411 while (oldPos && !attributes[oldPos].graphemeBoundary)-
412 oldPos--;-
413 } else {-
414 while (oldPos > 0 && attributes[oldPos - 1].whiteSpace)-
415 oldPos--;-
416-
417 if (oldPos && d->atWordSeparator(oldPos-1)) {-
418 oldPos--;-
419 while (oldPos && d->atWordSeparator(oldPos-1))-
420 oldPos--;-
421 } else {-
422 while (oldPos > 0 && !attributes[oldPos - 1].whiteSpace && !d->atWordSeparator(oldPos-1))-
423 oldPos--;-
424 }-
425 }-
426-
427 return oldPos;-
428}-
429int QTextLayout::rightCursorPosition(int oldPos) const-
430{-
431 int newPos = d->positionAfterVisualMovement(oldPos, QTextCursor::Right);-
432-
433 return newPos;-
434}-
435int QTextLayout::leftCursorPosition(int oldPos) const-
436{-
437 int newPos = d->positionAfterVisualMovement(oldPos, QTextCursor::Left);-
438-
439 return newPos;-
440}-
441bool QTextLayout::isValidCursorPosition(int pos) const-
442{-
443 const QCharAttributes *attributes = d->attributes();-
444 if (!attributes || pos < 0 || pos > (int)d->layoutData->string.length())-
445 return false;-
446 return attributes[pos].graphemeBoundary;-
447}-
448QTextLine QTextLayout::createLine()-
449{-
450-
451 if (!d->layoutData || d->layoutData->layoutState == QTextEngine::LayoutEmpty) {-
452 QMessageLogger(__FILE__, 820826, __PRETTY_FUNCTION__).warning("QTextLayout::createLine: Called without layouting");-
453 return QTextLine();-
454 }-
455-
456 if (d->layoutData->layoutState == QTextEngine::LayoutFailed)-
457 return QTextLine();-
458-
459 int l = d->lines.size();-
460 if (l && d->lines.at(l-1).length < 0) {-
461 QTextLine(l-1, d).setNumColumns(2147483647);-
462 }-
463 int from = l > 0 ? d->lines.at(l-1).from + d->lines.at(l-1).length + d->lines.at(l-1).trailingSpaces : 0;-
464 int strlen = d->layoutData->string.length();-
465 if (l && from >= strlen) {-
466 if (!d->lines.at(l-1).length || d->layoutData->string.at(strlen - 1) != QChar::LineSeparator)-
467 return QTextLine();-
468 }-
469-
470 QScriptLine line;-
471 line.from = from;-
472 line.length = -1;-
473 line.justified = false;-
474 line.gridfitted = false;-
475-
476 d->lines.append(line);-
477 return QTextLine(l, d);-
478}-
479-
480-
481-
482-
483-
484-
485int QTextLayout::lineCount() const-
486{-
487 return d->lines.size();-
488}-
489-
490-
491-
492-
493-
494-
495QTextLine QTextLayout::lineAt(int i) const-
496{-
497 return i < lineCount() ? QTextLine(i, d) : QTextLine();-
498}-
499-
500-
501-
502-
503-
504-
505QTextLine QTextLayout::lineForTextPosition(int pos) const-
506{-
507 int lineNum = d->lineNumberForTextPosition(pos);-
508 return lineNum >= 0 ? lineAt(lineNum) : QTextLine();-
509}-
510QPointF QTextLayout::position() const-
511{-
512 return d->position;-
513}-
514-
515-
516-
517-
518-
519-
520void QTextLayout::setPosition(const QPointF &p)-
521{-
522 d->position = p;-
523}-
524-
525-
526-
527-
528QRectF QTextLayout::boundingRect() const-
529{-
530 if (d->lines.isEmpty())-
531 return QRectF();-
532-
533 QFixed xmax, ymax;-
534 QFixed xmin = d->lines.at(0).x;-
535 QFixed ymin = d->lines.at(0).y;-
536-
537 for (int i = 0; i < d->lines.size(); ++i) {-
538 const QScriptLine &si = d->lines[i];-
539 xmin = qMin(xmin, si.x);-
540 ymin = qMin(ymin, si.y);-
541 QFixed lineWidth = si.width < (2147483647/256) ? qMax(si.width, si.textWidth) : si.textWidth;-
542 xmax = qMax(xmax, si.x+lineWidth);-
543-
544 ymax = qMax(ymax, si.y+si.height().ceil());-
545 }-
546 return QRectF(xmin.toReal(), ymin.toReal(), (xmax-xmin).toReal(), (ymax-ymin).toReal());-
547}-
548qreal QTextLayout::minimumWidth() const-
549{-
550 return d->minWidth.toReal();-
551}-
552qreal QTextLayout::maximumWidth() const-
553{-
554 return d->maxWidth.toReal();-
555}-
556-
557-
558-
559-
560-
561void QTextLayout::setFlags(int flags)-
562{-
563 if (flags & Qt::TextJustificationForced) {-
564 d->option.setAlignment(Qt::AlignJustify);-
565 d->forceJustification = true;-
566 }-
567-
568 if (flags & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {-
569 d->ignoreBidi = true;-
570 d->option.setTextDirection((flags & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);-
571 }-
572}-
573-
574static void addSelectedRegionsToPath(QTextEngine *eng, int lineNumber, const QPointF &pos, QTextLayout::FormatRange *selection,-
575 QPainterPath *region, QRectF boundingRect)-
576{-
577 const QScriptLine &line = eng->lines[lineNumber];-
578-
579 QTextLineItemIterator iterator(eng, lineNumber, pos, selection);-
580-
581-
582-
583 const qreal selectionY = pos.y() + line.y.toReal();-
584 const qreal lineHeight = line.height().toReal();-
585-
586 QFixed lastSelectionX = iterator.x;-
587 QFixed lastSelectionWidth;-
588-
589 while (!iterator.atEnd()) {-
590 iterator.next();-
591-
592 QFixed selectionX, selectionWidth;-
593 if (iterator.getSelectionBounds(&selectionX, &selectionWidth)) {-
594 if (selectionX == lastSelectionX + lastSelectionWidth) {-
595 lastSelectionWidth += selectionWidth;-
596 continue;-
597 }-
598-
599 if (lastSelectionWidth > 0) {-
600 QRectF rect = boundingRect & QRectF(lastSelectionX.toReal(), selectionY, lastSelectionWidth.toReal(), lineHeight);-
601 rect.moveLeft(qFloor(rect.left()));-
602 rect.moveTop(qFloor(rect.top()));-
603 region->addRect(rect);-
604 }-
605-
606 lastSelectionX = selectionX;-
607 lastSelectionWidth = selectionWidth;-
608 }-
609 }-
610 if (lastSelectionWidth > 0) {-
611 QRectF rect = boundingRect & QRectF(lastSelectionX.toReal(), selectionY, lastSelectionWidth.toReal(), lineHeight);-
612 rect.moveLeft(qFloor(rect.left()));-
613 rect.moveTop(qFloor(rect.top()));-
614 region->addRect(rect);-
615 }-
616}-
617-
618static inline QRectF clipIfValid(const QRectF &rect, const QRectF &clip)-
619{-
620 return clip.isValid() ? (rect & clip) : rect;-
621}-
622QList<QGlyphRun> QTextLayout::glyphRuns(int from, int length) const-
623{-
624 if (from < 0)-
625 from = 0;-
626 if (length < 0)-
627 length = text().length();-
628-
629 QHash<QPair<QFontEngine *, int>, QGlyphRun> glyphRunHash;-
630 for (int i=0; i<d->lines.size(); ++i) {-
631 if (d->lines[i].from > from + length)-
632 break;-
633 else if (d->lines[i].from + d->lines[i].length >= from) {-
634 QList<QGlyphRun> glyphRuns = QTextLine(i, d).glyphRuns(from, length);-
635-
636 for (int j = 0; j < glyphRuns.size(); j++) {-
637 const QGlyphRun &glyphRun = glyphRuns.at(j);-
638 QRawFont rawFont = glyphRun.rawFont();-
639-
640 QFontEngine *fontEngine = rawFont.d->fontEngine;-
641 QGlyphRun::GlyphRunFlags flags = glyphRun.flags();-
642 QPair<QFontEngine *, int> key(fontEngine, int(flags));-
643-
644 if (glyphRunHash.contains(key)) {-
645 QGlyphRun &oldGlyphRun = glyphRunHash[key];-
646-
647 QVector<quint32> indexes = oldGlyphRun.glyphIndexes();-
648 QVector<QPointF> positions = oldGlyphRun.positions();-
649 QRectF boundingRect = oldGlyphRun.boundingRect();-
650-
651 indexes += glyphRun.glyphIndexes();-
652 positions += glyphRun.positions();-
653 boundingRect = boundingRect.united(glyphRun.boundingRect());-
654-
655 oldGlyphRun.setGlyphIndexes(indexes);-
656 oldGlyphRun.setPositions(positions);-
657 oldGlyphRun.setBoundingRect(boundingRect);-
658 } else {-
659 glyphRunHash[key] = glyphRun;-
660 }-
661 }-
662 }-
663 }-
664-
665 return glyphRunHash.values();-
666}-
667-
668-
669-
670-
671-
672-
673-
674void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRange> &selections, const QRectF &clip) const-
675{-
676 if (d->lines.isEmpty())-
677 return;-
678-
679 if (!d->layoutData)-
680 d->itemize();-
681-
682 QPointF position = pos + d->position;-
683-
684 QFixed clipy = ((-2147483647 - 1)/256);-
685 QFixed clipe = (2147483647/256);-
686 if (clip.isValid()) {-
687 clipy = QFixed::fromReal(clip.y() - position.y());-
688 clipe = clipy + QFixed::fromReal(clip.height());-
689 }-
690-
691 int firstLine = 0;-
692 int lastLine = d->lines.size();-
693 for (int i = 0; i < d->lines.size(); ++i) {-
694 QTextLine l(i, d);-
695 const QScriptLine &sl = d->lines[i];-
696-
697 if (sl.y > clipe) {-
698 lastLine = i;-
699 break;-
700 }-
701 if ((sl.y + sl.height()) < clipy) {-
702 firstLine = i;-
703 continue;-
704 }-
705 }-
706-
707 QPainterPath excludedRegion;-
708 QPainterPath textDoneRegion;-
709 for (int i = 0; i < selections.size(); ++i) {-
710 FormatRange selection = selections.at(i);-
711 const QBrush bg = selection.format.background();-
712-
713 QPainterPath region;-
714 region.setFillRule(Qt::WindingFill);-
715-
716 for (int line = firstLine; line < lastLine; ++line) {-
717 const QScriptLine &sl = d->lines[line];-
718 QTextLine tl(line, d);-
719-
720 QRectF lineRect(tl.naturalTextRect());-
721 lineRect.translate(position);-
722 lineRect.adjust(0, 0, d->leadingSpaceWidth(sl).toReal(), 0);-
723-
724 bool isLastLineInBlock = (line == d->lines.size()-1);-
725 int sl_length = sl.length + (isLastLineInBlock? 1 : 0);-
726-
727-
728 if (sl.from > selection.start + selection.length || sl.from + sl_length <= selection.start)-
729 continue;-
730-
731 const bool selectionStartInLine = sl.from <= selection.start;-
732 const bool selectionEndInLine = selection.start + selection.length < sl.from + sl_length;-
733-
734 if (sl.length && (selectionStartInLine || selectionEndInLine)) {-
735 addSelectedRegionsToPath(d, line, position, &selection, &region, clipIfValid(lineRect, clip));-
736 } else {-
737 region.addRect(clipIfValid(lineRect, clip));-
738 }-
739-
740 if (selection.format.boolProperty(QTextFormat::FullWidthSelection)) {-
741 QRectF fullLineRect(tl.rect());-
742 fullLineRect.translate(position);-
743 fullLineRect.setRight((2147483647/256));-
744 if (!selectionEndInLine)-
745 region.addRect(clipIfValid(QRectF(lineRect.topRight(), fullLineRect.bottomRight()), clip));-
746 if (!selectionStartInLine)-
747 region.addRect(clipIfValid(QRectF(fullLineRect.topLeft(), lineRect.bottomLeft()), clip));-
748 } else if (!selectionEndInLine-
749 && isLastLineInBlock-
750 &&!(d->option.flags() & QTextOption::ShowLineAndParagraphSeparators)) {-
751 region.addRect(clipIfValid(QRectF(lineRect.right(), lineRect.top(),-
752 lineRect.height()/4, lineRect.height()), clip));-
753 }-
754-
755 }-
756 {-
757 const QPen oldPen = p->pen();-
758 const QBrush oldBrush = p->brush();-
759-
760 p->setPen(selection.format.penProperty(QTextFormat::OutlinePen));-
761 p->setBrush(selection.format.brushProperty(QTextFormat::BackgroundBrush));-
762 p->drawPath(region);-
763-
764 p->setPen(oldPen);-
765 p->setBrush(oldBrush);-
766 }-
767-
768-
769-
770 bool hasText = (selection.format.foreground().style() != Qt::NoBrush);-
771 bool hasBackground= (selection.format.background().style() != Qt::NoBrush);-
772-
773 if (hasBackground) {-
774 selection.format.setProperty((QTextFormat::ForegroundBrush + 1), selection.format.property(QTextFormat::BackgroundBrush));-
775-
776-
777 selection.format.setProperty(QTextFormat::BackgroundBrush, QBrush());-
778 selection.format.clearProperty(QTextFormat::OutlinePen);-
779 }-
780-
781 selection.format.setProperty(0x5012, !hasText);-
782-
783 if (hasText && !hasBackground && !(textDoneRegion & region).isEmpty())-
784 continue;-
785-
786 p->save();-
787 p->setClipPath(region, Qt::IntersectClip);-
788-
789 for (int line = firstLine; line < lastLine; ++line) {-
790 QTextLine l(line, d);-
791 l.draw(p, position, &selection);-
792 }-
793 p->restore();-
794-
795 if (hasText) {-
796 textDoneRegion += region;-
797 } else {-
798 if (hasBackground)-
799 textDoneRegion -= region;-
800 }-
801-
802 excludedRegion += region;-
803 }-
804-
805 QPainterPath needsTextButNoBackground = excludedRegion - textDoneRegion;-
806 if (!needsTextButNoBackground.isEmpty()){-
807 p->save();-
808 p->setClipPath(needsTextButNoBackground, Qt::IntersectClip);-
809 FormatRange selection;-
810 selection.start = 0;-
811 selection.length = 2147483647;-
812 selection.format.setProperty(0x513, true);-
813 for (int line = firstLine; line < lastLine; ++line) {-
814 QTextLine l(line, d);-
815 l.draw(p, position, &selection);-
816 }-
817 p->restore();-
818 }-
819-
820 if (!excludedRegion.isEmpty()) {-
821 p->save();-
822 QPainterPath path;-
823 QRectF br = boundingRect().translated(position);-
824 br.setRight((2147483647/256));-
825 if (!clip.isNull())-
826 br = br.intersected(clip);-
827 path.addRect(br);-
828 path -= excludedRegion;-
829 p->setClipPath(path, Qt::IntersectClip);-
830 }-
831-
832 for (int i = firstLine; i < lastLine; ++i) {-
833 QTextLine l(i, d);-
834 l.draw(p, position);-
835 }-
836 if (!excludedRegion.isEmpty())-
837 p->restore();-
838-
839-
840 if (!d->cacheGlyphs)-
841 d->freeMemory();-
842}-
843void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition) const-
844{-
845 drawCursor(p, pos, cursorPosition, 1);-
846}-
847void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition, int width) const-
848{-
849 if (d->lines.isEmpty())-
850 return;-
851-
852 if (!d->layoutData)-
853 d->itemize();-
854-
855 QPointF position = pos + d->position;-
856-
857 cursorPosition = qBound(0, cursorPosition, d->layoutData->string.length());-
858 int line = d->lineNumberForTextPosition(cursorPosition);-
859 if (line < 0)-
860 line = 0;-
861 if (line >= d->lines.size())-
862 return;-
863-
864 QTextLine l(line, d);-
865 const QScriptLine &sl = d->lines[line];-
866-
867 qreal x = position.x() + l.cursorToX(cursorPosition);-
868-
869 int itm;-
870-
871 if (d->visualCursorMovement()) {-
872 if (cursorPosition == sl.from + sl.length)-
873 cursorPosition--;-
874 itm = d->findItem(cursorPosition);-
875 } else-
876 itm = d->findItem(cursorPosition - 1);-
877-
878 QFixed base = sl.base();-
879 QFixed descent = sl.descent;-
880 bool rightToLeft = d->isRightToLeft();-
881 if (itm >= 0) {-
882 const QScriptItem &si = d->layoutData->items.at(itm);-
883 if (si.ascent > 0)-
884 base = si.ascent;-
885 if (si.descent > 0)-
886 descent = si.descent;-
887 rightToLeft = si.analysis.bidiLevel % 2;-
888 }-
889 qreal y = position.y() + (sl.y + sl.base() - base).toReal();-
890 bool toggleAntialiasing = !(p->renderHints() & QPainter::Antialiasing)-
891 && (p->transform().type() > QTransform::TxTranslate);-
892 if (toggleAntialiasing)-
893 p->setRenderHint(QPainter::Antialiasing);-
894 p->fillRect(QRectF(x, y, qreal(width), (base + descent).toReal()), p->pen().brush());-
895 if (toggleAntialiasing)-
896 p->setRenderHint(QPainter::Antialiasing, false);-
897 if (d->layoutData->hasBidi) {-
898 const int arrow_extent = 4;-
899 int sign = rightToLeft ? -1 : 1;-
900 p->drawLine(QLineF(x, y, x + (sign * arrow_extent/2), y + arrow_extent/2));-
901 p->drawLine(QLineF(x, y+arrow_extent, x + (sign * arrow_extent/2), y + arrow_extent/2));-
902 }-
903 return;-
904}-
905QRectF QTextLine::rect() const-
906{-
907 const QScriptLine& sl = eng->lines[index];-
908 return QRectF(sl.x.toReal(), sl.y.toReal(), sl.width.toReal(), sl.height().toReal());-
909}-
910-
911-
912-
913-
914QRectF QTextLine::naturalTextRect() const-
915{-
916 const QScriptLine& sl = eng->lines[index];-
917 QFixed x = sl.x + eng->alignLine(sl);-
918-
919 QFixed width = sl.textWidth;-
920 if (sl.justified)-
921 width = sl.width;-
922-
923 return QRectF(x.toReal(), sl.y.toReal(), width.toReal(), sl.height().toReal());-
924}-
925-
926-
927-
928-
929-
930-
931qreal QTextLine::x() const-
932{-
933 return eng->lines[index].x.toReal();-
934}-
935-
936-
937-
938-
939-
940-
941qreal QTextLine::y() const-
942{-
943 return eng->lines[index].y.toReal();-
944}-
945-
946-
947-
948-
949-
950-
951qreal QTextLine::width() const-
952{-
953 return eng->lines[index].width.toReal();-
954}-
955-
956-
957-
958-
959-
960-
961-
962qreal QTextLine::ascent() const-
963{-
964 return eng->lines[index].ascent.toReal();-
965}-
966-
967-
968-
969-
970-
971-
972qreal QTextLine::descent() const-
973{-
974 return eng->lines[index].descent.toReal();-
975}-
976qreal QTextLine::height() const-
977{-
978 return eng->lines[index].height().ceil().toReal();-
979}-
980qreal QTextLine::leading() const-
981{-
982 return eng->lines[index].leading.toReal();-
983}-
984void QTextLine::setLeadingIncluded(bool included)-
985{-
986 eng->lines[index].leadingIncluded= included;-
987-
988}-
989bool QTextLine::leadingIncluded() const-
990{-
991 return eng->lines[index].leadingIncluded;-
992}-
993-
994-
995-
996-
997-
998-
999qreal QTextLine::naturalTextWidth() const-
1000{-
1001 return eng->lines[index].textWidth.toReal();-
1002}-
1003qreal QTextLine::horizontalAdvance() const-
1004{-
1005 return eng->lines[index].textAdvance.toReal();-
1006}-
1007void QTextLine::setLineWidth(qreal width)-
1008{-
1009 QScriptLine &line = eng->lines[index];-
1010 if (!eng->layoutData) {-
1011 QMessageLogger(__FILE__, 15681574, __PRETTY_FUNCTION__).warning("QTextLine: Can't set a line width while not layouting.");-
1012 return;-
1013 }-
1014-
1015 if (width > (2147483647/256))-
1016 width = (2147483647/256);-
1017-
1018 line.width = QFixed::fromReal(width);-
1019 if (line.length-
1020 && line.textWidth <= line.width-
1021 && line.from + line.length == eng->layoutData->string.length())-
1022-
1023-
1024 return;-
1025 line.length = 0;-
1026 line.textWidth = 0;-
1027-
1028 layout_helper(2147483647);-
1029}-
1030void QTextLine::setNumColumns(int numColumns)-
1031{-
1032 QScriptLine &line = eng->lines[index];-
1033 line.width = (2147483647/256);-
1034 line.length = 0;-
1035 line.textWidth = 0;-
1036 layout_helper(numColumns);-
1037}-
1038void QTextLine::setNumColumns(int numColumns, qreal alignmentWidth)-
1039{-
1040 QScriptLine &line = eng->lines[index];-
1041 line.width = QFixed::fromReal(alignmentWidth);-
1042 line.length = 0;-
1043 line.textWidth = 0;-
1044 layout_helper(numColumns);-
1045}-
1046-
1047-
1048-
1049-
1050-
1051-
1052-
1053namespace {-
1054-
1055 struct LineBreakHelper-
1056 {-
1057 LineBreakHelper()-
1058 : glyphCount(0), maxGlyphs(0), currentPosition(0), fontEngine(0), logClusters(0),-
1059 manualWrap(false), whiteSpaceOrObject(true)-
1060 {-
1061 }-
1062-
1063-
1064 QScriptLine tmpData;-
1065 QScriptLine spaceData;-
1066-
1067 QGlyphLayout glyphs;-
1068-
1069 int glyphCount;-
1070 int maxGlyphs;-
1071 int currentPosition;-
1072 glyph_t previousGlyph;-
1073-
1074 QFixed minw;-
1075 QFixed softHyphenWidth;-
1076 QFixed rightBearing;-
1077 QFixed minimumRightBearing;-
1078-
1079 QFontEngine *fontEngine;-
1080 const unsigned short *logClusters;-
1081-
1082 bool manualWrap;-
1083 bool whiteSpaceOrObject;-
1084-
1085 bool checkFullOtherwiseExtend(QScriptLine &line);-
1086-
1087 QFixed calculateNewWidth(const QScriptLine &line) const {-
1088 return line.textWidth + tmpData.textWidth + spaceData.textWidth-
1089 + softHyphenWidth + negativeRightBearing();-
1090 }-
1091-
1092 inline glyph_t currentGlyph() const-
1093 {-
1094 ((!(currentPosition > 0)) ? qt_assert("currentPosition > 0",__FILE__,16681674) : qt_noop());-
1095 ((!(logClusters[currentPosition - 1] < glyphs.numGlyphs)) ? qt_assert("logClusters[currentPosition - 1] < glyphs.numGlyphs",__FILE__,16691675) : qt_noop());-
1096-
1097 return glyphs.glyphs[logClusters[currentPosition - 1]];-
1098 }-
1099-
1100 inline void saveCurrentGlyph()-
1101 {-
1102 previousGlyph = 0;-
1103 if (currentPosition > 0 &&-
1104 logClusters[currentPosition - 1] < glyphs.numGlyphs) {-
1105 previousGlyph = currentGlyph();-
1106 }-
1107 }-
1108-
1109 inline void calculateRightBearing(glyph_t glyph)-
1110 {-
1111 qreal rb;-
1112 fontEngine->getGlyphBearings(glyph, 0, &rb);-
1113-
1114-
1115-
1116-
1117-
1118 rightBearing = qMin(QFixed::fromReal(rb), QFixed(0));-
1119 }-
1120-
1121 inline void calculateRightBearing()-
1122 {-
1123 if (currentPosition <= 0)-
1124 return;-
1125 calculateRightBearing(currentGlyph());-
1126 }-
1127-
1128 inline void calculateRightBearingForPreviousGlyph()-
1129 {-
1130 if (previousGlyph > 0)-
1131 calculateRightBearing(previousGlyph);-
1132 }-
1133-
1134 static const QFixed RightBearingNotCalculated;-
1135-
1136 inline void resetRightBearing()-
1137 {-
1138 rightBearing = RightBearingNotCalculated;-
1139 }-
1140-
1141-
1142-
1143 inline QFixed negativeRightBearing() const-
1144 {-
1145 if (rightBearing == RightBearingNotCalculated)-
1146 return QFixed(0);-
1147-
1148 return qAbs(rightBearing);-
1149 }-
1150 };-
1151-
1152const QFixed LineBreakHelper::RightBearingNotCalculated = QFixed(1);-
1153-
1154inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line)-
1155{-
1156 if (0) QMessageLogger(__FILE__, 17301736, __PRETTY_FUNCTION__).debug("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal());
dead code: QMessageLogger(__FILE__, 1736, __PRETTY_FUNCTION__).debug("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal());
-
1157-
1158 QFixed newWidth = calculateNewWidth(line);-
1159 if (line.length && !manualWrap && (newWidth > line.width || glyphCount > maxGlyphs))-
1160 return true;-
1161-
1162 minw = qMax(minw, tmpData.textWidth);-
1163 line += tmpData;-
1164 line.textWidth += spaceData.textWidth;-
1165-
1166 line.length += spaceData.length;-
1167 tmpData.textWidth = 0;-
1168 tmpData.length = 0;-
1169 spaceData.textWidth = 0;-
1170 spaceData.length = 0;-
1171-
1172 return false;-
1173}-
1174-
1175}-
1176-
1177-
1178static inline void addNextCluster(int &pos, int end, QScriptLine &line, int &glyphCount,-
1179 const QScriptItem &current, const unsigned short *logClusters,-
1180 const QGlyphLayout &glyphs)-
1181{-
1182 int glyphPosition = logClusters[pos];-
1183 do {-
1184 ++pos;-
1185 ++line.length;-
1186 } while (pos < end && logClusters[pos] == glyphPosition);-
1187 do {-
1188 if (!glyphs.attributes[glyphPosition].dontPrint)-
1189 line.textWidth += glyphs.advances[glyphPosition];-
1190 ++glyphPosition;-
1191 } while (glyphPosition < current.num_glyphs && !glyphs.attributes[glyphPosition].clusterStart);-
1192-
1193 ((!((pos == end && glyphPosition == current.num_glyphs) || logClusters[pos] == glyphPosition)) ? qt_assert("(pos == end && glyphPosition == current.num_glyphs) || logClusters[pos] == glyphPosition",__FILE__,17671773) : qt_noop());-
1194-
1195 ++glyphCount;-
1196}-
1197-
1198-
1199-
1200void QTextLine::layout_helper(int maxGlyphs)-
1201{-
1202 QScriptLine &line = eng->lines[index];-
1203 line.length = 0;-
1204 line.trailingSpaces = 0;-
1205 line.textWidth = 0;-
1206 line.hasTrailingSpaces = false;-
1207-
1208 if (!eng->layoutData->items.size() || line.from >= eng->layoutData->string.length()) {-
1209 line.setDefaultHeight(eng);-
1210 return;-
1211 }-
1212-
1213 ((!(line.from < eng->layoutData->string.length())) ? qt_assert("line.from < eng->layoutData->string.length()",__FILE__,17871793) : qt_noop());-
1214-
1215 LineBreakHelper lbh;-
1216-
1217 lbh.maxGlyphs = maxGlyphs;-
1218-
1219 QTextOption::WrapMode wrapMode = eng->option.wrapMode();-
1220 bool breakany = (wrapMode == QTextOption::WrapAnywhere);-
1221 lbh.manualWrap = (wrapMode == QTextOption::ManualWrap || wrapMode == QTextOption::NoWrap);-
1222-
1223 int item = -1;-
1224 int newItem = eng->findItem(line.from);-
1225 ((!(newItem >= 0)) ? qt_assert("newItem >= 0",__FILE__,17991805) : qt_noop());-
1226-
1227 if (0) QMessageLogger(__FILE__, 18011807, __PRETTY_FUNCTION__).debug("from: %d: item=%d, total %d, width available %f", line.from, newItem, eng->layoutData->items.size(), line.width.toReal());
dead code: QMessageLogger(__FILE__, 1807, __PRETTY_FUNCTION__).debug("from: %d: item=%d, total %d, width available %f", line.from, newItem, eng->layoutData->items.size(), line.width.toReal());
-
1228-
1229 Qt::Alignment alignment = eng->option.alignment();-
1230-
1231 const QCharAttributes *attributes = eng->attributes();-
1232 if (!attributes)-
1233 return;-
1234 lbh.currentPosition = line.from;-
1235 int end = 0;-
1236 lbh.logClusters = eng->layoutData->logClustersPtr;-
1237 lbh.previousGlyph = 0;-
1238-
1239 while (newItem < eng->layoutData->items.size()) {-
1240 lbh.resetRightBearing();-
1241 lbh.softHyphenWidth = 0;-
1242 if (newItem != item) {-
1243 item = newItem;-
1244 const QScriptItem &current = eng->layoutData->items[item];-
1245 if (!current.num_glyphs) {-
1246 eng->shape(item);-
1247 attributes = eng->attributes();-
1248 if (!attributes)-
1249 return;-
1250 lbh.logClusters = eng->layoutData->logClustersPtr;-
1251 }-
1252 lbh.currentPosition = qMax(line.from, current.position);-
1253 end = current.position + eng->length(item);-
1254 lbh.glyphs = eng->shapedGlyphs(&current);-
1255 QFontEngine *fontEngine = eng->fontEngine(current);-
1256 if (lbh.fontEngine != fontEngine) {-
1257 lbh.fontEngine = fontEngine;-
1258 lbh.minimumRightBearing = qMin(QFixed(),-
1259 QFixed::fromReal(fontEngine->minRightBearing()));-
1260 }-
1261 }-
1262 const QScriptItem &current = eng->layoutData->items[item];-
1263-
1264 lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent,-
1265 current.leading + current.ascent) - qMax(lbh.tmpData.ascent,-
1266 current.ascent);-
1267 lbh.tmpData.ascent = qMax(lbh.tmpData.ascent, current.ascent);-
1268 lbh.tmpData.descent = qMax(lbh.tmpData.descent, current.descent);-
1269-
1270 if (current.analysis.flags == QScriptAnalysis::Tab && (alignment & (Qt::AlignLeft | Qt::AlignRight | Qt::AlignCenter | Qt::AlignJustify))) {-
1271 lbh.whiteSpaceOrObject = true;-
1272 if (lbh.checkFullOtherwiseExtend(line))-
1273 goto found;-
1274-
1275 QFixed x = line.x + line.textWidth + lbh.tmpData.textWidth + lbh.spaceData.textWidth;-
1276 QFixed tabWidth = eng->calculateTabWidth(item, x);-
1277 attributes = eng->attributes();-
1278 if (!attributes)-
1279 return;-
1280 lbh.logClusters = eng->layoutData->logClustersPtr;-
1281 lbh.glyphs = eng->shapedGlyphs(&current);-
1282-
1283 lbh.spaceData.textWidth += tabWidth;-
1284 lbh.spaceData.length++;-
1285 newItem = item + 1;-
1286-
1287 QFixed averageCharWidth = eng->fontEngine(current)->averageCharWidth();-
1288 lbh.glyphCount += qRound(tabWidth / averageCharWidth);-
1289-
1290 if (lbh.checkFullOtherwiseExtend(line))-
1291 goto found;-
1292 } else if (current.analysis.flags == QScriptAnalysis::LineOrParagraphSeparator) {-
1293 lbh.whiteSpaceOrObject = true;-
1294-
1295-
1296 if (!line.length && !lbh.tmpData.length)-
1297 line.setDefaultHeight(eng);-
1298 if (eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators) {-
1299 if (lbh.checkFullOtherwiseExtend(line))-
1300 goto found;-
1301-
1302 addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount,-
1303 current, lbh.logClusters, lbh.glyphs);-
1304 } else {-
1305 lbh.tmpData.length++;-
1306 lbh.calculateRightBearingForPreviousGlyph();-
1307 }-
1308 line += lbh.tmpData;-
1309 goto found;-
1310 } else if (current.analysis.flags == QScriptAnalysis::Object) {-
1311 lbh.whiteSpaceOrObject = true;-
1312 lbh.tmpData.length++;-
1313-
1314 if (eng->block.docHandle()) {-
1315 QTextInlineObject inlineObject(item, eng);-
1316 eng->docLayout()->positionInlineObject(inlineObject, eng->block.position() + current.position, inlineObject.format());-
1317 }-
1318-
1319 lbh.tmpData.textWidth += current.width;-
1320-
1321 newItem = item + 1;-
1322 ++lbh.glyphCount;-
1323 if (lbh.checkFullOtherwiseExtend(line))-
1324 goto found;-
1325 } else if (attributes[lbh.currentPosition].whiteSpace-
1326 && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak) {-
1327 lbh.whiteSpaceOrObject = true;-
1328 while (lbh.currentPosition < end-
1329 && attributes[lbh.currentPosition].whiteSpace-
1330 && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak) {-
1331 addNextCluster(lbh.currentPosition, end, lbh.spaceData, lbh.glyphCount,-
1332 current, lbh.logClusters, lbh.glyphs);-
1333 }-
1334-
1335 if (!lbh.manualWrap && lbh.spaceData.textWidth > line.width) {-
1336 lbh.spaceData.textWidth = line.width;-
1337 goto found;-
1338 }-
1339 } else {-
1340 lbh.whiteSpaceOrObject = false;-
1341 bool sb_or_ws = false;-
1342 lbh.saveCurrentGlyph();-
1343 do {-
1344 addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount,-
1345 current, lbh.logClusters, lbh.glyphs);-
1346-
1347-
1348-
1349-
1350-
1351-
1352 bool isBreakableSpace = lbh.currentPosition < eng->layoutData->string.length()-
1353 && attributes[lbh.currentPosition].whiteSpace-
1354 && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak;-
1355-
1356 if (lbh.currentPosition >= eng->layoutData->string.length()-
1357 || isBreakableSpace-
1358 || attributes[lbh.currentPosition].lineBreak) {-
1359 sb_or_ws = true;-
1360 break;-
1361 } else if (breakany && attributes[lbh.currentPosition].graphemeBoundary) {-
1362 break;-
1363 }-
1364 } while (lbh.currentPosition < end);-
1365 lbh.minw = qMax(lbh.tmpData.textWidth, lbh.minw);-
1366-
1367 if (lbh.currentPosition > 0 && lbh.currentPosition < end-
1368 && attributes[lbh.currentPosition].lineBreak-
1369 && eng->layoutData->string.at(lbh.currentPosition - 1).unicode() == QChar::SoftHyphen) {-
1370 if (line.length)-
1371 lbh.softHyphenWidth = lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]];-
1372 else if (breakany)-
1373 lbh.tmpData.textWidth += lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]];-
1374 }-
1375-
1376 if (sb_or_ws|breakany) {-
1377-
1378-
1379-
1380-
1381-
1382-
1383-
1384 QFixed previousRightBearing = lbh.rightBearing;-
1385 if ((lbh.calculateNewWidth(line) + qAbs(lbh.minimumRightBearing)) > line.width)-
1386 lbh.calculateRightBearing();-
1387-
1388 if (lbh.checkFullOtherwiseExtend(line)) {-
1389-
1390-
1391-
1392 if (previousRightBearing != LineBreakHelper::RightBearingNotCalculated)-
1393 lbh.rightBearing = previousRightBearing;-
1394 else-
1395 lbh.calculateRightBearingForPreviousGlyph();-
1396-
1397 if (!breakany) {-
1398 line.textWidth += lbh.softHyphenWidth;-
1399 }-
1400-
1401 goto found;-
1402 }-
1403 }-
1404 lbh.saveCurrentGlyph();-
1405 }-
1406 if (lbh.currentPosition == end)-
1407 newItem = item + 1;-
1408 }-
1409 if (0) QMessageLogger(__FILE__, 20092015, __PRETTY_FUNCTION__).debug("reached end of line");
dead code: QMessageLogger(__FILE__, 2015, __PRETTY_FUNCTION__).debug("reached end of line");
-
1410 lbh.checkFullOtherwiseExtend(line);-
1411found:-
1412 line.textAdvance = line.textWidth;-
1413-
1414-
1415 if (lbh.rightBearing == LineBreakHelper::RightBearingNotCalculated && !lbh.whiteSpaceOrObject)-
1416 lbh.calculateRightBearing();-
1417-
1418-
1419 line.textWidth += lbh.negativeRightBearing();-
1420-
1421 if (line.length == 0) {-
1422 if (0) QMessageLogger(__FILE__, 20222028, __PRETTY_FUNCTION__).debug("no break available in line, adding temp: length %d, width %f, space: length %d, width %f",
dead code: QMessageLogger(__FILE__, 2028, __PRETTY_FUNCTION__).debug("no break available in line, adding temp: length %d, width %f, space: length %d, width %f", lbh.tmpData.length, lbh.tmpData.textWidth.toReal(), lbh.spaceData.length, lbh.spaceData.textWidth.toReal());
-
1423 lbh.tmpData.length, lbh.tmpData.textWidth.toReal(),
dead code: QMessageLogger(__FILE__, 2028, __PRETTY_FUNCTION__).debug("no break available in line, adding temp: length %d, width %f, space: length %d, width %f", lbh.tmpData.length, lbh.tmpData.textWidth.toReal(), lbh.spaceData.length, lbh.spaceData.textWidth.toReal());
-
1424 lbh.spaceData.length, lbh.spaceData.textWidth.toReal());
dead code: QMessageLogger(__FILE__, 2028, __PRETTY_FUNCTION__).debug("no break available in line, adding temp: length %d, width %f, space: length %d, width %f", lbh.tmpData.length, lbh.tmpData.textWidth.toReal(), lbh.spaceData.length, lbh.spaceData.textWidth.toReal());
-
1425 line += lbh.tmpData;-
1426 }-
1427-
1428 if (0) QMessageLogger(__FILE__, 20282034, __PRETTY_FUNCTION__).debug("line length = %d, ascent=%f, descent=%f, textWidth=%f (spacew=%f)", line.length, line.ascent.toReal(),
dead code: QMessageLogger(__FILE__, 2034, __PRETTY_FUNCTION__).debug("line length = %d, ascent=%f, descent=%f, textWidth=%f (spacew=%f)", line.length, line.ascent.toReal(), line.descent.toReal(), line.textWidth.toReal(), lbh.spaceData.width.toReal());
-
1429 line.descent.toReal(), line.textWidth.toReal(), lbh.spaceData.width.toReal());
dead code: QMessageLogger(__FILE__, 2034, __PRETTY_FUNCTION__).debug("line length = %d, ascent=%f, descent=%f, textWidth=%f (spacew=%f)", line.length, line.ascent.toReal(), line.descent.toReal(), line.textWidth.toReal(), lbh.spaceData.width.toReal());
-
1430 if (0) QMessageLogger(__FILE__, 20302036, __PRETTY_FUNCTION__).debug(" : '%s'", eng->layoutData->string.mid(line.from, line.length).toUtf8().data());
dead code: QMessageLogger(__FILE__, 2036, __PRETTY_FUNCTION__).debug(" : '%s'", eng->layoutData->string.mid(line.from, line.length).toUtf8().data());
-
1431-
1432 if (lbh.manualWrap) {-
1433 eng->minWidth = qMax(eng->minWidth, line.textWidth);-
1434 eng->maxWidth = qMax(eng->maxWidth, line.textWidth);-
1435 } else {-
1436 eng->minWidth = qMax(eng->minWidth, lbh.minw);-
1437 eng->maxWidth += line.textWidth;-
1438 }-
1439-
1440 if (line.textWidth > 0 && item < eng->layoutData->items.size())-
1441 eng->maxWidth += lbh.spaceData.textWidth;-
1442 if (eng->option.flags() & QTextOption::IncludeTrailingSpaces)-
1443 line.textWidth += lbh.spaceData.textWidth;-
1444 if (lbh.spaceData.length) {-
1445 line.trailingSpaces = lbh.spaceData.length;-
1446 line.hasTrailingSpaces = true;-
1447 }-
1448-
1449 line.justified = false;-
1450 line.gridfitted = false;-
1451-
1452 if (eng->option.wrapMode() == QTextOption::WrapAtWordBoundaryOrAnywhere) {-
1453 if ((lbh.maxGlyphs != 2147483647 && lbh.glyphCount > lbh.maxGlyphs)-
1454 || (lbh.maxGlyphs == 2147483647 && line.textWidth > line.width)) {-
1455-
1456 eng->option.setWrapMode(QTextOption::WrapAnywhere);-
1457 line.length = 0;-
1458 line.textWidth = 0;-
1459 layout_helper(lbh.maxGlyphs);-
1460 eng->option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);-
1461 }-
1462 }-
1463}-
1464-
1465-
1466-
1467-
1468void QTextLine::setPosition(const QPointF &pos)-
1469{-
1470 eng->lines[index].x = QFixed::fromReal(pos.x());-
1471 eng->lines[index].y = QFixed::fromReal(pos.y());-
1472}-
1473-
1474-
1475-
1476-
1477QPointF QTextLine::position() const-
1478{-
1479 return QPointF(eng->lines[index].x.toReal(), eng->lines[index].y.toReal());-
1480}-
1481int QTextLine::textStart() const-
1482{-
1483 return eng->lines[index].from;-
1484}-
1485-
1486-
1487-
1488-
1489-
1490-
1491int QTextLine::textLength() const-
1492{-
1493 if (eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators-
1494 && eng->block.isValid() && index == eng->lines.count()-1) {-
1495 return eng->lines[index].length - 1;-
1496 }-
1497 return eng->lines[index].length + eng->lines[index].trailingSpaces;-
1498}-
1499-
1500static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const QTextCharFormat &chf, const QRectF &r)-
1501{-
1502 QBrush c = chf.foreground();-
1503 if (c.style() == Qt::NoBrush) {-
1504 p->setPen(defaultPen);-
1505 }-
1506-
1507 QBrush bg = chf.background();-
1508 if (bg.style() != Qt::NoBrush && !chf.property(0x513).toBool())-
1509 p->fillRect(QRectF(qFloor(r.x()), qFloor(r.y()), r.width(), r.height()), bg);-
1510 if (c.style() != Qt::NoBrush) {-
1511 p->setPen(QPen(c, 0));-
1512 }-
1513-
1514}-
1515-
1516-
1517static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine,-
1518 const QGlyphLayout &glyphLayout,-
1519 const QPointF &pos,-
1520 const QGlyphRun::GlyphRunFlags &flags,-
1521 const QFixed &selectionX,-
1522 const QFixed &selectionWidth,-
1523 int glyphsStart,-
1524 int glyphsEnd,-
1525 unsigned short *logClusters,-
1526 int textPosition,-
1527 int textLength)-
1528{-
1529 ((!(logClusters != 0)) ? qt_assert("logClusters != 0",__FILE__,21412147) : qt_noop());-
1530-
1531 QGlyphRun glyphRun;-
1532-
1533 QGlyphRunPrivate *d = QGlyphRunPrivate::get(glyphRun);-
1534-
1535 int rangeStart = textPosition;-
1536 while (*logClusters != glyphsStart && rangeStart < textPosition + textLength) {-
1537 ++logClusters;-
1538 ++rangeStart;-
1539 }-
1540-
1541 int rangeEnd = rangeStart;-
1542 while (*logClusters != glyphsEnd && rangeEnd < textPosition + textLength) {-
1543 ++logClusters;-
1544 ++rangeEnd;-
1545 }-
1546-
1547 d->textRangeStart = rangeStart;-
1548 d->textRangeEnd = rangeEnd;-
1549-
1550-
1551 QRawFont font;-
1552 QRawFontPrivate *fontD = QRawFontPrivate::get(font);-
1553 fontD->setFontEngine(fontEngine);-
1554-
1555 QVarLengthArray<glyph_t> glyphsArray;-
1556 QVarLengthArray<QFixedPoint> positionsArray;-
1557-
1558 QTextItem::RenderFlags renderFlags;-
1559 if (flags.testFlag(QGlyphRun::Overline))-
1560 renderFlags |= QTextItem::Overline;-
1561 if (flags.testFlag(QGlyphRun::Underline))-
1562 renderFlags |= QTextItem::Underline;-
1563 if (flags.testFlag(QGlyphRun::StrikeOut))-
1564 renderFlags |= QTextItem::StrikeOut;-
1565 if (flags.testFlag(QGlyphRun::RightToLeft))-
1566 renderFlags |= QTextItem::RightToLeft;-
1567-
1568 fontEngine->getGlyphPositions(glyphLayout, QTransform(), renderFlags, glyphsArray,-
1569 positionsArray);-
1570 ((!(glyphsArray.size() == positionsArray.size())) ? qt_assert("glyphsArray.size() == positionsArray.size()",__FILE__,21822188) : qt_noop());-
1571-
1572 qreal fontHeight = font.ascent() + font.descent();-
1573 qreal minY = 0;-
1574 qreal maxY = 0;-
1575 QVector<quint32> glyphs;-
1576 glyphs.reserve(glyphsArray.size());-
1577 QVector<QPointF> positions;-
1578 positions.reserve(glyphsArray.size());-
1579 for (int i=0; i<glyphsArray.size(); ++i) {-
1580 glyphs.append(glyphsArray.at(i) & 0xffffff);-
1581-
1582 QPointF position = positionsArray.at(i).toPointF() + pos;-
1583 positions.append(position);-
1584-
1585 if (i == 0) {-
1586 maxY = minY = position.y();-
1587 } else {-
1588 minY = qMin(minY, position.y());-
1589 maxY = qMax(maxY, position.y());-
1590 }-
1591 }-
1592-
1593 qreal height = maxY + fontHeight - minY;-
1594-
1595 glyphRun.setGlyphIndexes(glyphs);-
1596 glyphRun.setPositions(positions);-
1597 glyphRun.setFlags(flags);-
1598 glyphRun.setRawFont(font);-
1599-
1600 glyphRun.setBoundingRect(QRectF(selectionX.toReal(), minY - font.ascent(),-
1601 selectionWidth.toReal(), height));-
1602-
1603 return glyphRun;-
1604}-
1605QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const-
1606{-
1607 const QScriptLine &line = eng->lines[index];-
1608-
1609 if (line.length == 0)-
1610 return QList<QGlyphRun>();-
1611-
1612 if (from < 0)-
1613 from = textStart();-
1614-
1615 if (length < 0)-
1616 length = textLength();-
1617-
1618 if (length == 0)-
1619 return QList<QGlyphRun>();-
1620-
1621 QTextLayout::FormatRange selection;-
1622 selection.start = from;-
1623 selection.length = length;-
1624-
1625 QTextLineItemIterator iterator(eng, index, QPointF(), &selection);-
1626 qreal y = line.y.toReal() + line.base().toReal();-
1627 QList<QGlyphRun> glyphRuns;-
1628 while (!iterator.atEnd()) {-
1629 QScriptItem &si = iterator.next();-
1630 if (si.analysis.flags >= QScriptAnalysis::TabOrObject)-
1631 continue;-
1632-
1633 if (from >= 0 && length >= 0 && (from >= iterator.itemEnd || from + length <= iterator.itemStart))-
1634 continue;-
1635-
1636 QPointF pos(iterator.x.toReal(), y);-
1637-
1638 QFont font;-
1639 QGlyphRun::GlyphRunFlags flags;-
1640 if (!eng->useRawFont) {-
1641 font = eng->font(si);-
1642 if (font.overline())-
1643 flags |= QGlyphRun::Overline;-
1644 if (font.underline())-
1645 flags |= QGlyphRun::Underline;-
1646 if (font.strikeOut())-
1647 flags |= QGlyphRun::StrikeOut;-
1648 }-
1649-
1650 bool rtl = false;-
1651 if (si.analysis.bidiLevel % 2) {-
1652 flags |= QGlyphRun::RightToLeft;-
1653 rtl = true;-
1654 }-
1655-
1656 int relativeFrom = qMax(iterator.itemStart, from) - si.position;-
1657 int relativeTo = qMin(iterator.itemEnd, from + length) - 1 - si.position;-
1658-
1659 unsigned short *logClusters = eng->logClusters(&si);-
1660 int glyphsStart = logClusters[relativeFrom];-
1661 int glyphsEnd = (relativeTo == iterator.itemLength) ? si.num_glyphs - 1 : logClusters[relativeTo];-
1662-
1663 int nextGlyphIndex = (relativeTo < iterator.itemLength - 1) ? logClusters[relativeTo + 1] : si.num_glyphs;-
1664 if (nextGlyphIndex - 1 > glyphsEnd)-
1665 glyphsEnd = nextGlyphIndex - 1;-
1666 bool startsInsideLigature = relativeFrom > 0 && logClusters[relativeFrom - 1] == glyphsStart;-
1667 bool endsInsideLigature = nextGlyphIndex == glyphsEnd;-
1668-
1669 int itemGlyphsStart = logClusters[iterator.itemStart - si.position];-
1670 int itemGlyphsEnd = logClusters[iterator.itemEnd - 1 - si.position];-
1671-
1672 QGlyphLayout glyphLayout = eng->shapedGlyphs(&si);-
1673-
1674-
1675-
1676-
1677 if (relativeFrom != (iterator.itemStart - si.position) && !rtl) {-
1678 for (int i=itemGlyphsStart; i<glyphsStart; ++i) {-
1679 QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6);-
1680 pos.rx() += (glyphLayout.advances[i] + justification).toReal();-
1681 }-
1682 } else if (relativeTo != (iterator.itemEnd - si.position - 1) && rtl) {-
1683 for (int i=itemGlyphsEnd; i>glyphsEnd; --i) {-
1684 QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6);-
1685 pos.rx() += (glyphLayout.advances[i] + justification).toReal();-
1686 }-
1687 }-
1688-
1689 glyphLayout = glyphLayout.mid(glyphsStart, glyphsEnd - glyphsStart + 1);-
1690-
1691 QFixed x;-
1692 QFixed width;-
1693 iterator.getSelectionBounds(&x, &width);-
1694-
1695 if (glyphLayout.numGlyphs > 0) {-
1696 QFontEngine *mainFontEngine;-
1697-
1698 if (eng->useRawFont && eng->rawFont.isValid())-
1699 mainFontEngine= eng->fontEngine(si);-
1700 else-
1701-
1702 mainFontEngine = font.d->engineForScript(si.analysis.script);-
1703-
1704 if (mainFontEngine->type() == QFontEngine::Multi) {-
1705 QFontEngineMulti *multiFontEngine = static_cast<QFontEngineMulti *>(mainFontEngine);-
1706 int start = rtl ? glyphLayout.numGlyphs : 0;-
1707 int end = start - 1;-
1708 int which = glyphLayout.glyphs[rtl ? start - 1 : end + 1] >> 24;-
1709 for (; (rtl && start > 0) || (!rtl && end < glyphLayout.numGlyphs - 1);-
1710 rtl ? --start : ++end) {-
1711 const int e = glyphLayout.glyphs[rtl ? start - 1 : end + 1] >> 24;-
1712 if (e == which)-
1713 continue;-
1714-
1715 QGlyphLayout subLayout = glyphLayout.mid(start, end - start + 1);-
1716 multiFontEngine->ensureEngineAt(which);-
1717-
1718 QGlyphRun::GlyphRunFlags subFlags = flags;-
1719 if (start == 0 && startsInsideLigature)-
1720 subFlags |= QGlyphRun::SplitLigature;-
1721-
1722 glyphRuns.append(glyphRunWithInfo(multiFontEngine->engine(which),-
1723 subLayout,-
1724 pos,-
1725 subFlags,-
1726 x,-
1727 width,-
1728 glyphsStart + start,-
1729 glyphsStart + end,-
1730 logClusters + relativeFrom,-
1731 relativeFrom + si.position,-
1732 relativeTo - relativeFrom + 1));-
1733 for (int i = 0; i < subLayout.numGlyphs; ++i) {-
1734 QFixed justification = QFixed::fromFixed(subLayout.justifications[i].space_18d6);-
1735 pos.rx() += (subLayout.advances[i] + justification).toReal();-
1736 }-
1737-
1738 if (rtl)-
1739 end = start - 1;-
1740 else-
1741 start = end + 1;-
1742 which = e;-
1743 }-
1744-
1745 QGlyphLayout subLayout = glyphLayout.mid(start, end - start + 1);-
1746 multiFontEngine->ensureEngineAt(which);-
1747-
1748 QGlyphRun::GlyphRunFlags subFlags = flags;-
1749 if ((start == 0 && startsInsideLigature) || endsInsideLigature)-
1750 subFlags |= QGlyphRun::SplitLigature;-
1751-
1752 QGlyphRun glyphRun = glyphRunWithInfo(multiFontEngine->engine(which),-
1753 subLayout,-
1754 pos,-
1755 subFlags,-
1756 x,-
1757 width,-
1758 glyphsStart + start,-
1759 glyphsStart + end,-
1760 logClusters + relativeFrom,-
1761 relativeFrom + si.position,-
1762 relativeTo - relativeFrom + 1);-
1763 if (!glyphRun.isEmpty())-
1764 glyphRuns.append(glyphRun);-
1765 } else {-
1766 if (startsInsideLigature || endsInsideLigature)-
1767 flags |= QGlyphRun::SplitLigature;-
1768 QGlyphRun glyphRun = glyphRunWithInfo(mainFontEngine,-
1769 glyphLayout,-
1770 pos,-
1771 flags,-
1772 x,-
1773 width,-
1774 glyphsStart,-
1775 glyphsEnd,-
1776 logClusters + relativeFrom,-
1777 relativeFrom + si.position,-
1778 relativeTo - relativeFrom + 1);-
1779 if (!glyphRun.isEmpty())-
1780 glyphRuns.append(glyphRun);-
1781 }-
1782 }-
1783 }-
1784-
1785 return glyphRuns;-
1786}-
1787void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatRange *selection) const-
1788{-
1789-
1790-
1791 ((!(!eng->useRawFont)) ? qt_assert("!eng->useRawFont",__FILE__,24252431) : qt_noop());-
1792-
1793 const QScriptLine &line = eng->lines[index];-
1794 QPen pen = p->pen();-
1795-
1796 bool noText = (selection && selection->format.property(0x5012).toBool());-
1797-
1798 if (!line.length) {-
1799 if (selection-
1800 && selection->start <= line.from-
1801 && selection->start + selection->length > line.from) {-
1802-
1803 const qreal lineHeight = line.height().toReal();-
1804 QRectF r(pos.x() + line.x.toReal(), pos.y() + line.y.toReal(),-
1805 lineHeight / 2, QFontMetrics(eng->font()).width(QLatin1Char(' ')));-
1806 setPenAndDrawBackground(p, QPen(), selection->format, r);-
1807 p->setPen(pen);-
1808 }-
1809 return;-
1810 }-
1811-
1812-
1813 QTextLineItemIterator iterator(eng, index, pos, selection);-
1814 QFixed lineBase = line.base();-
1815 eng->clearDecorations();-
1816 eng->enableDelayDecorations();-
1817-
1818 const QFixed y = QFixed::fromReal(pos.y()) + line.y + lineBase;-
1819-
1820 bool suppressColors = (eng->option.flags() & QTextOption::SuppressColors);-
1821 while (!iterator.atEnd()) {-
1822 QScriptItem &si = iterator.next();-
1823-
1824 if (selection && selection->start >= 0 && iterator.isOutsideSelection())-
1825 continue;-
1826-
1827 if (si.analysis.flags == QScriptAnalysis::LineOrParagraphSeparator-
1828 && !(eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators))-
1829 continue;-
1830-
1831 QFixed itemBaseLine = y;-
1832 QFont f = eng->font(si);-
1833 QTextCharFormat format;-
1834-
1835 if (eng->hasFormats() || selection) {-
1836 format = eng->format(&si);-
1837 if (suppressColors) {-
1838 format.clearForeground();-
1839 format.clearBackground();-
1840 format.clearProperty(QTextFormat::TextUnderlineColor);-
1841 }-
1842 if (selection)-
1843 format.merge(selection->format);-
1844-
1845 setPenAndDrawBackground(p, pen, format, QRectF(iterator.x.toReal(), (y - lineBase).toReal(),-
1846 iterator.itemWidth.toReal(), line.height().toReal()));-
1847-
1848 QTextCharFormat::VerticalAlignment valign = format.verticalAlignment();-
1849 if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) {-
1850 QFontEngine *fe = f.d->engineForScript(si.analysis.script);-
1851 QFixed height = fe->ascent() + fe->descent();-
1852 if (valign == QTextCharFormat::AlignSubScript)-
1853 itemBaseLine += height / 6;-
1854 else if (valign == QTextCharFormat::AlignSuperScript)-
1855 itemBaseLine -= height / 2;-
1856 }-
1857 }-
1858-
1859 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {-
1860-
1861 if (eng->hasFormats()) {-
1862 p->save();-
1863 if (si.analysis.flags == QScriptAnalysis::Object && eng->block.docHandle()) {-
1864 QFixed itemY = y - si.ascent;-
1865 if (format.verticalAlignment() == QTextCharFormat::AlignTop) {-
1866 itemY = y - lineBase;-
1867 }-
1868-
1869 QRectF itemRect(iterator.x.toReal(), itemY.toReal(), iterator.itemWidth.toReal(), si.height().toReal());-
1870-
1871 eng->docLayout()->drawInlineObject(p, itemRect,-
1872 QTextInlineObject(iterator.item, eng),-
1873 si.position + eng->block.position(),-
1874 format);-
1875 if (selection) {-
1876 QBrush bg = format.brushProperty((QTextFormat::ForegroundBrush + 1));-
1877 if (bg.style() != Qt::NoBrush) {-
1878 QColor c = bg.color();-
1879 c.setAlpha(128);-
1880 p->fillRect(itemRect, c);-
1881 }-
1882 }-
1883 } else {-
1884 QFont f = eng->font(si);-
1885 QTextItemInt gf(si, &f, format);-
1886 gf.chars = 0;-
1887 gf.num_chars = 0;-
1888 gf.width = iterator.itemWidth;-
1889 QPainterPrivate::get(p)->drawTextItem(QPointF(iterator.x.toReal(), y.toReal()), gf, eng);-
1890 if (eng->option.flags() & QTextOption::ShowTabsAndSpaces) {-
1891 QChar visualTab(0x2192);-
1892 int w = QFontMetrics(f).width(visualTab);-
1893 qreal x = iterator.itemWidth.toReal() - w;-
1894 if (x < 0)-
1895 p->setClipRect(QRectF(iterator.x.toReal(), line.y.toReal(),-
1896 iterator.itemWidth.toReal(), line.height().toReal()),-
1897 Qt::IntersectClip);-
1898 else-
1899 x /= 2;-
1900 p->drawText(QPointF(iterator.x.toReal() + x,-
1901 y.toReal()), visualTab);-
1902 }-
1903-
1904 }-
1905 p->restore();-
1906 }-
1907-
1908 continue;-
1909 }-
1910-
1911 unsigned short *logClusters = eng->logClusters(&si);-
1912 QGlyphLayout glyphs = eng->shapedGlyphs(&si);-
1913-
1914 QTextItemInt gf(glyphs.mid(iterator.glyphsStart, iterator.glyphsEnd - iterator.glyphsStart),-
1915 &f, eng->layoutData->string.unicode() + iterator.itemStart,-
1916 iterator.itemEnd - iterator.itemStart, eng->fontEngine(si), format);-
1917 gf.logClusters = logClusters + iterator.itemStart - si.position;-
1918 gf.width = iterator.itemWidth;-
1919 gf.justified = line.justified;-
1920 gf.initWithScriptItem(si);-
1921-
1922 ((!(gf.fontEngine)) ? qt_assert("gf.fontEngine",__FILE__,25562562) : qt_noop());-
1923-
1924 QPointF pos(iterator.x.toReal(), itemBaseLine.toReal());-
1925 if (format.penProperty(QTextFormat::TextOutline).style() != Qt::NoPen) {-
1926 QPainterPath path;-
1927 path.setFillRule(Qt::WindingFill);-
1928-
1929 if (gf.glyphs.numGlyphs)-
1930 gf.fontEngine->addOutlineToPath(pos.x(), pos.y(), gf.glyphs, &path, gf.flags);-
1931 if (gf.flags) {-
1932 const QFontEngine *fe = gf.fontEngine;-
1933 const qreal lw = fe->lineThickness().toReal();-
1934 if (gf.flags & QTextItem::Underline) {-
1935 qreal offs = fe->underlinePosition().toReal();-
1936 path.addRect(pos.x(), pos.y() + offs, gf.width.toReal(), lw);-
1937 }-
1938 if (gf.flags & QTextItem::Overline) {-
1939 qreal offs = fe->ascent().toReal() + 1;-
1940 path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);-
1941 }-
1942 if (gf.flags & QTextItem::StrikeOut) {-
1943 qreal offs = fe->ascent().toReal() / 3;-
1944 path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);-
1945 }-
1946 }-
1947-
1948 p->save();-
1949 p->setRenderHint(QPainter::Antialiasing);-
1950-
1951-
1952 if (p->pen().style() == Qt::NoPen)-
1953 p->setBrush(Qt::NoBrush);-
1954 else-
1955 p->setBrush(p->pen().brush());-
1956-
1957 p->setPen(format.textOutline());-
1958 p->drawPath(path);-
1959 p->restore();-
1960 } else {-
1961 if (noText)-
1962 gf.glyphs.numGlyphs = 0;-
1963 QPainterPrivate::get(p)->drawTextItem(pos, gf, eng);-
1964 }-
1965-
1966 if (si.analysis.flags == QScriptAnalysis::Space-
1967 && (eng->option.flags() & QTextOption::ShowTabsAndSpaces)) {-
1968 QBrush c = format.foreground();-
1969 if (c.style() != Qt::NoBrush)-
1970 p->setPen(c.color());-
1971 QChar visualSpace((ushort)0xb7);-
1972 p->drawText(QPointF(iterator.x.toReal(), itemBaseLine.toReal()), visualSpace);-
1973 p->setPen(pen);-
1974 }-
1975 }-
1976 eng->drawDecorations(p);-
1977-
1978 if (eng->hasFormats())-
1979 p->setPen(pen);-
1980}-
1981qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const-
1982{-
1983 const QScriptLine &line = eng->lines[index];-
1984 bool lastLine = index >= eng->lines.size() - 1;-
1985-
1986 QFixed x = line.x + eng->alignLine(line) - eng->leadingSpaceWidth(line);-
1987-
1988 if (!eng->layoutData)-
1989 eng->itemize();-
1990 if (!eng->layoutData->items.size()) {-
1991 *cursorPos = line.from;-
1992 return x.toReal();-
1993 }-
1994-
1995 int lineEnd = line.from + line.length + line.trailingSpaces;-
1996 int pos = qBound(line.from, *cursorPos, lineEnd);-
1997 int itm;-
1998 const QCharAttributes *attributes = eng->attributes();-
1999 if (!attributes) {-
2000 *cursorPos = line.from;-
2001 return x.toReal();-
2002 }-
2003 while (pos < lineEnd && !attributes[pos].graphemeBoundary)-
2004 pos++;-
2005 if (pos == lineEnd) {-
2006-
2007 itm = eng->findItem(pos-1);-
2008 }-
2009 else-
2010 itm = eng->findItem(pos);-
2011 if (itm < 0) {-
2012 *cursorPos = line.from;-
2013 return x.toReal();-
2014 }-
2015 eng->shapeLine(line);-
2016-
2017 const QScriptItem *si = &eng->layoutData->items[itm];-
2018 if (!si->num_glyphs)-
2019 eng->shape(itm);-
2020-
2021 const int l = eng->length(itm);-
2022 pos = qBound(0, pos - si->position, l);-
2023-
2024 QGlyphLayout glyphs = eng->shapedGlyphs(si);-
2025 unsigned short *logClusters = eng->logClusters(si);-
2026 ((!(logClusters)) ? qt_assert("logClusters",__FILE__,26772683) : qt_noop());-
2027-
2028 int glyph_pos = pos == l ? si->num_glyphs : logClusters[pos];-
2029 if (edge == Trailing && glyph_pos < si->num_glyphs) {-
2030-
2031 glyph_pos++;-
2032 while (glyph_pos < si->num_glyphs && !glyphs.attributes[glyph_pos].clusterStart)-
2033 glyph_pos++;-
2034 }-
2035-
2036 bool reverse = si->analysis.bidiLevel % 2;-
2037-
2038-
2039-
2040-
2041 int firstItem = eng->findItem(line.from);-
2042 int lastItem = eng->findItem(lineEnd - 1, itm);-
2043 int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;-
2044-
2045 QVarLengthArray<int> visualOrder(nItems);-
2046 QVarLengthArray<uchar> levels(nItems);-
2047 for (int i = 0; i < nItems; ++i)-
2048 levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;-
2049 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());-
2050-
2051 for (int i = 0; i < nItems; ++i) {-
2052 int item = visualOrder[i]+firstItem;-
2053 if (item == itm)-
2054 break;-
2055 QScriptItem &si = eng->layoutData->items[item];-
2056 if (!si.num_glyphs)-
2057 eng->shape(item);-
2058-
2059 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {-
2060 x += si.width;-
2061 continue;-
2062 }-
2063-
2064 const int itemLength = eng->length(item);-
2065 int start = qMax(line.from, si.position);-
2066 int end = qMin(lineEnd, si.position + itemLength);-
2067-
2068 logClusters = eng->logClusters(&si);-
2069-
2070 int gs = logClusters[start-si.position];-
2071 int ge = (end == si.position + itemLength) ? si.num_glyphs-1 : logClusters[end-si.position-1];-
2072-
2073 QGlyphLayout glyphs = eng->shapedGlyphs(&si);-
2074-
2075 while (gs <= ge) {-
2076 x += glyphs.effectiveAdvance(gs);-
2077 ++gs;-
2078 }-
2079 }-
2080-
2081 logClusters = eng->logClusters(si);-
2082 glyphs = eng->shapedGlyphs(si);-
2083 if (si->analysis.flags >= QScriptAnalysis::TabOrObject) {-
2084 if (pos == (reverse ? 0 : l))-
2085 x += si->width;-
2086 } else {-
2087 bool rtl = eng->isRightToLeft();-
2088 bool visual = eng->visualCursorMovement();-
2089 int end = qMin(lineEnd, si->position + l) - si->position;-
2090 if (reverse) {-
2091 int glyph_end = end == l ? si->num_glyphs : logClusters[end];-
2092 int glyph_start = glyph_pos;-
2093 if (visual && !rtl && !(lastLine && itm == (visualOrder[nItems - 1] + firstItem)))-
2094 glyph_start++;-
2095 for (int i = glyph_end - 1; i >= glyph_start; i--)-
2096 x += glyphs.effectiveAdvance(i);-
2097 } else {-
2098 int start = qMax(line.from - si->position, 0);-
2099 int glyph_start = logClusters[start];-
2100 int glyph_end = glyph_pos;-
2101 if (!visual || !rtl || (lastLine && itm == visualOrder[0] + firstItem))-
2102 glyph_end--;-
2103 for (int i = glyph_start; i <= glyph_end; i++)-
2104 x += glyphs.effectiveAdvance(i);-
2105 }-
2106 x += eng->offsetInLigature(si, pos, end, glyph_pos);-
2107 }-
2108-
2109 if (eng->option.wrapMode() != QTextOption::NoWrap && x > line.x + line.width)-
2110 x = line.x + line.width;-
2111 if (eng->option.wrapMode() != QTextOption::NoWrap && x < 0)-
2112 x = 0;-
2113-
2114 *cursorPos = pos + si->position;-
2115 return x.toReal();-
2116}-
2117int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const-
2118{-
2119 QFixed x = QFixed::fromReal(_x);-
2120 const QScriptLine &line = eng->lines[index];-
2121 bool lastLine = index >= eng->lines.size() - 1;-
2122 int lineNum = index;-
2123-
2124 if (!eng->layoutData)-
2125 eng->itemize();-
2126-
2127 int line_length = textLength();-
2128-
2129 if (!line_length)-
2130 return line.from;-
2131-
2132 int firstItem = eng->findItem(line.from);-
2133 int lastItem = eng->findItem(line.from + line_length - 1, firstItem);-
2134 int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;-
2135-
2136 if (!nItems)-
2137 return 0;-
2138-
2139 x -= line.x;-
2140 x -= eng->alignLine(line);-
2141-
2142-
2143 QVarLengthArray<int> visualOrder(nItems);-
2144 QVarLengthArray<unsigned char> levels(nItems);-
2145 for (int i = 0; i < nItems; ++i)-
2146 levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;-
2147 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());-
2148-
2149 bool visual = eng->visualCursorMovement();-
2150 if (x <= 0) {-
2151-
2152 int item = visualOrder[0]+firstItem;-
2153 QScriptItem &si = eng->layoutData->items[item];-
2154 if (!si.num_glyphs)-
2155 eng->shape(item);-
2156 int pos = si.position;-
2157 if (si.analysis.bidiLevel % 2)-
2158 pos += eng->length(item);-
2159 pos = qMax(line.from, pos);-
2160 pos = qMin(line.from + line_length, pos);-
2161 return pos;-
2162 } else if (x < line.textWidth-
2163 || (line.justified && x < line.width)) {-
2164-
2165 QFixed pos;-
2166 bool rtl = eng->isRightToLeft();-
2167-
2168 eng->shapeLine(line);-
2169 QVector<int> insertionPoints;-
2170 if (visual && rtl)-
2171 eng->insertionPointsForLine(lineNum, insertionPoints);-
2172 int nchars = 0;-
2173 for (int i = 0; i < nItems; ++i) {-
2174 int item = visualOrder[i]+firstItem;-
2175 QScriptItem &si = eng->layoutData->items[item];-
2176 int item_length = eng->length(item);-
2177-
2178-
2179 int start = qMax(line.from - si.position, 0);-
2180 int end = qMin(line.from + line_length - si.position, item_length);-
2181-
2182 unsigned short *logClusters = eng->logClusters(&si);-
2183-
2184 int gs = logClusters[start];-
2185 int ge = (end == item_length ? si.num_glyphs : logClusters[end]) - 1;-
2186 QGlyphLayout glyphs = eng->shapedGlyphs(&si);-
2187-
2188 QFixed item_width = 0;-
2189 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {-
2190 item_width = si.width;-
2191 } else {-
2192 int g = gs;-
2193 while (g <= ge) {-
2194 item_width += glyphs.effectiveAdvance(g);-
2195 ++g;-
2196 }-
2197 }-
2198-
2199-
2200 if (pos + item_width < x) {-
2201 pos += item_width;-
2202 nchars += end;-
2203 continue;-
2204 }-
2205-
2206 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {-
2207 if (cpos == QTextLine::CursorOnCharacter)-
2208 return si.position;-
2209 bool left_half = (x - pos) < item_width/2;-
2210-
2211 if (bool(si.analysis.bidiLevel % 2) != left_half)-
2212 return si.position;-
2213 return si.position + 1;-
2214 }-
2215-
2216 int glyph_pos = -1;-
2217 QFixed edge;-
2218-
2219 if (cpos == QTextLine::CursorOnCharacter) {-
2220 if (si.analysis.bidiLevel % 2) {-
2221 pos += item_width;-
2222 glyph_pos = gs;-
2223 while (gs <= ge) {-
2224 if (glyphs.attributes[gs].clusterStart) {-
2225 if (pos < x)-
2226 break;-
2227 glyph_pos = gs;-
2228 edge = pos;-
2229 }-
2230 pos -= glyphs.effectiveAdvance(gs);-
2231 ++gs;-
2232 }-
2233 } else {-
2234 glyph_pos = gs;-
2235 while (gs <= ge) {-
2236 if (glyphs.attributes[gs].clusterStart) {-
2237 if (pos > x)-
2238 break;-
2239 glyph_pos = gs;-
2240 edge = pos;-
2241 }-
2242 pos += glyphs.effectiveAdvance(gs);-
2243 ++gs;-
2244 }-
2245 }-
2246 } else {-
2247 QFixed dist = 2147483647/256;-
2248 if (si.analysis.bidiLevel % 2) {-
2249 if (!visual || rtl || (lastLine && i == nItems - 1)) {-
2250 pos += item_width;-
2251 while (gs <= ge) {-
2252 if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {-
2253 glyph_pos = gs;-
2254 edge = pos;-
2255 dist = qAbs(x-pos);-
2256 }-
2257 pos -= glyphs.effectiveAdvance(gs);-
2258 ++gs;-
2259 }-
2260 } else {-
2261 while (ge >= gs) {-
2262 if (glyphs.attributes[ge].clusterStart && qAbs(x-pos) < dist) {-
2263 glyph_pos = ge;-
2264 edge = pos;-
2265 dist = qAbs(x-pos);-
2266 }-
2267 pos += glyphs.effectiveAdvance(ge);-
2268 --ge;-
2269 }-
2270 }-
2271 } else {-
2272 if (!visual || !rtl || (lastLine && i == 0)) {-
2273 while (gs <= ge) {-
2274 if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {-
2275 glyph_pos = gs;-
2276 edge = pos;-
2277 dist = qAbs(x-pos);-
2278 }-
2279 pos += glyphs.effectiveAdvance(gs);-
2280 ++gs;-
2281 }-
2282 } else {-
2283 QFixed oldPos = pos;-
2284 while (gs <= ge) {-
2285 pos += glyphs.effectiveAdvance(gs);-
2286 if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {-
2287 glyph_pos = gs;-
2288 edge = pos;-
2289 dist = qAbs(x-pos);-
2290 }-
2291 ++gs;-
2292 }-
2293 pos = oldPos;-
2294 }-
2295 }-
2296 if (qAbs(x-pos) < dist) {-
2297 if (visual) {-
2298 if (!rtl && i < nItems - 1) {-
2299 nchars += end;-
2300 continue;-
2301 }-
2302 if (rtl && nchars > 0)-
2303 return insertionPoints[lastLine ? nchars : nchars - 1];-
2304 }-
2305 return eng->positionInLigature(&si, end, x, pos, -1,-
2306 cpos == QTextLine::CursorOnCharacter);-
2307 }-
2308 }-
2309 ((!(glyph_pos != -1)) ? qt_assert("glyph_pos != -1",__FILE__,29702976) : qt_noop());-
2310 return eng->positionInLigature(&si, end, x, edge, glyph_pos,-
2311 cpos == QTextLine::CursorOnCharacter);-
2312 }-
2313 }-
2314-
2315-
2316 int item = visualOrder[nItems-1]+firstItem;-
2317 QScriptItem &si = eng->layoutData->items[item];-
2318 if (!si.num_glyphs)-
2319 eng->shape(item);-
2320 int pos = si.position;-
2321 if (!(si.analysis.bidiLevel % 2))-
2322 pos += eng->length(item);-
2323 pos = qMax(line.from, pos);-
2324-
2325 int maxPos = line.from + line_length;-
2326-
2327-
2328-
2329-
2330-
2331-
2332 if (this->index < eng->lines.count() - 1)-
2333 --maxPos;-
2334-
2335 pos = qMin(pos, maxPos);-
2336 return pos;-
2337}-
2338-
2339-
Switch to Source codePreprocessed file

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