summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/text/qglyphrun.cpp29
-rw-r--r--src/gui/text/qglyphrun.h2
-rw-r--r--src/gui/text/qrawfont.cpp14
-rw-r--r--src/gui/text/qrawfont.h1
-rw-r--r--src/gui/text/qtextlayout.cpp84
-rw-r--r--src/gui/text/qtextlayout.h10
-rw-r--r--src/gui/text/qtextobject.cpp2
-rw-r--r--src/gui/widgets/qlinecontrol_p.h7
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();