summaryrefslogtreecommitdiffstats
path: root/src/gui/text/qtextlayout.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/text/qtextlayout.cpp')
-rw-r--r--src/gui/text/qtextlayout.cpp124
1 files changed, 89 insertions, 35 deletions
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 013cd8ae0f..65650504ac 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -69,7 +69,7 @@ QT_BEGIN_NAMESPACE
for a specified area in the text layout's content.
\inmodule QtGui
- \sa QTextLayout::setAdditionalFormats(), QTextLayout::draw()
+ \sa QTextLayout::setFormats(), QTextLayout::draw()
*/
/*!
@@ -87,6 +87,20 @@ QT_BEGIN_NAMESPACE
Specifies the format to apply.
*/
+/*! \fn bool operator==(const FormatRange &lhs, const FormatRange &rhs)
+ \relates QTextLayout::FormatRange
+
+ Returns true if the \c {start}, \c {length}, and \c {format} fields
+ in \a lhs and \a rhs contain the same values respectively.
+ */
+
+/*! \fn bool operator!=(const FormatRange &lhs, const FormatRange &rhs)
+ \relates QTextLayout::FormatRange
+
+ Returns true if any of the \c {start}, \c {length}, or \c {format} fields
+ in \a lhs and \a rhs contain different values respectively.
+ */
+
/*!
\class QTextInlineObject
\reentrant
@@ -485,39 +499,76 @@ QString QTextLayout::preeditAreaText() const
return d->preeditAreaText();
}
+#if QT_DEPRECATED_SINCE(5, 6)
+/*!
+ \obsolete Use setFormats() instead.
+*/
+void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList)
+{
+ setFormats(formatList.toVector());
+}
+#endif // deprecated since 5.6
/*!
- Sets the additional formats supported by the text layout to \a formatList.
+ \since 5.6
+
+ Sets the additional formats supported by the text layout to \a formats.
The formats are applied with preedit area text in place.
- \sa additionalFormats(), clearAdditionalFormats()
+ \sa formats(), clearFormats()
*/
-void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList)
+void QTextLayout::setFormats(const QVector<FormatRange> &formats)
{
- d->setFormats(formatList);
+ d->setFormats(formats);
if (d->block.docHandle())
d->block.docHandle()->documentChange(d->block.position(), d->block.length());
}
+#if QT_DEPRECATED_SINCE(5, 6)
/*!
- Returns the list of additional formats supported by the text layout.
+ \obsolete Use formats() instead.
\sa setAdditionalFormats(), clearAdditionalFormats()
*/
QList<QTextLayout::FormatRange> QTextLayout::additionalFormats() const
{
+ return formats().toList();
+}
+#endif // deprecated since 5.6
+
+/*!
+ \since 5.6
+
+ Returns the list of additional formats supported by the text layout.
+
+ \sa setFormats(), clearFormats()
+*/
+QVector<QTextLayout::FormatRange> QTextLayout::formats() const
+{
return d->formats();
}
+#if QT_DEPRECATED_SINCE(5, 6)
/*!
+ \obsolete Use clearFormats() instead.
+*/
+void QTextLayout::clearAdditionalFormats()
+{
+ clearFormats();
+}
+#endif // deprecated since 5.6
+
+/*!
+ \since 5.6
+
Clears the list of additional formats supported by the text layout.
- \sa additionalFormats(), setAdditionalFormats()
+ \sa formats(), setFormats()
*/
-void QTextLayout::clearAdditionalFormats()
+void QTextLayout::clearFormats()
{
- setAdditionalFormats(QList<FormatRange>());
+ setFormats(QVector<FormatRange>());
}
/*!
@@ -1915,9 +1966,16 @@ void QTextLine::layout_helper(int maxGlyphs)
// end up breaking due to the current glyph being too wide.
QFixed previousRightBearing = lbh.rightBearing;
- // We ignore the right bearing if the minimum negative bearing is too little to
- // expand the text beyond the edge.
- if (lbh.calculateNewWidth(line) - lbh.minimumRightBearing > line.width)
+ // We skip calculating the right bearing if the minimum negative bearing is too
+ // small to possibly expand the text beyond the edge. Note that this optimization
+ // will in some cases fail, as the minimum right bearing reported by the font
+ // engine may not cover all the glyphs in the font. The result is that we think
+ // we don't need to break at the current glyph (because the right bearing is 0),
+ // and when we then end up breaking on the next glyph we compute the right bearing
+ // and end up with a line width that is slightly larger width than what was requested.
+ // Unfortunately we can't remove this optimization as it will slow down text
+ // layouting significantly, so we accept the slight correctnes issue.
+ if ((lbh.calculateNewWidth(line) + qAbs(lbh.minimumRightBearing)) > line.width)
lbh.calculateRightBearing();
if (lbh.checkFullOtherwiseExtend(line)) {
@@ -2559,33 +2617,31 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
inside the line, taking account of the \a edge.
If \a cursorPos is not a valid cursor position, the nearest valid
- cursor position will be used instead, and cpos will be modified to
+ cursor position will be used instead, and \a cursorPos will be modified to
point to this valid cursor position.
\sa xToCursor()
*/
qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
{
- if (!eng->layoutData)
- eng->itemize();
-
const QScriptLine &line = eng->lines[index];
bool lastLine = index >= eng->lines.size() - 1;
- QFixed x = line.x;
- x += eng->alignLine(line) - eng->leadingSpaceWidth(line);
+ QFixed x = line.x + eng->alignLine(line) - eng->leadingSpaceWidth(line);
- if (!index && !eng->layoutData->items.size()) {
- *cursorPos = 0;
+ if (!eng->layoutData)
+ eng->itemize();
+ if (!eng->layoutData->items.size()) {
+ *cursorPos = line.from;
return x.toReal();
}
int lineEnd = line.from + line.length + line.trailingSpaces;
- int pos = qBound(0, *cursorPos, lineEnd);
+ int pos = qBound(line.from, *cursorPos, lineEnd);
int itm;
const QCharAttributes *attributes = eng->attributes();
if (!attributes) {
- *cursorPos = 0;
+ *cursorPos = line.from;
return x.toReal();
}
while (pos < lineEnd && !attributes[pos].graphemeBoundary)
@@ -2597,7 +2653,7 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
else
itm = eng->findItem(pos);
if (itm < 0) {
- *cursorPos = 0;
+ *cursorPos = line.from;
return x.toReal();
}
eng->shapeLine(line);
@@ -2605,18 +2661,14 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
const QScriptItem *si = &eng->layoutData->items[itm];
if (!si->num_glyphs)
eng->shape(itm);
- pos -= si->position;
+
+ const int l = eng->length(itm);
+ pos = qBound(0, pos - si->position, l);
QGlyphLayout glyphs = eng->shapedGlyphs(si);
unsigned short *logClusters = eng->logClusters(si);
Q_ASSERT(logClusters);
- int l = eng->length(itm);
- if (pos > l)
- pos = l;
- if (pos < 0)
- pos = 0;
-
int glyph_pos = pos == l ? si->num_glyphs : logClusters[pos];
if (edge == Trailing && glyph_pos < si->num_glyphs) {
// trailing edge is leading edge of next cluster
@@ -2625,13 +2677,13 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
glyph_pos++;
}
- bool reverse = eng->layoutData->items[itm].analysis.bidiLevel % 2;
+ bool reverse = si->analysis.bidiLevel % 2;
// add the items left of the cursor
int firstItem = eng->findItem(line.from);
- int lastItem = eng->findItem(lineEnd - 1);
+ int lastItem = eng->findItem(lineEnd - 1, itm);
int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
QVarLengthArray<int> visualOrder(nItems);
@@ -2652,13 +2704,15 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
x += si.width;
continue;
}
+
+ const int itemLength = eng->length(item);
int start = qMax(line.from, si.position);
- int end = qMin(lineEnd, si.position + eng->length(item));
+ int end = qMin(lineEnd, si.position + itemLength);
logClusters = eng->logClusters(&si);
int gs = logClusters[start-si.position];
- int ge = (end == si.position + eng->length(item)) ? si.num_glyphs-1 : logClusters[end-si.position-1];
+ int ge = (end == si.position + itemLength) ? si.num_glyphs-1 : logClusters[end-si.position-1];
QGlyphLayout glyphs = eng->shapedGlyphs(&si);
@@ -2730,7 +2784,7 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
return line.from;
int firstItem = eng->findItem(line.from);
- int lastItem = eng->findItem(line.from + line_length - 1);
+ int lastItem = eng->findItem(line.from + line_length - 1, firstItem);
int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
if (!nItems)