diff options
-rw-r--r-- | src/gui/text/qglyphrun.cpp | 29 | ||||
-rw-r--r-- | src/gui/text/qglyphrun.h | 2 | ||||
-rw-r--r-- | src/gui/text/qrawfont.cpp | 14 | ||||
-rw-r--r-- | src/gui/text/qrawfont.h | 1 | ||||
-rw-r--r-- | src/gui/text/qtextlayout.cpp | 84 | ||||
-rw-r--r-- | src/gui/text/qtextlayout.h | 10 | ||||
-rw-r--r-- | src/gui/text/qtextobject.cpp | 2 | ||||
-rw-r--r-- | src/gui/widgets/qlinecontrol_p.h | 7 |
8 files changed, 126 insertions, 23 deletions
diff --git a/src/gui/text/qglyphrun.cpp b/src/gui/text/qglyphrun.cpp index ea527886cd..38ca998dd3 100644 --- a/src/gui/text/qglyphrun.cpp +++ b/src/gui/text/qglyphrun.cpp @@ -319,6 +319,35 @@ void QGlyphRun::setStrikeOut(bool strikeOut) d->strikeOut = strikeOut; } +/*! + Returns the smallest rectangle that contains all glyphs in this QGlyphRun. + + \since 5.0 +*/ +QRectF QGlyphRun::boundingRect() const +{ + qreal minX, minY, maxX, maxY; + + for (int i=0; i<qMin(d->glyphPositions.size(), d->glyphIndexes.size()); ++i) { + QRectF glyphRect = d->rawFont.boundingRect(d->glyphIndexes.at(i)); + glyphRect.translate(d->glyphPositions.at(i)); + + if (i == 0) { + minX = glyphRect.left(); + minY = glyphRect.top(); + maxX = glyphRect.right(); + maxY = glyphRect.bottom(); + } else { + minX = qMin(glyphRect.left(), minX); + minY = qMin(glyphRect.top(), minY); + maxX = qMax(glyphRect.right(),maxX); + maxY = qMax(glyphRect.bottom(), maxY); + } + } + + return QRectF(QPointF(minX, minY), QPointF(maxX, maxY)); +} + QT_END_NAMESPACE #endif // QT_NO_RAWFONT diff --git a/src/gui/text/qglyphrun.h b/src/gui/text/qglyphrun.h index dcc166ea3e..18afb2e1d8 100644 --- a/src/gui/text/qglyphrun.h +++ b/src/gui/text/qglyphrun.h @@ -87,6 +87,8 @@ public: void setStrikeOut(bool strikeOut); bool strikeOut() const; + QRectF boundingRect() const; + private: friend class QGlyphRunPrivate; friend class QTextLine; diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp index 44ddfd2d75..1c7d5ad4b6 100644 --- a/src/gui/text/qrawfont.cpp +++ b/src/gui/text/qrawfont.cpp @@ -718,6 +718,20 @@ void QRawFontPrivate::cleanUp() hintingPreference = QFont::PreferDefaultHinting; } +/*! + Returns the smallest rectangle containing the glyph with the given \a glyphIndex. + + \since 5.0 +*/ +QRectF QRawFont::boundingRect(quint32 glyphIndex) const +{ + if (!isValid()) + return QRectF(); + + glyph_metrics_t gm = d->fontEngine->boundingBox(glyphIndex); + return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal()); +} + #endif // QT_NO_RAWFONT QT_END_NAMESPACE diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h index 3875fec641..63f3d882aa 100644 --- a/src/gui/text/qrawfont.h +++ b/src/gui/text/qrawfont.h @@ -97,6 +97,7 @@ public: AntialiasingType antialiasingType = SubPixelAntialiasing, const QTransform &transform = QTransform()) const; QPainterPath pathForGlyph(quint32 glyphIndex) const; + QRectF boundingRect(quint32 glyphIndex) const; void setPixelSize(qreal pixelSize); qreal pixelSize() const; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 07aeb72a49..91809c3266 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -997,11 +997,20 @@ static inline QRectF clipIfValid(const QRectF &rect, const QRectF &clip) \sa draw(), QPainter::drawGlyphRun() */ #if !defined(QT_NO_RAWFONT) -QList<QGlyphRun> QTextLayout::glyphRuns() const -{ +QList<QGlyphRun> QTextLayout::glyphRuns(int from, int length) const +{ + if (from < 0) + from = 0; + if (length < 0) + length = text().length(); + QList<QGlyphRun> glyphs; - for (int i=0; i<d->lines.size(); ++i) - glyphs += QTextLine(i, d).glyphs(-1, -1); + for (int i=0; i<d->lines.size(); ++i) { + if (d->lines[i].from > from + length) + break; + else if (d->lines[i].from + d->lines[i].length >= from) + glyphs += QTextLine(i, d).glyphRuns(from, length); + } return glyphs; } @@ -2084,25 +2093,32 @@ namespace { } /*! - \internal + Returns the glyph indexes and positions for all glyphs in this QTextLine for characters + in the range defined by \a from and \a length. The \a from index is relative to the beginning + of the text in the containing QTextLayout, and the range must be within the range of QTextLine + as given by functions textStart() and textLength(). - Returns the glyph indexes and positions for all glyphs in this QTextLine which reside in - QScriptItems that overlap with the range defined by \a from and \a length. The arguments - specify characters, relative to the text in the layout. Note that it is not possible to - use this function to retrieve a subset of the glyphs in a QScriptItem. + If \a from is negative, it will default to textStart(), and if \a length is negative it will + default to the return value of textLength(). - \since 4.8 + \since 5.0 \sa QTextLayout::glyphRuns() */ #if !defined(QT_NO_RAWFONT) -QList<QGlyphRun> QTextLine::glyphs(int from, int length) const +QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const { const QScriptLine &line = eng->lines[i]; if (line.length == 0) return QList<QGlyphRun>(); + if (from < 0) + from = textStart(); + + if (length < 0) + length = textLength(); + QHash<QFontEngine *, GlyphInfo> glyphLayoutHash; QTextLineItemIterator iterator(eng, i); @@ -2114,8 +2130,9 @@ QList<QGlyphRun> QTextLine::glyphs(int from, int length) const QPointF pos(iterator.x.toReal(), y); if (from >= 0 && length >= 0 && - (from >= si.position + eng->length(&si) || from + length <= si.position)) + (from >= si.position + eng->length(&si) || from + length <= si.position)) { continue; + } QFont font = eng->font(si); @@ -2126,11 +2143,42 @@ QList<QGlyphRun> QTextLine::glyphs(int from, int length) const flags |= QTextItem::Underline; if (font.strikeOut()) flags |= QTextItem::StrikeOut; - if (si.analysis.bidiLevel % 2) + + bool rtl = false; + if (si.analysis.bidiLevel % 2) { flags |= QTextItem::RightToLeft; + rtl = true; + } - QGlyphLayout glyphLayout = eng->shapedGlyphs(&si).mid(iterator.glyphsStart, - iterator.glyphsEnd - iterator.glyphsStart); + int relativeFrom = qMax(iterator.itemStart, from) - si.position; + int relativeTo = qMin(iterator.itemEnd, from + length - 1) - si.position; + + unsigned short *logClusters = eng->logClusters(&si); + int glyphsStart = logClusters[relativeFrom]; + int glyphsEnd = (relativeTo == eng->length(&si)) + ? si.num_glyphs - 1 + : logClusters[relativeTo]; + + QGlyphLayout glyphLayout = eng->shapedGlyphs(&si); + + // Calculate new x position of glyph layout for a subset. This becomes somewhat complex + // when we're breaking a RTL script item, since the expected position passed into + // getGlyphPositions() is the left-most edge of the left-most glyph in an RTL run. + if (relativeFrom != (iterator.itemStart - si.position) && !rtl) { + for (int i=0; i<glyphsStart; ++i) { + QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6); + pos += QPointF((glyphLayout.advances_x[i] + justification).toReal(), + glyphLayout.advances_y[i].toReal()); + } + } else if (relativeTo != (iterator.itemEnd - si.position) && rtl) { + for (int i=glyphLayout.numGlyphs - 1; i>glyphsEnd; --i) { + QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6); + pos += QPointF((glyphLayout.advances_x[i] + justification).toReal(), + glyphLayout.advances_y[i].toReal()); + } + } + + glyphLayout = glyphLayout.mid(glyphsStart, glyphsEnd - glyphsStart + 1); if (glyphLayout.numGlyphs > 0) { QFontEngine *mainFontEngine = font.d->engineForScript(si.analysis.script); @@ -2147,9 +2195,10 @@ QList<QGlyphRun> QTextLine::glyphs(int from, int length) const QGlyphLayout subLayout = glyphLayout.mid(start, end - start); glyphLayoutHash.insertMulti(multiFontEngine->engine(which), GlyphInfo(subLayout, pos, flags)); - for (int i = 0; i < subLayout.numGlyphs; i++) + for (int i = 0; i < subLayout.numGlyphs; i++) { pos += QPointF(subLayout.advances_x[i].toReal(), subLayout.advances_y[i].toReal()); + } start = end; which = e; @@ -2501,8 +2550,9 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const pos = 0; int glyph_pos = pos == l ? si->num_glyphs : logClusters[pos]; - if (edge == Trailing) { + if (edge == Trailing && glyph_pos < si->num_glyphs) { // trailing edge is leading edge of next cluster + glyph_pos++; while (glyph_pos < si->num_glyphs && !glyphs.attributes[glyph_pos].clusterStart) glyph_pos++; } diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h index 89fbfb2072..9840a37eec 100644 --- a/src/gui/text/qtextlayout.h +++ b/src/gui/text/qtextlayout.h @@ -174,7 +174,7 @@ public: qreal maximumWidth() const; #if !defined(QT_NO_RAWFONT) - QList<QGlyphRun> glyphRuns() const; + QList<QGlyphRun> glyphRuns(int from = -1, int length = -1) const; #endif QTextEngine *engine() const { return d; } @@ -244,14 +244,14 @@ public: void draw(QPainter *p, const QPointF &point, const QTextLayout::FormatRange *selection = 0) const; +#if !defined(QT_NO_RAWFONT) + QList<QGlyphRun> glyphRuns(int from = -1, int length = -1) const; +#endif + private: QTextLine(int line, QTextEngine *e) : i(line), eng(e) {} void layout_helper(int numGlyphs); -#if !defined(QT_NO_RAWFONT) - QList<QGlyphRun> glyphs(int from, int length) const; -#endif - friend class QTextLayout; friend class QTextFragment; int i; diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index 8dabcc771b..4c03dafe1d 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -1685,7 +1685,7 @@ QList<QGlyphRun> QTextFragment::glyphRuns() const QList<QGlyphRun> ret; for (int i=0; i<layout->lineCount(); ++i) { QTextLine textLine = layout->lineAt(i); - ret += textLine.glyphs(pos, len); + ret += textLine.glyphRuns(pos, len); } return ret; diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 9764ba9c59..1530c756dc 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -302,6 +302,8 @@ public: void setCursorBlinkPeriod(int msec); void resetCursorBlinkTimer(); + bool cursorBlinkStatus() const { return m_blinkStatus; } + QString cancelText() const { return m_cancelText; } void setCancelText(const QString &text) { m_cancelText = text; } @@ -318,6 +320,11 @@ public: bool processEvent(QEvent *ev); + QTextLayout *textLayout() + { + return &m_textLayout; + } + private: void init(const QString &txt); void removeSelectedText(); |