diff options
Diffstat (limited to 'src/gui/text/qtextlayout.cpp')
-rw-r--r-- | src/gui/text/qtextlayout.cpp | 88 |
1 files changed, 68 insertions, 20 deletions
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 6e824b2ed1..be306ed224 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1006,10 +1006,8 @@ static void addSelectedRegionsToPath(QTextEngine *eng, int lineNumber, const QPo } if (lastSelectionWidth > 0) { - QRectF rect = boundingRect & QRectF(lastSelectionX.toReal(), selectionY, lastSelectionWidth.toReal(), lineHeight); - rect.moveLeft(qFloor(rect.left())); - rect.moveTop(qFloor(rect.top())); - region->addRect(rect); + const QRectF rect = boundingRect & QRectF(lastSelectionX.toReal(), selectionY, lastSelectionWidth.toReal(), lineHeight); + region->addRect(rect.toAlignedRect()); } lastSelectionX = selectionX; @@ -1017,10 +1015,8 @@ static void addSelectedRegionsToPath(QTextEngine *eng, int lineNumber, const QPo } } if (lastSelectionWidth > 0) { - QRectF rect = boundingRect & QRectF(lastSelectionX.toReal(), selectionY, lastSelectionWidth.toReal(), lineHeight); - rect.moveLeft(qFloor(rect.left())); - rect.moveTop(qFloor(rect.top())); - region->addRect(rect); + const QRectF rect = boundingRect & QRectF(lastSelectionX.toReal(), selectionY, lastSelectionWidth.toReal(), lineHeight); + region->addRect(rect.toAlignedRect()); } } @@ -1827,6 +1823,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; @@ -1855,8 +1854,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; @@ -1904,9 +1906,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; @@ -2042,6 +2053,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 ¤t = 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()); @@ -2135,7 +2183,7 @@ static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const Q QBrush bg = chf.background(); if (bg.style() != Qt::NoBrush && !chf.property(SuppressBackground).toBool()) - p->fillRect(QRectF(qFloor(r.x()), qFloor(r.y()), r.width(), r.height()), bg); + p->fillRect(r.toAlignedRect(), bg); if (c.style() != Qt::NoBrush) { p->setPen(QPen(c, 0)); } @@ -2515,6 +2563,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()); @@ -2614,12 +2664,13 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR QPainterPrivate::get(p)->drawTextItem(pos, gf, eng); } - if (si.analysis.flags == QScriptAnalysis::Space + if ((si.analysis.flags == QScriptAnalysis::Space + || si.analysis.flags == QScriptAnalysis::Nbsp) && (eng->option.flags() & QTextOption::ShowTabsAndSpaces)) { QBrush c = format.foreground(); if (c.style() != Qt::NoBrush) p->setPen(c.color()); - QChar visualSpace((ushort)0xb7); + QChar visualSpace(si.analysis.flags == QScriptAnalysis::Space ? (ushort)0xb7 : (ushort)0xb0); p->drawText(QPointF(iterator.x.toReal(), itemBaseLine.toReal()), visualSpace); p->setPen(pen); } @@ -2845,9 +2896,7 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const bool rtl = eng->isRightToLeft(); eng->shapeLine(line); - QVector<int> insertionPoints; - if (visual && rtl) - eng->insertionPointsForLine(lineNum, insertionPoints); + const auto insertionPoints = (visual && rtl) ? eng->insertionPointsForLine(lineNum) : std::vector<int>(); int nchars = 0; for (int i = 0; i < nItems; ++i) { int item = visualOrder[i]+firstItem; @@ -2979,7 +3028,7 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const continue; } if (rtl && nchars > 0) - return insertionPoints[lastLine ? nchars : nchars - 1]; + return insertionPoints[size_t(lastLine ? nchars : nchars - 1)]; } return eng->positionInLigature(&si, end, x, pos, -1, cpos == QTextLine::CursorOnCharacter); @@ -3007,9 +3056,8 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const // character between lines is a space and we want // to position the cursor to the left of that // character. - // ###### breaks with japanese for example if (this->index < eng->lines.count() - 1) - --maxPos; + maxPos = eng->previousLogicalPosition(maxPos); pos = qMin(pos, maxPos); return pos; |