summaryrefslogtreecommitdiffstats
path: root/src/gui/text
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2018-11-21 23:59:03 +0100
committerLiang Qi <liang.qi@qt.io>2018-11-22 01:53:29 +0100
commitbf58c70546c5f9cb66d99b82abfde9ba1a056192 (patch)
treedf3675d3377ef6576f82fb167ebd67fcc900a91b /src/gui/text
parent37f617c405ae4f26cbb6bb4f08d61d6ccc111a98 (diff)
parent41cba737a98b16a2767c55cda0532f38b6b6a37d (diff)
Merge remote-tracking branch 'origin/5.12' into dev
Conflicts: src/corelib/io/qdir.cpp src/corelib/kernel/qtimer.cpp src/corelib/kernel/qtimer.h Done-With: Edward Welbourne <edward.welbourne@qt.io> Change-Id: I683d897760ec06593136d77955f8bc87fdef3f9f
Diffstat (limited to 'src/gui/text')
-rw-r--r--src/gui/text/qfont.cpp2
-rw-r--r--src/gui/text/qtextdocument.cpp2
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp21
-rw-r--r--src/gui/text/qtextengine.cpp21
-rw-r--r--src/gui/text/qtextformat.cpp3
-rw-r--r--src/gui/text/qtextlayout.cpp60
6 files changed, 82 insertions, 27 deletions
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index 27d804a3b4..3654c28fc5 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -1287,7 +1287,7 @@ QFont::StyleStrategy QFont::styleStrategy() const
/*!
Returns the StyleHint.
- The style hint affects the \l{#fontmatching}{font matching algorithm}.
+ The style hint affects the \l{QFont#fontmatching}{font matching algorithm}.
See \l QFont::StyleHint for the list of available hints.
\sa setStyleHint(), QFont::StyleStrategy, QFontInfo::styleHint()
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index 008f695da0..4f187c6701 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -155,7 +155,7 @@ bool Qt::mightBeRichText(const QString& text)
This function is defined in the \c <QTextDocument> header file.
- \sa escape(), mightBeRichText()
+ \sa QString::toHtmlEscaped(), mightBeRichText()
*/
QString Qt::convertFromPlainText(const QString &plain, Qt::WhiteSpaceMode mode)
{
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index a9227f0171..ebd7a7d69f 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -2709,7 +2709,8 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
qreal(q->paintDevice()->logicalDpiY()) / qreal(qt_defaultDpi()) : 1;
getLineHeightParams(blockFormat, line, scaling, &lineAdjustment, &lineBreakHeight, &lineHeight, &lineBottom);
- if (layoutStruct->pageHeight > 0 && layoutStruct->absoluteY() + lineBreakHeight > layoutStruct->pageBottom) {
+ if (layoutStruct->pageHeight > 0 && layoutStruct->absoluteY() + lineBreakHeight > layoutStruct->pageBottom &&
+ layoutStruct->pageHeight >= lineBreakHeight) {
layoutStruct->newPage();
floatMargins(layoutStruct->y, layoutStruct, &left, &right);
@@ -3049,18 +3050,12 @@ void QTextDocumentLayout::resizeInlineObject(QTextInlineObject item, int posInDo
QSizeF inlineSize = (pos == QTextFrameFormat::InFlow ? intrinsic : QSizeF(0, 0));
item.setWidth(inlineSize.width());
- QFontMetrics m(f.font());
- switch (f.verticalAlignment())
- {
- case QTextCharFormat::AlignMiddle:
- item.setDescent(inlineSize.height() / 2);
- item.setAscent(inlineSize.height() / 2);
- break;
- case QTextCharFormat::AlignBaseline:
- item.setDescent(m.descent());
- item.setAscent(inlineSize.height() - m.descent());
- break;
- default:
+ if (f.verticalAlignment() == QTextCharFormat::AlignMiddle) {
+ QFontMetrics m(f.font());
+ qreal halfX = m.xHeight()/2.;
+ item.setAscent((inlineSize.height() + halfX) / 2.);
+ item.setDescent((inlineSize.height() - halfX) / 2.);
+ } else {
item.setDescent(0);
item.setAscent(inlineSize.height());
}
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 4e9b00f9c9..8de16038ad 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1962,19 +1962,24 @@ const QCharAttributes *QTextEngine::attributes() const
void QTextEngine::shape(int item) const
{
- if (layoutData->items.at(item).analysis.flags == QScriptAnalysis::Object) {
+ auto &li = layoutData->items[item];
+ if (li.analysis.flags == QScriptAnalysis::Object) {
ensureSpace(1);
if (block.docHandle()) {
docLayout()->resizeInlineObject(QTextInlineObject(item, const_cast<QTextEngine *>(this)),
- layoutData->items[item].position + block.position(),
- format(&layoutData->items[item]));
+ li.position + block.position(),
+ format(&li));
}
- } else if (layoutData->items.at(item).analysis.flags == QScriptAnalysis::Tab) {
+ // fix log clusters to point to the previous glyph, as the object doesn't have a glyph of it's own.
+ // This is required so that all entries in the array get initialized and are ordered correctly.
+ ushort *lc = logClusters(&li);
+ *lc = item ? lc[-1] : 0;
+ } else if (li.analysis.flags == QScriptAnalysis::Tab) {
// set up at least the ascent/descent/leading of the script item for the tab
- fontEngine(layoutData->items[item],
- &layoutData->items[item].ascent,
- &layoutData->items[item].descent,
- &layoutData->items[item].leading);
+ fontEngine(li, &li.ascent, &li.descent, &li.leading);
+ // see the comment above
+ ushort *lc = logClusters(&li);
+ *lc = item ? lc[-1] : 0;
} else {
shapeText(item);
}
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 18de8408b5..e814f4f718 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -649,6 +649,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
\value ImageName
\value ImageWidth
\value ImageHeight
+ \value ImageQuality
Selection properties
@@ -2274,7 +2275,7 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
\fn void QTextBlockFormat::setHeadingLevel(int level)
\since 5.12
- Sets the paragraph's heading level, where 1 is the highest-level heading
+ Sets the paragraph's heading \a level, where 1 is the highest-level heading
type (usually with the largest possible heading font size), and increasing
values are progressively deeper into the document (and usually with smaller
font sizes). For example when reading an HTML H1 tag, the heading level is
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index ec49406548..e85b408db9 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -1834,6 +1834,9 @@ void QTextLine::layout_helper(int maxGlyphs)
lbh.logClusters = eng->layoutData->logClustersPtr;
lbh.previousGlyph = 0;
+ bool hasInlineObject = false;
+ QFixed maxInlineObjectHeight = 0;
+
while (newItem < eng->layoutData->items.size()) {
lbh.resetRightBearing();
lbh.softHyphenWidth = 0;
@@ -1862,8 +1865,11 @@ void QTextLine::layout_helper(int maxGlyphs)
lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent,
current.leading + current.ascent) - qMax(lbh.tmpData.ascent,
current.ascent);
- lbh.tmpData.ascent = qMax(lbh.tmpData.ascent, current.ascent);
- lbh.tmpData.descent = qMax(lbh.tmpData.descent, current.descent);
+ if (current.analysis.flags != QScriptAnalysis::Object) {
+ // objects need some special treatment as they can special alignment or be floating
+ lbh.tmpData.ascent = qMax(lbh.tmpData.ascent, current.ascent);
+ lbh.tmpData.descent = qMax(lbh.tmpData.descent, current.descent);
+ }
if (current.analysis.flags == QScriptAnalysis::Tab && (alignment & (Qt::AlignLeft | Qt::AlignRight | Qt::AlignCenter | Qt::AlignJustify))) {
lbh.whiteSpaceOrObject = true;
@@ -1911,9 +1917,18 @@ void QTextLine::layout_helper(int maxGlyphs)
if (eng->block.docHandle()) {
QTextInlineObject inlineObject(item, eng);
- eng->docLayout()->positionInlineObject(inlineObject, eng->block.position() + current.position, inlineObject.format());
+ QTextFormat f = inlineObject.format();
+ eng->docLayout()->positionInlineObject(inlineObject, eng->block.position() + current.position, f);
+ QTextCharFormat::VerticalAlignment valign = f.toCharFormat().verticalAlignment();
+ if (valign != QTextCharFormat::AlignTop && valign != QTextCharFormat::AlignBottom) {
+ lbh.tmpData.ascent = qMax(lbh.tmpData.ascent, current.ascent);
+ lbh.tmpData.descent = qMax(lbh.tmpData.descent, current.descent);
+ }
}
+ hasInlineObject = true;
+ maxInlineObjectHeight = qMax(maxInlineObjectHeight, current.ascent + current.descent);
+
lbh.tmpData.textWidth += current.width;
newItem = item + 1;
@@ -2049,6 +2064,43 @@ found:
line += lbh.tmpData;
}
+ if (hasInlineObject && eng->block.docHandle()) {
+ // position top/bottom aligned inline objects
+ if (maxInlineObjectHeight > line.ascent + line.descent) {
+ // extend line height if required
+ QFixed toAdd = (maxInlineObjectHeight - line.ascent - line.descent)/2;
+ line.ascent += toAdd;
+ line.descent = maxInlineObjectHeight - line.ascent;
+ }
+ int startItem = eng->findItem(line.from);
+ int endItem = eng->findItem(line.from + line.length);
+ if (endItem < 0)
+ endItem = eng->layoutData->items.size();
+ for (int item = startItem; item < endItem; ++item) {
+ QScriptItem &current = eng->layoutData->items[item];
+ if (current.analysis.flags == QScriptAnalysis::Object) {
+ QTextInlineObject inlineObject(item, eng);
+ QTextCharFormat::VerticalAlignment align = inlineObject.format().toCharFormat().verticalAlignment();
+ QFixed height = current.ascent + current.descent;
+ switch (align) {
+ case QTextCharFormat::AlignTop:
+ current.ascent = line.ascent;
+ current.descent = height - line.ascent;
+ break;
+ case QTextCharFormat::AlignBottom:
+ current.descent = line.descent;
+ current.ascent = height - line.descent;
+ break;
+ default:
+ break;
+ }
+ Q_ASSERT(line.ascent >= current.ascent);
+ Q_ASSERT(line.descent >= current.descent);
+ }
+ }
+ }
+
+
LB_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());
LB_DEBUG(" : '%s'", eng->layoutData->string.mid(line.from, line.length).toUtf8().data());
@@ -2522,6 +2574,8 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
QFixed itemY = y - si.ascent;
if (format.verticalAlignment() == QTextCharFormat::AlignTop) {
itemY = y - lineBase;
+ } else if (format.verticalAlignment() == QTextCharFormat::AlignBottom) {
+ itemY = y + line.descent - si.ascent - si.descent;
}
QRectF itemRect(iterator.x.toReal(), itemY.toReal(), iterator.itemWidth.toReal(), si.height().toReal());