Skip to content

Commit

Permalink
Add QFontMetricsF methods taking text options into account
Browse files Browse the repository at this point in the history
This is needed by Qt Quick to be able to calculate font metrics using
design metrics matching Quick text rendering.

Task-number: QTBUG-85936
Task-number: QTBUG-94023
Change-Id: I67c74e2a912bd58df7a57349a858f20f04609f0f
Reviewed-by: Lars Knoll <[email protected]>
  • Loading branch information
Allan Sandfeld Jensen committed Oct 21, 2021
1 parent 8a4f252 commit c1a5f08
Show file tree
Hide file tree
Showing 2 changed files with 201 additions and 6 deletions.
200 changes: 194 additions & 6 deletions src/gui/text/qfontmetrics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,33 @@ int QFontMetrics::horizontalAdvance(const QString &text, int len) const
return qRound(layout.width(0, len));
}

/*!
Returns the horizontal advance in pixels of \a text laid out using \a option.
The advance is the distance appropriate for drawing a subsequent
character after \a text.
\since 6.3
\sa boundingRect()
*/
int QFontMetrics::horizontalAdvance(const QString &text, const QTextOption &option) const
{
int pos = text.indexOf(QLatin1Char('\x9c'));
int len = -1;
if (pos != -1) {
len = (len < 0) ? pos : qMin(pos, len);
} else if (len < 0) {
len = text.length();
}
if (len == 0)
return 0;

QStackTextEngine layout(text, QFont(d.data()));
layout.option = option;
return qRound(layout.width(0, len));
}

/*!
\overload
Expand Down Expand Up @@ -622,6 +649,42 @@ QRect QFontMetrics::boundingRect(const QString &text) const
return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
}

/*!
Returns the bounding rectangle of the characters in the string
specified by \a text laid out using \a option. The bounding rectangle always
covers at least the set of pixels the text would cover if drawn at (0, 0).
Note that the bounding rectangle may extend to the left of (0, 0),
e.g. for italicized fonts, and that the width of the returned
rectangle might be different than what the horizontalAdvance() method
returns.
If you want to know the advance width of the string (to lay out
a set of strings next to each other), use horizontalAdvance() instead.
Newline characters are processed as normal characters, \e not as
linebreaks.
The height of the bounding rectangle is at least as large as the
value returned by height().
\since 6.3
\sa horizontalAdvance(), height(), QPainter::boundingRect(),
tightBoundingRect()
*/
QRect QFontMetrics::boundingRect(const QString &text, const QTextOption &option) const
{
if (text.length() == 0)
return QRect();

QStackTextEngine layout(text, QFont(d.data()));
layout.option = option;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, text.length());
return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
}

/*!
Returns the rectangle that is covered by ink if character \a ch
were to be drawn at the origin of the coordinate system.
Expand Down Expand Up @@ -758,8 +821,6 @@ QSize QFontMetrics::size(int flags, const QString &text, int tabStops, int *tabA
}

/*!
\since 4.3
Returns a tight bounding rectangle around the characters in the
string specified by \a text. The bounding rectangle always covers
at least the set of pixels the text would cover if drawn at (0,
Expand All @@ -776,7 +837,7 @@ QSize QFontMetrics::size(int flags, const QString &text, int tabStops, int *tabA
Newline characters are processed as normal characters, \e not as
linebreaks.
\warning Calling this method is very slow on Windows.
\since 4.3
\sa horizontalAdvance(), height(), boundingRect()
*/
Expand All @@ -791,6 +852,38 @@ QRect QFontMetrics::tightBoundingRect(const QString &text) const
return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
}

/*!
Returns a tight bounding rectangle around the characters in the
string specified by \a text laid out using \a option. The bounding
rectangle always covers at least the set of pixels the text would
cover if drawn at (0, 0).
Note that the bounding rectangle may extend to the left of (0, 0),
e.g. for italicized fonts, and that the width of the returned
rectangle might be different than what the horizontalAdvance() method
returns.
If you want to know the advance width of the string (to lay out
a set of strings next to each other), use horizontalAdvance() instead.
Newline characters are processed as normal characters, \e not as
linebreaks.
\since 6.3
\sa horizontalAdvance(), height(), boundingRect()
*/
QRect QFontMetrics::tightBoundingRect(const QString &text, const QTextOption &option) const
{
if (text.length() == 0)
return QRect();

QStackTextEngine layout(text, QFont(d.data()));
layout.option = option;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
}

/*!
\since 4.2
Expand Down Expand Up @@ -1355,6 +1448,34 @@ qreal QFontMetricsF::horizontalAdvance(const QString &text, int length) const
return layout.width(0, length).toReal();
}

/*!
Returns the horizontal advance in pixels of \a text laid out using \a option.
The advance is the distance appropriate for drawing a subsequent
character after \a text.
\since 6.3
\sa boundingRect()
*/
qreal QFontMetricsF::horizontalAdvance(const QString &text, const QTextOption &option) const
{
int pos = text.indexOf(QLatin1Char('\x9c'));
int length = -1;
if (pos != -1)
length = (length < 0) ? pos : qMin(pos, length);
else if (length < 0)
length = text.length();

if (length == 0)
return 0;

QStackTextEngine layout(text, QFont(d.data()));
layout.option = option;
layout.itemize();
return layout.width(0, length).toReal();
}

/*!
\overload
Expand Down Expand Up @@ -1442,6 +1563,42 @@ QRectF QFontMetricsF::boundingRect(const QString &text) const
gm.width.toReal(), gm.height.toReal());
}

/*!
Returns the bounding rectangle of the characters in the string
specified by \a text laid out using \a option. The bounding
rectangle always covers at least the set of pixels the text
would cover if drawn at (0, 0).
Note that the bounding rectangle may extend to the left of (0, 0),
e.g. for italicized fonts, and that the width of the returned
rectangle might be different than what the horizontalAdvance() method returns.
If you want to know the advance width of the string (to lay out
a set of strings next to each other), use horizontalAdvance() instead.
Newline characters are processed as normal characters, \e not as
linebreaks.
The height of the bounding rectangle is at least as large as the
value returned height().
\since 6.3
\sa horizontalAdvance(), height(), QPainter::boundingRect()
*/
QRectF QFontMetricsF::boundingRect(const QString &text, const QTextOption &option) const
{
if (text.length() == 0)
return QRectF();

QStackTextEngine layout(text, QFont(d.data()));
layout.option = option;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, text.length());
return QRectF(gm.x.toReal(), gm.y.toReal(),
gm.width.toReal(), gm.height.toReal());
}


/*!
Returns the bounding rectangle of the character \a ch relative to
the left-most point on the base line.
Expand Down Expand Up @@ -1600,16 +1757,47 @@ QSizeF QFontMetricsF::size(int flags, const QString &text, int tabStops, int *ta
Newline characters are processed as normal characters, \e not as
linebreaks.
\warning Calling this method is very slow on Windows.
\sa horizontalAdvance(), height(), boundingRect()
*/
QRectF QFontMetricsF::tightBoundingRect(const QString &text) const
{
if (text.length() == 0)
return QRect();
return QRectF();

QStackTextEngine layout(text, QFont(d.data()));
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
}

/*!
Returns a tight bounding rectangle around the characters in the
string specified by \a text laid out using \a option. The bounding
rectangle always covers at least the set of pixels the text would
cover if drawn at (0,0).
Note that the bounding rectangle may extend to the left of (0, 0),
e.g. for italicized fonts, and that the width of the returned
rectangle might be different than what the horizontalAdvance() method
returns.
If you want to know the advance width of the string (to lay out
a set of strings next to each other), use horizontalAdvance() instead.
Newline characters are processed as normal characters, \e not as
linebreaks.
\since 6.3
\sa horizontalAdvance(), height(), boundingRect()
*/
QRectF QFontMetricsF::tightBoundingRect(const QString &text, const QTextOption &option) const
{
if (text.length() == 0)
return QRectF();

QStackTextEngine layout(text, QFont(d.data()));
layout.option = option;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
Expand Down
7 changes: 7 additions & 0 deletions src/gui/text/qfontmetrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
QT_BEGIN_NAMESPACE

class QRect;
class QTextOption;

class Q_GUI_EXPORT QFontMetrics
{
Expand Down Expand Up @@ -85,18 +86,21 @@ class Q_GUI_EXPORT QFontMetrics
int rightBearing(QChar) const;

int horizontalAdvance(const QString &, int len = -1) const;
int horizontalAdvance(const QString &, const QTextOption &textOption) const;
int horizontalAdvance(QChar) const;

QRect boundingRect(QChar) const;

QRect boundingRect(const QString &text) const;
QRect boundingRect(const QString &text, const QTextOption &textOption) const;
QRect boundingRect(const QRect &r, int flags, const QString &text, int tabstops = 0, int *tabarray = nullptr) const;
inline QRect boundingRect(int x, int y, int w, int h, int flags, const QString &text,
int tabstops = 0, int *tabarray = nullptr) const
{ return boundingRect(QRect(x, y, w, h), flags, text, tabstops, tabarray); }
QSize size(int flags, const QString& str, int tabstops = 0, int *tabarray = nullptr) const;

QRect tightBoundingRect(const QString &text) const;
QRect tightBoundingRect(const QString &text, const QTextOption &textOption) const;

QString elidedText(const QString &text, Qt::TextElideMode mode, int width, int flags = 0) const;

Expand Down Expand Up @@ -155,13 +159,16 @@ class Q_GUI_EXPORT QFontMetricsF

qreal horizontalAdvance(const QString &string, int length = -1) const;
qreal horizontalAdvance(QChar) const;
qreal horizontalAdvance(const QString &string, const QTextOption &textOption) const;

QRectF boundingRect(const QString &string) const;
QRectF boundingRect(const QString &text, const QTextOption &textOption) const;
QRectF boundingRect(QChar) const;
QRectF boundingRect(const QRectF &r, int flags, const QString& string, int tabstops = 0, int *tabarray = nullptr) const;
QSizeF size(int flags, const QString& str, int tabstops = 0, int *tabarray = nullptr) const;

QRectF tightBoundingRect(const QString &text) const;
QRectF tightBoundingRect(const QString &text, const QTextOption &textOption) const;

QString elidedText(const QString &text, Qt::TextElideMode mode, qreal width, int flags = 0) const;

Expand Down

0 comments on commit c1a5f08

Please sign in to comment.