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
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
1506{
1507 if ((resolve_mask & (QFont::StyleHintResolved | QFont::StyleStrategyResolved)) &&
1508 (StyleHint) d->request.styleHint == hint &&
1509 (StyleStrategy) d->request.styleStrategy == strategy)
1510 return;
1511
1512 detach();
1513
1514 d->request.styleHint = hint;
1515 d->request.styleStrategy = strategy;
1516 resolve_mask |= QFont::StyleHintResolved;
1517 resolve_mask |= QFont::StyleStrategyResolved;
1518
1519}
1520
1527{
1528 if ((resolve_mask & QFont::StyleStrategyResolved) &&
1530 return;
1531
1532 detach();
1533
1534 d->request.styleStrategy = s;
1535 resolve_mask |= QFont::StyleStrategyResolved;
1536}
1537
1538
1565{
1566 return d->request.stretch;
1567}
1568
1588void QFont::setStretch(int factor)
1589{
1590 if (factor < 0 || factor > 4000) {
1591 qWarning("QFont::setStretch: Parameter '%d' out of range", factor);
1592 return;
1593 }
1594
1595 if ((resolve_mask & QFont::StretchResolved) &&
1596 d->request.stretch == (uint)factor)
1597 return;
1598
1599 detach();
1600
1601 d->request.stretch = (uint)factor;
1602 resolve_mask |= QFont::StretchResolved;
1603}
1604
1622{
1623 return d->letterSpacing.toReal();
1624}
1625
1639{
1640 const QFixed newSpacing = QFixed::fromReal(spacing);
1641 const bool absoluteSpacing = type == AbsoluteSpacing;
1642 if ((resolve_mask & QFont::LetterSpacingResolved) &&
1643 d->letterSpacingIsAbsolute == absoluteSpacing &&
1644 d->letterSpacing == newSpacing)
1645 return;
1646
1648
1649 d->letterSpacing = newSpacing;
1650 d->letterSpacingIsAbsolute = absoluteSpacing;
1651 resolve_mask |= QFont::LetterSpacingResolved;
1652}
1653
1664
1672{
1673 return d->wordSpacing.toReal();
1674}
1675
1691{
1692 const QFixed newSpacing = QFixed::fromReal(spacing);
1693 if ((resolve_mask & QFont::WordSpacingResolved) &&
1694 d->wordSpacing == newSpacing)
1695 return;
1696
1698
1699 d->wordSpacing = newSpacing;
1700 resolve_mask |= QFont::WordSpacingResolved;
1701}
1702
1726{
1727 if ((resolve_mask & QFont::CapitalizationResolved) &&
1728 capitalization() == caps)
1729 return;
1730
1732
1733 d->capital = caps;
1734 resolve_mask |= QFont::CapitalizationResolved;
1735}
1736
1744{
1745 return static_cast<QFont::Capitalization> (d->capital);
1746}
1747
1755{
1756 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
1757 Q_ASSERT(engine != nullptr);
1758 return d->request.exactMatch(engine->fontDef);
1759}
1760
1770bool QFont::operator==(const QFont &f) const
1771{
1772 return (f.d == d
1773 || (f.d->request == d->request
1774 && f.d->request.pointSize == d->request.pointSize
1775 && f.d->underline == d->underline
1776 && f.d->overline == d->overline
1777 && f.d->strikeOut == d->strikeOut
1778 && f.d->kerning == d->kerning
1779 && f.d->capital == d->capital
1780 && f.d->letterSpacingIsAbsolute == d->letterSpacingIsAbsolute
1781 && f.d->letterSpacing == d->letterSpacing
1782 && f.d->wordSpacing == d->wordSpacing
1783 && f.d->features == d->features
1784 ));
1785}
1786
1787
1799bool QFont::operator<(const QFont &f) const
1800{
1801 if (f.d == d) return false;
1802 // the < operator for fontdefs ignores point sizes.
1803 const QFontDef &r1 = f.d->request;
1804 const QFontDef &r2 = d->request;
1805 if (r1.pointSize != r2.pointSize) return r1.pointSize < r2.pointSize;
1806 if (r1.pixelSize != r2.pixelSize) return r1.pixelSize < r2.pixelSize;
1807 if (r1.weight != r2.weight) return r1.weight < r2.weight;
1808 if (r1.style != r2.style) return r1.style < r2.style;
1809 if (r1.stretch != r2.stretch) return r1.stretch < r2.stretch;
1810 if (r1.styleHint != r2.styleHint) return r1.styleHint < r2.styleHint;
1811 if (r1.styleStrategy != r2.styleStrategy) return r1.styleStrategy < r2.styleStrategy;
1812 if (r1.families != r2.families) return r1.families < r2.families;
1813 if (f.d->capital != d->capital) return f.d->capital < d->capital;
1814
1815 if (f.d->letterSpacingIsAbsolute != d->letterSpacingIsAbsolute) return f.d->letterSpacingIsAbsolute < d->letterSpacingIsAbsolute;
1816 if (f.d->letterSpacing != d->letterSpacing) return f.d->letterSpacing < d->letterSpacing;
1817 if (f.d->wordSpacing != d->wordSpacing) return f.d->wordSpacing < d->wordSpacing;
1818
1819 int f1attrs = (f.d->underline << 3) + (f.d->overline << 2) + (f.d->strikeOut<<1) + f.d->kerning;
1820 int f2attrs = (d->underline << 3) + (d->overline << 2) + (d->strikeOut<<1) + d->kerning;
1821 if (f1attrs != f2attrs) return f1attrs < f2attrs;
1822
1823 if (d->features.size() != f.d->features.size())
1824 return f.d->features.size() < d->features.size();
1825
1826 {
1827 auto it = d->features.constBegin();
1828 auto jt = f.d->features.constBegin();
1829 for (; it != d->features.constEnd(); ++it, ++jt) {
1830 if (it.key() != jt.key())
1831 return jt.key() < it.key();
1832 if (it.value() != jt.value())
1833 return jt.value() < it.value();
1834 }
1835 }
1836
1837 if (r1.variableAxisValues.size() != r2.variableAxisValues.size())
1838 return r1.variableAxisValues.size() < r2.variableAxisValues.size();
1839
1840 {
1841 auto it = r1.variableAxisValues.constBegin();
1842 auto jt = r2.variableAxisValues.constBegin();
1843 for (; it != r1.variableAxisValues.constEnd(); ++it, ++jt) {
1844 if (it.key() != jt.key())
1845 return jt.key() < it.key();
1846 if (it.value() != jt.value())
1847 return jt.value() < it.value();
1848 }
1849 }
1850
1851 return false;
1852}
1853
1854
1864bool QFont::operator!=(const QFont &f) const
1865{
1866 return !(operator==(f));
1867}
1868
1872QFont::operator QVariant() const
1873{
1874 return QVariant::fromValue(*this);
1875}
1876
1884bool QFont::isCopyOf(const QFont & f) const
1885{
1886 return d == f.d;
1887}
1888
1894{
1895 if (resolve_mask == 0 || (resolve_mask == other.resolve_mask && *this == other)) {
1896 QFont o(other);
1897 o.resolve_mask = resolve_mask;
1898 return o;
1899 }
1900
1901 QFont font(*this);
1902 font.detach();
1903 font.d->resolve(resolve_mask, other.d.data());
1904
1905 return font;
1906}
1907
1919/*****************************************************************************
1920 QFont substitution management
1921 *****************************************************************************/
1922
1923typedef QHash<QString, QStringList> QFontSubst;
1924Q_GLOBAL_STATIC(QFontSubst, globalFontSubst)
1925
1926
1937QString QFont::substitute(const QString &familyName)
1938{
1939 QFontSubst *fontSubst = globalFontSubst();
1940 Q_ASSERT(fontSubst != nullptr);
1941 QFontSubst::ConstIterator it = fontSubst->constFind(familyName.toLower());
1942 if (it != fontSubst->constEnd() && !(*it).isEmpty())
1943 return (*it).first();
1944
1945 return familyName;
1946}
1947
1948
1959{
1960 QFontSubst *fontSubst = globalFontSubst();
1961 Q_ASSERT(fontSubst != nullptr);
1962 return fontSubst->value(familyName.toLower(), QStringList());
1963}
1964
1965
1975void QFont::insertSubstitution(const QString &familyName,
1976 const QString &substituteName)
1977{
1978 QFontSubst *fontSubst = globalFontSubst();
1979 Q_ASSERT(fontSubst != nullptr);
1980 QStringList &list = (*fontSubst)[familyName.toLower()];
1981 QString s = substituteName.toLower();
1982 if (!list.contains(s))
1983 list.append(s);
1984}
1985
1986
1998 const QStringList &substituteNames)
1999{
2000 QFontSubst *fontSubst = globalFontSubst();
2001 Q_ASSERT(fontSubst != nullptr);
2002 QStringList &list = (*fontSubst)[familyName.toLower()];
2003 for (const QString &substituteName : substituteNames) {
2004 const QString lowerSubstituteName = substituteName.toLower();
2005 if (!list.contains(lowerSubstituteName))
2006 list.append(lowerSubstituteName);
2007 }
2008}
2009
2017{
2018 QFontSubst *fontSubst = globalFontSubst();
2019 Q_ASSERT(fontSubst != nullptr);
2020 fontSubst->remove(familyName.toLower());
2021}
2022
2029{
2030 QFontSubst *fontSubst = globalFontSubst();
2031 Q_ASSERT(fontSubst != nullptr);
2032 QStringList ret = fontSubst->keys();
2033
2034 ret.sort();
2035 return ret;
2036}
2037
2038#ifndef QT_NO_DATASTREAM
2039/* \internal
2040 Internal function. Converts boolean font settings to an unsigned
2041 8-bit number. Used for serialization etc.
2042*/
2043static quint8 get_font_bits(int version, const QFontPrivate *f)
2044{
2045 Q_ASSERT(f != nullptr);
2046 quint8 bits = 0;
2047 if (f->request.style)
2048 bits |= 0x01;
2049 if (f->underline)
2050 bits |= 0x02;
2051 if (f->overline)
2052 bits |= 0x40;
2053 if (f->strikeOut)
2054 bits |= 0x04;
2055 if (f->request.fixedPitch)
2056 bits |= 0x08;
2057 // if (f.hintSetByUser)
2058 // bits |= 0x10;
2059 if (version >= QDataStream::Qt_4_0) {
2060 if (f->kerning)
2061 bits |= 0x10;
2062 }
2063 if (f->request.style == QFont::StyleOblique)
2064 bits |= 0x80;
2065 return bits;
2066}
2067
2069{
2070 Q_ASSERT(f != nullptr);
2071 quint8 bits = 0;
2072 if (f->request.ignorePitch)
2073 bits |= 0x01;
2074 if (f->letterSpacingIsAbsolute)
2075 bits |= 0x02;
2076 return bits;
2077}
2078
2079/* \internal
2080 Internal function. Sets boolean font settings from an unsigned
2081 8-bit number. Used for serialization etc.
2082*/
2083static void set_font_bits(int version, quint8 bits, QFontPrivate *f)
2084{
2085 Q_ASSERT(f != nullptr);
2086 f->request.style = (bits & 0x01) != 0 ? QFont::StyleItalic : QFont::StyleNormal;
2087 f->underline = (bits & 0x02) != 0;
2088 f->overline = (bits & 0x40) != 0;
2089 f->strikeOut = (bits & 0x04) != 0;
2090 f->request.fixedPitch = (bits & 0x08) != 0;
2091 // f->hintSetByUser = (bits & 0x10) != 0;
2092 if (version >= QDataStream::Qt_4_0)
2093 f->kerning = (bits & 0x10) != 0;
2094 if ((bits & 0x80) != 0)
2095 f->request.style = QFont::StyleOblique;
2096}
2097
2099{
2100 Q_ASSERT(f != nullptr);
2101 f->request.ignorePitch = (bits & 0x01) != 0;
2102 f->letterSpacingIsAbsolute = (bits & 0x02) != 0;
2103}
2104#endif
2105
2113{
2114 return toString();
2115}
2116
2144{
2145 const QChar comma(u',');
2146 QString fontDescription = family() + comma +
2147 QString::number( pointSizeF()) + comma +
2148 QString::number( pixelSize()) + comma +
2149 QString::number((int) styleHint()) + comma +
2150 QString::number( weight()) + comma +
2151 QString::number((int) style()) + comma +
2152 QString::number((int) underline()) + comma +
2153 QString::number((int) strikeOut()) + comma +
2154 QString::number((int)fixedPitch()) + comma +
2155 QString::number((int) false) + comma +
2156 QString::number((int)capitalization()) + comma +
2157 QString::number((int)letterSpacingType()) + comma +
2158 QString::number(letterSpacing()) + comma +
2159 QString::number(wordSpacing()) + comma +
2160 QString::number(stretch()) + comma +
2162
2164 if (!fontStyle.isEmpty())
2165 fontDescription += comma + fontStyle;
2166
2167 return fontDescription;
2168}
2169
2177size_t qHash(const QFont &font, size_t seed) noexcept
2178{
2180}
2181
2182
2190bool QFont::fromString(const QString &descrip)
2191{
2192 const auto sr = QStringView(descrip).trimmed();
2193 const auto l = sr.split(u',');
2194 const int count = l.size();
2195 if (!count || (count > 2 && count < 9) || count == 9 || count > 17 ||
2196 l.first().isEmpty()) {
2197 qWarning("QFont::fromString: Invalid description '%s'",
2198 descrip.isEmpty() ? "(empty)" : descrip.toLatin1().data());
2199 return false;
2200 }
2201
2202 setFamily(l[0].toString());
2203 if (count > 1 && l[1].toDouble() > 0.0)
2204 setPointSizeF(l[1].toDouble());
2205 if (count == 9) {
2206 setStyleHint((StyleHint) l[2].toInt());
2207 setWeight(QFont::Weight(l[3].toInt()));
2208 setItalic(l[4].toInt());
2209 setUnderline(l[5].toInt());
2210 setStrikeOut(l[6].toInt());
2211 setFixedPitch(l[7].toInt());
2212 } else if (count >= 10) {
2213 if (l[2].toInt() > 0)
2214 setPixelSize(l[2].toInt());
2215 setStyleHint((StyleHint) l[3].toInt());
2216 if (count >= 16)
2217 setWeight(QFont::Weight(l[4].toInt()));
2218 else
2220 setStyle((QFont::Style)l[5].toInt());
2221 setUnderline(l[6].toInt());
2222 setStrikeOut(l[7].toInt());
2223 setFixedPitch(l[8].toInt());
2224 if (count >= 16) {
2226 setLetterSpacing((SpacingType)l[11].toInt(), l[12].toDouble());
2227 setWordSpacing(l[13].toDouble());
2228 setStretch(l[14].toInt());
2230 }
2231 if (count == 11 || count == 17)
2232 d->request.styleName = l[count - 1].toString();
2233 else
2234 d->request.styleName.clear();
2235 }
2236
2237 if (count >= 9 && !d->request.fixedPitch) // assume 'false' fixedPitch equals default
2238 d->request.ignorePitch = true;
2239
2240 return true;
2241}
2242
2251{
2252}
2253
2260{
2262}
2263
2269{
2270}
2271
2376std::optional<QFont::Tag> QFont::Tag::fromString(QAnyStringView view) noexcept
2377{
2378 if (view.size() != 4) {
2379 qWarning("The tag name must be exactly 4 characters long!");
2380 return std::nullopt;
2381 }
2382 const QFont::Tag maybeTag = view.visit([](auto view) {
2383 using CharType = decltype(view.at(0));
2384 if constexpr (std::is_same_v<CharType, char>) {
2385 const char bytes[5] = { view.at(0), view.at(1), view.at(2), view.at(3), 0 };
2386 return Tag(bytes);
2387 } else {
2388 const char bytes[5] = { view.at(0).toLatin1(), view.at(1).toLatin1(),
2389 view.at(2).toLatin1(), view.at(3).toLatin1(), 0 };
2390 return Tag(bytes);
2391 }
2392 });
2393 return maybeTag.isValid() ? std::optional<Tag>(maybeTag) : std::nullopt;
2394}
2395
2443{
2444 if (tag.isValid()) {
2445 if (resolve_mask & QFont::VariableAxesResolved && d->hasVariableAxis(tag, value))
2446 return;
2447
2448 detach();
2449
2451 resolve_mask |= QFont::VariableAxesResolved;
2452 }
2453}
2454
2466{
2467 if (tag.isValid()) {
2468 detach();
2469
2471 resolve_mask |= QFont::VariableAxesResolved;
2472 }
2473}
2474
2484QList<QFont::Tag> QFont::variableAxisTags() const
2485{
2486 return d->request.variableAxisValues.keys();
2487}
2488
2500{
2502}
2503
2515{
2517}
2518
2529{
2531 return;
2532
2533 detach();
2535}
2536
2537
2575{
2576 if (tag.isValid()) {
2577 d->detachButKeepEngineData(this);
2578 d->setFeature(tag, value);
2579 resolve_mask |= QFont::FeaturesResolved;
2580 }
2581}
2582
2599{
2600 if (tag.isValid()) {
2601 d->detachButKeepEngineData(this);
2602 d->unsetFeature(tag);
2603 resolve_mask |= QFont::FeaturesResolved;
2604 }
2605}
2606
2616QList<QFont::Tag> QFont::featureTags() const
2617{
2618 return d->features.keys();
2619}
2620
2632{
2633 return d->features.value(tag);
2634}
2635
2647{
2648 return d->features.contains(tag);
2649}
2650
2661{
2662 if (d->features.isEmpty())
2663 return;
2664
2665 d->detachButKeepEngineData(this);
2666 d->features.clear();
2667}
2668
2669extern QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style,
2670 QFont::StyleHint styleHint, QChar::Script script);
2671
2681{
2683 , QFont::StyleHint(d->request.styleHint), QChar::Script_Common);
2684 if (!fallbacks.isEmpty())
2685 return fallbacks.first();
2686 return QString();
2687}
2688
2700{
2701 return d->request.families;
2702}
2703
2721void QFont::setFamilies(const QStringList &families)
2722{
2723 if ((resolve_mask & QFont::FamiliesResolved) && d->request.families == families)
2724 return;
2725 detach();
2727 resolve_mask |= QFont::FamiliesResolved;
2728}
2729
2730
2731/*****************************************************************************
2732 QFont stream functions
2733 *****************************************************************************/
2734#ifndef QT_NO_DATASTREAM
2735
2745{
2746 if (s.version() == 1) {
2747 s << font.d->request.families.constFirst().toLatin1();
2748 } else {
2749 s << font.d->request.families.constFirst();
2750 if (s.version() >= QDataStream::Qt_5_4)
2751 s << font.d->request.styleName;
2752 }
2753
2754 if (s.version() >= QDataStream::Qt_4_0) {
2755 // 4.0
2756 double pointSize = font.d->request.pointSize;
2757 qint32 pixelSize = font.d->request.pixelSize;
2758 s << pointSize;
2759 s << pixelSize;
2760 } else if (s.version() <= 3) {
2761 qint16 pointSize = (qint16) (font.d->request.pointSize * 10);
2762 if (pointSize < 0) {
2763 pointSize = (qint16)QFontInfo(font).pointSize() * 10;
2764 }
2765 s << pointSize;
2766 } else {
2767 s << (qint16) (font.d->request.pointSize * 10);
2768 s << (qint16) font.d->request.pixelSize;
2769 }
2770
2771 s << (quint8) font.d->request.styleHint;
2772 if (s.version() >= QDataStream::Qt_3_1) {
2773 // Continue writing 8 bits for versions < 5.4 so that we don't write too much,
2774 // even though we need 16 to store styleStrategy, so there is some data loss.
2775 if (s.version() >= QDataStream::Qt_5_4)
2777 else
2779 }
2780
2781 if (s.version() < QDataStream::Qt_6_0)
2783 else
2784 s << quint16(font.d->request.weight);
2785
2786 s << get_font_bits(s.version(), font.d.data());
2787 if (s.version() >= QDataStream::Qt_4_3)
2788 s << (quint16)font.d->request.stretch;
2789 if (s.version() >= QDataStream::Qt_4_4)
2791 if (s.version() >= QDataStream::Qt_4_5) {
2792 s << font.d->letterSpacing.value();
2793 s << font.d->wordSpacing.value();
2794 }
2795 if (s.version() >= QDataStream::Qt_5_4)
2797 if (s.version() >= QDataStream::Qt_5_6)
2798 s << (quint8)font.d->capital;
2799 if (s.version() >= QDataStream::Qt_5_13) {
2800 if (s.version() < QDataStream::Qt_6_0)
2801 s << font.d->request.families.mid(1);
2802 else
2803 s << font.d->request.families;
2804 }
2805 if (s.version() >= QDataStream::Qt_6_6)
2806 s << font.d->features;
2807 if (s.version() >= QDataStream::Qt_6_7)
2809 return s;
2810}
2811
2812
2822{
2823 font.d = new QFontPrivate;
2824 font.resolve_mask = QFont::AllPropertiesResolved;
2825
2826 quint8 styleHint, bits;
2827 quint16 styleStrategy = QFont::PreferDefault;
2828
2829 if (s.version() == 1) {
2830 QByteArray fam;
2831 s >> fam;
2833 } else {
2834 QString fam;
2835 s >> fam;
2836 font.d->request.families = QStringList(fam);
2837 if (s.version() >= QDataStream::Qt_5_4)
2838 s >> font.d->request.styleName;
2839 }
2840
2841 if (s.version() >= QDataStream::Qt_4_0) {
2842 // 4.0
2843 double pointSize;
2844 qint32 pixelSize;
2845 s >> pointSize;
2846 s >> pixelSize;
2847 font.d->request.pointSize = qreal(pointSize);
2848 font.d->request.pixelSize = pixelSize;
2849 } else {
2850 qint16 pointSize, pixelSize = -1;
2851 s >> pointSize;
2852 if (s.version() >= 4)
2853 s >> pixelSize;
2854 font.d->request.pointSize = qreal(pointSize / 10.);
2855 font.d->request.pixelSize = pixelSize;
2856 }
2857 s >> styleHint;
2858 if (s.version() >= QDataStream::Qt_3_1) {
2859 if (s.version() >= QDataStream::Qt_5_4) {
2860 s >> styleStrategy;
2861 } else {
2862 quint8 tempStyleStrategy;
2863 s >> tempStyleStrategy;
2864 styleStrategy = tempStyleStrategy;
2865 }
2866 }
2867
2868 if (s.version() < QDataStream::Qt_6_0) {
2869 quint8 charSet;
2870 quint8 weight;
2871 s >> charSet;
2872 s >> weight;
2874 } else {
2876 s >> weight;
2878 }
2879
2880 s >> bits;
2881
2882 font.d->request.styleHint = styleHint;
2883 font.d->request.styleStrategy = styleStrategy;
2884
2885 set_font_bits(s.version(), bits, font.d.data());
2886
2887 if (s.version() >= QDataStream::Qt_4_3) {
2888 quint16 stretch;
2889 s >> stretch;
2890 font.d->request.stretch = stretch;
2891 }
2892
2893 if (s.version() >= QDataStream::Qt_4_4) {
2894 quint8 extendedBits;
2895 s >> extendedBits;
2896 set_extended_font_bits(extendedBits, font.d.data());
2897 }
2898 if (s.version() >= QDataStream::Qt_4_5) {
2899 int value;
2900 s >> value;
2902 s >> value;
2904 }
2905 if (s.version() >= QDataStream::Qt_5_4) {
2906 quint8 value;
2907 s >> value;
2909 }
2910 if (s.version() >= QDataStream::Qt_5_6) {
2911 quint8 value;
2912 s >> value;
2914 }
2915 if (s.version() >= QDataStream::Qt_5_13) {
2917 s >> value;
2918 if (s.version() < QDataStream::Qt_6_0)
2919 font.d->request.families.append(value);
2920 else
2922 }
2923 if (s.version() >= QDataStream::Qt_6_6) {
2924 font.d->features.clear();
2925 s >> font.d->features;
2926 }
2927 if (s.version() >= QDataStream::Qt_6_7) {
2930 }
2931
2932 return s;
2933}
2934
2936{
2937 stream << tag.value();
2938 return stream;
2939}
2940
2942{
2943 quint32 value;
2944 stream >> value;
2945 if (const auto maybeTag = QFont::Tag::fromValue(value))
2946 tag = *maybeTag;
2947 else
2948 stream.setStatus(QDataStream::ReadCorruptData);
2949 return stream;
2950}
2951
2952#endif // QT_NO_DATASTREAM
2953
2954
2955/*****************************************************************************
2956 QFontInfo member functions
2957 *****************************************************************************/
2958
3051 : d(font.d)
3052{
3053}
3054
3059 : d(fi.d)
3060{
3061}
3062
3069
3074{
3075 d = fi.d;
3076 return *this;
3077}
3078
3093{
3094 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3095 Q_ASSERT(engine != nullptr);
3096 return engine->fontDef.families.isEmpty() ? QString() : engine->fontDef.families.constFirst();
3097}
3098
3108{
3109 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3110 Q_ASSERT(engine != nullptr);
3111 return engine->fontDef.styleName;
3112}
3113
3120{
3121 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3122 Q_ASSERT(engine != nullptr);
3123 return qRound(engine->fontDef.pointSize);
3124}
3125
3132{
3133 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3134 Q_ASSERT(engine != nullptr);
3135 return engine->fontDef.pointSize;
3136}
3137
3144{
3145 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3146 Q_ASSERT(engine != nullptr);
3147 return engine->fontDef.pixelSize;
3148}
3149
3156{
3157 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3158 Q_ASSERT(engine != nullptr);
3159 return engine->fontDef.style != QFont::StyleNormal;
3160}
3161
3168{
3169 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3170 Q_ASSERT(engine != nullptr);
3171 return (QFont::Style)engine->fontDef.style;
3172}
3173
3174
3175#if QT_DEPRECATED_SINCE(6, 0)
3189int QFontInfo::legacyWeight() const
3190{
3192}
3193#endif // QT_DEPRECATED_SINCE(6, 0)
3194
3195
3202{
3203 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3204 Q_ASSERT(engine != nullptr);
3205 return engine->fontDef.weight;
3206
3207}
3208
3229{
3230 return d->underline;
3231}
3232
3244{
3245 return d->overline;
3246}
3247
3257{
3258 return d->strikeOut;
3259}
3260
3267{
3268 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3269 Q_ASSERT(engine != nullptr);
3270#ifdef Q_OS_MAC
3271 if (!engine->fontDef.fixedPitchComputed) {
3272 QChar ch[2] = { u'i', u'm' };
3273 QGlyphLayoutArray<2> g;
3274 int l = 2;
3275 if (engine->stringToCMap(ch, 2, &g, &l, {}) < 0)
3276 Q_UNREACHABLE();
3277 Q_ASSERT(l == 2);
3278 engine->fontDef.fixedPitch = g.advances[0] == g.advances[1];
3279 engine->fontDef.fixedPitchComputed = true;
3280 }
3281#endif
3282 return engine->fontDef.fixedPitch;
3283}
3284
3293{
3294 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3295 Q_ASSERT(engine != nullptr);
3296 return (QFont::StyleHint) engine->fontDef.styleHint;
3297}
3298
3306{
3307 QFontEngine *engine = d->engineForScript(QChar::Script_Common);
3308 Q_ASSERT(engine != nullptr);
3309 return d->request.exactMatch(engine->fontDef);
3310}
3311
3312
3313
3314
3315// **********************************************************************
3316// QFontCache
3317// **********************************************************************
3318
3319using namespace std::chrono_literals;
3320
3321#ifdef QFONTCACHE_DEBUG
3322// fast timeouts for debugging
3323static constexpr auto fast_timeout = 1s;
3324static constexpr auto slow_timeout = 5s;
3325#else
3326static constexpr auto fast_timeout = 10s;
3327static constexpr auto slow_timeout = 5min;
3328#endif // QFONTCACHE_DEBUG
3329
3330#ifndef QFONTCACHE_MIN_COST
3331# define QFONTCACHE_MIN_COST 4*1024 // 4mb
3332#endif
3333const uint QFontCache::min_cost = QFONTCACHE_MIN_COST;
3334Q_GLOBAL_STATIC(QThreadStorage<QFontCache *>, theFontCache)
3335
3337{
3338 QFontCache *&fontCache = theFontCache()->localData();
3339 if (!fontCache)
3340 fontCache = new QFontCache;
3341 return fontCache;
3342}
3343
3345{
3346 QThreadStorage<QFontCache *> *cache = nullptr;
3347 QT_TRY {
3348 cache = theFontCache();
3349 } QT_CATCH (const std::bad_alloc &) {
3350 // no cache - just ignore
3351 }
3352 if (cache && cache->hasLocalData())
3353 cache->setLocalData(nullptr);
3354}
3355
3357
3359 : QObject(), total_cost(0), max_cost(min_cost),
3360 current_timestamp(0), fast(false),
3361 autoClean(QGuiApplication::instance()
3362 && (QGuiApplication::instance()->thread() == QThread::currentThread())),
3363 timer_id(-1),
3364 m_id(font_cache_id.fetchAndAddRelaxed(1) + 1)
3365{
3366}
3367
3369{
3370 clear();
3371}
3372
3374{
3375 {
3378 while (it != end) {
3379 QFontEngineData *data = it.value();
3380 for (int i = 0; i < QChar::ScriptCount; ++i) {
3381 if (data->engines[i]) {
3382 if (!data->engines[i]->ref.deref()) {
3383 Q_ASSERT(engineCacheCount.value(data->engines[i]) == 0);
3384 delete data->engines[i];
3385 }
3386 data->engines[i] = nullptr;
3387 }
3388 }
3389 if (!data->ref.deref()) {
3390 delete data;
3391 } else {
3392 FC_DEBUG("QFontCache::clear: engineData %p still has refcount %d",
3393 data, data->ref.loadRelaxed());
3394 }
3395 ++it;
3396 }
3397 }
3398
3400
3401
3402 bool mightHaveEnginesLeftForCleanup;
3403 do {
3404 mightHaveEnginesLeftForCleanup = false;
3406 it != end; ++it) {
3407 QFontEngine *engine = it.value().data;
3408 if (engine) {
3409 const int cacheCount = --engineCacheCount[engine];
3410 Q_ASSERT(cacheCount >= 0);
3411 if (!engine->ref.deref()) {
3412 Q_ASSERT(cacheCount == 0);
3413 mightHaveEnginesLeftForCleanup = engine->type() == QFontEngine::Multi;
3414 delete engine;
3415 } else if (cacheCount == 0) {
3416 FC_DEBUG("QFontCache::clear: engine %p still has refcount %d",
3417 engine, engine->ref.loadRelaxed());
3418 }
3419 it.value().data = nullptr;
3420 }
3421 }
3422 } while (mightHaveEnginesLeftForCleanup);
3423
3426
3427
3428 total_cost = 0;
3429 max_cost = min_cost;
3430}
3431
3432
3434{
3436 if (it == engineDataCache.constEnd())
3437 return nullptr;
3438
3439 // found
3440 return it.value();
3441}
3442
3444{
3445#ifdef QFONTCACHE_DEBUG
3446 FC_DEBUG("QFontCache: inserting new engine data %p", engineData);
3447 if (engineDataCache.contains(def)) {
3448 FC_DEBUG(" QFontCache already contains engine data %p for key=(%g %g %d %d %d)",
3450 def.pixelSize, def.weight, def.style, def.fixedPitch);
3451 }
3452#endif
3454
3455 engineData->ref.ref();
3456 // Decrease now rather than waiting
3457 if (total_cost > min_cost * 2 && engineDataCache.size() >= QFONTCACHE_DECREASE_TRIGGER_LIMIT)
3458 decreaseCache();
3459
3460 engineDataCache.insert(def, engineData);
3461 increaseCost(sizeof(QFontEngineData));
3462}
3463
3465{
3467 end = engineCache.end();
3468 if (it == end) return nullptr;
3469
3470 Q_ASSERT(it.value().data != nullptr);
3471 Q_ASSERT(key.multi == (it.value().data->type() == QFontEngine::Multi));
3472
3473 // found... update the hitcount and timestamp
3475
3476 return it.value().data;
3477}
3478
3480{
3481 value.hits++;
3482 value.timestamp = ++current_timestamp;
3483
3484 FC_DEBUG("QFontCache: found font engine\n"
3485 " %p: timestamp %4u hits %3u ref %2d/%2d, type %d",
3486 value.data, value.timestamp, value.hits,
3487 value.data->ref.loadRelaxed(), engineCacheCount.value(value.data),
3488 value.data->type());
3489}
3490
3491void QFontCache::insertEngine(const Key &key, QFontEngine *engine, bool insertMulti)
3492{
3493 Q_ASSERT(engine != nullptr);
3494 Q_ASSERT(key.multi == (engine->type() == QFontEngine::Multi));
3495
3496#ifdef QFONTCACHE_DEBUG
3497 FC_DEBUG("QFontCache: inserting new engine %p, refcount %d", engine, engine->ref.loadRelaxed());
3498 if (!insertMulti && engineCache.contains(key)) {
3499 FC_DEBUG(" QFontCache already contains engine %p for key=(%g %g %d %d %d)",
3500 engineCache.value(key).data, key.def.pointSize,
3501 key.def.pixelSize, key.def.weight, key.def.style, key.def.fixedPitch);
3502 }
3503#endif
3504 engine->ref.ref();
3505 // Decrease now rather than waiting
3506 if (total_cost > min_cost * 2 && engineCache.size() >= QFONTCACHE_DECREASE_TRIGGER_LIMIT)
3507 decreaseCache();
3508
3510 data.timestamp = ++current_timestamp;
3511
3512 if (insertMulti)
3514 else
3516 // only increase the cost if this is the first time we insert the engine
3517 if (++engineCacheCount[engine] == 1)
3518 increaseCost(engine->cache_cost);
3519}
3520
3521void QFontCache::increaseCost(uint cost)
3522{
3523 cost = (cost + 512) / 1024; // store cost in kb
3524 cost = cost > 0 ? cost : 1;
3525 total_cost += cost;
3526
3527 FC_DEBUG(" COST: increased %u kb, total_cost %u kb, max_cost %u kb",
3528 cost, total_cost, max_cost);
3529
3530 if (total_cost > max_cost) {
3531 max_cost = total_cost;
3532
3533 if (!autoClean)
3534 return;
3535
3536 if (timer_id == -1 || ! fast) {
3537 FC_DEBUG(" TIMER: starting fast timer (%d s)", static_cast<int>(fast_timeout.count()));
3538
3539 if (timer_id != -1)
3540 killTimer(timer_id);
3541 timer_id = startTimer(fast_timeout);
3542 fast = true;
3543 }
3544 }
3545}
3546
3547void QFontCache::decreaseCost(uint cost)
3548{
3549 cost = (cost + 512) / 1024; // cost is stored in kb
3550 cost = cost > 0 ? cost : 1;
3551 Q_ASSERT(cost <= total_cost);
3552 total_cost -= cost;
3553
3554 FC_DEBUG(" COST: decreased %u kb, total_cost %u kb, max_cost %u kb",
3555 cost, total_cost, max_cost);
3556}
3557
3559{
3560 FC_DEBUG("QFontCache::timerEvent: performing cache maintenance (timestamp %u)",
3561 current_timestamp);
3562
3563 if (total_cost <= max_cost && max_cost <= min_cost) {
3564 FC_DEBUG(" cache redused sufficiently, stopping timer");
3565
3566 killTimer(timer_id);
3567 timer_id = -1;
3568 fast = false;
3569
3570 return;
3571 }
3572 decreaseCache();
3573}
3574
3575void QFontCache::decreaseCache()
3576{
3577 // go through the cache and count up everything in use
3578 uint in_use_cost = 0;
3579
3580 {
3581 FC_DEBUG(" SWEEP engine data:");
3582
3583 // make sure the cost of each engine data is at least 1kb
3584 const uint engine_data_cost =
3585 sizeof(QFontEngineData) > 1024 ? sizeof(QFontEngineData) : 1024;
3586
3589 for (; it != end; ++it) {
3590 FC_DEBUG(" %p: ref %2d", it.value(), int(it.value()->ref.loadRelaxed()));
3591
3592 if (it.value()->ref.loadRelaxed() != 1)
3593 in_use_cost += engine_data_cost;
3594 }
3595 }
3596
3597 {
3598 FC_DEBUG(" SWEEP engine:");
3599
3602 for (; it != end; ++it) {
3603 FC_DEBUG(" %p: timestamp %4u hits %2u ref %2d/%2d, cost %u bytes",
3604 it.value().data, it.value().timestamp, it.value().hits,
3605 it.value().data->ref.loadRelaxed(), engineCacheCount.value(it.value().data),
3606 it.value().data->cache_cost);
3607
3608 if (it.value().data->ref.loadRelaxed() > engineCacheCount.value(it.value().data))
3609 in_use_cost += it.value().data->cache_cost / engineCacheCount.value(it.value().data);
3610 }
3611
3612 // attempt to make up for rounding errors
3613 in_use_cost += engineCache.size();
3614 }
3615
3616 in_use_cost = (in_use_cost + 512) / 1024; // cost is stored in kb
3617
3618 /*
3619 calculate the new maximum cost for the cache
3620
3621 NOTE: in_use_cost is *not* correct due to rounding errors in the
3622 above algorithm. instead of worrying about getting the
3623 calculation correct, we are more interested in speed, and use
3624 in_use_cost as a floor for new_max_cost
3625 */
3626 uint new_max_cost = qMax(qMax(max_cost / 2, in_use_cost), min_cost);
3627
3628 FC_DEBUG(" after sweep, in use %u kb, total %u kb, max %u kb, new max %u kb",
3629 in_use_cost, total_cost, max_cost, new_max_cost);
3630
3631 if (autoClean) {
3632 if (new_max_cost == max_cost) {
3633 if (fast) {
3634 FC_DEBUG(" cannot shrink cache, slowing timer");
3635
3636 if (timer_id != -1) {
3637 killTimer(timer_id);
3638 timer_id = startTimer(slow_timeout);
3639 fast = false;
3640 }
3641
3642 return;
3643 } else if (! fast) {
3644 FC_DEBUG(" dropping into passing gear");
3645
3646 if (timer_id != -1)
3647 killTimer(timer_id);
3648 timer_id = startTimer(fast_timeout);
3649 fast = true; }
3650 }
3651 }
3652
3653 max_cost = new_max_cost;
3654
3655 {
3656 FC_DEBUG(" CLEAN engine data:");
3657
3658 // clean out all unused engine data
3660 while (it != engineDataCache.end()) {
3661 if (it.value()->ref.loadRelaxed() == 1) {
3662 FC_DEBUG(" %p", it.value());
3663 decreaseCost(sizeof(QFontEngineData));
3664 it.value()->ref.deref();
3665 delete it.value();
3667 } else {
3668 ++it;
3669 }
3670 }
3671 }
3672
3673 FC_DEBUG(" CLEAN engine:");
3674
3675 // clean out the engine cache just enough to get below our new max cost
3676 bool cost_decreased;
3677 do {
3678 cost_decreased = false;
3679
3681 end = engineCache.end();
3682 // determine the oldest and least popular of the unused engines
3683 uint oldest = ~0u;
3684 uint least_popular = ~0u;
3685
3687
3688 for ( ; it != end; ++it) {
3689 if (it.value().data->ref.loadRelaxed() != engineCacheCount.value(it.value().data))
3690 continue;
3691
3692 if (it.value().timestamp < oldest && it.value().hits <= least_popular) {
3693 oldest = it.value().timestamp;
3694 least_popular = it.value().hits;
3695 jt = it;
3696 }
3697 }
3698
3699 it = jt;
3700 if (it != end) {
3701 FC_DEBUG(" %p: timestamp %4u hits %2u ref %2d/%2d, type %d",
3702 it.value().data, it.value().timestamp, it.value().hits,
3703 it.value().data->ref.loadRelaxed(), engineCacheCount.value(it.value().data),
3704 it.value().data->type());
3705
3706 QFontEngine *fontEngine = it.value().data;
3707 // get rid of all occurrences
3708 it = engineCache.begin();
3709 while (it != engineCache.end()) {
3710 if (it.value().data == fontEngine) {
3711 fontEngine->ref.deref();
3713 } else {
3714 ++it;
3715 }
3716 }
3717 // and delete the last occurrence
3718 Q_ASSERT(fontEngine->ref.loadRelaxed() == 0);
3719 decreaseCost(fontEngine->cache_cost);
3720 delete fontEngine;
3721 engineCacheCount.remove(fontEngine);
3722
3723 cost_decreased = true;
3724 }
3725 } while (cost_decreased && total_cost > max_cost);
3726}
3727
3728
3729#ifndef QT_NO_DEBUG_STREAM
3731{
3732 QDebugStateSaver saver(stream);
3733 stream.nospace().noquote();
3734 stream << "QFont(";
3735
3736 if (stream.verbosity() == QDebug::DefaultVerbosity) {
3737 stream << font.toString() << ")";
3738 return stream;
3739 }
3740
3741 QString fontDescription;
3742 QDebug debug(&fontDescription);
3743 debug.nospace();
3744
3745 const QFont defaultFont(new QFontPrivate);
3746
3747 for (int property = QFont::SizeResolved; property < QFont::AllPropertiesResolved; property <<= 1) {
3748 const bool resolved = (font.resolve_mask & property) != 0;
3749 if (!resolved && stream.verbosity() == QDebug::MinimumVerbosity)
3750 continue;
3751
3752 #define QFONT_DEBUG_SKIP_DEFAULT(prop) \
3753 if ((font.prop() == defaultFont.prop()) && stream.verbosity() == 1) \
3754 continue;
3755
3756 QDebugStateSaver saver(debug);
3757
3758 switch (property) {
3760 if (font.pointSizeF() >= 0)
3761 debug << font.pointSizeF() << "pt";
3762 else if (font.pixelSize() >= 0)
3763 debug << font.pixelSize() << "px";
3764 else
3765 Q_UNREACHABLE();
3766 break;
3768 QFONT_DEBUG_SKIP_DEFAULT(styleHint);
3769 debug.verbosity(1) << font.styleHint(); break;
3771 QFONT_DEBUG_SKIP_DEFAULT(styleStrategy);
3772 debug.verbosity(1) << font.styleStrategy(); break;
3774 debug.verbosity(1) << QFont::Weight(font.weight()); break;
3777 debug.verbosity(0) << font.style(); break;
3779 QFONT_DEBUG_SKIP_DEFAULT(underline);
3780 debug << "underline=" << font.underline(); break;
3782 QFONT_DEBUG_SKIP_DEFAULT(overline);
3783 debug << "overline=" << font.overline(); break;
3785 QFONT_DEBUG_SKIP_DEFAULT(strikeOut);
3786 debug << "strikeOut=" << font.strikeOut(); break;
3788 QFONT_DEBUG_SKIP_DEFAULT(fixedPitch);
3789 debug << "fixedPitch=" << font.fixedPitch(); break;
3791 QFONT_DEBUG_SKIP_DEFAULT(stretch);
3792 debug.verbosity(0) << QFont::Stretch(font.stretch()); break;
3795 debug << "kerning=" << font.kerning(); break;
3797 QFONT_DEBUG_SKIP_DEFAULT(capitalization);
3798 debug.verbosity(0) << font.capitalization(); break;
3800 QFONT_DEBUG_SKIP_DEFAULT(letterSpacing);
3801 debug << "letterSpacing=" << font.letterSpacing();
3802 debug.verbosity(0) << " (" << font.letterSpacingType() << ")";
3803 break;
3805 QFONT_DEBUG_SKIP_DEFAULT(hintingPreference);
3806 debug.verbosity(0) << font.hintingPreference(); break;
3808 QFONT_DEBUG_SKIP_DEFAULT(styleName);
3809 debug << "styleName=" << font.styleName(); break;
3810 default:
3811 continue;
3812 };
3813
3814 #undef QFONT_DEBUG_SKIP_DEFAULT
3815
3816 debug << ", ";
3817 }
3818
3819 if (stream.verbosity() > QDebug::MinimumVerbosity)
3820 debug.verbosity(0) << "resolveMask=" << QFlags<QFont::ResolveProperties>(font.resolve_mask);
3821 else
3822 fontDescription.chop(2); // Last ', '
3823
3824 stream << fontDescription << ')';
3825
3826 return stream;
3827}
3828
3830{
3831 QDebugStateSaver saver(debug);
3832 debug.noquote() << tag.toString();
3833 return debug;
3834}
3835#endif
3836
3838
3839#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:46
\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:3344
void insertEngineData(const QFontDef &def, QFontEngineData *engineData)
Definition qfont.cpp:3443
EngineDataCache engineDataCache
Definition qfont_p.h:256
void clear()
Definition qfont.cpp:3373
QFontEngine * findEngine(const Key &key)
Definition qfont.cpp:3464
QFontEngineData * findEngineData(const QFontDef &def) const
Definition qfont.cpp:3433
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:3558
static QFontCache * instance()
Definition qfont.cpp:3336
void updateHitCountAndTimeStamp(Engine &value)
Definition qfont.cpp:3479
void insertEngine(const Key &key, QFontEngine *engine, bool insertMulti=false)
Definition qfont.cpp:3491
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:3131
int pointSize() const
Returns the point size of the matched window system font.
Definition qfont.cpp:3119
int pixelSize() const
Returns the pixel size of the matched window system font.
Definition qfont.cpp:3143
QString family() const
Returns the family name of the matched window system font.
Definition qfont.cpp:3092
bool italic() const
Returns the italic value of the matched window system font.
Definition qfont.cpp:3155
QFontInfo & operator=(const QFontInfo &)
Assigns the font info in fi.
Definition qfont.cpp:3073
QString styleName() const
Definition qfont.cpp:3107
bool fixedPitch() const
Returns the fixed pitch value of the matched window system font.
Definition qfont.cpp:3266
QFontInfo(const QFont &)
Constructs a font info object for font.
Definition qfont.cpp:3050
QFont::StyleHint styleHint() const
Returns the style of the matched window system font.
Definition qfont.cpp:3292
bool strikeOut() const
Returns the strikeout value of the matched window system font.
Definition qfont.cpp:3256
bool overline() const
Returns the overline value of the matched window system font.
Definition qfont.cpp:3243
QFont::Style style() const
Returns the style value of the matched window system font.
Definition qfont.cpp:3167
int weight() const
Returns the weight of the matched window system font.
Definition qfont.cpp:3201
~QFontInfo()
Destroys the font info object.
Definition qfont.cpp:3066
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:3305
bool underline() const
Returns the underline value of the matched window system font.
Definition qfont.cpp:3228
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:1958
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:2250
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:2268
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:2660
static void cleanup()
Definition qfont.cpp:2259
bool isCopyOf(const QFont &) const
Returns true if this font and f are copies of each other, i.e.
Definition qfont.cpp:1884
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:376
QFont()
Constructs a font object that uses the application's default font.
Definition qfont.cpp:685
friend class QFontPrivate
Definition qfont.h:326
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:2190
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:2177
bool underline() const
Returns true if underline has been set; otherwise returns false.
Definition qfont.cpp:1251
Capitalization
Definition qfont.h:97
@ AllLowercase
Definition qfont.h:100
@ AllUppercase
Definition qfont.h:99
@ MixedCase
Definition qfont.h:98
@ SmallCaps
Definition qfont.h:101
void setFamilies(const QStringList &)
Definition qfont.cpp:2721
bool operator!=(const QFont &) const
Returns true if this font is different from f; otherwise returns false.
Definition qfont.cpp:1864
void setCapitalization(Capitalization)
Definition qfont.cpp:1725
QString toString() const
Returns a description of the font.
Definition qfont.cpp:2143
qreal letterSpacing() const
Definition qfont.cpp:1621
void setWordSpacing(qreal spacing)
Definition qfont.cpp:1690
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:1526
bool exactMatch() const
Returns true if a window system font exactly matching the settings of this font is available.
Definition qfont.cpp:1754
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:1893
static void insertSubstitution(const QString &, const QString &)
Inserts substituteName into the substitution table for the family familyName.
Definition qfont.cpp:1975
bool isVariableAxisSet(Tag tag) const
Definition qfont.cpp:2514
HintingPreference hintingPreference() const
Definition qfont.cpp:974
quint32 featureValue(Tag tag) const
Definition qfont.cpp:2631
QList< Tag > featureTags() const
Definition qfont.cpp:2616
SpacingType
Definition qfont.h:106
@ AbsoluteSpacing
Definition qfont.h:108
@ PercentageSpacing
Definition qfont.h:107
bool operator<(const QFont &) const
Provides an arbitrary comparison of this font and font f.
Definition qfont.cpp:1799
Capitalization capitalization() const
Definition qfont.cpp:1743
static void removeSubstitutions(const QString &)
Removes all the substitutions for familyName.
Definition qfont.cpp:2016
QList< Tag > variableAxisTags() const
Definition qfont.cpp:2484
QStringList families() const
Definition qfont.cpp:2699
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:124
@ LetterSpacingResolved
Definition qfont.h:127
@ SizeResolved
Definition qfont.h:115
@ OverlineResolved
Definition qfont.h:121
@ UnderlineResolved
Definition qfont.h:120
@ StyleHintResolved
Definition qfont.h:116
@ StyleNameResolved
Definition qfont.h:130
@ AllPropertiesResolved
Definition qfont.h:134
@ StrikeOutResolved
Definition qfont.h:122
@ KerningResolved
Definition qfont.h:125
@ FeaturesResolved
Definition qfont.h:132
@ WeightResolved
Definition qfont.h:118
@ VariableAxesResolved
Definition qfont.h:133
@ CapitalizationResolved
Definition qfont.h:126
@ HintingPreferenceResolved
Definition qfont.h:129
@ FixedPitchResolved
Definition qfont.h:123
@ WordSpacingResolved
Definition qfont.h:128
@ StyleStrategyResolved
Definition qfont.h:117
@ StyleResolved
Definition qfont.h:119
@ FamiliesResolved
Definition qfont.h:131
void setLetterSpacing(SpacingType type, qreal spacing)
Definition qfont.cpp:1638
void unsetVariableAxis(Tag tag)
Definition qfont.cpp:2465
qreal wordSpacing() const
Definition qfont.cpp:1671
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:1564
static QStringList substitutions()
Returns a sorted list of substituted family names.
Definition qfont.cpp:2028
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:2680
QString key() const
Returns the font's key, a textual representation of a font.
Definition qfont.cpp:2112
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:2646
bool operator==(const QFont &) const
Returns true if this font is equal to f; otherwise returns false.
Definition qfont.cpp:1770
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:381
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:1505
HintingPreference
Definition qfont.h:55
void unsetFeature(Tag tag)
Definition qfont.cpp:2598
QFont & operator=(const QFont &)
Move-assigns other to this QFont instance.
Definition qfont.cpp:796
void setVariableAxis(Tag tag, float value)
Definition qfont.cpp:2442
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:1588
SpacingType letterSpacingType() const
Definition qfont.cpp:1660
void clearVariableAxes()
Definition qfont.cpp:2528
void setFeature(Tag tag, quint32 value)
Definition qfont.cpp:2574
Stretch
Predefined stretch values that follow the CSS naming convention.
Definition qfont.h:83
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:63
@ DemiBold
Definition qfont.h:69
@ Thin
Definition qfont.h:64
@ ExtraBold
Definition qfont.h:71
@ Black
Definition qfont.h:72
@ Bold
Definition qfont.h:70
@ ExtraLight
Definition qfont.h:65
@ Normal
Definition qfont.h:67
@ Light
Definition qfont.h:66
@ Medium
Definition qfont.h:68
float variableAxisValue(Tag tag) const
Definition qfont.cpp:2499
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:76
@ StyleItalic
Definition qfont.h:78
@ StyleNormal
Definition qfont.h:77
@ StyleOblique
Definition qfont.h:79
static void insertSubstitutions(const QString &, const QStringList &)
Inserts the list of families substituteNames into the substitution list for familyName.
Definition qfont.cpp:1997
\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:958
qsizetype size() const noexcept
Returns the number of items in the hash.
Definition qhash.h:927
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:1219
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:1215
QList< Key > keys() const
Returns a list containing all the keys in the hash, in an arbitrary order.
Definition qhash.h:1086
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:1007
T value(const Key &key) const noexcept
Definition qhash.h:1054
const_iterator ConstIterator
Qt-style synonym for QHash::const_iterator.
Definition qhash.h:1289
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:951
bool isEmpty() const noexcept
Returns true if the hash contains no items; otherwise returns false.
Definition qhash.h:928
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1303
qsizetype size() const noexcept
Definition qlist.h:397
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
void append(parameter_type t)
Definition qlist.h:458
iterator insert(const Key &key, const T &value)
Definition qmap.h:688
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:357
iterator erase(const_iterator it)
Definition qmap.h:619
bool contains(const Key &key) const
Definition qmap.h:341
size_type remove(const Key &key)
Definition qmap.h:300
const_iterator constFind(const Key &key) const
Definition qmap.h:655
void clear()
Definition qmap.h:289
QList< Key > keys() const
Definition qmap.h:383
bool isEmpty() const
Definition qmap.h:269
iterator begin()
Definition qmap.h:598
iterator end()
Definition qmap.h:602
const_iterator constBegin() const
Definition qmap.h:600
size_type size() const
Definition qmap.h:267
const_iterator constEnd() const
Definition qmap.h:604
iterator replace(const Key &key, const T &value)
Definition qmap.h:1501
const_iterator constEnd() const
Definition qmap.h:1329
bool contains(const Key &key) const
Definition qmap.h:1045
iterator end()
Definition qmap.h:1327
const_iterator ConstIterator
Definition qmap.h:1364
iterator find(const Key &key)
Definition qmap.h:1371
iterator insert(const Key &key, const T &value)
Definition qmap.h:1452
iterator erase(const_iterator it)
Definition qmap.h:1344
size_type size() const
Definition qmap.h:938
const_iterator constBegin() const
Definition qmap.h:1325
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:1066
void clear()
Definition qmap.h:960
iterator begin()
Definition qmap.h:1323
\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:143
const_iterator constFind(const T &value) const
Definition qset.h:161
\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:8249
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:5455
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
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:8218
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
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:5506
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:8084
\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:536
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.
AudioChannelLayoutTag tag
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:2083
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:3327
QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
static constexpr auto fast_timeout
Definition qfont.cpp:3326
#define QFONT_DEBUG_SKIP_DEFAULT(prop)
#define QFONTCACHE_MIN_COST
Definition qfont.cpp:3331
#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:2068
static Q_CONSTINIT QBasicAtomicInt font_cache_id
Definition qfont.cpp:3356
#define QFONTCACHE_DECREASE_TRIGGER_LIMIT
Definition qfont.cpp:46
QDataStream & operator>>(QDataStream &stream, QFont::Tag &tag)
Definition qfont.cpp:2941
QDataStream & operator<<(QDataStream &stream, QFont::Tag tag)
Definition qfont.cpp:2935
QHash< QString, QStringList > QFontSubst
Definition qfont.cpp:1923
static quint8 get_font_bits(int version, const QFontPrivate *f)
Definition qfont.cpp:2043
static void set_extended_font_bits(quint8 bits, QFontPrivate *f)
Definition qfont.cpp:2098
#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:166
return ret
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
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:101
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:215
static Q_GUI_EXPORT std::optional< Tag > fromString(QAnyStringView view) noexcept
Returns a tag constructed from the string in view.
Definition qfont.cpp:2376
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:239
bool contains(const AT &t) const noexcept
Definition qlist.h:45