Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qfont.cpp
Go to the documentation of this file.
1// Copyright (C) 2019 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 "qdebug.h"
6#include "qpaintdevice.h"
7#include "qfontdatabase.h"
8#include "qfontmetrics.h"
9#include "qfontinfo.h"
10#include "qpainter.h"
11#include "qhash.h"
12#include "qdatastream.h"
13#include "qguiapplication.h"
14#include "qstringlist.h"
15#include "qscreen.h"
16
17#include "qthread.h"
18#include "qthreadstorage.h"
19
20#include "qfont_p.h"
21#include <private/qfontengine_p.h>
22#include <private/qpainter_p.h>
23#include <private/qtextengine_p.h>
24#include <limits.h>
25
26#include <qpa/qplatformscreen.h>
27#include <qpa/qplatformintegration.h>
28#include <qpa/qplatformfontdatabase.h>
29#include <QtGui/private/qguiapplication_p.h>
30
31#include <QtCore/QMutexLocker>
32#include <QtCore/QMutex>
33
34#include <array>
35
36// #define QFONTCACHE_DEBUG
37#ifdef QFONTCACHE_DEBUG
38# define FC_DEBUG qDebug
39#else
40# define FC_DEBUG if (false) qDebug
41#endif
42
44
45#ifndef QFONTCACHE_DECREASE_TRIGGER_LIMIT
46# define QFONTCACHE_DECREASE_TRIGGER_LIMIT 256
47#endif
48
50{
51 /*
52 QFontDef comparison is more complicated than just simple
53 per-member comparisons.
54
55 When comparing point/pixel sizes, either point or pixelsize
56 could be -1. in This case we have to compare the non negative
57 size value.
58
59 This test will fail if the point-sizes differ by 1/2 point or
60 more or they do not round to the same value. We have to do this
61 since our API still uses 'int' point-sizes in the API, but store
62 deci-point-sizes internally.
63
64 To compare the family members, we need to parse the font names
65 and compare the family/foundry strings separately. This allows
66 us to compare e.g. "Helvetica" and "Helvetica [Adobe]" with
67 positive results.
68 */
69 if (pixelSize != -1 && other.pixelSize != -1) {
70 if (pixelSize != other.pixelSize)
71 return false;
72 } else if (pointSize != -1 && other.pointSize != -1) {
73 if (pointSize != other.pointSize)
74 return false;
75 } else {
76 return false;
77 }
78
79 if (!ignorePitch && !other.ignorePitch && fixedPitch != other.fixedPitch)
80 return false;
81
82 if (stretch != 0 && other.stretch != 0 && stretch != other.stretch)
83 return false;
84
85 QString this_family, this_foundry, other_family, other_foundry;
86 for (int i = 0; i < families.size(); ++i) {
87 QFontDatabasePrivate::parseFontName(families.at(i), this_foundry, this_family);
88 QFontDatabasePrivate::parseFontName(other.families.at(i), other_foundry, other_family);
89 if (this_family != other_family || this_foundry != other_foundry)
90 return false;
91 }
92
93 if (variableAxisValues != other.variableAxisValues)
94 return false;
95
96 return (styleHint == other.styleHint
97 && styleStrategy == other.styleStrategy
98 && weight == other.weight
99 && style == other.style
100 && this_family == other_family
101 && (styleName.isEmpty() || other.styleName.isEmpty() || styleName == other.styleName)
102 && (this_foundry.isEmpty()
103 || other_foundry.isEmpty()
104 || this_foundry == other_foundry)
105 );
106}
107
108extern bool qt_is_tty_app;
109
110Q_GUI_EXPORT int qt_defaultDpiX()
111{
112 if (QCoreApplication::instance()->testAttribute(Qt::AA_Use96Dpi))
113 return 96;
114
115 if (qt_is_tty_app)
116 return 75;
117
120
121 //PI has not been initialised, or it is being initialised. Give a default dpi
122 return 100;
123}
124
125Q_GUI_EXPORT int qt_defaultDpiY()
126{
127 if (QCoreApplication::instance()->testAttribute(Qt::AA_Use96Dpi))
128 return 96;
129
130 if (qt_is_tty_app)
131 return 75;
132
135
136 //PI has not been initialised, or it is being initialised. Give a default dpi
137 return 100;
138}
139
140Q_GUI_EXPORT int qt_defaultDpi()
141{
142 return qt_defaultDpiY();
143}
144
145/* Helper function to convert between legacy Qt and OpenType font weights. */
146static int convertWeights(int weight, bool inverted)
147{
148 static constexpr std::array<int, 2> legacyToOpenTypeMap[] = {
149 { 0, QFont::Thin }, { 12, QFont::ExtraLight }, { 25, QFont::Light },
150 { 50, QFont::Normal }, { 57, QFont::Medium }, { 63, QFont::DemiBold },
151 { 75, QFont::Bold }, { 81, QFont::ExtraBold }, { 87, QFont::Black },
152 };
153
154 int closestDist = INT_MAX;
155 int result = -1;
156
157 // Go through and find the closest mapped value
158 for (auto mapping : legacyToOpenTypeMap) {
159 const int weightOld = mapping[ inverted];
160 const int weightNew = mapping[!inverted];
161 const int dist = qAbs(weightOld - weight);
162 if (dist < closestDist) {
163 result = weightNew;
164 closestDist = dist;
165 } else {
166 // Break early since following values will be further away
167 break;
168 }
169 }
170
171 return result;
172}
173
174// Splits the family string on a comma and returns the list based on that
176{
178 if (family.isEmpty())
179 return familyList;
180 const auto list = QStringView{family}.split(u',');
181 const int numFamilies = list.size();
182 familyList.reserve(numFamilies);
183 for (int i = 0; i < numFamilies; ++i) {
184 auto str = list.at(i).trimmed();
185 if ((str.startsWith(u'"') && str.endsWith(u'"'))
186 || (str.startsWith(u'\'') && str.endsWith(u'\''))) {
187 str = str.mid(1, str.size() - 2);
188 }
189 familyList << str.toString();
190 }
191 return familyList;
192}
193
194/* Converts from legacy Qt font weight (Qt < 6.0) to OpenType font weight (Qt >= 6.0) */
196{
197 return convertWeights(weight, false);
198}
199
200/* Converts from OpenType font weight (Qt >= 6.0) to legacy Qt font weight (Qt < 6.0) */
202{
203 return convertWeights(weight, true);
204}
205
207 : engineData(nullptr), dpi(qt_defaultDpi()),
208 underline(false), overline(false), strikeOut(false), kerning(true),
209 capital(0), letterSpacingIsAbsolute(false), scFont(nullptr)
210{
211}
212
214 : request(other.request), engineData(nullptr), dpi(other.dpi),
215 underline(other.underline), overline(other.overline),
216 strikeOut(other.strikeOut), kerning(other.kerning),
217 capital(other.capital), letterSpacingIsAbsolute(other.letterSpacingIsAbsolute),
218 letterSpacing(other.letterSpacing), wordSpacing(other.wordSpacing),
219 features(other.features), scFont(other.scFont)
220{
221 if (scFont && scFont != this)
222 scFont->ref.ref();
223}
224
226{
227 if (engineData && !engineData->ref.deref())
228 delete engineData;
229 engineData = nullptr;
230 if (scFont && scFont != this) {
231 if (!scFont->ref.deref())
232 delete scFont;
233 }
234 scFont = nullptr;
235}
236
238
239#define QT_FONT_ENGINE_FROM_DATA(data, script) data->engines[script]
240
242{
244 if (script <= QChar::Script_Latin)
245 script = QChar::Script_Common;
247 // throw out engineData that came from a different thread
248 if (!engineData->ref.deref())
249 delete engineData;
250 engineData = nullptr;
251 }
253 QFontDatabasePrivate::load(this, script);
254 return QT_FONT_ENGINE_FROM_DATA(engineData, script);
255}
256
258 switch (capital) {
260 case QFont::SmallCaps:
261 c = c.toUpper();
262 break;
264 c = c.toLower();
265 break;
266 case QFont::MixedCase:
267 break;
268 }
269}
270
272{
273 if (scFont)
274 return scFont;
275 QFont font(const_cast<QFontPrivate *>(this));
276 qreal pointSize = font.pointSizeF();
277 if (pointSize > 0)
278 font.setPointSizeF(pointSize * .7);
279 else
280 font.setPixelSize((font.pixelSize() * 7 + 5) / 10);
281 scFont = font.d.data();
282 if (scFont != this)
283 scFont->ref.ref();
284 return scFont;
285}
286
287
289{
290 Q_ASSERT(other != nullptr);
291
292 dpi = other->dpi;
293
295
296 // assign the unset-bits with the set-bits of the other font def
298 request.families = other->request.families;
299
301 request.styleName = other->request.styleName;
302
303 if (! (mask & QFont::SizeResolved)) {
304 request.pointSize = other->request.pointSize;
305 request.pixelSize = other->request.pixelSize;
306 }
307
309 request.styleHint = other->request.styleHint;
310
312 request.styleStrategy = other->request.styleStrategy;
313
314 if (! (mask & QFont::WeightResolved))
315 request.weight = other->request.weight;
316
317 if (! (mask & QFont::StyleResolved))
318 request.style = other->request.style;
319
321 request.fixedPitch = other->request.fixedPitch;
322
324 request.stretch = other->request.stretch;
325
327 request.hintingPreference = other->request.hintingPreference;
328
330 underline = other->underline;
331
333 overline = other->overline;
334
336 strikeOut = other->strikeOut;
337
339 kerning = other->kerning;
340
342 letterSpacing = other->letterSpacing;
343 letterSpacingIsAbsolute = other->letterSpacingIsAbsolute;
344 }
346 wordSpacing = other->wordSpacing;
348 capital = other->capital;
349
351 features = other->features;
352
354 request.variableAxisValues = other->request.variableAxisValues;
355}
356
358{
360}
361
366
371
376
381
382
384 : ref(0), fontCacheId(QFontCache::instance()->id())
385{
386 memset(engines, 0, QChar::ScriptCount * sizeof(QFontEngine *));
387}
388
390{
391 Q_ASSERT(ref.loadRelaxed() == 0);
392 for (int i = 0; i < QChar::ScriptCount; ++i) {
393 if (engines[i]) {
394 if (!engines[i]->ref.deref())
395 delete engines[i];
396 engines[i] = nullptr;
397 }
398 }
399}
400
401
402
403
622 : resolve_mask(font.resolve_mask)
623{
624 Q_ASSERT(pd);
625 const int dpi = pd->logicalDpiY();
626 if (font.d->dpi != dpi) {
627 d = new QFontPrivate(*font.d);
628 d->dpi = dpi;
629 } else {
630 d = font.d;
631 }
632}
633
638 : d(data), resolve_mask(QFont::AllPropertiesResolved)
639{
640}
641
645void QFont::detach()
646{
647 if (d->ref.loadRelaxed() == 1) {
648 if (d->engineData && !d->engineData->ref.deref())
649 delete d->engineData;
650 d->engineData = nullptr;
651 if (d->scFont && d->scFont != d.data()) {
652 if (!d->scFont->ref.deref())
653 delete d->scFont;
654 }
655 d->scFont = nullptr;
656 return;
657 }
658
659 d.detach();
660}
661
669{
670 if (font->d->ref.loadRelaxed() == 1)
671 return;
672
674 if (engineData)
675 engineData->ref.ref();
676 font->d.detach();
678}
679
686 : d(QGuiApplicationPrivate::instance() ? QGuiApplication::font().d.data() : new QFontPrivate()), resolve_mask(0)
687{
688}
689
712QFont::QFont(const QString &family, int pointSize, int weight, bool italic)
713 : d(new QFontPrivate()), resolve_mask(QFont::FamiliesResolved)
714{
715 if (pointSize <= 0) {
716 pointSize = 12;
717 } else {
718 resolve_mask |= QFont::SizeResolved;
719 }
720
721 if (weight < 0) {
722 weight = Normal;
723 } else {
725 }
726
727 if (italic)
728 resolve_mask |= QFont::StyleResolved;
729
732 d->request.pixelSize = -1;
733 d->request.weight = weight;
735}
736
755QFont::QFont(const QStringList &families, int pointSize, int weight, bool italic)
756 : d(new QFontPrivate()), resolve_mask(QFont::FamiliesResolved)
757{
758 if (pointSize <= 0)
759 pointSize = 12;
760 else
761 resolve_mask |= QFont::SizeResolved;
762
763 if (weight < 0)
764 weight = Normal;
765 else
767
768 if (italic)
769 resolve_mask |= QFont::StyleResolved;
770
773 d->request.pixelSize = -1;
774 d->request.weight = weight;
776}
777
782 : d(font.d), resolve_mask(font.resolve_mask)
783{
784}
785
790{
791}
792
797{
798 d = font.d;
799 resolve_mask = font.resolve_mask;
800 return *this;
801}
802
818{
819 return d->request.families.isEmpty() ? QString() : d->request.families.constFirst();
820}
821
835void QFont::setFamily(const QString &family)
836{
838}
839
850{
851 return d->request.styleName;
852}
853
867void QFont::setStyleName(const QString &styleName)
868{
869 if ((resolve_mask & QFont::StyleNameResolved) && d->request.styleName == styleName)
870 return;
871
872 detach();
873
875 resolve_mask |= QFont::StyleNameResolved;
876}
877
885{
886 return qRound(d->request.pointSize);
887}
888
958{
960 return;
961
962 detach();
963
965
966 resolve_mask |= QFont::HintingPreferenceResolved;
967}
968
978
985void QFont::setPointSize(int pointSize)
986{
987 if (pointSize <= 0) {
988 qWarning("QFont::setPointSize: Point size <= 0 (%d), must be greater than 0", pointSize);
989 return;
990 }
991
992 if ((resolve_mask & QFont::SizeResolved) && d->request.pointSize == qreal(pointSize))
993 return;
994
995 detach();
996
998 d->request.pixelSize = -1;
999
1000 resolve_mask |= QFont::SizeResolved;
1001}
1002
1011{
1012 if (pointSize <= 0) {
1013 qWarning("QFont::setPointSizeF: Point size <= 0 (%f), must be greater than 0", pointSize);
1014 return;
1015 }
1016
1017 if ((resolve_mask & QFont::SizeResolved) && d->request.pointSize == pointSize)
1018 return;
1019
1020 detach();
1021
1023 d->request.pixelSize = -1;
1024
1025 resolve_mask |= QFont::SizeResolved;
1026}
1027
1035{
1036 return d->request.pointSize;
1037}
1038
1049void QFont::setPixelSize(int pixelSize)
1050{
1051 if (pixelSize <= 0) {
1052 qWarning("QFont::setPixelSize: Pixel size <= 0 (%d)", pixelSize);
1053 return;
1054 }
1055
1056 if ((resolve_mask & QFont::SizeResolved) && d->request.pixelSize == qreal(pixelSize))
1057 return;
1058
1059 detach();
1060
1062 d->request.pointSize = -1;
1063
1064 resolve_mask |= QFont::SizeResolved;
1065}
1066
1075{
1076 return d->request.pixelSize;
1077}
1078
1106{
1107 return (QFont::Style)d->request.style;
1108}
1109
1110
1117{
1118 if ((resolve_mask & QFont::StyleResolved) && d->request.style == style)
1119 return;
1120
1121 detach();
1122
1123 d->request.style = style;
1124 resolve_mask |= QFont::StyleResolved;
1125}
1126
1134{
1135 return static_cast<Weight>(d->request.weight);
1136}
1137
1157#if QT_DEPRECATED_SINCE(6, 0)
1173void QFont::setLegacyWeight(int legacyWeight)
1174{
1176}
1177
1191int QFont::legacyWeight() const
1192{
1194}
1195#endif // QT_DEPRECATED_SINCE(6, 0)
1196
1206{
1207 const int weightValue = qBound(QFONT_WEIGHT_MIN, static_cast<int>(weight), QFONT_WEIGHT_MAX);
1208 if (weightValue != static_cast<int>(weight)) {
1209 qWarning() << "QFont::setWeight: Weight must be between 1 and 1000, attempted to set "
1210 << static_cast<int>(weight);
1211 }
1212
1213 if ((resolve_mask & QFont::WeightResolved) && d->request.weight == weightValue)
1214 return;
1215
1216 detach();
1217
1218 d->request.weight = weightValue;
1219 resolve_mask |= QFont::WeightResolved;
1220}
1221
1252{
1253 return d->underline;
1254}
1255
1263{
1264 if ((resolve_mask & QFont::UnderlineResolved) && d->underline == enable)
1265 return;
1266
1268
1269 d->underline = enable;
1270 resolve_mask |= QFont::UnderlineResolved;
1271}
1272
1279{
1280 return d->overline;
1281}
1282
1289{
1290 if ((resolve_mask & QFont::OverlineResolved) && d->overline == enable)
1291 return;
1292
1294
1295 d->overline = enable;
1296 resolve_mask |= QFont::OverlineResolved;
1297}
1298
1305{
1306 return d->strikeOut;
1307}
1308
1316{
1317 if ((resolve_mask & QFont::StrikeOutResolved) && d->strikeOut == enable)
1318 return;
1319
1321
1322 d->strikeOut = enable;
1323 resolve_mask |= QFont::StrikeOutResolved;
1324}
1325
1332{
1333 return d->request.fixedPitch;
1334}
1335
1343{
1344 if ((resolve_mask & QFont::FixedPitchResolved) && d->request.fixedPitch == enable)
1345 return;
1346
1347 detach();
1348
1350 d->request.ignorePitch = false;
1351 resolve_mask |= QFont::FixedPitchResolved;
1352}
1353
1359bool QFont::kerning() const
1360{
1361 return d->kerning;
1362}
1363
1376{
1377 if ((resolve_mask & QFont::KerningResolved) && d->kerning == enable)
1378 return;
1379
1381
1382 d->kerning = enable;
1383 resolve_mask |= QFont::KerningResolved;
1384}
1385
1398
1408{
1409 return (StyleHint) d->request.styleHint;
1410}
1411
1523{
1524 if ((resolve_mask & (QFont::StyleHintResolved | QFont::StyleStrategyResolved)) &&
1525 (StyleHint) d->request.styleHint == hint &&
1526 (StyleStrategy) d->request.styleStrategy == strategy)
1527 return;
1528
1529 detach();
1530
1531 d->request.styleHint = hint;
1532 d->request.styleStrategy = strategy;
1533 resolve_mask |= QFont::StyleHintResolved;
1534 resolve_mask |= QFont::StyleStrategyResolved;
1535
1536}
1537
1544{
1545 if ((resolve_mask & QFont::StyleStrategyResolved) &&
1547 return;
1548
1549 detach();
1550
1551 d->request.styleStrategy = s;
1552 resolve_mask |= QFont::StyleStrategyResolved;
1553}
1554
1555
1582{
1583 return d->request.stretch;
1584}
1585
1605void QFont::setStretch(int factor)
1606{
1607 if (factor < 0 || factor > 4000) {
1608 qWarning("QFont::setStretch: Parameter '%d' out of range", factor);
1609 return;
1610 }
1611
1612 if ((resolve_mask & QFont::StretchResolved) &&
1613 d->request.stretch == (uint)factor)
1614 return;
1615
1616 detach();
1617
1618 d->request.stretch = (uint)factor;
1619 resolve_mask |= QFont::StretchResolved;
1620}
1621
1639{
1640 return d->letterSpacing.toReal();
1641}
1642
1656{
1657 const QFixed newSpacing = QFixed::fromReal(spacing);
1658 const bool absoluteSpacing = type == AbsoluteSpacing;
1659 if ((resolve_mask & QFont::LetterSpacingResolved) &&
1660 d->letterSpacingIsAbsolute == absoluteSpacing &&
1661 d->letterSpacing == newSpacing)
1662 return;
1663
1665
1666 d->letterSpacing = newSpacing;
1667 d->letterSpacingIsAbsolute = absoluteSpacing;
1668 resolve_mask |= QFont::LetterSpacingResolved;
1669}
1670
1681
1689{
1690 return d->wordSpacing.toReal();
1691}
1692
1708{
1709 const QFixed newSpacing = QFixed::fromReal(spacing);
1710 if ((resolve_mask & QFont::WordSpacingResolved) &&
1711 d->wordSpacing == newSpacing)
1712 return;
1713
1715
1716 d->wordSpacing = newSpacing;
1717 resolve_mask |= QFont::WordSpacingResolved;
1718}
1719
1743{
1744 if ((resolve_mask & QFont::CapitalizationResolved) &&
1745 capitalization() == caps)
1746 return;
1747
1749
1750 d->capital = caps;
1751 resolve_mask |= QFont::CapitalizationResolved;
1752}
1753
1761{
1762 return static_cast<QFont::Capitalization> (d->capital);
1763}
1764
1772{
1773 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
1774 Q_ASSERT(engine != nullptr);
1775 return d->request.exactMatch(engine->fontDef);
1776}
1777
1787bool QFont::operator==(const QFont &f) const
1788{
1789 return (f.d == d
1790 || (f.d->request == d->request
1791 && f.d->request.pointSize == d->request.pointSize
1792 && f.d->underline == d->underline
1793 && f.d->overline == d->overline
1794 && f.d->strikeOut == d->strikeOut
1795 && f.d->kerning == d->kerning
1796 && f.d->capital == d->capital
1797 && f.d->letterSpacingIsAbsolute == d->letterSpacingIsAbsolute
1798 && f.d->letterSpacing == d->letterSpacing
1799 && f.d->wordSpacing == d->wordSpacing
1800 && f.d->features == d->features
1801 ));
1802}
1803
1804
1816bool QFont::operator<(const QFont &f) const
1817{
1818 if (f.d == d) return false;
1819 // the < operator for fontdefs ignores point sizes.
1820 const QFontDef &r1 = f.d->request;
1821 const QFontDef &r2 = d->request;
1822 if (r1.pointSize != r2.pointSize) return r1.pointSize < r2.pointSize;
1823 if (r1.pixelSize != r2.pixelSize) return r1.pixelSize < r2.pixelSize;
1824 if (r1.weight != r2.weight) return r1.weight < r2.weight;
1825 if (r1.style != r2.style) return r1.style < r2.style;
1826 if (r1.stretch != r2.stretch) return r1.stretch < r2.stretch;
1827 if (r1.styleHint != r2.styleHint) return r1.styleHint < r2.styleHint;
1828 if (r1.styleStrategy != r2.styleStrategy) return r1.styleStrategy < r2.styleStrategy;
1829 if (r1.families != r2.families) return r1.families < r2.families;
1830 if (f.d->capital != d->capital) return f.d->capital < d->capital;
1831
1832 if (f.d->letterSpacingIsAbsolute != d->letterSpacingIsAbsolute) return f.d->letterSpacingIsAbsolute < d->letterSpacingIsAbsolute;
1833 if (f.d->letterSpacing != d->letterSpacing) return f.d->letterSpacing < d->letterSpacing;
1834 if (f.d->wordSpacing != d->wordSpacing) return f.d->wordSpacing < d->wordSpacing;
1835
1836 int f1attrs = (f.d->underline << 3) + (f.d->overline << 2) + (f.d->strikeOut<<1) + f.d->kerning;
1837 int f2attrs = (d->underline << 3) + (d->overline << 2) + (d->strikeOut<<1) + d->kerning;
1838 if (f1attrs != f2attrs) return f1attrs < f2attrs;
1839
1840 if (d->features.size() != f.d->features.size())
1841 return f.d->features.size() < d->features.size();
1842
1843 {
1844 auto it = d->features.constBegin();
1845 auto jt = f.d->features.constBegin();
1846 for (; it != d->features.constEnd(); ++it, ++jt) {
1847 if (it.key() != jt.key())
1848 return jt.key() < it.key();
1849 if (it.value() != jt.value())
1850 return jt.value() < it.value();
1851 }
1852 }
1853
1854 if (r1.variableAxisValues.size() != r2.variableAxisValues.size())
1855 return r1.variableAxisValues.size() < r2.variableAxisValues.size();
1856
1857 {
1858 auto it = r1.variableAxisValues.constBegin();
1859 auto jt = r2.variableAxisValues.constBegin();
1860 for (; it != r1.variableAxisValues.constEnd(); ++it, ++jt) {
1861 if (it.key() != jt.key())
1862 return jt.key() < it.key();
1863 if (it.value() != jt.value())
1864 return jt.value() < it.value();
1865 }
1866 }
1867
1868 return false;
1869}
1870
1871
1881bool QFont::operator!=(const QFont &f) const
1882{
1883 return !(operator==(f));
1884}
1885
1889QFont::operator QVariant() const
1890{
1891 return QVariant::fromValue(*this);
1892}
1893
1901bool QFont::isCopyOf(const QFont & f) const
1902{
1903 return d == f.d;
1904}
1905
1911{
1912 if (resolve_mask == 0 || (resolve_mask == other.resolve_mask && *this == other)) {
1913 QFont o(other);
1914 o.resolve_mask = resolve_mask;
1915 return o;
1916 }
1917
1918 QFont font(*this);
1919 font.detach();
1920 font.d->resolve(resolve_mask, other.d.data());
1921
1922 return font;
1923}
1924
1936/*****************************************************************************
1937 QFont substitution management
1938 *****************************************************************************/
1939
1940typedef QHash<QString, QStringList> QFontSubst;
1941Q_GLOBAL_STATIC(QFontSubst, globalFontSubst)
1942
1943
1954QString QFont::substitute(const QString &familyName)
1955{
1956 QFontSubst *fontSubst = globalFontSubst();
1957 Q_ASSERT(fontSubst != nullptr);
1958 QFontSubst::ConstIterator it = fontSubst->constFind(familyName.toLower());
1959 if (it != fontSubst->constEnd() && !(*it).isEmpty())
1960 return (*it).first();
1961
1962 return familyName;
1963}
1964
1965
1976{
1977 QFontSubst *fontSubst = globalFontSubst();
1978 Q_ASSERT(fontSubst != nullptr);
1979 return fontSubst->value(familyName.toLower(), QStringList());
1980}
1981
1982
1992void QFont::insertSubstitution(const QString &familyName,
1993 const QString &substituteName)
1994{
1995 QFontSubst *fontSubst = globalFontSubst();
1996 Q_ASSERT(fontSubst != nullptr);
1997 QStringList &list = (*fontSubst)[familyName.toLower()];
1998 QString s = substituteName.toLower();
1999 if (!list.contains(s))
2000 list.append(s);
2001}
2002
2003
2015 const QStringList &substituteNames)
2016{
2017 QFontSubst *fontSubst = globalFontSubst();
2018 Q_ASSERT(fontSubst != nullptr);
2019 QStringList &list = (*fontSubst)[familyName.toLower()];
2020 for (const QString &substituteName : substituteNames) {
2021 const QString lowerSubstituteName = substituteName.toLower();
2022 if (!list.contains(lowerSubstituteName))
2023 list.append(lowerSubstituteName);
2024 }
2025}
2026
2034{
2035 QFontSubst *fontSubst = globalFontSubst();
2036 Q_ASSERT(fontSubst != nullptr);
2037 fontSubst->remove(familyName.toLower());
2038}
2039
2046{
2047 QFontSubst *fontSubst = globalFontSubst();
2048 Q_ASSERT(fontSubst != nullptr);
2049 QStringList ret = fontSubst->keys();
2050
2051 ret.sort();
2052 return ret;
2053}
2054
2055#ifndef QT_NO_DATASTREAM
2056/* \internal
2057 Internal function. Converts boolean font settings to an unsigned
2058 8-bit number. Used for serialization etc.
2059*/
2060static quint8 get_font_bits(int version, const QFontPrivate *f)
2061{
2062 Q_ASSERT(f != nullptr);
2063 quint8 bits = 0;
2064 if (f->request.style)
2065 bits |= 0x01;
2066 if (f->underline)
2067 bits |= 0x02;
2068 if (f->overline)
2069 bits |= 0x40;
2070 if (f->strikeOut)
2071 bits |= 0x04;
2072 if (f->request.fixedPitch)
2073 bits |= 0x08;
2074 // if (f.hintSetByUser)
2075 // bits |= 0x10;
2076 if (version >= QDataStream::Qt_4_0) {
2077 if (f->kerning)
2078 bits |= 0x10;
2079 }
2080 if (f->request.style == QFont::StyleOblique)
2081 bits |= 0x80;
2082 return bits;
2083}
2084
2086{
2087 Q_ASSERT(f != nullptr);
2088 quint8 bits = 0;
2089 if (f->request.ignorePitch)
2090 bits |= 0x01;
2091 if (f->letterSpacingIsAbsolute)
2092 bits |= 0x02;
2093 return bits;
2094}
2095
2096/* \internal
2097 Internal function. Sets boolean font settings from an unsigned
2098 8-bit number. Used for serialization etc.
2099*/
2100static void set_font_bits(int version, quint8 bits, QFontPrivate *f)
2101{
2102 Q_ASSERT(f != nullptr);
2103 f->request.style = (bits & 0x01) != 0 ? QFont::StyleItalic : QFont::StyleNormal;
2104 f->underline = (bits & 0x02) != 0;
2105 f->overline = (bits & 0x40) != 0;
2106 f->strikeOut = (bits & 0x04) != 0;
2107 f->request.fixedPitch = (bits & 0x08) != 0;
2108 // f->hintSetByUser = (bits & 0x10) != 0;
2109 if (version >= QDataStream::Qt_4_0)
2110 f->kerning = (bits & 0x10) != 0;
2111 if ((bits & 0x80) != 0)
2112 f->request.style = QFont::StyleOblique;
2113}
2114
2116{
2117 Q_ASSERT(f != nullptr);
2118 f->request.ignorePitch = (bits & 0x01) != 0;
2119 f->letterSpacingIsAbsolute = (bits & 0x02) != 0;
2120}
2121#endif
2122
2130{
2131 return toString();
2132}
2133
2161{
2162 const QChar comma(u',');
2163 QString fontDescription = family() + comma +
2164 QString::number( pointSizeF()) + comma +
2165 QString::number( pixelSize()) + comma +
2166 QString::number((int) styleHint()) + comma +
2167 QString::number( weight()) + comma +
2168 QString::number((int) style()) + comma +
2169 QString::number((int) underline()) + comma +
2170 QString::number((int) strikeOut()) + comma +
2171 QString::number((int)fixedPitch()) + comma +
2172 QString::number((int) false) + comma +
2173 QString::number((int)capitalization()) + comma +
2174 QString::number((int)letterSpacingType()) + comma +
2175 QString::number(letterSpacing()) + comma +
2176 QString::number(wordSpacing()) + comma +
2177 QString::number(stretch()) + comma +
2179
2181 if (!fontStyle.isEmpty())
2182 fontDescription += comma + fontStyle;
2183
2184 return fontDescription;
2185}
2186
2194size_t qHash(const QFont &font, size_t seed) noexcept
2195{
2197}
2198
2199
2207bool QFont::fromString(const QString &descrip)
2208{
2209 const auto sr = QStringView(descrip).trimmed();
2210 const auto l = sr.split(u',');
2211 const int count = l.size();
2212 if (!count || (count > 2 && count < 9) || count == 9 || count > 17 ||
2213 l.first().isEmpty()) {
2214 qWarning("QFont::fromString: Invalid description '%s'",
2215 descrip.isEmpty() ? "(empty)" : descrip.toLatin1().data());
2216 return false;
2217 }
2218
2219 setFamily(l[0].toString());
2220 if (count > 1 && l[1].toDouble() > 0.0)
2221 setPointSizeF(l[1].toDouble());
2222 if (count == 9) {
2223 setStyleHint((StyleHint) l[2].toInt());
2224 setWeight(QFont::Weight(l[3].toInt()));
2225 setItalic(l[4].toInt());
2226 setUnderline(l[5].toInt());
2227 setStrikeOut(l[6].toInt());
2228 setFixedPitch(l[7].toInt());
2229 } else if (count >= 10) {
2230 if (l[2].toInt() > 0)
2231 setPixelSize(l[2].toInt());
2232 setStyleHint((StyleHint) l[3].toInt());
2233 if (count >= 16)
2234 setWeight(QFont::Weight(l[4].toInt()));
2235 else
2237 setStyle((QFont::Style)l[5].toInt());
2238 setUnderline(l[6].toInt());
2239 setStrikeOut(l[7].toInt());
2240 setFixedPitch(l[8].toInt());
2241 if (count >= 16) {
2243 setLetterSpacing((SpacingType)l[11].toInt(), l[12].toDouble());
2244 setWordSpacing(l[13].toDouble());
2245 setStretch(l[14].toInt());
2247 }
2248 if (count == 11 || count == 17)
2249 d->request.styleName = l[count - 1].toString();
2250 else
2251 d->request.styleName.clear();
2252 }
2253
2254 if (count >= 9 && !d->request.fixedPitch) // assume 'false' fixedPitch equals default
2255 d->request.ignorePitch = true;
2256
2257 return true;
2258}
2259
2268{
2269}
2270
2277{
2279}
2280
2286{
2287}
2288
2393std::optional<QFont::Tag> QFont::Tag::fromString(QAnyStringView view) noexcept
2394{
2395 if (view.size() != 4) {
2396 qWarning("The tag name must be exactly 4 characters long!");
2397 return std::nullopt;
2398 }
2399 const QFont::Tag maybeTag = view.visit([](auto view) {
2400 using CharType = decltype(view.at(0));
2401 if constexpr (std::is_same_v<CharType, char>) {
2402 const char bytes[5] = { view.at(0), view.at(1), view.at(2), view.at(3), 0 };
2403 return Tag(bytes);
2404 } else {
2405 const char bytes[5] = { view.at(0).toLatin1(), view.at(1).toLatin1(),
2406 view.at(2).toLatin1(), view.at(3).toLatin1(), 0 };
2407 return Tag(bytes);
2408 }
2409 });
2410 return maybeTag.isValid() ? std::optional<Tag>(maybeTag) : std::nullopt;
2411}
2412
2460{
2461 if (tag.isValid()) {
2462 if (resolve_mask & QFont::VariableAxesResolved && d->hasVariableAxis(tag, value))
2463 return;
2464
2465 detach();
2466
2467 d->setVariableAxis(tag, value);
2468 resolve_mask |= QFont::VariableAxesResolved;
2469 }
2470}
2471
2483{
2484 if (tag.isValid()) {
2485 detach();
2486
2487 d->unsetVariableAxis(tag);
2488 resolve_mask |= QFont::VariableAxesResolved;
2489 }
2490}
2491
2501QList<QFont::Tag> QFont::variableAxisTags() const
2502{
2503 return d->request.variableAxisValues.keys();
2504}
2505
2517{
2518 return d->request.variableAxisValues.value(tag);
2519}
2520
2532{
2533 return d->request.variableAxisValues.contains(tag);
2534}
2535
2546{
2548 return;
2549
2550 detach();
2552}
2553
2554
2592{
2593 if (tag.isValid()) {
2594 d->detachButKeepEngineData(this);
2595 d->setFeature(tag, value);
2596 resolve_mask |= QFont::FeaturesResolved;
2597 }
2598}
2599
2616{
2617 if (tag.isValid()) {
2618 d->detachButKeepEngineData(this);
2619 d->unsetFeature(tag);
2620 resolve_mask |= QFont::FeaturesResolved;
2621 }
2622}
2623
2633QList<QFont::Tag> QFont::featureTags() const
2634{
2635 return d->features.keys();
2636}
2637
2649{
2650 return d->features.value(tag);
2651}
2652
2664{
2665 return d->features.contains(tag);
2666}
2667
2678{
2679 if (d->features.isEmpty())
2680 return;
2681
2682 d->detachButKeepEngineData(this);
2683 d->features.clear();
2684}
2685
2686extern QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style,
2687 QFont::StyleHint styleHint, QChar::Script script);
2688
2698{
2700 , QFont::StyleHint(d->request.styleHint), QChar::Script_Common);
2701 if (!fallbacks.isEmpty())
2702 return fallbacks.first();
2703 return QString();
2704}
2705
2717{
2718 return d->request.families;
2719}
2720
2738void QFont::setFamilies(const QStringList &families)
2739{
2740 if ((resolve_mask & QFont::FamiliesResolved) && d->request.families == families)
2741 return;
2742 detach();
2744 resolve_mask |= QFont::FamiliesResolved;
2745}
2746
2747
2748/*****************************************************************************
2749 QFont stream functions
2750 *****************************************************************************/
2751#ifndef QT_NO_DATASTREAM
2752
2762{
2763 if (s.version() == 1) {
2764 s << font.d->request.families.constFirst().toLatin1();
2765 } else {
2766 s << font.d->request.families.constFirst();
2767 if (s.version() >= QDataStream::Qt_5_4)
2768 s << font.d->request.styleName;
2769 }
2770
2771 if (s.version() >= QDataStream::Qt_4_0) {
2772 // 4.0
2773 double pointSize = font.d->request.pointSize;
2774 qint32 pixelSize = font.d->request.pixelSize;
2775 s << pointSize;
2776 s << pixelSize;
2777 } else if (s.version() <= 3) {
2778 qint16 pointSize = (qint16) (font.d->request.pointSize * 10);
2779 if (pointSize < 0) {
2780 pointSize = (qint16)QFontInfo(font).pointSize() * 10;
2781 }
2782 s << pointSize;
2783 } else {
2784 s << (qint16) (font.d->request.pointSize * 10);
2785 s << (qint16) font.d->request.pixelSize;
2786 }
2787
2788 s << (quint8) font.d->request.styleHint;
2789 if (s.version() >= QDataStream::Qt_3_1) {
2790 // Continue writing 8 bits for versions < 5.4 so that we don't write too much,
2791 // even though we need 16 to store styleStrategy, so there is some data loss.
2792 if (s.version() >= QDataStream::Qt_5_4)
2794 else
2796 }
2797
2798 if (s.version() < QDataStream::Qt_6_0)
2800 else
2801 s << quint16(font.d->request.weight);
2802
2803 s << get_font_bits(s.version(), font.d.data());
2804 if (s.version() >= QDataStream::Qt_4_3)
2805 s << (quint16)font.d->request.stretch;
2806 if (s.version() >= QDataStream::Qt_4_4)
2808 if (s.version() >= QDataStream::Qt_4_5) {
2809 s << font.d->letterSpacing.value();
2810 s << font.d->wordSpacing.value();
2811 }
2812 if (s.version() >= QDataStream::Qt_5_4)
2814 if (s.version() >= QDataStream::Qt_5_6)
2815 s << (quint8)font.d->capital;
2816 if (s.version() >= QDataStream::Qt_5_13) {
2817 if (s.version() < QDataStream::Qt_6_0)
2818 s << font.d->request.families.mid(1);
2819 else
2820 s << font.d->request.families;
2821 }
2822 if (s.version() >= QDataStream::Qt_6_6)
2823 s << font.d->features;
2824 if (s.version() >= QDataStream::Qt_6_7)
2826 return s;
2827}
2828
2829
2839{
2840 font.d = new QFontPrivate;
2841 font.resolve_mask = QFont::AllPropertiesResolved;
2842
2843 quint8 styleHint, bits;
2844 quint16 styleStrategy = QFont::PreferDefault;
2845
2846 if (s.version() == 1) {
2847 QByteArray fam;
2848 s >> fam;
2850 } else {
2851 QString fam;
2852 s >> fam;
2853 font.d->request.families = QStringList(fam);
2854 if (s.version() >= QDataStream::Qt_5_4)
2855 s >> font.d->request.styleName;
2856 }
2857
2858 if (s.version() >= QDataStream::Qt_4_0) {
2859 // 4.0
2860 double pointSize;
2861 qint32 pixelSize;
2862 s >> pointSize;
2863 s >> pixelSize;
2864 font.d->request.pointSize = qreal(pointSize);
2865 font.d->request.pixelSize = pixelSize;
2866 } else {
2867 qint16 pointSize, pixelSize = -1;
2868 s >> pointSize;
2869 if (s.version() >= 4)
2870 s >> pixelSize;
2871 font.d->request.pointSize = qreal(pointSize / 10.);
2872 font.d->request.pixelSize = pixelSize;
2873 }
2874 s >> styleHint;
2875 if (s.version() >= QDataStream::Qt_3_1) {
2876 if (s.version() >= QDataStream::Qt_5_4) {
2877 s >> styleStrategy;
2878 } else {
2879 quint8 tempStyleStrategy;
2880 s >> tempStyleStrategy;
2881 styleStrategy = tempStyleStrategy;
2882 }
2883 }
2884
2885 if (s.version() < QDataStream::Qt_6_0) {
2886 quint8 charSet;
2887 quint8 weight;
2888 s >> charSet;
2889 s >> weight;
2891 } else {
2893 s >> weight;
2895 }
2896
2897 s >> bits;
2898
2899 font.d->request.styleHint = styleHint;
2900 font.d->request.styleStrategy = styleStrategy;
2901
2902 set_font_bits(s.version(), bits, font.d.data());
2903
2904 if (s.version() >= QDataStream::Qt_4_3) {
2905 quint16 stretch;
2906 s >> stretch;
2907 font.d->request.stretch = stretch;
2908 }
2909
2910 if (s.version() >= QDataStream::Qt_4_4) {
2911 quint8 extendedBits;
2912 s >> extendedBits;
2913 set_extended_font_bits(extendedBits, font.d.data());
2914 }
2915 if (s.version() >= QDataStream::Qt_4_5) {
2916 int value;
2917 s >> value;
2919 s >> value;
2921 }
2922 if (s.version() >= QDataStream::Qt_5_4) {
2923 quint8 value;
2924 s >> value;
2926 }
2927 if (s.version() >= QDataStream::Qt_5_6) {
2928 quint8 value;
2929 s >> value;
2931 }
2932 if (s.version() >= QDataStream::Qt_5_13) {
2934 s >> value;
2935 if (s.version() < QDataStream::Qt_6_0)
2936 font.d->request.families.append(value);
2937 else
2939 }
2940 if (s.version() >= QDataStream::Qt_6_6) {
2941 font.d->features.clear();
2942 s >> font.d->features;
2943 }
2944 if (s.version() >= QDataStream::Qt_6_7) {
2947 }
2948
2949 return s;
2950}
2951
2953{
2954 stream << tag.value();
2955 return stream;
2956}
2957
2959{
2960 quint32 value;
2961 stream >> value;
2962 if (const auto maybeTag = QFont::Tag::fromValue(value))
2963 tag = *maybeTag;
2964 else
2965 stream.setStatus(QDataStream::ReadCorruptData);
2966 return stream;
2967}
2968
2969#endif // QT_NO_DATASTREAM
2970
2971
2972/*****************************************************************************
2973 QFontInfo member functions
2974 *****************************************************************************/
2975
3068 : d(font.d)
3069{
3070}
3071
3076 : d(fi.d)
3077{
3078}
3079
3086
3091{
3092 d = fi.d;
3093 return *this;
3094}
3095
3110{
3111 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3112 Q_ASSERT(engine != nullptr);
3113 return engine->fontDef.families.isEmpty() ? QString() : engine->fontDef.families.constFirst();
3114}
3115
3125{
3126 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3127 Q_ASSERT(engine != nullptr);
3128 return engine->fontDef.styleName;
3129}
3130
3137{
3138 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3139 Q_ASSERT(engine != nullptr);
3140 return qRound(engine->fontDef.pointSize);
3141}
3142
3149{
3150 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3151 Q_ASSERT(engine != nullptr);
3152 return engine->fontDef.pointSize;
3153}
3154
3161{
3162 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3163 Q_ASSERT(engine != nullptr);
3164 return engine->fontDef.pixelSize;
3165}
3166
3173{
3174 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3175 Q_ASSERT(engine != nullptr);
3176 return engine->fontDef.style != QFont::StyleNormal;
3177}
3178
3185{
3186 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3187 Q_ASSERT(engine != nullptr);
3188 return (QFont::Style)engine->fontDef.style;
3189}
3190
3191
3192#if QT_DEPRECATED_SINCE(6, 0)
3206int QFontInfo::legacyWeight() const
3207{
3209}
3210#endif // QT_DEPRECATED_SINCE(6, 0)
3211
3212
3219{
3220 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3221 Q_ASSERT(engine != nullptr);
3222 return engine->fontDef.weight;
3223
3224}
3225
3246{
3247 return d->underline;
3248}
3249
3261{
3262 return d->overline;
3263}
3264
3274{
3275 return d->strikeOut;
3276}
3277
3284{
3285 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3286 Q_ASSERT(engine != nullptr);
3287#ifdef Q_OS_MAC
3288 if (!engine->fontDef.fixedPitchComputed) {
3289 QChar ch[2] = { u'i', u'm' };
3290 QGlyphLayoutArray<2> g;
3291 int l = 2;
3292 if (engine->stringToCMap(ch, 2, &g, &l, {}) < 0)
3293 Q_UNREACHABLE();
3294 Q_ASSERT(l == 2);
3295 engine->fontDef.fixedPitch = g.advances[0] == g.advances[1];
3296 engine->fontDef.fixedPitchComputed = true;
3297 }
3298#endif
3299 return engine->fontDef.fixedPitch;
3300}
3301
3310{
3311 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3312 Q_ASSERT(engine != nullptr);
3313 return (QFont::StyleHint) engine->fontDef.styleHint;
3314}
3315
3323{
3324 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3325 Q_ASSERT(engine != nullptr);
3326 return d->request.exactMatch(engine->fontDef);
3327}
3328
3329
3330
3331
3332// **********************************************************************
3333// QFontCache
3334// **********************************************************************
3335
3336using namespace std::chrono_literals;
3337
3338#ifdef QFONTCACHE_DEBUG
3339// fast timeouts for debugging
3340static constexpr auto fast_timeout = 1s;
3341static constexpr auto slow_timeout = 5s;
3342#else
3343static constexpr auto fast_timeout = 10s;
3344static constexpr auto slow_timeout = 5min;
3345#endif // QFONTCACHE_DEBUG
3346
3347#ifndef QFONTCACHE_MIN_COST
3348# define QFONTCACHE_MIN_COST 4*1024 // 4mb
3349#endif
3350const uint QFontCache::min_cost = QFONTCACHE_MIN_COST;
3351Q_GLOBAL_STATIC(QThreadStorage<QFontCache *>, theFontCache)
3352
3354{
3355 QFontCache *&fontCache = theFontCache()->localData();
3356 if (!fontCache)
3357 fontCache = new QFontCache;
3358 return fontCache;
3359}
3360
3362{
3363 QThreadStorage<QFontCache *> *cache = nullptr;
3364 QT_TRY {
3365 cache = theFontCache();
3366 } QT_CATCH (const std::bad_alloc &) {
3367 // no cache - just ignore
3368 }
3369 if (cache && cache->hasLocalData())
3370 cache->setLocalData(nullptr);
3371}
3372
3374
3376 : QObject(), total_cost(0), max_cost(min_cost),
3377 current_timestamp(0), fast(false),
3378 autoClean(QGuiApplication::instance()
3379 && (QGuiApplication::instance()->thread() == QThread::currentThread())),
3380 timer_id(-1),
3381 m_id(font_cache_id.fetchAndAddRelaxed(1) + 1)
3382{
3383}
3384
3386{
3387 clear();
3388}
3389
3391{
3392 {
3395 while (it != end) {
3396 QFontEngineData *data = it.value();
3397 for (int i = 0; i < QChar::ScriptCount; ++i) {
3398 if (data->engines[i]) {
3399 if (!data->engines[i]->ref.deref()) {
3400 Q_ASSERT(engineCacheCount.value(data->engines[i]) == 0);
3401 delete data->engines[i];
3402 }
3403 data->engines[i] = nullptr;
3404 }
3405 }
3406 if (!data->ref.deref()) {
3407 delete data;
3408 } else {
3409 FC_DEBUG("QFontCache::clear: engineData %p still has refcount %d",
3410 data, data->ref.loadRelaxed());
3411 }
3412 ++it;
3413 }
3414 }
3415
3417
3418
3419 bool mightHaveEnginesLeftForCleanup;
3420 do {
3421 mightHaveEnginesLeftForCleanup = false;
3423 it != end; ++it) {
3424 QFontEngine *engine = it.value().data;
3425 if (engine) {
3426 const int cacheCount = --engineCacheCount[engine];
3427 Q_ASSERT(cacheCount >= 0);
3428 if (!engine->ref.deref()) {
3429 Q_ASSERT(cacheCount == 0);
3430 mightHaveEnginesLeftForCleanup = engine->type() == QFontEngine::Multi;
3431 delete engine;
3432 } else if (cacheCount == 0) {
3433 FC_DEBUG("QFontCache::clear: engine %p still has refcount %d",
3434 engine, engine->ref.loadRelaxed());
3435 }
3436 it.value().data = nullptr;
3437 }
3438 }
3439 } while (mightHaveEnginesLeftForCleanup);
3440
3443
3444
3445 total_cost = 0;
3446 max_cost = min_cost;
3447}
3448
3449
3451{
3453 if (it == engineDataCache.constEnd())
3454 return nullptr;
3455
3456 // found
3457 return it.value();
3458}
3459
3461{
3462#ifdef QFONTCACHE_DEBUG
3463 FC_DEBUG("QFontCache: inserting new engine data %p", engineData);
3464 if (engineDataCache.contains(def)) {
3465 FC_DEBUG(" QFontCache already contains engine data %p for key=(%g %g %d %d %d)",
3467 def.pixelSize, def.weight, def.style, def.fixedPitch);
3468 }
3469#endif
3471
3472 engineData->ref.ref();
3473 // Decrease now rather than waiting
3474 if (total_cost > min_cost * 2 && engineDataCache.size() >= QFONTCACHE_DECREASE_TRIGGER_LIMIT)
3475 decreaseCache();
3476
3477 engineDataCache.insert(def, engineData);
3478 increaseCost(sizeof(QFontEngineData));
3479}
3480
3482{
3484 end = engineCache.end();
3485 if (it == end) return nullptr;
3486
3487 Q_ASSERT(it.value().data != nullptr);
3488 Q_ASSERT(key.multi == (it.value().data->type() == QFontEngine::Multi));
3489
3490 // found... update the hitcount and timestamp
3492
3493 return it.value().data;
3494}
3495
3497{
3498 value.hits++;
3499 value.timestamp = ++current_timestamp;
3500
3501 FC_DEBUG("QFontCache: found font engine\n"
3502 " %p: timestamp %4u hits %3u ref %2d/%2d, type %d",
3503 value.data, value.timestamp, value.hits,
3504 value.data->ref.loadRelaxed(), engineCacheCount.value(value.data),
3505 value.data->type());
3506}
3507
3508void QFontCache::insertEngine(const Key &key, QFontEngine *engine, bool insertMulti)
3509{
3510 Q_ASSERT(engine != nullptr);
3511 Q_ASSERT(key.multi == (engine->type() == QFontEngine::Multi));
3512
3513#ifdef QFONTCACHE_DEBUG
3514 FC_DEBUG("QFontCache: inserting new engine %p, refcount %d", engine, engine->ref.loadRelaxed());
3515 if (!insertMulti && engineCache.contains(key)) {
3516 FC_DEBUG(" QFontCache already contains engine %p for key=(%g %g %d %d %d)",
3517 engineCache.value(key).data, key.def.pointSize,
3518 key.def.pixelSize, key.def.weight, key.def.style, key.def.fixedPitch);
3519 }
3520#endif
3521 engine->ref.ref();
3522 // Decrease now rather than waiting
3523 if (total_cost > min_cost * 2 && engineCache.size() >= QFONTCACHE_DECREASE_TRIGGER_LIMIT)
3524 decreaseCache();
3525
3527 data.timestamp = ++current_timestamp;
3528
3529 if (insertMulti)
3531 else
3533 // only increase the cost if this is the first time we insert the engine
3534 if (++engineCacheCount[engine] == 1)
3535 increaseCost(engine->cache_cost);
3536}
3537
3538void QFontCache::increaseCost(uint cost)
3539{
3540 cost = (cost + 512) / 1024; // store cost in kb
3541 cost = cost > 0 ? cost : 1;
3542 total_cost += cost;
3543
3544 FC_DEBUG(" COST: increased %u kb, total_cost %u kb, max_cost %u kb",
3545 cost, total_cost, max_cost);
3546
3547 if (total_cost > max_cost) {
3548 max_cost = total_cost;
3549
3550 if (!autoClean)
3551 return;
3552
3553 if (timer_id == -1 || ! fast) {
3554 FC_DEBUG(" TIMER: starting fast timer (%d s)", static_cast<int>(fast_timeout.count()));
3555
3556 if (timer_id != -1)
3557 killTimer(timer_id);
3558 timer_id = startTimer(fast_timeout);
3559 fast = true;
3560 }
3561 }
3562}
3563
3564void QFontCache::decreaseCost(uint cost)
3565{
3566 cost = (cost + 512) / 1024; // cost is stored in kb
3567 cost = cost > 0 ? cost : 1;
3568 Q_ASSERT(cost <= total_cost);
3569 total_cost -= cost;
3570
3571 FC_DEBUG(" COST: decreased %u kb, total_cost %u kb, max_cost %u kb",
3572 cost, total_cost, max_cost);
3573}
3574
3576{
3577 FC_DEBUG("QFontCache::timerEvent: performing cache maintenance (timestamp %u)",
3578 current_timestamp);
3579
3580 if (total_cost <= max_cost && max_cost <= min_cost) {
3581 FC_DEBUG(" cache redused sufficiently, stopping timer");
3582
3583 killTimer(timer_id);
3584 timer_id = -1;
3585 fast = false;
3586
3587 return;
3588 }
3589 decreaseCache();
3590}
3591
3592void QFontCache::decreaseCache()
3593{
3594 // go through the cache and count up everything in use
3595 uint in_use_cost = 0;
3596
3597 {
3598 FC_DEBUG(" SWEEP engine data:");
3599
3600 // make sure the cost of each engine data is at least 1kb
3601 const uint engine_data_cost =
3602 sizeof(QFontEngineData) > 1024 ? sizeof(QFontEngineData) : 1024;
3603
3606 for (; it != end; ++it) {
3607 FC_DEBUG(" %p: ref %2d", it.value(), int(it.value()->ref.loadRelaxed()));
3608
3609 if (it.value()->ref.loadRelaxed() != 1)
3610 in_use_cost += engine_data_cost;
3611 }
3612 }
3613
3614 {
3615 FC_DEBUG(" SWEEP engine:");
3616
3619 for (; it != end; ++it) {
3620 FC_DEBUG(" %p: timestamp %4u hits %2u ref %2d/%2d, cost %u bytes",
3621 it.value().data, it.value().timestamp, it.value().hits,
3622 it.value().data->ref.loadRelaxed(), engineCacheCount.value(it.value().data),
3623 it.value().data->cache_cost);
3624
3625 if (it.value().data->ref.loadRelaxed() > engineCacheCount.value(it.value().data))
3626 in_use_cost += it.value().data->cache_cost / engineCacheCount.value(it.value().data);
3627 }
3628
3629 // attempt to make up for rounding errors
3630 in_use_cost += engineCache.size();
3631 }
3632
3633 in_use_cost = (in_use_cost + 512) / 1024; // cost is stored in kb
3634
3635 /*
3636 calculate the new maximum cost for the cache
3637
3638 NOTE: in_use_cost is *not* correct due to rounding errors in the
3639 above algorithm. instead of worrying about getting the
3640 calculation correct, we are more interested in speed, and use
3641 in_use_cost as a floor for new_max_cost
3642 */
3643 uint new_max_cost = qMax(qMax(max_cost / 2, in_use_cost), min_cost);
3644
3645 FC_DEBUG(" after sweep, in use %u kb, total %u kb, max %u kb, new max %u kb",
3646 in_use_cost, total_cost, max_cost, new_max_cost);
3647
3648 if (autoClean) {
3649 if (new_max_cost == max_cost) {
3650 if (fast) {
3651 FC_DEBUG(" cannot shrink cache, slowing timer");
3652
3653 if (timer_id != -1) {
3654 killTimer(timer_id);
3655 timer_id = startTimer(slow_timeout);
3656 fast = false;
3657 }
3658
3659 return;
3660 } else if (! fast) {
3661 FC_DEBUG(" dropping into passing gear");
3662
3663 if (timer_id != -1)
3664 killTimer(timer_id);
3665 timer_id = startTimer(fast_timeout);
3666 fast = true; }
3667 }
3668 }
3669
3670 max_cost = new_max_cost;
3671
3672 {
3673 FC_DEBUG(" CLEAN engine data:");
3674
3675 // clean out all unused engine data
3677 while (it != engineDataCache.end()) {
3678 if (it.value()->ref.loadRelaxed() == 1) {
3679 FC_DEBUG(" %p", it.value());
3680 decreaseCost(sizeof(QFontEngineData));
3681 it.value()->ref.deref();
3682 delete it.value();
3684 } else {
3685 ++it;
3686 }
3687 }
3688 }
3689
3690 FC_DEBUG(" CLEAN engine:");
3691
3692 // clean out the engine cache just enough to get below our new max cost
3693 bool cost_decreased;
3694 do {
3695 cost_decreased = false;
3696
3698 end = engineCache.end();
3699 // determine the oldest and least popular of the unused engines
3700 uint oldest = ~0u;
3701 uint least_popular = ~0u;
3702
3704
3705 for ( ; it != end; ++it) {
3706 if (it.value().data->ref.loadRelaxed() != engineCacheCount.value(it.value().data))
3707 continue;
3708
3709 if (it.value().timestamp < oldest && it.value().hits <= least_popular) {
3710 oldest = it.value().timestamp;
3711 least_popular = it.value().hits;
3712 jt = it;
3713 }
3714 }
3715
3716 it = jt;
3717 if (it != end) {
3718 FC_DEBUG(" %p: timestamp %4u hits %2u ref %2d/%2d, type %d",
3719 it.value().data, it.value().timestamp, it.value().hits,
3720 it.value().data->ref.loadRelaxed(), engineCacheCount.value(it.value().data),
3721 it.value().data->type());
3722
3723 QFontEngine *fontEngine = it.value().data;
3724 // get rid of all occurrences
3725 it = engineCache.begin();
3726 while (it != engineCache.end()) {
3727 if (it.value().data == fontEngine) {
3728 fontEngine->ref.deref();
3730 } else {
3731 ++it;
3732 }
3733 }
3734 // and delete the last occurrence
3735 Q_ASSERT(fontEngine->ref.loadRelaxed() == 0);
3736 decreaseCost(fontEngine->cache_cost);
3737 delete fontEngine;
3738 engineCacheCount.remove(fontEngine);
3739
3740 cost_decreased = true;
3741 }
3742 } while (cost_decreased && total_cost > max_cost);
3743}
3744
3745
3746#ifndef QT_NO_DEBUG_STREAM
3748{
3749 QDebugStateSaver saver(stream);
3750 stream.nospace().noquote();
3751 stream << "QFont(";
3752
3753 if (stream.verbosity() == QDebug::DefaultVerbosity) {
3754 stream << font.toString() << ")";
3755 return stream;
3756 }
3757
3758 QString fontDescription;
3759 QDebug debug(&fontDescription);
3760 debug.nospace();
3761
3762 const QFont defaultFont(new QFontPrivate);
3763
3764 for (int property = QFont::SizeResolved; property < QFont::AllPropertiesResolved; property <<= 1) {
3765 const bool resolved = (font.resolve_mask & property) != 0;
3766 if (!resolved && stream.verbosity() == QDebug::MinimumVerbosity)
3767 continue;
3768
3769 #define QFONT_DEBUG_SKIP_DEFAULT(prop) \
3770 if ((font.prop() == defaultFont.prop()) && stream.verbosity() == 1) \
3771 continue;
3772
3773 QDebugStateSaver saver(debug);
3774
3775 switch (property) {
3777 if (font.pointSizeF() >= 0)
3778 debug << font.pointSizeF() << "pt";
3779 else if (font.pixelSize() >= 0)
3780 debug << font.pixelSize() << "px";
3781 else
3782 Q_UNREACHABLE();
3783 break;
3785 QFONT_DEBUG_SKIP_DEFAULT(styleHint);
3786 debug.verbosity(1) << font.styleHint(); break;
3788 QFONT_DEBUG_SKIP_DEFAULT(styleStrategy);
3789 debug.verbosity(1) << font.styleStrategy(); break;
3791 debug.verbosity(1) << QFont::Weight(font.weight()); break;
3794 debug.verbosity(0) << font.style(); break;
3796 QFONT_DEBUG_SKIP_DEFAULT(underline);
3797 debug << "underline=" << font.underline(); break;
3799 QFONT_DEBUG_SKIP_DEFAULT(overline);
3800 debug << "overline=" << font.overline(); break;
3802 QFONT_DEBUG_SKIP_DEFAULT(strikeOut);
3803 debug << "strikeOut=" << font.strikeOut(); break;
3805 QFONT_DEBUG_SKIP_DEFAULT(fixedPitch);
3806 debug << "fixedPitch=" << font.fixedPitch(); break;
3808 QFONT_DEBUG_SKIP_DEFAULT(stretch);
3809 debug.verbosity(0) << QFont::Stretch(font.stretch()); break;
3812 debug << "kerning=" << font.kerning(); break;
3814 QFONT_DEBUG_SKIP_DEFAULT(capitalization);
3815 debug.verbosity(0) << font.capitalization(); break;
3817 QFONT_DEBUG_SKIP_DEFAULT(letterSpacing);
3818 debug << "letterSpacing=" << font.letterSpacing();
3819 debug.verbosity(0) << " (" << font.letterSpacingType() << ")";
3820 break;
3822 QFONT_DEBUG_SKIP_DEFAULT(hintingPreference);
3823 debug.verbosity(0) << font.hintingPreference(); break;
3825 QFONT_DEBUG_SKIP_DEFAULT(styleName);
3826 debug << "styleName=" << font.styleName(); break;
3827 default:
3828 continue;
3829 };
3830
3831 #undef QFONT_DEBUG_SKIP_DEFAULT
3832
3833 debug << ", ";
3834 }
3835
3836 if (stream.verbosity() > QDebug::MinimumVerbosity)
3837 debug.verbosity(0) << "resolveMask=" << QFlags<QFont::ResolveProperties>(font.resolve_mask);
3838 else
3839 fontDescription.chop(2); // Last ', '
3840
3841 stream << fontDescription << ')';
3842
3843 return stream;
3844}
3845
3847{
3848 QDebugStateSaver saver(debug);
3849 debug.noquote() << tag.toString();
3850 return debug;
3851}
3852#endif
3853
3855
3856#include "moc_qfont.cpp"
\inmodule QtCore
bool ref() noexcept
bool deref() noexcept
T loadRelaxed() const noexcept
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
\inmodule QtCore\reentrant
Definition qdatastream.h:47
\inmodule QtCore
\inmodule QtCore
void detach()
If the shared data object's reference count is greater than 1, this function creates a deep copy of t...
T * data() const noexcept
Returns a pointer to the shared data object.
static void cleanup()
Definition qfont.cpp:3361
void insertEngineData(const QFontDef &def, QFontEngineData *engineData)
Definition qfont.cpp:3460
EngineDataCache engineDataCache
Definition qfont_p.h:256
void clear()
Definition qfont.cpp:3390
QFontEngine * findEngine(const Key &key)
Definition qfont.cpp:3481
QFontEngineData * findEngineData(const QFontDef &def) const
Definition qfont.cpp:3450
EngineCache engineCache
Definition qfont_p.h:272
void timerEvent(QTimerEvent *event) override
This event handler can be reimplemented in a subclass to receive timer events for the object.
Definition qfont.cpp:3575
static QFontCache * instance()
Definition qfont.cpp:3353
void updateHitCountAndTimeStamp(Engine &value)
Definition qfont.cpp:3496
void insertEngine(const Key &key, QFontEngine *engine, bool insertMulti=false)
Definition qfont.cpp:3508
QHash< QFontEngine *, int > engineCacheCount
Definition qfont_p.h:273
static void parseFontName(const QString &name, QString &foundry, QString &family)
static void load(const QFontPrivate *d, int script)
QAtomicInt ref
Definition qfont_p.h:152
QFontEngine * engines[QChar::ScriptCount]
Definition qfont_p.h:155
const int fontCacheId
Definition qfont_p.h:153
QAtomicInt ref
\reentrant
Definition qfontinfo.h:16
qreal pointSizeF() const
Returns the point size of the matched window system font.
Definition qfont.cpp:3148
int pointSize() const
Returns the point size of the matched window system font.
Definition qfont.cpp:3136
int pixelSize() const
Returns the pixel size of the matched window system font.
Definition qfont.cpp:3160
QString family() const
Returns the family name of the matched window system font.
Definition qfont.cpp:3109
bool italic() const
Returns the italic value of the matched window system font.
Definition qfont.cpp:3172
QFontInfo & operator=(const QFontInfo &)
Assigns the font info in fi.
Definition qfont.cpp:3090
QString styleName() const
Definition qfont.cpp:3124
bool fixedPitch() const
Returns the fixed pitch value of the matched window system font.
Definition qfont.cpp:3283
QFontInfo(const QFont &)
Constructs a font info object for font.
Definition qfont.cpp:3067
QFont::StyleHint styleHint() const
Returns the style of the matched window system font.
Definition qfont.cpp:3309
bool strikeOut() const
Returns the strikeout value of the matched window system font.
Definition qfont.cpp:3273
bool overline() const
Returns the overline value of the matched window system font.
Definition qfont.cpp:3260
QFont::Style style() const
Returns the style value of the matched window system font.
Definition qfont.cpp:3184
int weight() const
Returns the weight of the matched window system font.
Definition qfont.cpp:3218
~QFontInfo()
Destroys the font info object.
Definition qfont.cpp:3083
bool exactMatch() const
Returns true if the matched window system font is exactly the same as the one specified by the font; ...
Definition qfont.cpp:3322
bool underline() const
Returns the underline value of the matched window system font.
Definition qfont.cpp:3245
void unsetFeature(QFont::Tag tag)
Definition qfont.cpp:377
bool letterSpacingIsAbsolute
Definition qfont_p.h:183
uint overline
Definition qfont_p.h:179
uint strikeOut
Definition qfont_p.h:180
QAtomicInt ref
Definition qfont_p.h:173
QFontDef request
Definition qfont_p.h:174
static QFontPrivate * get(const QFont &font)
Definition qfont_p.h:193
QFontPrivate * smallCapsFontPrivate() const
Definition qfont.cpp:271
bool hasVariableAxis(QFont::Tag tag, float value) const
Definition qfont.cpp:357
uint underline
Definition qfont_p.h:178
QFontEngine * engineForScript(int script) const
Definition qfont.cpp:241
QFixed wordSpacing
Definition qfont_p.h:186
uint kerning
Definition qfont_p.h:181
QFixed letterSpacing
Definition qfont_p.h:185
void resolve(uint mask, const QFontPrivate *other)
Definition qfont.cpp:288
void unsetVariableAxis(QFont::Tag tag)
Definition qfont.cpp:367
void setFeature(QFont::Tag tag, quint32 value)
Definition qfont.cpp:372
QFontEngineData * engineData
Definition qfont_p.h:175
void setVariableAxis(QFont::Tag tag, float value)
Definition qfont.cpp:362
uint capital
Definition qfont_p.h:182
QFontPrivate * scFont
Definition qfont_p.h:189
QHash< QFont::Tag, quint32 > features
Definition qfont_p.h:187
void alterCharForCapitalization(QChar &c) const
Definition qfont.cpp:257
static void detachButKeepEngineData(QFont *font)
Definition qfont.cpp:668
\reentrant
Definition qfont.h:22
static QStringList substitutes(const QString &)
Returns a list of family names to be used whenever familyName is specified.
Definition qfont.cpp:1975
StyleHint
Style hints are used by the \l{QFont}{font matching} algorithm to find an appropriate default family ...
Definition qfont.h:25
void setStyle(Style style)
Sets the style of the font to style.
Definition qfont.cpp:1116
QString family() const
Returns the requested font family name.
Definition qfont.cpp:817
static void initialize()
Definition qfont.cpp:2267
StyleStrategy styleStrategy() const
Returns the StyleStrategy.
Definition qfont.cpp:1394
void setPointSize(int)
Sets the point size to pointSize.
Definition qfont.cpp:985
static void cacheStatistics()
Definition qfont.cpp:2285
void setOverline(bool)
If enable is true, sets overline on; otherwise sets overline off.
Definition qfont.cpp:1288
QString styleName() const
Definition qfont.cpp:849
void setStrikeOut(bool)
If enable is true, sets strikeout on; otherwise sets strikeout off.
Definition qfont.cpp:1315
void clearFeatures()
Definition qfont.cpp:2677
static void cleanup()
Definition qfont.cpp:2276
bool isCopyOf(const QFont &) const
Returns true if this font and f are copies of each other, i.e.
Definition qfont.cpp:1901
int pixelSize() const
Returns the pixel size of the font if it was set with setPixelSize().
Definition qfont.cpp:1074
bool italic() const
Returns true if the style() of the font is not QFont::StyleNormal.
Definition qfont.h:377
QFont()
Constructs a font object that uses the application's default font.
Definition qfont.cpp:685
friend class QFontPrivate
Definition qfont.h:327
StyleHint styleHint() const
Returns the StyleHint.
Definition qfont.cpp:1407
bool fromString(const QString &)
Sets this font to match the description descrip.
Definition qfont.cpp:2207
bool strikeOut() const
Returns true if strikeout has been set; otherwise returns false.
Definition qfont.cpp:1304
size_t qHash(const QFont &font, size_t seed) noexcept
Returns the hash value for font.
Definition qfont.cpp:2194
bool underline() const
Returns true if underline has been set; otherwise returns false.
Definition qfont.cpp:1251
Capitalization
Definition qfont.h:98
@ AllLowercase
Definition qfont.h:101
@ AllUppercase
Definition qfont.h:100
@ MixedCase
Definition qfont.h:99
@ SmallCaps
Definition qfont.h:102
void setFamilies(const QStringList &)
Definition qfont.cpp:2738
bool operator!=(const QFont &) const
Returns true if this font is different from f; otherwise returns false.
Definition qfont.cpp:1881
void setCapitalization(Capitalization)
Definition qfont.cpp:1742
QString toString() const
Returns a description of the font.
Definition qfont.cpp:2160
qreal letterSpacing() const
Definition qfont.cpp:1638
void setWordSpacing(qreal spacing)
Definition qfont.cpp:1707
void setFixedPitch(bool)
If enable is true, sets fixed pitch on; otherwise sets fixed pitch off.
Definition qfont.cpp:1342
void setFamily(const QString &)
Sets the family name of the font.
Definition qfont.cpp:835
void setStyleStrategy(StyleStrategy s)
Sets the style strategy for the font to s.
Definition qfont.cpp:1543
bool exactMatch() const
Returns true if a window system font exactly matching the settings of this font is available.
Definition qfont.cpp:1771
QFont resolve(const QFont &) const
Returns a new QFont that has attributes copied from other that have not been previously set on this f...
Definition qfont.cpp:1910
static void insertSubstitution(const QString &, const QString &)
Inserts substituteName into the substitution table for the family familyName.
Definition qfont.cpp:1992
bool isVariableAxisSet(Tag tag) const
Definition qfont.cpp:2531
HintingPreference hintingPreference() const
Definition qfont.cpp:974
quint32 featureValue(Tag tag) const
Definition qfont.cpp:2648
QList< Tag > featureTags() const
Definition qfont.cpp:2633
SpacingType
Definition qfont.h:107
@ AbsoluteSpacing
Definition qfont.h:109
@ PercentageSpacing
Definition qfont.h:108
bool operator<(const QFont &) const
Provides an arbitrary comparison of this font and font f.
Definition qfont.cpp:1816
Capitalization capitalization() const
Definition qfont.cpp:1760
static void removeSubstitutions(const QString &)
Removes all the substitutions for familyName.
Definition qfont.cpp:2033
QList< Tag > variableAxisTags() const
Definition qfont.cpp:2501
QStringList families() const
Definition qfont.cpp:2716
Weight weight() const
Returns the weight of the font, using the same scale as the \l{QFont::Weight} enumeration.
Definition qfont.cpp:1133
@ StretchResolved
Definition qfont.h:125
@ LetterSpacingResolved
Definition qfont.h:128
@ SizeResolved
Definition qfont.h:116
@ OverlineResolved
Definition qfont.h:122
@ UnderlineResolved
Definition qfont.h:121
@ StyleHintResolved
Definition qfont.h:117
@ StyleNameResolved
Definition qfont.h:131
@ AllPropertiesResolved
Definition qfont.h:135
@ StrikeOutResolved
Definition qfont.h:123
@ KerningResolved
Definition qfont.h:126
@ FeaturesResolved
Definition qfont.h:133
@ WeightResolved
Definition qfont.h:119
@ VariableAxesResolved
Definition qfont.h:134
@ CapitalizationResolved
Definition qfont.h:127
@ HintingPreferenceResolved
Definition qfont.h:130
@ FixedPitchResolved
Definition qfont.h:124
@ WordSpacingResolved
Definition qfont.h:129
@ StyleStrategyResolved
Definition qfont.h:118
@ StyleResolved
Definition qfont.h:120
@ FamiliesResolved
Definition qfont.h:132
void setLetterSpacing(SpacingType type, qreal spacing)
Definition qfont.cpp:1655
void unsetVariableAxis(Tag tag)
Definition qfont.cpp:2482
qreal wordSpacing() const
Definition qfont.cpp:1688
int pointSize() const
Returns the point size of the font.
Definition qfont.cpp:884
void setKerning(bool)
Enables kerning for this font if enable is true; otherwise disables it.
Definition qfont.cpp:1375
int stretch() const
Returns the stretch factor for the font.
Definition qfont.cpp:1581
static QStringList substitutions()
Returns a sorted list of substituted family names.
Definition qfont.cpp:2045
bool kerning() const
Returns true if kerning should be used when drawing text with this font.
Definition qfont.cpp:1359
QString defaultFamily() const
Returns the family name that corresponds to the current style hint.
Definition qfont.cpp:2697
QString key() const
Returns the font's key, a textual representation of a font.
Definition qfont.cpp:2129
void setPixelSize(int)
Sets the font size to pixelSize pixels, with a maxiumum size of an unsigned 16-bit integer.
Definition qfont.cpp:1049
bool isFeatureSet(Tag tag) const
Definition qfont.cpp:2663
bool operator==(const QFont &) const
Returns true if this font is equal to f; otherwise returns false.
Definition qfont.cpp:1787
void setHintingPreference(HintingPreference hintingPreference)
Definition qfont.cpp:957
void setItalic(bool b)
Sets the style() of the font to QFont::StyleItalic if enable is true; otherwise the style is set to Q...
Definition qfont.h:382
bool fixedPitch() const
Returns true if fixed pitch has been set; otherwise returns false.
Definition qfont.cpp:1331
void setUnderline(bool)
If enable is true, sets underline on; otherwise sets underline off.
Definition qfont.cpp:1262
void setStyleHint(StyleHint, StyleStrategy=PreferDefault)
Sets the style hint and strategy to hint and strategy, respectively.
Definition qfont.cpp:1522
HintingPreference
Definition qfont.h:56
void unsetFeature(Tag tag)
Definition qfont.cpp:2615
QFont & operator=(const QFont &)
Move-assigns other to this QFont instance.
Definition qfont.cpp:796
void setVariableAxis(Tag tag, float value)
Definition qfont.cpp:2459
qreal pointSizeF() const
Returns the point size of the font.
Definition qfont.cpp:1034
void setStyleName(const QString &)
Definition qfont.cpp:867
void setStretch(int)
Sets the stretch factor for the font.
Definition qfont.cpp:1605
SpacingType letterSpacingType() const
Definition qfont.cpp:1677
void clearVariableAxes()
Definition qfont.cpp:2545
void setFeature(Tag tag, quint32 value)
Definition qfont.cpp:2591
Stretch
Predefined stretch values that follow the CSS naming convention.
Definition qfont.h:84
Style style() const
Returns the style of the font.
Definition qfont.cpp:1105
StyleStrategy
The style strategy tells the \l{QFont}{font matching} algorithm what type of fonts should be used to ...
Definition qfont.h:38
@ PreferDefault
Definition qfont.h:39
void setPointSizeF(qreal)
Sets the point size to pointSize.
Definition qfont.cpp:1010
Weight
Qt uses a weighting scale from 1 to 1000 compatible with OpenType.
Definition qfont.h:64
@ DemiBold
Definition qfont.h:70
@ Thin
Definition qfont.h:65
@ ExtraBold
Definition qfont.h:72
@ Black
Definition qfont.h:73
@ Bold
Definition qfont.h:71
@ ExtraLight
Definition qfont.h:66
@ Normal
Definition qfont.h:68
@ Light
Definition qfont.h:67
@ Medium
Definition qfont.h:69
float variableAxisValue(Tag tag) const
Definition qfont.cpp:2516
void setWeight(Weight weight)
Sets the weight of the font to weight, using the scale defined by \l QFont::Weight enumeration.
Definition qfont.cpp:1205
bool overline() const
Returns true if overline has been set; otherwise returns false.
Definition qfont.cpp:1278
~QFont()
Destroys the font object and frees all allocated resources.
Definition qfont.cpp:789
Style
This enum describes the different styles of glyphs that are used to display text.
Definition qfont.h:77
@ StyleItalic
Definition qfont.h:79
@ StyleNormal
Definition qfont.h:78
@ StyleOblique
Definition qfont.h:80
static void insertSubstitutions(const QString &, const QStringList &)
Inserts the list of families substituteNames into the substitution list for familyName.
Definition qfont.cpp:2014
\macro qGuiApp
QScreen * primaryScreen
the primary (or default) screen of the application.
bool remove(const Key &key)
Removes the item that has the key from the hash.
Definition qhash.h:959
qsizetype size() const noexcept
Returns the number of items in the hash.
Definition qhash.h:928
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
Definition qhash.h:1220
const_iterator constBegin() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
Definition qhash.h:1216
QList< Key > keys() const
Returns a list containing all the keys in the hash, in an arbitrary order.
Definition qhash.h:1087
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:1008
T value(const Key &key) const noexcept
Definition qhash.h:1055
const_iterator ConstIterator
Qt-style synonym for QHash::const_iterator.
Definition qhash.h:1290
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
Definition qhash.h:952
bool isEmpty() const noexcept
Returns true if the hash contains no items; otherwise returns false.
Definition qhash.h:929
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1304
qsizetype size() const noexcept
Definition qlist.h:398
const_reference at(qsizetype i) const noexcept
Definition qlist.h:447
void append(parameter_type t)
Definition qlist.h:459
iterator insert(const Key &key, const T &value)
Definition qmap.h:689
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:358
iterator erase(const_iterator it)
Definition qmap.h:620
bool contains(const Key &key) const
Definition qmap.h:342
size_type remove(const Key &key)
Definition qmap.h:301
const_iterator constFind(const Key &key) const
Definition qmap.h:656
void clear()
Definition qmap.h:290
QList< Key > keys() const
Definition qmap.h:384
bool isEmpty() const
Definition qmap.h:270
iterator begin()
Definition qmap.h:599
iterator end()
Definition qmap.h:603
const_iterator constBegin() const
Definition qmap.h:601
size_type size() const
Definition qmap.h:268
const_iterator constEnd() const
Definition qmap.h:605
iterator replace(const Key &key, const T &value)
Definition qmap.h:1502
const_iterator constEnd() const
Definition qmap.h:1330
bool contains(const Key &key) const
Definition qmap.h:1046
iterator end()
Definition qmap.h:1328
const_iterator ConstIterator
Definition qmap.h:1365
iterator find(const Key &key)
Definition qmap.h:1372
iterator insert(const Key &key, const T &value)
Definition qmap.h:1453
iterator erase(const_iterator it)
Definition qmap.h:1345
size_type size() const
Definition qmap.h:939
const_iterator constBegin() const
Definition qmap.h:1326
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:1067
void clear()
Definition qmap.h:961
iterator begin()
Definition qmap.h:1324
\inmodule QtCore
Definition qmutex.h:313
\inmodule QtCore
Definition qobject.h:103
int startTimer(int interval, Qt::TimerType timerType=Qt::CoarseTimer)
This is an overloaded function that will start a timer of type timerType and a timeout of interval mi...
Definition qobject.cpp:1817
void killTimer(int id)
Kills the timer with timer identifier, id.
Definition qobject.cpp:1912
int logicalDpiY() const
constexpr QSize size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:242
\inmodule QtCore
Definition qmutex.h:309
The QScreen class is used to query screen properties. \inmodule QtGui.
Definition qscreen.h:32
qreal logicalDotsPerInchY
the number of logical dots or pixels per inch in the vertical direction
Definition qscreen.h:57
qreal logicalDotsPerInchX
the number of logical dots or pixels per inch in the horizontal direction
Definition qscreen.h:56
const_iterator constEnd() const noexcept
Definition qset.h:144
const_iterator constFind(const T &value) const
Definition qset.h:162
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:78
Q_CORE_EXPORT QList< QStringView > split(QStringView sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the view into substring views wherever sep occurs, and returns the list of those string views.
Definition qstring.cpp:8260
QStringView trimmed() const noexcept
Strips leading and trailing whitespace and returns the result.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5465
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5881
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
Definition qstring.cpp:8229
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5307
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1252
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition qstring.cpp:5516
QString toLower() const &
Definition qstring.h:435
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8095
\inmodule QtCore
Definition qcoreevent.h:366
\inmodule QtCore
Definition qvariant.h:65
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:537
QString str
[2]
qreal spacing
QCache< int, Employee > cache
[0]
QSet< QString >::iterator it
Combined button and popup list for selecting options.
@ AA_Use96Dpi
Definition qnamespace.h:433
#define Q_BASIC_ATOMIC_INITIALIZER(a)
QList< QString > QStringList
Constructs a string list that contains the given string, str.
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define QT_CATCH(A)
#define QT_TRY
size_t qHash(const QFileSystemWatcherPathKey &key, size_t seed=0)
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
Q_GUI_EXPORT int qt_openTypeToLegacyWeight(int weight)
Definition qfont.cpp:201
static void set_font_bits(int version, quint8 bits, QFontPrivate *f)
Definition qfont.cpp:2100
QRecursiveMutex * qt_fontdatabase_mutex()
static int convertWeights(int weight, bool inverted)
Definition qfont.cpp:146
Q_GUI_EXPORT int qt_defaultDpiX()
Definition qfont.cpp:110
static QStringList splitIntoFamilies(const QString &family)
Definition qfont.cpp:175
#define FC_DEBUG
Definition qfont.cpp:40
Q_GUI_EXPORT int qt_legacyToOpenTypeWeight(int weight)
Definition qfont.cpp:195
Q_GUI_EXPORT int qt_defaultDpi()
Definition qfont.cpp:140
static constexpr auto slow_timeout
Definition qfont.cpp:3344
QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
static constexpr auto fast_timeout
Definition qfont.cpp:3343
#define QFONT_DEBUG_SKIP_DEFAULT(prop)
#define QFONTCACHE_MIN_COST
Definition qfont.cpp:3348
#define QT_FONT_ENGINE_FROM_DATA(data, script)
Definition qfont.cpp:239
Q_GUI_EXPORT int qt_defaultDpiY()
Definition qfont.cpp:125
bool qt_is_tty_app
static quint8 get_extended_font_bits(const QFontPrivate *f)
Definition qfont.cpp:2085
static Q_CONSTINIT QBasicAtomicInt font_cache_id
Definition qfont.cpp:3373
#define QFONTCACHE_DECREASE_TRIGGER_LIMIT
Definition qfont.cpp:46
QDataStream & operator>>(QDataStream &stream, QFont::Tag &tag)
Definition qfont.cpp:2958
QDataStream & operator<<(QDataStream &stream, QFont::Tag tag)
Definition qfont.cpp:2952
QHash< QString, QStringList > QFontSubst
Definition qfont.cpp:1940
static quint8 get_font_bits(int version, const QFontPrivate *f)
Definition qfont.cpp:2060
static void set_extended_font_bits(quint8 bits, QFontPrivate *f)
Definition qfont.cpp:2115
#define QFONT_WEIGHT_MIN
Definition qfont_p.h:33
#define QFONT_WEIGHT_MAX
Definition qfont_p.h:34
static QStringList familyList(const QFontDef &req)
static QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs)
quint32 Tag
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qWarning
Definition qlogging.h:167
return ret
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:23
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:21
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
GLuint64 key
GLuint GLuint end
GLenum GLuint id
[7]
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLuint GLuint GLfloat weight
GLenum type
GLboolean enable
GLenum const void GLbitfield fontStyle
GLboolean GLboolean g
GLint ref
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
GLuint64EXT * result
[6]
GLenum GLenum GLenum GLenum mapping
static qsizetype cost(const QPixmap &pixmap)
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static QT_BEGIN_NAMESPACE QVariant hint(QPlatformIntegration::StyleHint h)
QScreen * screen
[1]
Definition main.cpp:29
unsigned int quint32
Definition qtypes.h:50
short qint16
Definition qtypes.h:47
unsigned short quint16
Definition qtypes.h:48
int qint32
Definition qtypes.h:49
unsigned int uint
Definition qtypes.h:34
double qreal
Definition qtypes.h:187
unsigned char quint8
Definition qtypes.h:46
static int toInt(const QChar &qc, int R)
static double toDouble(Value v)
const char property[13]
Definition qwizard.cpp:100
QList< int > list
[14]
std::uniform_real_distribution dist(1, 2.5)
[2]
QObject::connect nullptr
QRect r1(100, 200, 11, 16)
[0]
QRect r2(QPoint(100, 200), QSize(11, 16))
QSharedPointer< T > other(t)
[5]
QNetworkRequest request(url)
QQuickView * view
[0]
QJSEngine engine
[0]
static constexpr QFixed fromReal(qreal r)
Definition qfixed_p.h:35
constexpr int value() const
Definition qfixed_p.h:38
void setValue(int value)
Definition qfixed_p.h:39
constexpr qreal toReal() const
Definition qfixed_p.h:42
QFontEngine * data
Definition qfont_p.h:266
uint hintingPreference
Definition qfont_p.h:67
uint stretch
Definition qfont_p.h:65
uint style
Definition qfont_p.h:66
uint styleStrategy
Definition qfont_p.h:64
uint fixedPitch
Definition qfont_p.h:71
qreal pixelSize
Definition qfont_p.h:61
QMap< QFont::Tag, float > variableAxisValues
Definition qfont_p.h:58
uint ignorePitch
Definition qfont_p.h:72
uint weight
Definition qfont_p.h:70
QStringList families
Definition qfont_p.h:54
QString styleName
Definition qfont_p.h:55
bool exactMatch(const QFontDef &other) const
Definition qfont.cpp:49
uint styleHint
Definition qfont_p.h:69
qreal pointSize
Definition qfont_p.h:60
The QFont::Tag type provides access to advanced font features.
Definition qfont.h:216
static Q_GUI_EXPORT std::optional< Tag > fromString(QAnyStringView view) noexcept
Returns a tag constructed from the string in view.
Definition qfont.cpp:2393
QByteArray toString() const
Returns the string representation of this tag as a byte array.
Definition qfont.h:230
static constexpr std::optional< Tag > fromValue(quint32 value) noexcept
Returns a tag constructed from value, or std::nullopt if the tag produced would be invalid.
Definition qfont.h:240
constexpr quint32 value() const noexcept
Returns the numerical value of this tag.
Definition qfont.h:228
constexpr bool isValid() const noexcept
Returns whether the tag is valid.
Definition qfont.h:227
bool contains(const AT &t) const noexcept
Definition qlist.h:46