1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qfont.h"
5#include "qpaintdevice.h"
6#include "qfontmetrics.h"
7
8#include "qfont_p.h"
9#include "qfontengine_p.h"
10
11QT_BEGIN_NAMESPACE
12
13
14extern void qt_format_text(const QFont& font, const QRectF &_r,
15 int tf, const QString &text, QRectF *brect,
16 int tabStops, int *tabArray, int tabArrayLen,
17 QPainter *painter);
18
19/*****************************************************************************
20 QFontMetrics member functions
21 *****************************************************************************/
22
23/*!
24 \class QFontMetrics
25 \reentrant
26 \inmodule QtGui
27
28 \brief The QFontMetrics class provides font metrics information.
29
30 \ingroup painting
31 \ingroup shared
32
33 QFontMetrics functions calculate the size of characters and
34 strings for a given font. There are three ways you can create a
35 QFontMetrics object:
36
37 \list 1
38 \li Calling the QFontMetrics constructor with a QFont creates a
39 font metrics object for a screen-compatible font, i.e. the font
40 cannot be a printer font. If the font is changed
41 later, the font metrics object is \e not updated.
42
43 (Note: If you use a printer font the values returned may be
44 inaccurate. Printer fonts are not always accessible so the nearest
45 screen font is used if a printer font is supplied.)
46
47 \li QWidget::fontMetrics() returns the font metrics for a widget's
48 font. This is equivalent to QFontMetrics(widget->font()). If the
49 widget's font is changed later, the font metrics object is \e not
50 updated.
51
52 \li QPainter::fontMetrics() returns the font metrics for a
53 painter's current font. If the painter's font is changed later, the
54 font metrics object is \e not updated.
55 \endlist
56
57 Once created, the object provides functions to access the
58 individual metrics of the font, its characters, and for strings
59 rendered in the font.
60
61 There are several functions that operate on the font: ascent(),
62 descent(), height(), leading() and lineSpacing() return the basic
63 size properties of the font. The underlinePos(), overlinePos(),
64 strikeOutPos() and lineWidth() functions, return the properties of
65 the line that underlines, overlines or strikes out the
66 characters. These functions are all fast.
67
68 There are also some functions that operate on the set of glyphs in
69 the font: minLeftBearing(), minRightBearing() and maxWidth().
70 These are by necessity slow, and we recommend avoiding them if
71 possible.
72
73 For each character, you can get its horizontalAdvance(), leftBearing(),
74 and rightBearing(), and find out whether it is in the font using
75 inFont(). You can also treat the character as a string, and use
76 the string functions on it.
77
78 The string functions include horizontalAdvance(), to return the advance
79 width of a string in pixels (or points, for a printer), boundingRect(),
80 to return a rectangle large enough to contain the rendered string,
81 and size(), to return the size of that rectangle.
82
83 \note The advance width can be different from the width of the actual
84 rendered text. It refers to the distance from the origin of the string to
85 where you would append additional characters. As text may have overhang
86 (in the case of an italic font for instance) or padding between
87 characters, the advance width can be either smaller or larger than the
88 actual rendering of the text. This is called the right bearing of the
89 text.
90
91 Example:
92 \snippet code/src_gui_text_qfontmetrics.cpp 0
93
94 \sa QFont, QFontInfo, QFontDatabase
95*/
96
97/*!
98 \fn QRect QFontMetrics::boundingRect(int x, int y, int width, int height,
99 int flags, const QString &text, int tabStops, int *tabArray) const
100 \overload
101
102 Returns the bounding rectangle for the given \a text within the
103 rectangle specified by the \a x and \a y coordinates, \a width, and
104 \a height.
105
106 If Qt::TextExpandTabs is set in \a flags and \a tabArray is
107 non-null, it specifies a 0-terminated sequence of pixel-positions
108 for tabs; otherwise, if \a tabStops is non-zero, it is used as the
109 tab spacing (in pixels).
110*/
111
112/*!
113 Constructs a font metrics object for \a font.
114
115 The font metrics will be compatible with the paintdevice used to
116 create \a font.
117
118 The font metrics object holds the information for the font that is
119 passed in the constructor at the time it is created, and is not
120 updated if the font's attributes are changed later.
121
122 Use QFontMetrics(const QFont &, QPaintDevice *) to get the font
123 metrics that are compatible with a certain paint device.
124*/
125QFontMetrics::QFontMetrics(const QFont &font)
126 : d(font.d)
127{
128}
129
130/*!
131 \since 5.13
132 \fn QFontMetrics::QFontMetrics(const QFont &font, const QPaintDevice *paintdevice)
133 Constructs a font metrics object for \a font and \a paintdevice.
134
135 The font metrics will be compatible with the paintdevice passed.
136 If the \a paintdevice is \nullptr, the metrics will be screen-compatible,
137 ie. the metrics you get if you use the font for drawing text on a
138 \l{QWidget}{widgets} or \l{QPixmap}{pixmaps},
139 not on a QPicture or QPrinter.
140
141 The font metrics object holds the information for the font that is
142 passed in the constructor at the time it is created, and is not
143 updated if the font's attributes are changed later.
144*/
145QFontMetrics::QFontMetrics(const QFont &font, const QPaintDevice *paintdevice)
146{
147 const int dpi = paintdevice ? paintdevice->logicalDpiY() : qt_defaultDpi();
148 if (font.d->dpi != dpi) {
149 d = new QFontPrivate(*font.d);
150 d->dpi = dpi;
151 } else {
152 d = font.d;
153 }
154
155}
156
157/*!
158 Constructs a copy of \a fm.
159*/
160QFontMetrics::QFontMetrics(const QFontMetrics &fm)
161 : d(fm.d)
162{
163}
164
165/*!
166 Destroys the font metrics object and frees all allocated
167 resources.
168*/
169QFontMetrics::~QFontMetrics()
170{
171}
172
173/*!
174 Assigns the font metrics \a fm.
175*/
176QFontMetrics &QFontMetrics::operator=(const QFontMetrics &fm)
177{
178 d = fm.d;
179 return *this;
180}
181
182/*!
183 \fn QFontMetrics &QFontMetrics::operator=(QFontMetrics &&other)
184
185 Move-assigns \a other to this QFontMetrics instance.
186
187 \since 5.2
188*/
189/*!
190 \fn QFontMetricsF &QFontMetricsF::operator=(QFontMetricsF &&other)
191
192 Move-assigns \a other to this QFontMetricsF instance.
193*/
194
195/*!
196 \fn void QFontMetrics::swap(QFontMetrics &other)
197 \since 5.0
198
199 Swaps this font metrics instance with \a other. This function is
200 very fast and never fails.
201*/
202
203/*!
204 Returns \c true if \a other is equal to this object; otherwise
205 returns \c false.
206
207 Two font metrics are considered equal if they were constructed
208 from the same QFont and the paint devices they were constructed
209 for are considered compatible.
210
211 \sa operator!=()
212*/
213bool QFontMetrics::operator ==(const QFontMetrics &other) const
214{
215 return d == other.d;
216}
217
218/*!
219 \fn bool QFontMetrics::operator !=(const QFontMetrics &other) const
220
221 Returns \c true if \a other is not equal to this object; otherwise returns \c false.
222
223 Two font metrics are considered equal if they were constructed
224 from the same QFont and the paint devices they were constructed
225 for are considered compatible.
226
227 \sa operator==()
228*/
229
230/*!
231 Returns the ascent of the font.
232
233 The ascent of a font is the distance from the baseline to the
234 highest position characters extend to. In practice, some font
235 designers break this rule, e.g. when they put more than one accent
236 on top of a character, or to accommodate a certain character, so it
237 is possible (though rare) that this value will be too small.
238
239 \sa descent()
240*/
241int QFontMetrics::ascent() const
242{
243 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
244 Q_ASSERT(engine != nullptr);
245 return qRound(f: engine->ascent());
246}
247
248/*!
249 Returns the cap height of the font.
250
251 \since 5.8
252
253 The cap height of a font is the height of a capital letter above
254 the baseline. It specifically is the height of capital letters
255 that are flat - such as H or I - as opposed to round letters such
256 as O, or pointed letters like A, both of which may display overshoot.
257
258 \sa ascent()
259*/
260int QFontMetrics::capHeight() const
261{
262 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
263 Q_ASSERT(engine != nullptr);
264 return qRound(f: engine->capHeight());
265}
266
267/*!
268 Returns the descent of the font.
269
270 The descent is the distance from the base line to the lowest point
271 characters extend to. In practice, some font designers break this rule,
272 e.g. to accommodate a certain character, so it is possible (though
273 rare) that this value will be too small.
274
275 \sa ascent()
276*/
277int QFontMetrics::descent() const
278{
279 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
280 Q_ASSERT(engine != nullptr);
281 return qRound(f: engine->descent());
282}
283
284/*!
285 Returns the height of the font.
286
287 This is always equal to ascent()+descent().
288
289 \sa leading(), lineSpacing()
290*/
291int QFontMetrics::height() const
292{
293 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
294 Q_ASSERT(engine != nullptr);
295 return qRound(f: engine->ascent()) + qRound(f: engine->descent());
296}
297
298/*!
299 Returns the leading of the font.
300
301 This is the natural inter-line spacing.
302
303 \sa height(), lineSpacing()
304*/
305int QFontMetrics::leading() const
306{
307 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
308 Q_ASSERT(engine != nullptr);
309 return qRound(f: engine->leading());
310}
311
312/*!
313 Returns the distance from one base line to the next.
314
315 This value is always equal to leading()+height().
316
317 \sa height(), leading()
318*/
319int QFontMetrics::lineSpacing() const
320{
321 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
322 Q_ASSERT(engine != nullptr);
323 return qRound(f: engine->leading()) + qRound(f: engine->ascent()) + qRound(f: engine->descent());
324}
325
326/*!
327 Returns the minimum left bearing of the font.
328
329 This is the smallest leftBearing(char) of all characters in the
330 font.
331
332 Note that this function can be very slow if the font is large.
333
334 \sa minRightBearing(), leftBearing()
335*/
336int QFontMetrics::minLeftBearing() const
337{
338 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
339 Q_ASSERT(engine != nullptr);
340 return qRound(d: engine->minLeftBearing());
341}
342
343/*!
344 Returns the minimum right bearing of the font.
345
346 This is the smallest rightBearing(char) of all characters in the
347 font.
348
349 Note that this function can be very slow if the font is large.
350
351 \sa minLeftBearing(), rightBearing()
352*/
353int QFontMetrics::minRightBearing() const
354{
355 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
356 Q_ASSERT(engine != nullptr);
357 return qRound(d: engine->minRightBearing());
358}
359
360/*!
361 Returns the width of the widest character in the font.
362*/
363int QFontMetrics::maxWidth() const
364{
365 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
366 Q_ASSERT(engine != nullptr);
367 return qRound(d: engine->maxCharWidth());
368}
369
370/*!
371 Returns the 'x' height of the font. This is often but not always
372 the same as the height of the character 'x'.
373*/
374int QFontMetrics::xHeight() const
375{
376 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
377 Q_ASSERT(engine != nullptr);
378 if (d->capital == QFont::SmallCaps)
379 return qRound(f: d->smallCapsFontPrivate()->engineForScript(script: QChar::Script_Common)->ascent());
380 return qRound(f: engine->xHeight());
381}
382
383/*!
384 \since 4.2
385
386 Returns the average width of glyphs in the font.
387*/
388int QFontMetrics::averageCharWidth() const
389{
390 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
391 Q_ASSERT(engine != nullptr);
392 return qRound(f: engine->averageCharWidth());
393}
394
395/*!
396 Returns \c true if character \a ch is a valid character in the font;
397 otherwise returns \c false.
398*/
399bool QFontMetrics::inFont(QChar ch) const
400{
401 return inFontUcs4(ucs4: ch.unicode());
402}
403
404/*!
405 Returns \c true if the character \a ucs4 encoded in UCS-4/UTF-32 is a valid
406 character in the font; otherwise returns \c false.
407*/
408bool QFontMetrics::inFontUcs4(uint ucs4) const
409{
410 const int script = QChar::script(ucs4);
411 QFontEngine *engine = d->engineForScript(script);
412 Q_ASSERT(engine != nullptr);
413 if (engine->type() == QFontEngine::Box)
414 return false;
415 return engine->canRender(ucs4);
416}
417
418/*!
419 Returns the left bearing of character \a ch in the font.
420
421 The left bearing is the right-ward distance of the left-most pixel
422 of the character from the logical origin of the character. This
423 value is negative if the pixels of the character extend to the
424 left of the logical origin.
425
426 See horizontalAdvance() for a graphical description of this metric.
427
428 \sa rightBearing(), minLeftBearing(), horizontalAdvance()
429*/
430int QFontMetrics::leftBearing(QChar ch) const
431{
432 const int script = ch.script();
433 QFontEngine *engine;
434 if (d->capital == QFont::SmallCaps && ch.isLower())
435 engine = d->smallCapsFontPrivate()->engineForScript(script);
436 else
437 engine = d->engineForScript(script);
438 Q_ASSERT(engine != nullptr);
439 if (engine->type() == QFontEngine::Box)
440 return 0;
441
442 d->alterCharForCapitalization(c&: ch);
443
444 glyph_t glyph = engine->glyphIndex(ucs4: ch.unicode());
445
446 qreal lb;
447 engine->getGlyphBearings(glyph, leftBearing: &lb);
448 return qRound(d: lb);
449}
450
451/*!
452 Returns the right bearing of character \a ch in the font.
453
454 The right bearing is the left-ward distance of the right-most
455 pixel of the character from the logical origin of a subsequent
456 character. This value is negative if the pixels of the character
457 extend to the right of the horizontalAdvance() of the character.
458
459 See horizontalAdvance() for a graphical description of this metric.
460
461 \sa leftBearing(), minRightBearing(), horizontalAdvance()
462*/
463int QFontMetrics::rightBearing(QChar ch) const
464{
465 const int script = ch.script();
466 QFontEngine *engine;
467 if (d->capital == QFont::SmallCaps && ch.isLower())
468 engine = d->smallCapsFontPrivate()->engineForScript(script);
469 else
470 engine = d->engineForScript(script);
471 Q_ASSERT(engine != nullptr);
472 if (engine->type() == QFontEngine::Box)
473 return 0;
474
475 d->alterCharForCapitalization(c&: ch);
476
477 glyph_t glyph = engine->glyphIndex(ucs4: ch.unicode());
478
479 qreal rb;
480 engine->getGlyphBearings(glyph, leftBearing: nullptr, rightBearing: &rb);
481 return qRound(d: rb);
482}
483
484static constexpr QLatin1Char s_variableLengthStringSeparator('\x9c');
485
486/*!
487 Returns the horizontal advance in pixels of the first \a len characters of \a
488 text. If \a len is negative (the default), the entire string is
489 used. The entire length of \a text is analysed even if \a len is substantially
490 shorter.
491
492 This is the distance appropriate for drawing a subsequent character
493 after \a text.
494
495 \since 5.11
496
497 \sa boundingRect()
498*/
499int QFontMetrics::horizontalAdvance(const QString &text, int len) const
500{
501 int pos = (len >= 0)
502 ? QStringView(text).left(n: len).indexOf(c: s_variableLengthStringSeparator)
503 : text.indexOf(c: s_variableLengthStringSeparator);
504 if (pos != -1) {
505 len = pos;
506 } else if (len < 0) {
507 len = text.size();
508 }
509 if (len == 0)
510 return 0;
511
512 QStackTextEngine layout(text, QFont(d.data()));
513 return qRound(f: layout.width(charFrom: 0, numChars: len));
514}
515
516/*!
517 Returns the horizontal advance in pixels of \a text laid out using \a option.
518
519 The advance is the distance appropriate for drawing a subsequent
520 character after \a text.
521
522 \since 6.3
523
524 \sa boundingRect()
525*/
526int QFontMetrics::horizontalAdvance(const QString &text, const QTextOption &option) const
527{
528 int pos = text.indexOf(c: s_variableLengthStringSeparator);
529 int len = -1;
530 if (pos != -1) {
531 len = pos;
532 } else {
533 len = text.size();
534 }
535 if (len == 0)
536 return 0;
537
538 QStackTextEngine layout(text, QFont(d.data()));
539 layout.option = option;
540 return qRound(f: layout.width(charFrom: 0, numChars: len));
541}
542
543/*!
544 \overload
545
546 \image bearings.png Bearings
547
548 Returns the horizontal advance of character \a ch in pixels. This is a
549 distance appropriate for drawing a subsequent character after \a
550 ch.
551
552 Some of the metrics are described in the image. The
553 central dark rectangles cover the logical horizontalAdvance() of each
554 character. The outer pale rectangles cover the leftBearing() and
555 rightBearing() of each character. Notice that the bearings of "f"
556 in this particular font are both negative, while the bearings of
557 "o" are both positive.
558
559 \warning This function will produce incorrect results for Arabic
560 characters or non-spacing marks in the middle of a string, as the
561 glyph shaping and positioning of marks that happens when
562 processing strings cannot be taken into account. When implementing
563 an interactive text control, use QTextLayout instead.
564
565 \since 5.11
566
567 \sa boundingRect()
568*/
569int QFontMetrics::horizontalAdvance(QChar ch) const
570{
571 if (QChar::category(ucs4: ch.unicode()) == QChar::Mark_NonSpacing)
572 return 0;
573
574 const int script = ch.script();
575 QFontEngine *engine;
576 if (d->capital == QFont::SmallCaps && ch.isLower())
577 engine = d->smallCapsFontPrivate()->engineForScript(script);
578 else
579 engine = d->engineForScript(script);
580 Q_ASSERT(engine != nullptr);
581
582 d->alterCharForCapitalization(c&: ch);
583
584 glyph_t glyph = engine->glyphIndex(ucs4: ch.unicode());
585 QFixed advance;
586
587 QGlyphLayout glyphs;
588 glyphs.numGlyphs = 1;
589 glyphs.glyphs = &glyph;
590 glyphs.advances = &advance;
591 engine->recalcAdvances(&glyphs, { });
592
593 return qRound(f: advance);
594}
595
596/*!
597 Returns the bounding rectangle of the characters in the string
598 specified by \a text. The bounding rectangle always covers at least
599 the set of pixels the text would cover if drawn at (0, 0).
600
601 Note that the bounding rectangle may extend to the left of (0, 0),
602 e.g. for italicized fonts, and that the width of the returned
603 rectangle might be different than what the horizontalAdvance() method
604 returns.
605
606 If you want to know the advance width of the string (to lay out
607 a set of strings next to each other), use horizontalAdvance() instead.
608
609 Newline characters are processed as normal characters, \e not as
610 linebreaks.
611
612 The height of the bounding rectangle is at least as large as the
613 value returned by height().
614
615 \sa horizontalAdvance(), height(), QPainter::boundingRect(),
616 tightBoundingRect()
617*/
618QRect QFontMetrics::boundingRect(const QString &text) const
619{
620 if (text.size() == 0)
621 return QRect();
622
623 QStackTextEngine layout(text, QFont(d.data()));
624 layout.itemize();
625 glyph_metrics_t gm = layout.boundingBox(from: 0, len: text.size());
626 return QRect(qRound(f: gm.x), qRound(f: gm.y), qRound(f: gm.width), qRound(f: gm.height));
627}
628
629/*!
630 Returns the bounding rectangle of the characters in the string
631 specified by \a text laid out using \a option. The bounding rectangle always
632 covers at least the set of pixels the text would cover if drawn at (0, 0).
633
634 Note that the bounding rectangle may extend to the left of (0, 0),
635 e.g. for italicized fonts, and that the width of the returned
636 rectangle might be different than what the horizontalAdvance() method
637 returns.
638
639 If you want to know the advance width of the string (to lay out
640 a set of strings next to each other), use horizontalAdvance() instead.
641
642 Newline characters are processed as normal characters, \e not as
643 linebreaks.
644
645 The height of the bounding rectangle is at least as large as the
646 value returned by height().
647
648 \since 6.3
649
650 \sa horizontalAdvance(), height(), QPainter::boundingRect(),
651 tightBoundingRect()
652*/
653QRect QFontMetrics::boundingRect(const QString &text, const QTextOption &option) const
654{
655 if (text.size() == 0)
656 return QRect();
657
658 QStackTextEngine layout(text, QFont(d.data()));
659 layout.option = option;
660 layout.itemize();
661 glyph_metrics_t gm = layout.boundingBox(from: 0, len: text.size());
662 return QRect(qRound(f: gm.x), qRound(f: gm.y), qRound(f: gm.width), qRound(f: gm.height));
663}
664
665/*!
666 Returns the rectangle that is covered by ink if character \a ch
667 were to be drawn at the origin of the coordinate system.
668
669 Note that the bounding rectangle may extend to the left of (0, 0)
670 (e.g., for italicized fonts), and that the text output may cover \e
671 all pixels in the bounding rectangle. For a space character the rectangle
672 will usually be empty.
673
674 Note that the rectangle usually extends both above and below the
675 base line.
676
677 \warning The width of the returned rectangle is not the advance width
678 of the character. Use boundingRect(const QString &) or horizontalAdvance() instead.
679
680 \sa horizontalAdvance()
681*/
682QRect QFontMetrics::boundingRect(QChar ch) const
683{
684 const int script = ch.script();
685 QFontEngine *engine;
686 if (d->capital == QFont::SmallCaps && ch.isLower())
687 engine = d->smallCapsFontPrivate()->engineForScript(script);
688 else
689 engine = d->engineForScript(script);
690 Q_ASSERT(engine != nullptr);
691
692 d->alterCharForCapitalization(c&: ch);
693
694 glyph_t glyph = engine->glyphIndex(ucs4: ch.unicode());
695
696 glyph_metrics_t gm = engine->boundingBox(glyph);
697 return QRect(qRound(f: gm.x), qRound(f: gm.y), qRound(f: gm.width), qRound(f: gm.height));
698}
699
700/*!
701 \overload
702
703 Returns the bounding rectangle of the characters in the string
704 specified by \a text, which is the set of pixels the text would
705 cover if drawn at (0, 0). The drawing, and hence the bounding
706 rectangle, is constrained to the rectangle \a rect.
707
708 The \a flags argument is the bitwise OR of the following flags:
709 \list
710 \li Qt::AlignLeft aligns to the left border, except for
711 Arabic and Hebrew where it aligns to the right.
712 \li Qt::AlignRight aligns to the right border, except for
713 Arabic and Hebrew where it aligns to the left.
714 \li Qt::AlignJustify produces justified text.
715 \li Qt::AlignHCenter aligns horizontally centered.
716 \li Qt::AlignTop aligns to the top border.
717 \li Qt::AlignBottom aligns to the bottom border.
718 \li Qt::AlignVCenter aligns vertically centered
719 \li Qt::AlignCenter (== \c{Qt::AlignHCenter | Qt::AlignVCenter})
720 \li Qt::TextSingleLine ignores newline characters in the text.
721 \li Qt::TextExpandTabs expands tabs (see below)
722 \li Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined.
723 \li Qt::TextWordWrap breaks the text to fit the rectangle.
724 \endlist
725
726 Qt::Horizontal alignment defaults to Qt::AlignLeft and vertical
727 alignment defaults to Qt::AlignTop.
728
729 If several of the horizontal or several of the vertical alignment
730 flags are set, the resulting alignment is undefined.
731
732 If Qt::TextExpandTabs is set in \a flags, then: if \a tabArray is
733 non-null, it specifies a 0-terminated sequence of pixel-positions
734 for tabs; otherwise if \a tabStops is non-zero, it is used as the
735 tab spacing (in pixels).
736
737 Note that the bounding rectangle may extend to the left of (0, 0),
738 e.g. for italicized fonts, and that the text output may cover \e
739 all pixels in the bounding rectangle.
740
741 Newline characters are processed as linebreaks.
742
743 Despite the different actual character heights, the heights of the
744 bounding rectangles of "Yes" and "yes" are the same.
745
746 The bounding rectangle returned by this function is somewhat larger
747 than that calculated by the simpler boundingRect() function. This
748 function uses the \l{minLeftBearing()}{maximum left} and
749 \l{minRightBearing()}{right} font bearings as is
750 necessary for multi-line text to align correctly. Also,
751 fontHeight() and lineSpacing() are used to calculate the height,
752 rather than individual character heights.
753
754 \sa horizontalAdvance(), QPainter::boundingRect(), Qt::Alignment
755*/
756QRect QFontMetrics::boundingRect(const QRect &rect, int flags, const QString &text, int tabStops,
757 int *tabArray) const
758{
759 int tabArrayLen = 0;
760 if (tabArray)
761 while (tabArray[tabArrayLen])
762 tabArrayLen++;
763
764 QRectF rb;
765 QRectF rr(rect);
766 qt_format_text(font: QFont(d.data()), r: rr, tf: flags | Qt::TextDontPrint, text, brect: &rb, tabStops, tabArray,
767 tabArrayLen, painter: nullptr);
768
769 return rb.toAlignedRect();
770}
771
772/*!
773 Returns the size in pixels of \a text.
774
775 The \a flags argument is the bitwise OR of the following flags:
776 \list
777 \li Qt::TextSingleLine ignores newline characters.
778 \li Qt::TextExpandTabs expands tabs (see below)
779 \li Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined.
780 \li Qt::TextWordWrap breaks the text to fit the rectangle.
781 \endlist
782
783 If Qt::TextExpandTabs is set in \a flags, then: if \a tabArray is
784 non-null, it specifies a 0-terminated sequence of pixel-positions
785 for tabs; otherwise if \a tabStops is non-zero, it is used as the
786 tab spacing (in pixels).
787
788 Newline characters are processed as linebreaks.
789
790 Despite the different actual character heights, the heights of the
791 bounding rectangles of "Yes" and "yes" are the same.
792
793 \sa boundingRect()
794*/
795QSize QFontMetrics::size(int flags, const QString &text, int tabStops, int *tabArray) const
796{
797 return boundingRect(rect: QRect(0,0,0,0), flags: flags | Qt::TextLongestVariant, text, tabStops, tabArray).size();
798}
799
800/*!
801 Returns a tight bounding rectangle around the characters in the
802 string specified by \a text. The bounding rectangle always covers
803 at least the set of pixels the text would cover if drawn at (0,
804 0).
805
806 Note that the bounding rectangle may extend to the left of (0, 0),
807 e.g. for italicized fonts, and that the width of the returned
808 rectangle might be different than what the horizontalAdvance() method
809 returns.
810
811 If you want to know the advance width of the string (to lay out
812 a set of strings next to each other), use horizontalAdvance() instead.
813
814 Newline characters are processed as normal characters, \e not as
815 linebreaks.
816
817 \since 4.3
818
819 \sa horizontalAdvance(), height(), boundingRect()
820*/
821QRect QFontMetrics::tightBoundingRect(const QString &text) const
822{
823 if (text.size() == 0)
824 return QRect();
825
826 QStackTextEngine layout(text, QFont(d.data()));
827 layout.itemize();
828 glyph_metrics_t gm = layout.tightBoundingBox(from: 0, len: text.size());
829 return QRect(qRound(f: gm.x), qRound(f: gm.y), qRound(f: gm.width), qRound(f: gm.height));
830}
831
832/*!
833 Returns a tight bounding rectangle around the characters in the
834 string specified by \a text laid out using \a option. The bounding
835 rectangle always covers at least the set of pixels the text would
836 cover if drawn at (0, 0).
837
838 Note that the bounding rectangle may extend to the left of (0, 0),
839 e.g. for italicized fonts, and that the width of the returned
840 rectangle might be different than what the horizontalAdvance() method
841 returns.
842
843 If you want to know the advance width of the string (to lay out
844 a set of strings next to each other), use horizontalAdvance() instead.
845
846 Newline characters are processed as normal characters, \e not as
847 linebreaks.
848
849 \since 6.3
850
851 \sa horizontalAdvance(), height(), boundingRect()
852*/
853QRect QFontMetrics::tightBoundingRect(const QString &text, const QTextOption &option) const
854{
855 if (text.size() == 0)
856 return QRect();
857
858 QStackTextEngine layout(text, QFont(d.data()));
859 layout.option = option;
860 layout.itemize();
861 glyph_metrics_t gm = layout.tightBoundingBox(from: 0, len: text.size());
862 return QRect(qRound(f: gm.x), qRound(f: gm.y), qRound(f: gm.width), qRound(f: gm.height));
863}
864
865/*!
866 \since 4.2
867
868 If the string \a text is wider than \a width, returns an elided
869 version of the string (i.e., a string with "..." in it).
870 Otherwise, returns the original string.
871
872 The \a mode parameter specifies whether the text is elided on the
873 left (e.g., "...tech"), in the middle (e.g., "Tr...ch"), or on
874 the right (e.g., "Trol...").
875
876 The \a width is specified in pixels, not characters.
877
878 The \a flags argument is optional and currently only supports
879 Qt::TextShowMnemonic as value.
880
881 The elide mark follows the \l{Qt::LayoutDirection}{layoutdirection}.
882 For example, it will be on the right side of the text for right-to-left
883 layouts if the \a mode is \c{Qt::ElideLeft}, and on the left side of the
884 text if the \a mode is \c{Qt::ElideRight}.
885
886*/
887QString QFontMetrics::elidedText(const QString &text, Qt::TextElideMode mode, int width, int flags) const
888{
889 QString _text = text;
890 if (!(flags & Qt::TextLongestVariant)) {
891 int posA = 0;
892 int posB = _text.indexOf(c: s_variableLengthStringSeparator);
893 while (posB >= 0) {
894 QString portion = _text.mid(position: posA, n: posB - posA);
895 if (size(flags, text: portion).width() <= width)
896 return portion;
897 posA = posB + 1;
898 posB = _text.indexOf(c: s_variableLengthStringSeparator, from: posA);
899 }
900 _text = _text.mid(position: posA);
901 }
902 QStackTextEngine engine(_text, QFont(d.data()));
903 return engine.elidedText(mode, width, flags);
904}
905
906/*!
907 Returns the distance from the base line to where an underscore
908 should be drawn.
909
910 \sa overlinePos(), strikeOutPos(), lineWidth()
911*/
912int QFontMetrics::underlinePos() const
913{
914 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
915 Q_ASSERT(engine != nullptr);
916 return qRound(f: engine->underlinePosition());
917}
918
919/*!
920 Returns the distance from the base line to where an overline
921 should be drawn.
922
923 \sa underlinePos(), strikeOutPos(), lineWidth()
924*/
925int QFontMetrics::overlinePos() const
926{
927 return ascent() + 1;
928}
929
930/*!
931 Returns the distance from the base line to where the strikeout
932 line should be drawn.
933
934 \sa underlinePos(), overlinePos(), lineWidth()
935*/
936int QFontMetrics::strikeOutPos() const
937{
938 int pos = ascent() / 3;
939 return pos > 0 ? pos : 1;
940}
941
942/*!
943 Returns the width of the underline and strikeout lines, adjusted
944 for the point size of the font.
945
946 \sa underlinePos(), overlinePos(), strikeOutPos()
947*/
948int QFontMetrics::lineWidth() const
949{
950 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
951 Q_ASSERT(engine != nullptr);
952 return qRound(f: engine->lineThickness());
953}
954
955/*!
956 \since 5.14
957
958 Returns the font DPI.
959*/
960qreal QFontMetrics::fontDpi() const
961{
962 return d->dpi;
963}
964
965/*****************************************************************************
966 QFontMetricsF member functions
967 *****************************************************************************/
968
969/*!
970 \class QFontMetricsF
971 \reentrant
972 \inmodule QtGui
973
974 \brief The QFontMetricsF class provides font metrics information.
975
976 \ingroup painting
977 \ingroup shared
978
979 QFontMetricsF functions calculate the size of characters and
980 strings for a given font. You can construct a QFontMetricsF object
981 with an existing QFont to obtain metrics for that font. If the
982 font is changed later, the font metrics object is \e not updated.
983
984 Once created, the object provides functions to access the
985 individual metrics of the font, its characters, and for strings
986 rendered in the font.
987
988 There are several functions that operate on the font: ascent(),
989 descent(), height(), leading() and lineSpacing() return the basic
990 size properties of the font. The underlinePos(), overlinePos(),
991 strikeOutPos() and lineWidth() functions, return the properties of
992 the line that underlines, overlines or strikes out the
993 characters. These functions are all fast.
994
995 There are also some functions that operate on the set of glyphs in
996 the font: minLeftBearing(), minRightBearing() and maxWidth().
997 These are by necessity slow, and we recommend avoiding them if
998 possible.
999
1000 For each character, you can get its horizontalAdvance(), leftBearing(), and
1001 rightBearing(), and find out whether it is in the font using
1002 inFont(). You can also treat the character as a string, and use
1003 the string functions on it.
1004
1005 The string functions include horizontalAdvance(), to return the width of a
1006 string in pixels (or points, for a printer), boundingRect(), to
1007 return a rectangle large enough to contain the rendered string,
1008 and size(), to return the size of that rectangle.
1009
1010 Example:
1011 \snippet code/src_gui_text_qfontmetrics.cpp 1
1012
1013 \sa QFont, QFontInfo, QFontDatabase
1014*/
1015
1016/*!
1017 \since 4.2
1018
1019 Constructs a font metrics object with floating point precision
1020 from the given \a fontMetrics object.
1021*/
1022QFontMetricsF::QFontMetricsF(const QFontMetrics &fontMetrics)
1023 : d(fontMetrics.d)
1024{
1025}
1026
1027/*!
1028 \since 4.2
1029
1030 Assigns \a other to this object.
1031*/
1032QFontMetricsF &QFontMetricsF::operator=(const QFontMetrics &other)
1033{
1034 d = other.d;
1035 return *this;
1036}
1037
1038/*!
1039 \fn void QFontMetricsF::swap(QFontMetricsF &other)
1040 \since 5.0
1041
1042 Swaps this font metrics instance with \a other. This function is
1043 very fast and never fails.
1044*/
1045
1046
1047
1048/*!
1049 Constructs a font metrics object for \a font.
1050
1051 The font metrics will be compatible with the paintdevice used to
1052 create \a font.
1053
1054 The font metrics object holds the information for the font that is
1055 passed in the constructor at the time it is created, and is not
1056 updated if the font's attributes are changed later.
1057
1058 Use QFontMetricsF(const QFont &, QPaintDevice *) to get the font
1059 metrics that are compatible with a certain paint device.
1060*/
1061QFontMetricsF::QFontMetricsF(const QFont &font)
1062 : d(font.d)
1063{
1064}
1065
1066/*!
1067 \fn QFontMetricsF::QFontMetricsF(const QFont &font, const QPaintDevice *paintdevice)
1068 \since 5.13
1069 Constructs a font metrics object for \a font and \a paintdevice.
1070
1071 The font metrics will be compatible with the paintdevice passed.
1072 If the \a paintdevice is \nullptr, the metrics will be screen-compatible,
1073 ie. the metrics you get if you use the font for drawing text on a
1074 \l{QWidget}{widgets} or \l{QPixmap}{pixmaps},
1075 not on a QPicture or QPrinter.
1076
1077 The font metrics object holds the information for the font that is
1078 passed in the constructor at the time it is created, and is not
1079 updated if the font's attributes are changed later.
1080*/
1081QFontMetricsF::QFontMetricsF(const QFont &font, const QPaintDevice *paintdevice)
1082{
1083 int dpi = paintdevice ? paintdevice->logicalDpiY() : qt_defaultDpi();
1084 if (font.d->dpi != dpi) {
1085 d = new QFontPrivate(*font.d);
1086 d->dpi = dpi;
1087 } else {
1088 d = font.d;
1089 }
1090
1091}
1092
1093/*!
1094 Constructs a copy of \a fm.
1095*/
1096QFontMetricsF::QFontMetricsF(const QFontMetricsF &fm)
1097 : d(fm.d)
1098{
1099}
1100
1101/*!
1102 Destroys the font metrics object and frees all allocated
1103 resources.
1104*/
1105QFontMetricsF::~QFontMetricsF()
1106{
1107}
1108
1109/*!
1110 Assigns the font metrics \a fm to this font metrics object.
1111*/
1112QFontMetricsF &QFontMetricsF::operator=(const QFontMetricsF &fm)
1113{
1114 d = fm.d;
1115 return *this;
1116}
1117
1118/*!
1119 Returns \c true if the font metrics are equal to the \a other font
1120 metrics; otherwise returns \c false.
1121
1122 Two font metrics are considered equal if they were constructed from the
1123 same QFont and the paint devices they were constructed for are
1124 considered to be compatible.
1125*/
1126bool QFontMetricsF::operator ==(const QFontMetricsF &other) const
1127{
1128 return d == other.d;
1129}
1130
1131/*!
1132 \fn bool QFontMetricsF::operator !=(const QFontMetricsF &other) const
1133 \overload
1134
1135 Returns \c true if the font metrics are not equal to the \a other font
1136 metrics; otherwise returns \c false.
1137
1138 \sa operator==()
1139*/
1140
1141/*!
1142 Returns the ascent of the font.
1143
1144 The ascent of a font is the distance from the baseline to the
1145 highest position characters extend to. In practice, some font
1146 designers break this rule, e.g. when they put more than one accent
1147 on top of a character, or to accommodate a certain character, so
1148 it is possible (though rare) that this value will be too small.
1149
1150 \sa descent()
1151*/
1152qreal QFontMetricsF::ascent() const
1153{
1154 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
1155 Q_ASSERT(engine != nullptr);
1156 return engine->ascent().toReal();
1157}
1158
1159/*!
1160 Returns the cap height of the font.
1161
1162 \since 5.8
1163
1164 The cap height of a font is the height of a capital letter above
1165 the baseline. It specifically is the height of capital letters
1166 that are flat - such as H or I - as opposed to round letters such
1167 as O, or pointed letters like A, both of which may display overshoot.
1168
1169 \sa ascent()
1170*/
1171qreal QFontMetricsF::capHeight() const
1172{
1173 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
1174 Q_ASSERT(engine != nullptr);
1175 return engine->capHeight().toReal();
1176}
1177
1178/*!
1179 Returns the descent of the font.
1180
1181 The descent is the distance from the base line to the lowest point
1182 characters extend to. (Note that this is different from X, which
1183 adds 1 pixel.) In practice, some font designers break this rule,
1184 e.g. to accommodate a certain character, so it is possible (though
1185 rare) that this value will be too small.
1186
1187 \sa ascent()
1188*/
1189qreal QFontMetricsF::descent() const
1190{
1191 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
1192 Q_ASSERT(engine != nullptr);
1193 return engine->descent().toReal();
1194}
1195
1196/*!
1197 Returns the height of the font.
1198
1199 This is always equal to ascent()+descent().
1200
1201 \sa leading(), lineSpacing()
1202*/
1203qreal QFontMetricsF::height() const
1204{
1205 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
1206 Q_ASSERT(engine != nullptr);
1207
1208 return (engine->ascent() + engine->descent()).toReal();
1209}
1210
1211/*!
1212 Returns the leading of the font.
1213
1214 This is the natural inter-line spacing.
1215
1216 \sa height(), lineSpacing()
1217*/
1218qreal QFontMetricsF::leading() const
1219{
1220 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
1221 Q_ASSERT(engine != nullptr);
1222 return engine->leading().toReal();
1223}
1224
1225/*!
1226 Returns the distance from one base line to the next.
1227
1228 This value is always equal to leading()+height().
1229
1230 \sa height(), leading()
1231*/
1232qreal QFontMetricsF::lineSpacing() const
1233{
1234 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
1235 Q_ASSERT(engine != nullptr);
1236 return (engine->leading() + engine->ascent() + engine->descent()).toReal();
1237}
1238
1239/*!
1240 Returns the minimum left bearing of the font.
1241
1242 This is the smallest leftBearing(char) of all characters in the
1243 font.
1244
1245 Note that this function can be very slow if the font is large.
1246
1247 \sa minRightBearing(), leftBearing()
1248*/
1249qreal QFontMetricsF::minLeftBearing() const
1250{
1251 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
1252 Q_ASSERT(engine != nullptr);
1253 return engine->minLeftBearing();
1254}
1255
1256/*!
1257 Returns the minimum right bearing of the font.
1258
1259 This is the smallest rightBearing(char) of all characters in the
1260 font.
1261
1262 Note that this function can be very slow if the font is large.
1263
1264 \sa minLeftBearing(), rightBearing()
1265*/
1266qreal QFontMetricsF::minRightBearing() const
1267{
1268 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
1269 Q_ASSERT(engine != nullptr);
1270 return engine->minRightBearing();
1271}
1272
1273/*!
1274 Returns the width of the widest character in the font.
1275*/
1276qreal QFontMetricsF::maxWidth() const
1277{
1278 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
1279 Q_ASSERT(engine != nullptr);
1280 return engine->maxCharWidth();
1281}
1282
1283/*!
1284 Returns the 'x' height of the font. This is often but not always
1285 the same as the height of the character 'x'.
1286*/
1287qreal QFontMetricsF::xHeight() const
1288{
1289 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
1290 Q_ASSERT(engine != nullptr);
1291 if (d->capital == QFont::SmallCaps)
1292 return d->smallCapsFontPrivate()->engineForScript(script: QChar::Script_Common)->ascent().toReal();
1293 return engine->xHeight().toReal();
1294}
1295
1296/*!
1297 \since 4.2
1298
1299 Returns the average width of glyphs in the font.
1300*/
1301qreal QFontMetricsF::averageCharWidth() const
1302{
1303 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
1304 Q_ASSERT(engine != nullptr);
1305 return engine->averageCharWidth().toReal();
1306}
1307
1308/*!
1309 Returns \c true if character \a ch is a valid character in the font;
1310 otherwise returns \c false.
1311*/
1312bool QFontMetricsF::inFont(QChar ch) const
1313{
1314 return inFontUcs4(ucs4: ch.unicode());
1315}
1316
1317/*!
1318 \fn bool QFontMetricsF::inFontUcs4(uint ch) const
1319
1320 Returns \c true if the character given by \a ch, encoded in UCS-4/UTF-32,
1321 is a valid character in the font; otherwise returns \c false.
1322*/
1323bool QFontMetricsF::inFontUcs4(uint ucs4) const
1324{
1325 const int script = QChar::script(ucs4);
1326 QFontEngine *engine = d->engineForScript(script);
1327 Q_ASSERT(engine != nullptr);
1328 if (engine->type() == QFontEngine::Box)
1329 return false;
1330 return engine->canRender(ucs4);
1331}
1332
1333/*!
1334 Returns the left bearing of character \a ch in the font.
1335
1336 The left bearing is the right-ward distance of the left-most pixel
1337 of the character from the logical origin of the character. This
1338 value is negative if the pixels of the character extend to the
1339 left of the logical origin.
1340
1341 See horizontalAdvance() for a graphical description of this metric.
1342
1343 \sa rightBearing(), minLeftBearing(), horizontalAdvance()
1344*/
1345qreal QFontMetricsF::leftBearing(QChar ch) const
1346{
1347 const int script = ch.script();
1348 QFontEngine *engine;
1349 if (d->capital == QFont::SmallCaps && ch.isLower())
1350 engine = d->smallCapsFontPrivate()->engineForScript(script);
1351 else
1352 engine = d->engineForScript(script);
1353 Q_ASSERT(engine != nullptr);
1354 if (engine->type() == QFontEngine::Box)
1355 return 0;
1356
1357 d->alterCharForCapitalization(c&: ch);
1358
1359 glyph_t glyph = engine->glyphIndex(ucs4: ch.unicode());
1360
1361 qreal lb;
1362 engine->getGlyphBearings(glyph, leftBearing: &lb);
1363 return lb;
1364}
1365
1366/*!
1367 Returns the right bearing of character \a ch in the font.
1368
1369 The right bearing is the left-ward distance of the right-most
1370 pixel of the character from the logical origin of a subsequent
1371 character. This value is negative if the pixels of the character
1372 extend to the right of the horizontalAdvance() of the character.
1373
1374 See horizontalAdvance() for a graphical description of this metric.
1375
1376 \sa leftBearing(), minRightBearing(), horizontalAdvance()
1377*/
1378qreal QFontMetricsF::rightBearing(QChar ch) const
1379{
1380 const int script = ch.script();
1381 QFontEngine *engine;
1382 if (d->capital == QFont::SmallCaps && ch.isLower())
1383 engine = d->smallCapsFontPrivate()->engineForScript(script);
1384 else
1385 engine = d->engineForScript(script);
1386 Q_ASSERT(engine != nullptr);
1387 if (engine->type() == QFontEngine::Box)
1388 return 0;
1389
1390 d->alterCharForCapitalization(c&: ch);
1391
1392 glyph_t glyph = engine->glyphIndex(ucs4: ch.unicode());
1393
1394 qreal rb;
1395 engine->getGlyphBearings(glyph, leftBearing: nullptr, rightBearing: &rb);
1396 return rb;
1397
1398}
1399
1400/*!
1401 Returns the horizontal advance in pixels of the first \a length characters of \a
1402 text. If \a length is negative (the default), the entire string is
1403 used. The entire length of \a text is analysed even if \a length is substantially
1404 shorter.
1405
1406 The advance is the distance appropriate for drawing a subsequent
1407 character after \a text.
1408
1409 \since 5.11
1410
1411 \sa boundingRect()
1412*/
1413qreal QFontMetricsF::horizontalAdvance(const QString &text, int length) const
1414{
1415 int pos = (length >= 0)
1416 ? QStringView(text).left(n: length).indexOf(c: s_variableLengthStringSeparator)
1417 : text.indexOf(c: s_variableLengthStringSeparator);
1418 if (pos != -1)
1419 length = pos;
1420 else if (length < 0)
1421 length = text.size();
1422
1423 if (length == 0)
1424 return 0;
1425
1426 QStackTextEngine layout(text, QFont(d.data()));
1427 layout.itemize();
1428 return layout.width(charFrom: 0, numChars: length).toReal();
1429}
1430
1431/*!
1432 Returns the horizontal advance in pixels of \a text laid out using \a option.
1433
1434 The advance is the distance appropriate for drawing a subsequent
1435 character after \a text.
1436
1437 \since 6.3
1438
1439 \sa boundingRect()
1440*/
1441qreal QFontMetricsF::horizontalAdvance(const QString &text, const QTextOption &option) const
1442{
1443 int pos = text.indexOf(c: s_variableLengthStringSeparator);
1444 int length = -1;
1445 if (pos != -1)
1446 length = pos;
1447 else
1448 length = text.size();
1449
1450 if (length == 0)
1451 return 0;
1452
1453 QStackTextEngine layout(text, QFont(d.data()));
1454 layout.option = option;
1455 layout.itemize();
1456 return layout.width(charFrom: 0, numChars: length).toReal();
1457}
1458
1459/*!
1460 \overload
1461
1462 \image bearings.png Bearings
1463
1464 Returns the horizontal advance of character \a ch in pixels. This is a
1465 distance appropriate for drawing a subsequent character after \a
1466 ch.
1467
1468 Some of the metrics are described in the image to the right. The
1469 central dark rectangles cover the logical horizontalAdvance() of each
1470 character. The outer pale rectangles cover the leftBearing() and
1471 rightBearing() of each character. Notice that the bearings of "f"
1472 in this particular font are both negative, while the bearings of
1473 "o" are both positive.
1474
1475 \warning This function will produce incorrect results for Arabic
1476 characters or non-spacing marks in the middle of a string, as the
1477 glyph shaping and positioning of marks that happens when
1478 processing strings cannot be taken into account. When implementing
1479 an interactive text control, use QTextLayout instead.
1480
1481 \since 5.11
1482
1483 \sa boundingRect()
1484*/
1485qreal QFontMetricsF::horizontalAdvance(QChar ch) const
1486{
1487 if (ch.category() == QChar::Mark_NonSpacing)
1488 return 0.;
1489
1490 const int script = ch.script();
1491 QFontEngine *engine;
1492 if (d->capital == QFont::SmallCaps && ch.isLower())
1493 engine = d->smallCapsFontPrivate()->engineForScript(script);
1494 else
1495 engine = d->engineForScript(script);
1496 Q_ASSERT(engine != nullptr);
1497
1498 d->alterCharForCapitalization(c&: ch);
1499
1500 glyph_t glyph = engine->glyphIndex(ucs4: ch.unicode());
1501 QFixed advance;
1502
1503 QGlyphLayout glyphs;
1504 glyphs.numGlyphs = 1;
1505 glyphs.glyphs = &glyph;
1506 glyphs.advances = &advance;
1507 engine->recalcAdvances(&glyphs, { });
1508
1509 return advance.toReal();
1510}
1511
1512
1513/*!
1514 Returns the bounding rectangle of the characters in the string
1515 specified by \a text. The bounding rectangle always covers at least
1516 the set of pixels the text would cover if drawn at (0, 0).
1517
1518 Note that the bounding rectangle may extend to the left of (0, 0),
1519 e.g. for italicized fonts, and that the width of the returned
1520 rectangle might be different than what the horizontalAdvance() method returns.
1521
1522 If you want to know the advance width of the string (to lay out
1523 a set of strings next to each other), use horizontalAdvance() instead.
1524
1525 Newline characters are processed as normal characters, \e not as
1526 linebreaks.
1527
1528 The height of the bounding rectangle is at least as large as the
1529 value returned height().
1530
1531 \sa horizontalAdvance(), height(), QPainter::boundingRect()
1532*/
1533QRectF QFontMetricsF::boundingRect(const QString &text) const
1534{
1535 int len = text.size();
1536 if (len == 0)
1537 return QRectF();
1538
1539 QStackTextEngine layout(text, QFont(d.data()));
1540 layout.itemize();
1541 glyph_metrics_t gm = layout.boundingBox(from: 0, len);
1542 return QRectF(gm.x.toReal(), gm.y.toReal(),
1543 gm.width.toReal(), gm.height.toReal());
1544}
1545
1546/*!
1547 Returns the bounding rectangle of the characters in the string
1548 specified by \a text laid out using \a option. The bounding
1549 rectangle always covers at least the set of pixels the text
1550 would cover if drawn at (0, 0).
1551
1552 Note that the bounding rectangle may extend to the left of (0, 0),
1553 e.g. for italicized fonts, and that the width of the returned
1554 rectangle might be different than what the horizontalAdvance() method returns.
1555
1556 If you want to know the advance width of the string (to lay out
1557 a set of strings next to each other), use horizontalAdvance() instead.
1558
1559 Newline characters are processed as normal characters, \e not as
1560 linebreaks.
1561
1562 The height of the bounding rectangle is at least as large as the
1563 value returned height().
1564
1565 \since 6.3
1566 \sa horizontalAdvance(), height(), QPainter::boundingRect()
1567*/
1568QRectF QFontMetricsF::boundingRect(const QString &text, const QTextOption &option) const
1569{
1570 if (text.size() == 0)
1571 return QRectF();
1572
1573 QStackTextEngine layout(text, QFont(d.data()));
1574 layout.option = option;
1575 layout.itemize();
1576 glyph_metrics_t gm = layout.boundingBox(from: 0, len: text.size());
1577 return QRectF(gm.x.toReal(), gm.y.toReal(),
1578 gm.width.toReal(), gm.height.toReal());
1579}
1580
1581
1582/*!
1583 Returns the bounding rectangle of the character \a ch relative to
1584 the left-most point on the base line.
1585
1586 Note that the bounding rectangle may extend to the left of (0, 0),
1587 e.g. for italicized fonts, and that the text output may cover \e
1588 all pixels in the bounding rectangle.
1589
1590 Note that the rectangle usually extends both above and below the
1591 base line.
1592
1593 \sa horizontalAdvance()
1594*/
1595QRectF QFontMetricsF::boundingRect(QChar ch) const
1596{
1597 const int script = ch.script();
1598 QFontEngine *engine;
1599 if (d->capital == QFont::SmallCaps && ch.isLower())
1600 engine = d->smallCapsFontPrivate()->engineForScript(script);
1601 else
1602 engine = d->engineForScript(script);
1603 Q_ASSERT(engine != nullptr);
1604
1605 d->alterCharForCapitalization(c&: ch);
1606
1607 glyph_t glyph = engine->glyphIndex(ucs4: ch.unicode());
1608
1609 glyph_metrics_t gm = engine->boundingBox(glyph);
1610 return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
1611}
1612
1613/*!
1614 \overload
1615
1616 Returns the bounding rectangle of the characters in the given \a text.
1617 This is the set of pixels the text would cover if drawn when constrained
1618 to the bounding rectangle specified by \a rect. If \a rect is a reference
1619 to a \nullptr object, e.g. when passing a default constructed QRectF, the
1620 bounding rectangle will not constrain itself to the size.
1621
1622 The \a flags argument is the bitwise OR of the following flags:
1623 \list
1624 \li Qt::AlignLeft aligns to the left border, except for
1625 Arabic and Hebrew where it aligns to the right.
1626 \li Qt::AlignRight aligns to the right border, except for
1627 Arabic and Hebrew where it aligns to the left.
1628 \li Qt::AlignJustify produces justified text.
1629 \li Qt::AlignHCenter aligns horizontally centered.
1630 \li Qt::AlignTop aligns to the top border.
1631 \li Qt::AlignBottom aligns to the bottom border.
1632 \li Qt::AlignVCenter aligns vertically centered
1633 \li Qt::AlignCenter (== \c{Qt::AlignHCenter | Qt::AlignVCenter})
1634 \li Qt::TextSingleLine ignores newline characters in the text.
1635 \li Qt::TextExpandTabs expands tabs (see below)
1636 \li Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined.
1637 \li Qt::TextWordWrap breaks the text to fit the rectangle.
1638 \endlist
1639
1640 Qt::Horizontal alignment defaults to Qt::AlignLeft and vertical
1641 alignment defaults to Qt::AlignTop.
1642
1643 If several of the horizontal or several of the vertical alignment
1644 flags are set, the resulting alignment is undefined.
1645
1646 These flags are defined in \l{Qt::AlignmentFlag}.
1647
1648 If Qt::TextExpandTabs is set in \a flags, the following behavior is
1649 used to interpret tab characters in the text:
1650 \list
1651 \li If \a tabArray is non-null, it specifies a 0-terminated sequence of
1652 pixel-positions for tabs in the text.
1653 \li If \a tabStops is non-zero, it is used as the tab spacing (in pixels).
1654 \endlist
1655
1656 Note that the bounding rectangle may extend to the left of (0, 0),
1657 e.g. for italicized fonts.
1658
1659 Newline characters are processed as line breaks.
1660
1661 Despite the different actual character heights, the heights of the
1662 bounding rectangles of "Yes" and "yes" are the same.
1663
1664 The bounding rectangle returned by this function is somewhat larger
1665 than that calculated by the simpler boundingRect() function. This
1666 function uses the \l{minLeftBearing()}{maximum left} and
1667 \l{minRightBearing()}{right} font bearings as is
1668 necessary for multi-line text to align correctly. Also,
1669 fontHeight() and lineSpacing() are used to calculate the height,
1670 rather than individual character heights.
1671
1672 \sa horizontalAdvance(), QPainter::boundingRect(), Qt::Alignment
1673*/
1674QRectF QFontMetricsF::boundingRect(const QRectF &rect, int flags, const QString& text,
1675 int tabStops, int *tabArray) const
1676{
1677 int tabArrayLen = 0;
1678 if (tabArray)
1679 while (tabArray[tabArrayLen])
1680 tabArrayLen++;
1681
1682 QRectF rb;
1683 qt_format_text(font: QFont(d.data()), r: rect, tf: flags | Qt::TextDontPrint, text, brect: &rb, tabStops, tabArray,
1684 tabArrayLen, painter: nullptr);
1685 return rb;
1686}
1687
1688/*!
1689 Returns the size in pixels of the characters in the given \a text.
1690
1691 The \a flags argument is the bitwise OR of the following flags:
1692 \list
1693 \li Qt::TextSingleLine ignores newline characters.
1694 \li Qt::TextExpandTabs expands tabs (see below)
1695 \li Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined.
1696 \li Qt::TextWordWrap breaks the text to fit the rectangle.
1697 \endlist
1698
1699 These flags are defined in the \l{Qt::TextFlag} enum.
1700
1701 If Qt::TextExpandTabs is set in \a flags, the following behavior is
1702 used to interpret tab characters in the text:
1703 \list
1704 \li If \a tabArray is non-null, it specifies a 0-terminated sequence of
1705 pixel-positions for tabs in the text.
1706 \li If \a tabStops is non-zero, it is used as the tab spacing (in pixels).
1707 \endlist
1708
1709 Newline characters are processed as line breaks.
1710
1711 Note: Despite the different actual character heights, the heights of the
1712 bounding rectangles of "Yes" and "yes" are the same.
1713
1714 \sa boundingRect()
1715*/
1716QSizeF QFontMetricsF::size(int flags, const QString &text, int tabStops, int *tabArray) const
1717{
1718 return boundingRect(rect: QRectF(), flags: flags | Qt::TextLongestVariant, text, tabStops, tabArray).size();
1719}
1720
1721/*!
1722 \since 4.3
1723
1724 Returns a tight bounding rectangle around the characters in the
1725 string specified by \a text. The bounding rectangle always covers
1726 at least the set of pixels the text would cover if drawn at (0,
1727 0).
1728
1729 Note that the bounding rectangle may extend to the left of (0, 0),
1730 e.g. for italicized fonts, and that the width of the returned
1731 rectangle might be different than what the horizontalAdvance() method
1732 returns.
1733
1734 If you want to know the advance width of the string (to lay out
1735 a set of strings next to each other), use horizontalAdvance() instead.
1736
1737 Newline characters are processed as normal characters, \e not as
1738 linebreaks.
1739
1740 \sa horizontalAdvance(), height(), boundingRect()
1741*/
1742QRectF QFontMetricsF::tightBoundingRect(const QString &text) const
1743{
1744 if (text.size() == 0)
1745 return QRectF();
1746
1747 QStackTextEngine layout(text, QFont(d.data()));
1748 layout.itemize();
1749 glyph_metrics_t gm = layout.tightBoundingBox(from: 0, len: text.size());
1750 return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
1751}
1752
1753/*!
1754 Returns a tight bounding rectangle around the characters in the
1755 string specified by \a text laid out using \a option. The bounding
1756 rectangle always covers at least the set of pixels the text would
1757 cover if drawn at (0,0).
1758
1759 Note that the bounding rectangle may extend to the left of (0, 0),
1760 e.g. for italicized fonts, and that the width of the returned
1761 rectangle might be different than what the horizontalAdvance() method
1762 returns.
1763
1764 If you want to know the advance width of the string (to lay out
1765 a set of strings next to each other), use horizontalAdvance() instead.
1766
1767 Newline characters are processed as normal characters, \e not as
1768 linebreaks.
1769
1770 \since 6.3
1771
1772 \sa horizontalAdvance(), height(), boundingRect()
1773*/
1774QRectF QFontMetricsF::tightBoundingRect(const QString &text, const QTextOption &option) const
1775{
1776 if (text.size() == 0)
1777 return QRectF();
1778
1779 QStackTextEngine layout(text, QFont(d.data()));
1780 layout.option = option;
1781 layout.itemize();
1782 glyph_metrics_t gm = layout.tightBoundingBox(from: 0, len: text.size());
1783 return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
1784}
1785
1786/*!
1787 \since 4.2
1788
1789 If the string \a text is wider than \a width, returns an elided
1790 version of the string (i.e., a string with "..." in it).
1791 Otherwise, returns the original string.
1792
1793 The \a mode parameter specifies whether the text is elided on the
1794 left (for example, "...tech"), in the middle (for example, "Tr...ch"), or
1795 on the right (for example, "Trol...").
1796
1797 The \a width is specified in pixels, not characters.
1798
1799 The \a flags argument is optional and currently only supports
1800 Qt::TextShowMnemonic as value.
1801
1802 The elide mark follows the \l{Qt::LayoutDirection}{layoutdirection}.
1803 For example, it will be on the right side of the text for right-to-left
1804 layouts if the \a mode is \c{Qt::ElideLeft}, and on the left side of the
1805 text if the \a mode is \c{Qt::ElideRight}.
1806*/
1807QString QFontMetricsF::elidedText(const QString &text, Qt::TextElideMode mode, qreal width, int flags) const
1808{
1809 QString _text = text;
1810 if (!(flags & Qt::TextLongestVariant)) {
1811 int posA = 0;
1812 int posB = _text.indexOf(c: s_variableLengthStringSeparator);
1813 while (posB >= 0) {
1814 QString portion = _text.mid(position: posA, n: posB - posA);
1815 if (size(flags, text: portion).width() <= width)
1816 return portion;
1817 posA = posB + 1;
1818 posB = _text.indexOf(c: s_variableLengthStringSeparator, from: posA);
1819 }
1820 _text = _text.mid(position: posA);
1821 }
1822 QStackTextEngine engine(_text, QFont(d.data()));
1823 return engine.elidedText(mode, width: QFixed::fromReal(r: width), flags);
1824}
1825
1826/*!
1827 Returns the distance from the base line to where an underscore
1828 should be drawn.
1829
1830 \sa overlinePos(), strikeOutPos(), lineWidth()
1831*/
1832qreal QFontMetricsF::underlinePos() const
1833{
1834 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
1835 Q_ASSERT(engine != nullptr);
1836 return engine->underlinePosition().toReal();
1837}
1838
1839/*!
1840 Returns the distance from the base line to where an overline
1841 should be drawn.
1842
1843 \sa underlinePos(), strikeOutPos(), lineWidth()
1844*/
1845qreal QFontMetricsF::overlinePos() const
1846{
1847 return ascent() + 1;
1848}
1849
1850/*!
1851 Returns the distance from the base line to where the strikeout
1852 line should be drawn.
1853
1854 \sa underlinePos(), overlinePos(), lineWidth()
1855*/
1856qreal QFontMetricsF::strikeOutPos() const
1857{
1858 return ascent() / 3.;
1859}
1860
1861/*!
1862 Returns the width of the underline and strikeout lines, adjusted
1863 for the point size of the font.
1864
1865 \sa underlinePos(), overlinePos(), strikeOutPos()
1866*/
1867qreal QFontMetricsF::lineWidth() const
1868{
1869 QFontEngine *engine = d->engineForScript(script: QChar::Script_Common);
1870 Q_ASSERT(engine != nullptr);
1871 return engine->lineThickness().toReal();
1872}
1873
1874/*!
1875 \since 5.14
1876
1877 Returns the font DPI.
1878*/
1879qreal QFontMetricsF::fontDpi() const
1880{
1881 return d->dpi;
1882}
1883
1884QT_END_NAMESPACE
1885

source code of qtbase/src/gui/text/qfontmetrics.cpp