diff options
Diffstat (limited to 'src/gui/text/qtextlayout.cpp')
-rw-r--r-- | src/gui/text/qtextlayout.cpp | 46 |
1 files changed, 37 insertions, 9 deletions
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index b2f12ef1ce..30f07ba69b 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -850,6 +850,10 @@ QTextLine QTextLayout::createLine() int l = d->lines.size(); if (l && d->lines.at(l-1).length < 0) { QTextLine(l-1, d).setNumColumns(INT_MAX); + if (d->maxWidth > QFIXED_MAX / 2) { + qWarning("QTextLayout: text too long, truncated."); + return QTextLine(); + } } int from = l > 0 ? d->lines.at(l-1).from + d->lines.at(l-1).length + d->lines.at(l-1).trailingSpaces : 0; int strlen = d->layoutData->string.length(); @@ -1169,10 +1173,17 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRang QRectF fullLineRect(tl.rect()); fullLineRect.translate(position); fullLineRect.setRight(QFIXED_MAX); - if (!selectionEndInLine) - region.addRect(clipIfValid(QRectF(lineRect.topRight(), fullLineRect.bottomRight()), clip)); - if (!selectionStartInLine) - region.addRect(clipIfValid(QRectF(fullLineRect.topLeft(), lineRect.bottomLeft()), clip)); + + const bool rightToLeft = d->isRightToLeft(); + + if (!selectionEndInLine) { + region.addRect(clipIfValid(rightToLeft ? QRectF(fullLineRect.topLeft(), lineRect.bottomLeft()) + : QRectF(lineRect.topRight(), fullLineRect.bottomRight()), clip)); + } + if (!selectionStartInLine) { + region.addRect(clipIfValid(rightToLeft ? QRectF(lineRect.topRight(), fullLineRect.bottomRight()) + : QRectF(fullLineRect.topLeft(), lineRect.bottomLeft()), clip)); + } } else if (!selectionEndInLine && isLastLineInBlock &&!(d->option.flags() & QTextOption::ShowLineAndParagraphSeparators)) { @@ -1325,13 +1336,13 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition bool rightToLeft = d->isRightToLeft(); if (itm >= 0) { const QScriptItem &si = d->layoutData->items.at(itm); - if (si.ascent > 0) + if (si.ascent >= 0) base = si.ascent; - if (si.descent > 0) + if (si.descent >= 0) descent = si.descent; rightToLeft = si.analysis.bidiLevel % 2; } - qreal y = position.y() + (sl.y + sl.base() - base).toReal(); + qreal y = position.y() + (sl.y + sl.base() + sl.descent - base - descent).toReal(); bool toggleAntialiasing = !(p->renderHints() & QPainter::Antialiasing) && (p->transform().type() > QTransform::TxTranslate); if (toggleAntialiasing) @@ -1339,7 +1350,20 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition QPainter::CompositionMode origCompositionMode = p->compositionMode(); if (p->paintEngine()->hasFeature(QPaintEngine::RasterOpModes)) p->setCompositionMode(QPainter::RasterOp_NotDestination); - p->fillRect(QRectF(x, y, qreal(width), (base + descent).toReal()), p->pen().brush()); + const QTransform &deviceTransform = p->deviceTransform(); + const qreal xScale = deviceTransform.m11(); + if (deviceTransform.type() != QTransform::TxScale || std::trunc(xScale) == xScale) { + p->fillRect(QRectF(x, y, qreal(width), (base + descent).toReal()), p->pen().brush()); + } else { + // Ensure consistently rendered cursor width under fractional scaling + const QPen origPen = p->pen(); + QPen pen(origPen.brush(), qRound(width * xScale), Qt::SolidLine, Qt::FlatCap); + pen.setCosmetic(true); + const qreal center = x + qreal(width) / 2; + p->setPen(pen); + p->drawLine(QPointF(center, y), QPointF(center, y + (base + descent).toReal())); + p->setPen(origPen); + } p->setCompositionMode(origCompositionMode); if (toggleAntialiasing) p->setRenderHint(QPainter::Antialiasing, false); @@ -1976,7 +2000,8 @@ void QTextLine::layout_helper(int maxGlyphs) if (lbh.currentPosition >= eng->layoutData->string.length() || isBreakableSpace - || attributes[lbh.currentPosition].lineBreak) { + || attributes[lbh.currentPosition].lineBreak + || lbh.tmpData.textWidth >= QFIXED_MAX) { sb_or_ws = true; break; } else if (attributes[lbh.currentPosition].graphemeBoundary) { @@ -2535,6 +2560,9 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR return; } + static QRectF maxFixedRect(QPointF(-QFIXED_MAX, -QFIXED_MAX), QPointF(QFIXED_MAX, QFIXED_MAX)); + if (!maxFixedRect.contains(pos)) + return; QTextLineItemIterator iterator(eng, index, pos, selection); QFixed lineBase = line.base(); |