Handle negative leading in layout

Adjust line positions to deal with negative leading which isn't included
in height of QTextLine.

Change-Id: Id7918968c0f9d7e65700b9e7a08fc5d761883f22
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
This commit is contained in:
Allan Sandfeld Jensen 2018-02-02 17:08:58 +01:00
parent b72a9cbaaf
commit b46cb00fc0
3 changed files with 27 additions and 21 deletions

View File

@ -2549,12 +2549,14 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout
}
static inline void getLineHeightParams(const QTextBlockFormat &blockFormat, const QTextLine &line, qreal scaling,
QFixed *lineAdjustment, QFixed *lineBreakHeight, QFixed *lineHeight)
QFixed *lineAdjustment, QFixed *lineBreakHeight, QFixed *lineHeight, QFixed *lineBottom)
{
*lineHeight = QFixed::fromReal(blockFormat.lineHeight(line.height(), scaling));
qreal rawHeight = qCeil(line.ascent() + line.descent() + line.leading());
*lineHeight = QFixed::fromReal(blockFormat.lineHeight(rawHeight, scaling));
*lineBottom = QFixed::fromReal(blockFormat.lineHeight(line.height(), scaling));
if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight || blockFormat.lineHeightType() == QTextBlockFormat::MinimumHeight) {
*lineBreakHeight = *lineHeight;
*lineBreakHeight = *lineBottom;
if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight)
*lineAdjustment = QFixed::fromReal(line.ascent() + qMax(line.leading(), qreal(0.0))) - ((*lineHeight * 4) / 5);
else
@ -2632,6 +2634,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
const QFixed cy = layoutStruct->y;
const QFixed l = layoutStruct->x_left + totalLeftMargin;
const QFixed r = layoutStruct->x_right - totalRightMargin;
QFixed bottom;
tl->beginLayout();
bool firstLine = true;
@ -2701,10 +2704,10 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
}
QFixed lineBreakHeight, lineHeight, lineAdjustment;
QFixed lineBreakHeight, lineHeight, lineAdjustment, lineBottom;
qreal scaling = (q->paintDevice() && q->paintDevice()->logicalDpiY() != qt_defaultDpi()) ?
qreal(q->paintDevice()->logicalDpiY()) / qreal(qt_defaultDpi()) : 1;
getLineHeightParams(blockFormat, line, scaling, &lineAdjustment, &lineBreakHeight, &lineHeight);
getLineHeightParams(blockFormat, line, scaling, &lineAdjustment, &lineBreakHeight, &lineHeight, &lineBottom);
if (layoutStruct->pageHeight > 0 && layoutStruct->absoluteY() + lineBreakHeight > layoutStruct->pageBottom) {
layoutStruct->newPage();
@ -2719,6 +2722,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
}
line.setPosition(QPointF((left - layoutStruct->x_left).toReal(), (layoutStruct->y - cy - lineAdjustment).toReal()));
bottom = layoutStruct->y + lineBottom;
layoutStruct->y += lineHeight;
layoutStruct->contentsWidth
= qMax<QFixed>(layoutStruct->contentsWidth, QFixed::fromReal(line.x() + line.naturalTextWidth()) + totalRightMargin);
@ -2730,27 +2734,31 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
}
layoutStruct->pendingFloats.clear();
}
layoutStruct->y = qMax(layoutStruct->y, bottom);
tl->endLayout();
} else {
const int cnt = tl->lineCount();
QFixed bottom;
for (int i = 0; i < cnt; ++i) {
LDEBUG << "going to move text line" << i;
QTextLine line = tl->lineAt(i);
layoutStruct->contentsWidth
= qMax(layoutStruct->contentsWidth, QFixed::fromReal(line.x() + tl->lineAt(i).naturalTextWidth()) + totalRightMargin);
QFixed lineBreakHeight, lineHeight, lineAdjustment;
QFixed lineBreakHeight, lineHeight, lineAdjustment, lineBottom;
qreal scaling = (q->paintDevice() && q->paintDevice()->logicalDpiY() != qt_defaultDpi()) ?
qreal(q->paintDevice()->logicalDpiY()) / qreal(qt_defaultDpi()) : 1;
getLineHeightParams(blockFormat, line, scaling, &lineAdjustment, &lineBreakHeight, &lineHeight);
getLineHeightParams(blockFormat, line, scaling, &lineAdjustment, &lineBreakHeight, &lineHeight, &lineBottom);
if (layoutStruct->pageHeight != QFIXED_MAX) {
if (layoutStruct->absoluteY() + lineBreakHeight > layoutStruct->pageBottom)
layoutStruct->newPage();
line.setPosition(QPointF(line.position().x(), (layoutStruct->y - lineAdjustment).toReal() - tl->position().y()));
}
bottom = layoutStruct->y + lineBottom;
layoutStruct->y += lineHeight;
}
layoutStruct->y = qMax(layoutStruct->y, bottom);
if (layoutStruct->updateRect.isValid()
&& blockLength > 1) {
if (layoutFrom >= blockPosition + blockLength) {

View File

@ -46,6 +46,7 @@
#include <qdebug.h>
#include <qdrag.h>
#include <qclipboard.h>
#include <qmath.h>
#if QT_CONFIG(menu)
#include <qmenu.h>
#endif
@ -380,6 +381,8 @@ void QPlainTextDocumentLayout::layoutBlock(const QTextBlock &block)
line.setLineWidth(availableWidth);
line.setPosition(QPointF(margin, height));
height += line.height();
if (line.leading() < 0)
height += qCeil(line.leading());
blockMaximumWidth = qMax(blockMaximumWidth, line.naturalTextWidth() + 2*margin);
}
tl->endLayout();

View File

@ -245,38 +245,33 @@ void tst_QStaticText::compareToDrawText()
QPainter p(&imageDrawStaticPlainText);
p.setFont(font);
QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
text.setTextWidth(30),
text.setTextWidth(10),
p.setClipRect(QRectF(11, 12, 30, 500));
text.setTextFormat(Qt::PlainText);
p.drawStaticText(QPointF(11, 12), text);
}
#if defined(DEBUG_SAVE_IMAGE)
imageDrawText.save("compareToDrawText_imageDrawText.png");
imageDrawStaticPlainText.save("compareToDrawText_imageDrawStaticPlainText.png");
#endif
QVERIFY(imageDrawText.toImage() != m_whiteSquare);
QCOMPARE(imageDrawStaticPlainText, imageDrawText);
// Rich text rendering does not take negative leading into account.
#if 0
QPixmap imageDrawStaticRichText(1000, 1000);
imageDrawStaticRichText.fill(Qt::white);
{
QPainter p(&imageDrawStaticRichText);
p.setFont(font);
QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
text.setTextWidth(30),
text.setTextWidth(10),
p.setClipRect(QRectF(11, 12, 30, 500));
text.setTextFormat(Qt::RichText);
p.drawStaticText(QPointF(11, 12), text);
}
#if defined(DEBUG_SAVE_IMAGE)
imageDrawStaticRichText.save("compareToDrawText_imageDrawStaticRichText.png");
imageDrawText.save("compareToDrawText_imageDrawText.png");
imageDrawStaticText.save("compareToDrawText_imageDrawStaticPlainText.png");
imageDrawStaticText.save("compareToDrawText_imageDrawStaticRichText.png");
#endif
QVERIFY(imageDrawText.toImage() != m_whiteSquare);
QCOMPARE(imageDrawStaticPlainText, imageDrawText);
QCOMPARE(imageDrawStaticRichText, imageDrawText);
#endif
}
void tst_QStaticText::prepareToCorrectData()