QtBase  v6.3.1
qfont.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qfont.h"
41 #include "qdebug.h"
42 #include "qpaintdevice.h"
43 #include "qfontdatabase.h"
44 #include "qfontmetrics.h"
45 #include "qfontinfo.h"
46 #include "qpainter.h"
47 #include "qhash.h"
48 #include "qdatastream.h"
49 #include "qguiapplication.h"
50 #include "qstringlist.h"
51 #include "qscreen.h"
52 
53 #include "qthread.h"
54 #include "qthreadstorage.h"
55 
56 #include "qfont_p.h"
57 #include <private/qfontengine_p.h>
58 #include <private/qpainter_p.h>
59 #include <private/qtextengine_p.h>
60 #include <limits.h>
61 
62 #include <qpa/qplatformscreen.h>
63 #include <qpa/qplatformintegration.h>
64 #include <qpa/qplatformfontdatabase.h>
65 #include <QtGui/private/qguiapplication_p.h>
66 
67 #include <QtCore/QMutexLocker>
68 #include <QtCore/QMutex>
69 
70 // #define QFONTCACHE_DEBUG
71 #ifdef QFONTCACHE_DEBUG
72 # define FC_DEBUG qDebug
73 #else
74 # define FC_DEBUG if (false) qDebug
75 #endif
76 
78 
79 #ifndef QFONTCACHE_DECREASE_TRIGGER_LIMIT
80 # define QFONTCACHE_DECREASE_TRIGGER_LIMIT 256
81 #endif
82 
84 {
85  /*
86  QFontDef comparison is more complicated than just simple
87  per-member comparisons.
88 
89  When comparing point/pixel sizes, either point or pixelsize
90  could be -1. in This case we have to compare the non negative
91  size value.
92 
93  This test will fail if the point-sizes differ by 1/2 point or
94  more or they do not round to the same value. We have to do this
95  since our API still uses 'int' point-sizes in the API, but store
96  deci-point-sizes internally.
97 
98  To compare the family members, we need to parse the font names
99  and compare the family/foundry strings separately. This allows
100  us to compare e.g. "Helvetica" and "Helvetica [Adobe]" with
101  positive results.
102  */
103  if (pixelSize != -1 && other.pixelSize != -1) {
104  if (pixelSize != other.pixelSize)
105  return false;
106  } else if (pointSize != -1 && other.pointSize != -1) {
107  if (pointSize != other.pointSize)
108  return false;
109  } else {
110  return false;
111  }
112 
113  if (!ignorePitch && !other.ignorePitch && fixedPitch != other.fixedPitch)
114  return false;
115 
116  if (stretch != 0 && other.stretch != 0 && stretch != other.stretch)
117  return false;
118 
119  QString this_family, this_foundry, other_family, other_foundry;
120  for (int i = 0; i < families.size(); ++i) {
121  QFontDatabasePrivate::parseFontName(families.at(i), this_foundry, this_family);
122  QFontDatabasePrivate::parseFontName(other.families.at(i), other_foundry, other_family);
123  if (this_family != other_family || this_foundry != other_foundry)
124  return false;
125  }
126 
127  return (styleHint == other.styleHint
128  && styleStrategy == other.styleStrategy
129  && weight == other.weight
130  && style == other.style
131  && this_family == other_family
132  && (styleName.isEmpty() || other.styleName.isEmpty() || styleName == other.styleName)
133  && (this_foundry.isEmpty()
134  || other_foundry.isEmpty()
135  || this_foundry == other_foundry)
136  );
137 }
138 
139 extern bool qt_is_tty_app;
140 
141 Q_GUI_EXPORT int qt_defaultDpiX()
142 {
143  if (QCoreApplication::instance()->testAttribute(Qt::AA_Use96Dpi))
144  return 96;
145 
146  if (qt_is_tty_app)
147  return 75;
148 
150  return qRound(screen->logicalDotsPerInchX());
151 
152  //PI has not been initialised, or it is being initialised. Give a default dpi
153  return 100;
154 }
155 
156 Q_GUI_EXPORT int qt_defaultDpiY()
157 {
158  if (QCoreApplication::instance()->testAttribute(Qt::AA_Use96Dpi))
159  return 96;
160 
161  if (qt_is_tty_app)
162  return 75;
163 
165  return qRound(screen->logicalDotsPerInchY());
166 
167  //PI has not been initialised, or it is being initialised. Give a default dpi
168  return 100;
169 }
170 
171 Q_GUI_EXPORT int qt_defaultDpi()
172 {
173  return qt_defaultDpiY();
174 }
175 
176 /* Helper function to convert between legacy Qt and OpenType font weights. */
177 static int convertWeights(int weight, bool inverted)
178 {
179  static const QVarLengthArray<QPair<int, int>, 9> legacyToOpenTypeMap = {
180  { 0, QFont::Thin }, { 12, QFont::ExtraLight }, { 25, QFont::Light },
181  { 50, QFont::Normal }, { 57, QFont::Medium }, { 63, QFont::DemiBold },
182  { 75, QFont::Bold }, { 81, QFont::ExtraBold }, { 87, QFont::Black },
183  };
184 
185  int closestDist = INT_MAX;
186  int result = -1;
187 
188  // Go through and find the closest mapped value
189  for (auto mapping : legacyToOpenTypeMap) {
190  const int weightOld = inverted ? mapping.second : mapping.first;
191  const int weightNew = inverted ? mapping.first : mapping.second;
192  const int dist = qAbs(weightOld - weight);
193  if (dist < closestDist) {
194  result = weightNew;
195  closestDist = dist;
196  } else {
197  // Break early since following values will be further away
198  break;
199  }
200  }
201 
202  return result;
203 }
204 
205 // Splits the family string on a comma and returns the list based on that
206 static QStringList splitIntoFamilies(const QString &family)
207 {
208  QStringList familyList;
209  if (family.isEmpty())
210  return familyList;
211  const auto list = QStringView{family}.split(QLatin1Char(','));
212  const int numFamilies = list.size();
213  familyList.reserve(numFamilies);
214  for (int i = 0; i < numFamilies; ++i) {
215  auto str = list.at(i).trimmed();
216  if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"')))
217  || (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\'')))) {
218  str = str.mid(1, str.length() - 2);
219  }
220  familyList << str.toString();
221  }
222  return familyList;
223 }
224 
225 /* Converts from legacy Qt font weight (Qt < 6.0) to OpenType font weight (Qt >= 6.0) */
226 Q_GUI_EXPORT int qt_legacyToOpenTypeWeight(int weight)
227 {
228  return convertWeights(weight, false);
229 }
230 
231 /* Converts from OpenType font weight (Qt >= 6.0) to legacy Qt font weight (Qt < 6.0) */
232 Q_GUI_EXPORT int qt_openTypeToLegacyWeight(int weight)
233 {
234  return convertWeights(weight, true);
235 }
236 
238  : engineData(nullptr), dpi(qt_defaultDpi()),
239  underline(false), overline(false), strikeOut(false), kerning(true),
240  capital(0), letterSpacingIsAbsolute(false), scFont(nullptr)
241 {
242 }
243 
245  : request(other.request), engineData(nullptr), dpi(other.dpi),
246  underline(other.underline), overline(other.overline),
247  strikeOut(other.strikeOut), kerning(other.kerning),
248  capital(other.capital), letterSpacingIsAbsolute(other.letterSpacingIsAbsolute),
249  letterSpacing(other.letterSpacing), wordSpacing(other.wordSpacing),
250  scFont(other.scFont)
251 {
252  if (scFont && scFont != this)
253  scFont->ref.ref();
254 }
255 
257 {
258  if (engineData && !engineData->ref.deref())
259  delete engineData;
260  engineData = nullptr;
261  if (scFont && scFont != this) {
262  if (!scFont->ref.deref())
263  delete scFont;
264  }
265  scFont = nullptr;
266 }
267 
269 
270 #define QT_FONT_ENGINE_FROM_DATA(data, script) data->engines[script]
271 
273 {
278  // throw out engineData that came from a different thread
279  if (!engineData->ref.deref())
280  delete engineData;
281  engineData = nullptr;
282  }
286 }
287 
289  switch (capital) {
290  case QFont::AllUppercase:
291  case QFont::SmallCaps:
292  c = c.toUpper();
293  break;
294  case QFont::AllLowercase:
295  c = c.toLower();
296  break;
297  case QFont::MixedCase:
298  break;
299  }
300 }
301 
303 {
304  if (scFont)
305  return scFont;
306  QFont font(const_cast<QFontPrivate *>(this));
307  qreal pointSize = font.pointSizeF();
308  if (pointSize > 0)
309  font.setPointSizeF(pointSize * .7);
310  else
311  font.setPixelSize((font.pixelSize() * 7 + 5) / 10);
312  scFont = font.d.data();
313  if (scFont != this)
314  scFont->ref.ref();
315  return scFont;
316 }
317 
318 
320 {
321  Q_ASSERT(other != nullptr);
322 
323  dpi = other->dpi;
324 
326 
327  // assign the unset-bits with the set-bits of the other font def
328  if (!(mask & QFont::FamiliesResolved))
329  request.families = other->request.families;
330 
331  if (! (mask & QFont::StyleNameResolved))
332  request.styleName = other->request.styleName;
333 
334  if (! (mask & QFont::SizeResolved)) {
335  request.pointSize = other->request.pointSize;
336  request.pixelSize = other->request.pixelSize;
337  }
338 
339  if (! (mask & QFont::StyleHintResolved))
340  request.styleHint = other->request.styleHint;
341 
343  request.styleStrategy = other->request.styleStrategy;
344 
345  if (! (mask & QFont::WeightResolved))
346  request.weight = other->request.weight;
347 
348  if (! (mask & QFont::StyleResolved))
349  request.style = other->request.style;
350 
352  request.fixedPitch = other->request.fixedPitch;
353 
354  if (! (mask & QFont::StretchResolved))
355  request.stretch = other->request.stretch;
356 
358  request.hintingPreference = other->request.hintingPreference;
359 
360  if (! (mask & QFont::UnderlineResolved))
361  underline = other->underline;
362 
363  if (! (mask & QFont::OverlineResolved))
364  overline = other->overline;
365 
366  if (! (mask & QFont::StrikeOutResolved))
367  strikeOut = other->strikeOut;
368 
369  if (! (mask & QFont::KerningResolved))
370  kerning = other->kerning;
371 
373  letterSpacing = other->letterSpacing;
374  letterSpacingIsAbsolute = other->letterSpacingIsAbsolute;
375  }
377  wordSpacing = other->wordSpacing;
379  capital = other->capital;
380 }
381 
382 
383 
384 
386  : ref(0), fontCacheId(QFontCache::instance()->id())
387 {
388  memset(engines, 0, QChar::ScriptCount * sizeof(QFontEngine *));
389 }
390 
392 {
393  Q_ASSERT(ref.loadRelaxed() == 0);
394  for (int i = 0; i < QChar::ScriptCount; ++i) {
395  if (engines[i]) {
396  if (!engines[i]->ref.deref())
397  delete engines[i];
398  engines[i] = nullptr;
399  }
400  }
401 }
402 
403 
404 
405 
626  : resolve_mask(font.resolve_mask)
627 {
628  Q_ASSERT(pd);
629  const int dpi = pd->logicalDpiY();
630  if (font.d->dpi != dpi) {
631  d = new QFontPrivate(*font.d);
632  d->dpi = dpi;
633  } else {
634  d = font.d;
635  }
636 }
637 
642  : d(data), resolve_mask(QFont::AllPropertiesResolved)
643 {
644 }
645 
649 void QFont::detach()
650 {
651  if (d->ref.loadRelaxed() == 1) {
652  if (d->engineData && !d->engineData->ref.deref())
653  delete d->engineData;
654  d->engineData = nullptr;
655  if (d->scFont && d->scFont != d.data()) {
656  if (!d->scFont->ref.deref())
657  delete d->scFont;
658  }
659  d->scFont = nullptr;
660  return;
661  }
662 
663  d.detach();
664 }
665 
673 {
674  if (font->d->ref.loadRelaxed() == 1)
675  return;
676 
678  if (engineData)
679  engineData->ref.ref();
680  font->d.detach();
681  font->d->engineData = engineData;
682 }
683 
690  : d(QGuiApplicationPrivate::instance() ? QGuiApplication::font().d.data() : new QFontPrivate()), resolve_mask(0)
691 {
692 }
693 
716 QFont::QFont(const QString &family, int pointSize, int weight, bool italic)
717  : d(new QFontPrivate()), resolve_mask(QFont::FamiliesResolved)
718 {
719  if (pointSize <= 0) {
720  pointSize = 12;
721  } else {
722  resolve_mask |= QFont::SizeResolved;
723  }
724 
725  if (weight < 0) {
726  weight = Normal;
727  } else {
729  }
730 
731  if (italic)
732  resolve_mask |= QFont::StyleResolved;
733 
734  d->request.families = splitIntoFamilies(family);
736  d->request.pixelSize = -1;
737  d->request.weight = weight;
739 }
740 
759 QFont::QFont(const QStringList &families, int pointSize, int weight, bool italic)
760  : d(new QFontPrivate()), resolve_mask(QFont::FamiliesResolved)
761 {
762  if (pointSize <= 0)
763  pointSize = 12;
764  else
765  resolve_mask |= QFont::SizeResolved;
766 
767  if (weight < 0)
768  weight = Normal;
769  else
771 
772  if (italic)
773  resolve_mask |= QFont::StyleResolved;
774 
777  d->request.pixelSize = -1;
778  d->request.weight = weight;
780 }
781 
786  : d(font.d), resolve_mask(font.resolve_mask)
787 {
788 }
789 
794 {
795 }
796 
801 {
802  d = font.d;
803  resolve_mask = font.resolve_mask;
804  return *this;
805 }
806 
822 {
823  return d->request.families.isEmpty() ? QString() : d->request.families.first();
824 }
825 
844 void QFont::setFamily(const QString &family)
845 {
846 #ifdef QT_DEBUG
847  if (family.contains(QLatin1Char(','))) {
848  qWarning("From Qt 6.2, QFont::setFamily() will no long split the family string on the comma"
849  " and will keep it as a single family");
850  }
851 #endif
852  setFamilies(splitIntoFamilies(family));
853 }
854 
865 {
866  return d->request.styleName;
867 }
868 
882 void QFont::setStyleName(const QString &styleName)
883 {
884  if ((resolve_mask & QFont::StyleNameResolved) && d->request.styleName == styleName)
885  return;
886 
887  detach();
888 
890  resolve_mask |= QFont::StyleNameResolved;
891 }
892 
899 int QFont::pointSize() const
900 {
901  return qRound(d->request.pointSize);
902 }
903 
979 {
981  return;
982 
983  detach();
984 
986 
987  resolve_mask |= QFont::HintingPreferenceResolved;
988 }
989 
996 {
998 }
999 
1006 void QFont::setPointSize(int pointSize)
1007 {
1008  if (pointSize <= 0) {
1009  qWarning("QFont::setPointSize: Point size <= 0 (%d), must be greater than 0", pointSize);
1010  return;
1011  }
1012 
1013  if ((resolve_mask & QFont::SizeResolved) && d->request.pointSize == qreal(pointSize))
1014  return;
1015 
1016  detach();
1017 
1019  d->request.pixelSize = -1;
1020 
1021  resolve_mask |= QFont::SizeResolved;
1022 }
1023 
1032 {
1033  if (pointSize <= 0) {
1034  qWarning("QFont::setPointSizeF: Point size <= 0 (%f), must be greater than 0", pointSize);
1035  return;
1036  }
1037 
1038  if ((resolve_mask & QFont::SizeResolved) && d->request.pointSize == pointSize)
1039  return;
1040 
1041  detach();
1042 
1044  d->request.pixelSize = -1;
1045 
1046  resolve_mask |= QFont::SizeResolved;
1047 }
1048 
1056 {
1057  return d->request.pointSize;
1058 }
1059 
1069 void QFont::setPixelSize(int pixelSize)
1070 {
1071  if (pixelSize <= 0) {
1072  qWarning("QFont::setPixelSize: Pixel size <= 0 (%d)", pixelSize);
1073  return;
1074  }
1075 
1076  if ((resolve_mask & QFont::SizeResolved) && d->request.pixelSize == qreal(pixelSize))
1077  return;
1078 
1079  detach();
1080 
1082  d->request.pointSize = -1;
1083 
1084  resolve_mask |= QFont::SizeResolved;
1085 }
1086 
1094 int QFont::pixelSize() const
1095 {
1096  return d->request.pixelSize;
1097 }
1098 
1126 {
1127  return (QFont::Style)d->request.style;
1128 }
1129 
1130 
1137 {
1138  if ((resolve_mask & QFont::StyleResolved) && d->request.style == style)
1139  return;
1140 
1141  detach();
1142 
1143  d->request.style = style;
1144  resolve_mask |= QFont::StyleResolved;
1145 }
1146 
1154 {
1155  return static_cast<Weight>(d->request.weight);
1156 }
1157 
1177 #if QT_DEPRECATED_SINCE(6, 0)
1193 void QFont::setLegacyWeight(int legacyWeight)
1194 {
1196 }
1197 
1211 int QFont::legacyWeight() const
1212 {
1214 }
1215 #endif // QT_DEPRECATED_SINCE(6, 0)
1216 
1226 {
1227  const int weightValue = qBound(QFONT_WEIGHT_MIN, static_cast<int>(weight), QFONT_WEIGHT_MAX);
1228  if (weightValue != static_cast<int>(weight)) {
1229  qWarning() << "QFont::setWeight: Weight must be between 1 and 1000, attempted to set "
1230  << static_cast<int>(weight);
1231  }
1232 
1233  if ((resolve_mask & QFont::WeightResolved) && d->request.weight == weightValue)
1234  return;
1235 
1236  detach();
1237 
1238  d->request.weight = weightValue;
1239  resolve_mask |= QFont::WeightResolved;
1240 }
1241 
1271 bool QFont::underline() const
1272 {
1273  return d->underline;
1274 }
1275 
1283 {
1284  if ((resolve_mask & QFont::UnderlineResolved) && d->underline == enable)
1285  return;
1286 
1288 
1289  d->underline = enable;
1290  resolve_mask |= QFont::UnderlineResolved;
1291 }
1292 
1298 bool QFont::overline() const
1299 {
1300  return d->overline;
1301 }
1302 
1309 {
1310  if ((resolve_mask & QFont::OverlineResolved) && d->overline == enable)
1311  return;
1312 
1314 
1315  d->overline = enable;
1316  resolve_mask |= QFont::OverlineResolved;
1317 }
1318 
1324 bool QFont::strikeOut() const
1325 {
1326  return d->strikeOut;
1327 }
1328 
1336 {
1337  if ((resolve_mask & QFont::StrikeOutResolved) && d->strikeOut == enable)
1338  return;
1339 
1341 
1342  d->strikeOut = enable;
1343  resolve_mask |= QFont::StrikeOutResolved;
1344 }
1345 
1351 bool QFont::fixedPitch() const
1352 {
1353  return d->request.fixedPitch;
1354 }
1355 
1363 {
1364  if ((resolve_mask & QFont::FixedPitchResolved) && d->request.fixedPitch == enable)
1365  return;
1366 
1367  detach();
1368 
1369  d->request.fixedPitch = enable;
1370  d->request.ignorePitch = false;
1371  resolve_mask |= QFont::FixedPitchResolved;
1372 }
1373 
1379 bool QFont::kerning() const
1380 {
1381  return d->kerning;
1382 }
1383 
1396 {
1397  if ((resolve_mask & QFont::KerningResolved) && d->kerning == enable)
1398  return;
1399 
1401 
1402  d->kerning = enable;
1403  resolve_mask |= QFont::KerningResolved;
1404 }
1405 
1415 {
1416  return (StyleStrategy) d->request.styleStrategy;
1417 }
1418 
1428 {
1429  return (StyleHint) d->request.styleHint;
1430 }
1431 
1518 {
1519  if ((resolve_mask & (QFont::StyleHintResolved | QFont::StyleStrategyResolved)) &&
1520  (StyleHint) d->request.styleHint == hint &&
1521  (StyleStrategy) d->request.styleStrategy == strategy)
1522  return;
1523 
1524  detach();
1525 
1526  d->request.styleHint = hint;
1527  d->request.styleStrategy = strategy;
1528  resolve_mask |= QFont::StyleHintResolved;
1529  resolve_mask |= QFont::StyleStrategyResolved;
1530 
1531 }
1532 
1539 {
1540  if ((resolve_mask & QFont::StyleStrategyResolved) &&
1542  return;
1543 
1544  detach();
1545 
1546  d->request.styleStrategy = s;
1547  resolve_mask |= QFont::StyleStrategyResolved;
1548 }
1549 
1550 
1576 int QFont::stretch() const
1577 {
1578  return d->request.stretch;
1579 }
1580 
1601 {
1602  if (factor < 0 || factor > 4000) {
1603  qWarning("QFont::setStretch: Parameter '%d' out of range", factor);
1604  return;
1605  }
1606 
1607  if ((resolve_mask & QFont::StretchResolved) &&
1608  d->request.stretch == (uint)factor)
1609  return;
1610 
1611  detach();
1612 
1613  d->request.stretch = (uint)factor;
1614  resolve_mask |= QFont::StretchResolved;
1615 }
1616 
1634 {
1635  return d->letterSpacing.toReal();
1636 }
1637 
1651 {
1652  const QFixed newSpacing = QFixed::fromReal(spacing);
1653  const bool absoluteSpacing = type == AbsoluteSpacing;
1654  if ((resolve_mask & QFont::LetterSpacingResolved) &&
1655  d->letterSpacingIsAbsolute == absoluteSpacing &&
1656  d->letterSpacing == newSpacing)
1657  return;
1658 
1660 
1661  d->letterSpacing = newSpacing;
1662  d->letterSpacingIsAbsolute = absoluteSpacing;
1663  resolve_mask |= QFont::LetterSpacingResolved;
1664 }
1665 
1673 {
1675 }
1676 
1684 {
1685  return d->wordSpacing.toReal();
1686 }
1687 
1703 {
1704  const QFixed newSpacing = QFixed::fromReal(spacing);
1705  if ((resolve_mask & QFont::WordSpacingResolved) &&
1706  d->wordSpacing == newSpacing)
1707  return;
1708 
1710 
1711  d->wordSpacing = newSpacing;
1712  resolve_mask |= QFont::WordSpacingResolved;
1713 }
1714 
1738 {
1739  if ((resolve_mask & QFont::CapitalizationResolved) &&
1740  capitalization() == caps)
1741  return;
1742 
1744 
1745  d->capital = caps;
1746  resolve_mask |= QFont::CapitalizationResolved;
1747 }
1748 
1756 {
1757  return static_cast<QFont::Capitalization> (d->capital);
1758 }
1759 
1766 bool QFont::exactMatch() const
1767 {
1769  Q_ASSERT(engine != nullptr);
1770  return d->request.exactMatch(engine->fontDef);
1771 }
1772 
1782 bool QFont::operator==(const QFont &f) const
1783 {
1784  return (f.d == d
1785  || (f.d->request == d->request
1786  && f.d->request.pointSize == d->request.pointSize
1787  && f.d->underline == d->underline
1788  && f.d->overline == d->overline
1789  && f.d->strikeOut == d->strikeOut
1790  && f.d->kerning == d->kerning
1791  && f.d->capital == d->capital
1792  && f.d->letterSpacingIsAbsolute == d->letterSpacingIsAbsolute
1793  && f.d->letterSpacing == d->letterSpacing
1794  && f.d->wordSpacing == d->wordSpacing
1795  ));
1796 }
1797 
1798 
1810 bool QFont::operator<(const QFont &f) const
1811 {
1812  if (f.d == d) return false;
1813  // the < operator for fontdefs ignores point sizes.
1814  const QFontDef &r1 = f.d->request;
1815  const QFontDef &r2 = d->request;
1816  if (r1.pointSize != r2.pointSize) return r1.pointSize < r2.pointSize;
1817  if (r1.pixelSize != r2.pixelSize) return r1.pixelSize < r2.pixelSize;
1818  if (r1.weight != r2.weight) return r1.weight < r2.weight;
1819  if (r1.style != r2.style) return r1.style < r2.style;
1820  if (r1.stretch != r2.stretch) return r1.stretch < r2.stretch;
1821  if (r1.styleHint != r2.styleHint) return r1.styleHint < r2.styleHint;
1822  if (r1.styleStrategy != r2.styleStrategy) return r1.styleStrategy < r2.styleStrategy;
1823  if (r1.families != r2.families) return r1.families < r2.families;
1824  if (f.d->capital != d->capital) return f.d->capital < d->capital;
1825 
1826  if (f.d->letterSpacingIsAbsolute != d->letterSpacingIsAbsolute) return f.d->letterSpacingIsAbsolute < d->letterSpacingIsAbsolute;
1827  if (f.d->letterSpacing != d->letterSpacing) return f.d->letterSpacing < d->letterSpacing;
1828  if (f.d->wordSpacing != d->wordSpacing) return f.d->wordSpacing < d->wordSpacing;
1829 
1830  int f1attrs = (f.d->underline << 3) + (f.d->overline << 2) + (f.d->strikeOut<<1) + f.d->kerning;
1831  int f2attrs = (d->underline << 3) + (d->overline << 2) + (d->strikeOut<<1) + d->kerning;
1832  return f1attrs < f2attrs;
1833 }
1834 
1835 
1845 bool QFont::operator!=(const QFont &f) const
1846 {
1847  return !(operator==(f));
1848 }
1849 
1853 QFont::operator QVariant() const
1854 {
1855  return QVariant::fromValue(*this);
1856 }
1857 
1865 bool QFont::isCopyOf(const QFont & f) const
1866 {
1867  return d == f.d;
1868 }
1869 
1875 {
1876  if (resolve_mask == 0 || (resolve_mask == other.resolve_mask && *this == other)) {
1877  QFont o(other);
1878  o.resolve_mask = resolve_mask;
1879  return o;
1880  }
1881 
1882  QFont font(*this);
1883  font.detach();
1884  font.d->resolve(resolve_mask, other.d.data());
1885 
1886  return font;
1887 }
1888 
1900 /*****************************************************************************
1901  QFont substitution management
1902  *****************************************************************************/
1903 
1905 Q_GLOBAL_STATIC(QFontSubst, globalFontSubst)
1906 
1907 
1918 QString QFont::substitute(const QString &familyName)
1919 {
1920  QFontSubst *fontSubst = globalFontSubst();
1921  Q_ASSERT(fontSubst != nullptr);
1922  QFontSubst::ConstIterator it = fontSubst->constFind(familyName.toLower());
1923  if (it != fontSubst->constEnd() && !(*it).isEmpty())
1924  return (*it).first();
1925 
1926  return familyName;
1927 }
1928 
1929 
1940 {
1941  QFontSubst *fontSubst = globalFontSubst();
1942  Q_ASSERT(fontSubst != nullptr);
1943  return fontSubst->value(familyName.toLower(), QStringList());
1944 }
1945 
1946 
1956 void QFont::insertSubstitution(const QString &familyName,
1957  const QString &substituteName)
1958 {
1959  QFontSubst *fontSubst = globalFontSubst();
1960  Q_ASSERT(fontSubst != nullptr);
1961  QStringList &list = (*fontSubst)[familyName.toLower()];
1962  QString s = substituteName.toLower();
1963  if (!list.contains(s))
1964  list.append(s);
1965 }
1966 
1967 
1978 void QFont::insertSubstitutions(const QString &familyName,
1979  const QStringList &substituteNames)
1980 {
1981  QFontSubst *fontSubst = globalFontSubst();
1982  Q_ASSERT(fontSubst != nullptr);
1983  QStringList &list = (*fontSubst)[familyName.toLower()];
1984  for (const QString &substituteName : substituteNames) {
1985  const QString lowerSubstituteName = substituteName.toLower();
1986  if (!list.contains(lowerSubstituteName))
1987  list.append(lowerSubstituteName);
1988  }
1989 }
1990 
1997 void QFont::removeSubstitutions(const QString &familyName)
1998 {
1999  QFontSubst *fontSubst = globalFontSubst();
2000  Q_ASSERT(fontSubst != nullptr);
2001  fontSubst->remove(familyName.toLower());
2002 }
2003 
2010 {
2011  QFontSubst *fontSubst = globalFontSubst();
2012  Q_ASSERT(fontSubst != nullptr);
2013  QStringList ret = fontSubst->keys();
2014 
2015  ret.sort();
2016  return ret;
2017 }
2018 
2019 #ifndef QT_NO_DATASTREAM
2020 /* \internal
2021  Internal function. Converts boolean font settings to an unsigned
2022  8-bit number. Used for serialization etc.
2023 */
2024 static quint8 get_font_bits(int version, const QFontPrivate *f)
2025 {
2026  Q_ASSERT(f != nullptr);
2027  quint8 bits = 0;
2028  if (f->request.style)
2029  bits |= 0x01;
2030  if (f->underline)
2031  bits |= 0x02;
2032  if (f->overline)
2033  bits |= 0x40;
2034  if (f->strikeOut)
2035  bits |= 0x04;
2036  if (f->request.fixedPitch)
2037  bits |= 0x08;
2038  // if (f.hintSetByUser)
2039  // bits |= 0x10;
2040  if (version >= QDataStream::Qt_4_0) {
2041  if (f->kerning)
2042  bits |= 0x10;
2043  }
2044  if (f->request.style == QFont::StyleOblique)
2045  bits |= 0x80;
2046  return bits;
2047 }
2048 
2049 static quint8 get_extended_font_bits(const QFontPrivate *f)
2050 {
2051  Q_ASSERT(f != nullptr);
2052  quint8 bits = 0;
2053  if (f->request.ignorePitch)
2054  bits |= 0x01;
2055  if (f->letterSpacingIsAbsolute)
2056  bits |= 0x02;
2057  return bits;
2058 }
2059 
2060 /* \internal
2061  Internal function. Sets boolean font settings from an unsigned
2062  8-bit number. Used for serialization etc.
2063 */
2064 static void set_font_bits(int version, quint8 bits, QFontPrivate *f)
2065 {
2066  Q_ASSERT(f != nullptr);
2067  f->request.style = (bits & 0x01) != 0 ? QFont::StyleItalic : QFont::StyleNormal;
2068  f->underline = (bits & 0x02) != 0;
2069  f->overline = (bits & 0x40) != 0;
2070  f->strikeOut = (bits & 0x04) != 0;
2071  f->request.fixedPitch = (bits & 0x08) != 0;
2072  // f->hintSetByUser = (bits & 0x10) != 0;
2074  f->kerning = (bits & 0x10) != 0;
2075  if ((bits & 0x80) != 0)
2076  f->request.style = QFont::StyleOblique;
2077 }
2078 
2079 static void set_extended_font_bits(quint8 bits, QFontPrivate *f)
2080 {
2081  Q_ASSERT(f != nullptr);
2082  f->request.ignorePitch = (bits & 0x01) != 0;
2083  f->letterSpacingIsAbsolute = (bits & 0x02) != 0;
2084 }
2085 #endif
2086 
2094 {
2095  return toString();
2096 }
2097 
2125 {
2126  const QChar comma(QLatin1Char(','));
2127  QString fontDescription = family() + comma +
2130  QString::number((int) styleHint()) + comma +
2131  QString::number( weight()) + comma +
2132  QString::number((int) style()) + comma +
2133  QString::number((int) underline()) + comma +
2134  QString::number((int) strikeOut()) + comma +
2135  QString::number((int)fixedPitch()) + comma +
2136  QString::number((int) false) + comma +
2143 
2145  if (!fontStyle.isEmpty())
2146  fontDescription += comma + fontStyle;
2147 
2148  return fontDescription;
2149 }
2150 
2158 size_t qHash(const QFont &font, size_t seed) noexcept
2159 {
2160  return qHash(QFontPrivate::get(font)->request, seed);
2161 }
2162 
2163 
2171 bool QFont::fromString(const QString &descrip)
2172 {
2173  const auto sr = QStringView(descrip).trimmed();
2174  const auto l = sr.split(QLatin1Char(','));
2175  const int count = l.count();
2176  if (!count || (count > 2 && count < 9) || count == 9 || count > 17 ||
2177  l.first().isEmpty()) {
2178  qWarning("QFont::fromString: Invalid description '%s'",
2179  descrip.isEmpty() ? "(empty)" : descrip.toLatin1().data());
2180  return false;
2181  }
2182 
2183  setFamily(l[0].toString());
2184  if (count > 1 && l[1].toDouble() > 0.0)
2185  setPointSizeF(l[1].toDouble());
2186  if (count == 9) {
2187  setStyleHint((StyleHint) l[2].toInt());
2188  setWeight(QFont::Weight(l[3].toInt()));
2189  setItalic(l[4].toInt());
2190  setUnderline(l[5].toInt());
2191  setStrikeOut(l[6].toInt());
2192  setFixedPitch(l[7].toInt());
2193  } else if (count >= 10) {
2194  if (l[2].toInt() > 0)
2195  setPixelSize(l[2].toInt());
2196  setStyleHint((StyleHint) l[3].toInt());
2197  if (count >= 16)
2198  setWeight(QFont::Weight(l[4].toInt()));
2199  else
2201  setStyle((QFont::Style)l[5].toInt());
2202  setUnderline(l[6].toInt());
2203  setStrikeOut(l[7].toInt());
2204  setFixedPitch(l[8].toInt());
2205  if (count >= 16) {
2206  setCapitalization((Capitalization)l[10].toInt());
2207  setLetterSpacing((SpacingType)l[11].toInt(), l[12].toDouble());
2208  setWordSpacing(l[13].toDouble());
2209  setStretch(l[14].toInt());
2210  setStyleStrategy((StyleStrategy)l[15].toInt());
2211  }
2212  if (count == 11 || count == 17)
2213  d->request.styleName = l[count - 1].toString();
2214  else
2215  d->request.styleName.clear();
2216  }
2217 
2218  if (count >= 9 && !d->request.fixedPitch) // assume 'false' fixedPitch equals default
2219  d->request.ignorePitch = true;
2220 
2221  return true;
2222 }
2223 
2232 {
2233 }
2234 
2241 {
2243 }
2244 
2250 {
2251 }
2252 
2253 
2256 
2266 {
2269  if (!fallbacks.isEmpty())
2270  return fallbacks.first();
2271  return QString();
2272 }
2273 
2285 {
2286  return d->request.families;
2287 }
2288 
2306 void QFont::setFamilies(const QStringList &families)
2307 {
2308  if ((resolve_mask & QFont::FamiliesResolved) && d->request.families == families)
2309  return;
2310  detach();
2311  d->request.families = families;
2312  resolve_mask |= QFont::FamiliesResolved;
2313 }
2314 
2315 
2316 /*****************************************************************************
2317  QFont stream functions
2318  *****************************************************************************/
2319 #ifndef QT_NO_DATASTREAM
2320 
2330 {
2331  if (s.version() == 1) {
2332  s << font.d->request.families.first().toLatin1();
2333  } else {
2334  s << font.d->request.families.first();
2335  if (s.version() >= QDataStream::Qt_5_4)
2336  s << font.d->request.styleName;
2337  }
2338 
2339  if (s.version() >= QDataStream::Qt_4_0) {
2340  // 4.0
2341  double pointSize = font.d->request.pointSize;
2342  qint32 pixelSize = font.d->request.pixelSize;
2343  s << pointSize;
2344  s << pixelSize;
2345  } else if (s.version() <= 3) {
2346  qint16 pointSize = (qint16) (font.d->request.pointSize * 10);
2347  if (pointSize < 0) {
2348  pointSize = (qint16)QFontInfo(font).pointSize() * 10;
2349  }
2350  s << pointSize;
2351  } else {
2352  s << (qint16) (font.d->request.pointSize * 10);
2353  s << (qint16) font.d->request.pixelSize;
2354  }
2355 
2356  s << (quint8) font.d->request.styleHint;
2357  if (s.version() >= QDataStream::Qt_3_1) {
2358  // Continue writing 8 bits for versions < 5.4 so that we don't write too much,
2359  // even though we need 16 to store styleStrategy, so there is some data loss.
2360  if (s.version() >= QDataStream::Qt_5_4)
2362  else
2363  s << (quint8) font.d->request.styleStrategy;
2364  }
2365 
2366  if (s.version() < QDataStream::Qt_6_0)
2368  else
2369  s << quint16(font.d->request.weight);
2370 
2371  s << get_font_bits(s.version(), font.d.data());
2372  if (s.version() >= QDataStream::Qt_4_3)
2373  s << (quint16)font.d->request.stretch;
2374  if (s.version() >= QDataStream::Qt_4_4)
2375  s << get_extended_font_bits(font.d.data());
2376  if (s.version() >= QDataStream::Qt_4_5) {
2377  s << font.d->letterSpacing.value();
2378  s << font.d->wordSpacing.value();
2379  }
2380  if (s.version() >= QDataStream::Qt_5_4)
2382  if (s.version() >= QDataStream::Qt_5_6)
2383  s << (quint8)font.d->capital;
2384  if (s.version() >= QDataStream::Qt_5_13) {
2385  if (s.version() < QDataStream::Qt_6_0)
2386  s << font.d->request.families.mid(1);
2387  else
2388  s << font.d->request.families;
2389  }
2390  return s;
2391 }
2392 
2393 
2403 {
2404  font.d = new QFontPrivate;
2405  font.resolve_mask = QFont::AllPropertiesResolved;
2406 
2407  quint8 styleHint, bits;
2408  quint16 styleStrategy = QFont::PreferDefault;
2409 
2410  if (s.version() == 1) {
2411  QByteArray fam;
2412  s >> fam;
2414  } else {
2415  QString fam;
2416  s >> fam;
2417  font.d->request.families = QStringList(fam);
2418  if (s.version() >= QDataStream::Qt_5_4)
2419  s >> font.d->request.styleName;
2420  }
2421 
2422  if (s.version() >= QDataStream::Qt_4_0) {
2423  // 4.0
2424  double pointSize;
2425  qint32 pixelSize;
2426  s >> pointSize;
2427  s >> pixelSize;
2428  font.d->request.pointSize = qreal(pointSize);
2429  font.d->request.pixelSize = pixelSize;
2430  } else {
2431  qint16 pointSize, pixelSize = -1;
2432  s >> pointSize;
2433  if (s.version() >= 4)
2434  s >> pixelSize;
2435  font.d->request.pointSize = qreal(pointSize / 10.);
2436  font.d->request.pixelSize = pixelSize;
2437  }
2438  s >> styleHint;
2439  if (s.version() >= QDataStream::Qt_3_1) {
2440  if (s.version() >= QDataStream::Qt_5_4) {
2441  s >> styleStrategy;
2442  } else {
2443  quint8 tempStyleStrategy;
2444  s >> tempStyleStrategy;
2445  styleStrategy = tempStyleStrategy;
2446  }
2447  }
2448 
2449  if (s.version() < QDataStream::Qt_6_0) {
2450  quint8 charSet;
2451  quint8 weight;
2452  s >> charSet;
2453  s >> weight;
2455  } else {
2456  quint16 weight;
2457  s >> weight;
2458  font.d->request.weight = weight;
2459  }
2460 
2461  s >> bits;
2462 
2463  font.d->request.styleHint = styleHint;
2464  font.d->request.styleStrategy = styleStrategy;
2465 
2466  set_font_bits(s.version(), bits, font.d.data());
2467 
2468  if (s.version() >= QDataStream::Qt_4_3) {
2469  quint16 stretch;
2470  s >> stretch;
2471  font.d->request.stretch = stretch;
2472  }
2473 
2474  if (s.version() >= QDataStream::Qt_4_4) {
2475  quint8 extendedBits;
2476  s >> extendedBits;
2477  set_extended_font_bits(extendedBits, font.d.data());
2478  }
2479  if (s.version() >= QDataStream::Qt_4_5) {
2480  int value;
2481  s >> value;
2483  s >> value;
2485  }
2486  if (s.version() >= QDataStream::Qt_5_4) {
2487  quint8 value;
2488  s >> value;
2490  }
2491  if (s.version() >= QDataStream::Qt_5_6) {
2492  quint8 value;
2493  s >> value;
2495  }
2496  if (s.version() >= QDataStream::Qt_5_13) {
2498  s >> value;
2499  if (s.version() < QDataStream::Qt_6_0)
2500  font.d->request.families.append(value);
2501  else
2502  font.d->request.families = value;
2503  }
2504  return s;
2505 }
2506 
2507 #endif // QT_NO_DATASTREAM
2508 
2509 
2510 /*****************************************************************************
2511  QFontInfo member functions
2512  *****************************************************************************/
2513 
2575  : d(font.d)
2576 {
2577 }
2578 
2583  : d(fi.d)
2584 {
2585 }
2586 
2591 {
2592 }
2593 
2598 {
2599  d = fi.d;
2600  return *this;
2601 }
2602 
2617 {
2619  Q_ASSERT(engine != nullptr);
2620  return engine->fontDef.families.isEmpty() ? QString() : engine->fontDef.families.first();
2621 }
2622 
2632 {
2634  Q_ASSERT(engine != nullptr);
2635  return engine->fontDef.styleName;
2636 }
2637 
2644 {
2646  Q_ASSERT(engine != nullptr);
2647  return qRound(engine->fontDef.pointSize);
2648 }
2649 
2656 {
2658  Q_ASSERT(engine != nullptr);
2659  return engine->fontDef.pointSize;
2660 }
2661 
2668 {
2670  Q_ASSERT(engine != nullptr);
2671  return engine->fontDef.pixelSize;
2672 }
2673 
2679 bool QFontInfo::italic() const
2680 {
2682  Q_ASSERT(engine != nullptr);
2683  return engine->fontDef.style != QFont::StyleNormal;
2684 }
2685 
2692 {
2694  Q_ASSERT(engine != nullptr);
2695  return (QFont::Style)engine->fontDef.style;
2696 }
2697 
2698 
2699 #if QT_DEPRECATED_SINCE(6, 0)
2713 int QFontInfo::legacyWeight() const
2714 {
2716 }
2717 #endif // QT_DEPRECATED_SINCE(6, 0)
2718 
2719 
2726 {
2728  Q_ASSERT(engine != nullptr);
2729  return engine->fontDef.weight;
2730 
2731 }
2732 
2753 {
2754  return d->underline;
2755 }
2756 
2768 {
2769  return d->overline;
2770 }
2771 
2781 {
2782  return d->strikeOut;
2783 }
2784 
2791 {
2793  Q_ASSERT(engine != nullptr);
2794 #ifdef Q_OS_MAC
2795  if (!engine->fontDef.fixedPitchComputed) {
2796  QChar ch[2] = { QLatin1Char('i'), QLatin1Char('m') };
2798  int l = 2;
2799  if (!engine->stringToCMap(ch, 2, &g, &l, {}))
2800  Q_UNREACHABLE();
2801  Q_ASSERT(l == 2);
2802  engine->fontDef.fixedPitch = g.advances[0] == g.advances[1];
2803  engine->fontDef.fixedPitchComputed = true;
2804  }
2805 #endif
2806  return engine->fontDef.fixedPitch;
2807 }
2808 
2817 {
2819  Q_ASSERT(engine != nullptr);
2820  return (QFont::StyleHint) engine->fontDef.styleHint;
2821 }
2822 
2830 {
2832  Q_ASSERT(engine != nullptr);
2833  return d->request.exactMatch(engine->fontDef);
2834 }
2835 
2836 
2837 
2838 
2839 // **********************************************************************
2840 // QFontCache
2841 // **********************************************************************
2842 
2843 #ifdef QFONTCACHE_DEBUG
2844 // fast timeouts for debugging
2845 static const int fast_timeout = 1000; // 1s
2846 static const int slow_timeout = 5000; // 5s
2847 #else
2848 static const int fast_timeout = 10000; // 10s
2849 static const int slow_timeout = 300000; // 5m
2850 #endif // QFONTCACHE_DEBUG
2851 
2852 #ifndef QFONTCACHE_MIN_COST
2853 # define QFONTCACHE_MIN_COST 4*1024 // 4mb
2854 #endif
2855 const uint QFontCache::min_cost = QFONTCACHE_MIN_COST;
2857 
2859 {
2860  QFontCache *&fontCache = theFontCache()->localData();
2861  if (!fontCache)
2862  fontCache = new QFontCache;
2863  return fontCache;
2864 }
2865 
2867 {
2869  QT_TRY {
2870  cache = theFontCache();
2871  } QT_CATCH (const std::bad_alloc &) {
2872  // no cache - just ignore
2873  }
2874  if (cache && cache->hasLocalData())
2875  cache->setLocalData(nullptr);
2876 }
2877 
2878 static QBasicAtomicInt font_cache_id = Q_BASIC_ATOMIC_INITIALIZER(0);
2879 
2881  : QObject(), total_cost(0), max_cost(min_cost),
2882  current_timestamp(0), fast(false),
2883  autoClean(QGuiApplication::instance()
2884  && (QGuiApplication::instance()->thread() == QThread::currentThread())),
2885  timer_id(-1),
2886  m_id(font_cache_id.fetchAndAddRelaxed(1) + 1)
2887 {
2888 }
2889 
2891 {
2892  clear();
2893 }
2894 
2896 {
2897  {
2899  end = engineDataCache.end();
2900  while (it != end) {
2901  QFontEngineData *data = it.value();
2902  for (int i = 0; i < QChar::ScriptCount; ++i) {
2903  if (data->engines[i]) {
2904  if (!data->engines[i]->ref.deref()) {
2905  Q_ASSERT(engineCacheCount.value(data->engines[i]) == 0);
2906  delete data->engines[i];
2907  }
2908  data->engines[i] = nullptr;
2909  }
2910  }
2911  if (!data->ref.deref()) {
2912  delete data;
2913  } else {
2914  FC_DEBUG("QFontCache::clear: engineData %p still has refcount %d",
2915  data, data->ref.loadRelaxed());
2916  }
2917  ++it;
2918  }
2919  }
2920 
2922 
2923 
2924  bool mightHaveEnginesLeftForCleanup;
2925  do {
2926  mightHaveEnginesLeftForCleanup = false;
2928  it != end; ++it) {
2929  QFontEngine *engine = it.value().data;
2930  if (engine) {
2931  const int cacheCount = --engineCacheCount[engine];
2932  Q_ASSERT(cacheCount >= 0);
2933  if (!engine->ref.deref()) {
2934  Q_ASSERT(cacheCount == 0);
2935  mightHaveEnginesLeftForCleanup = engine->type() == QFontEngine::Multi;
2936  delete engine;
2937  } else if (cacheCount == 0) {
2938  FC_DEBUG("QFontCache::clear: engine %p still has refcount %d",
2939  engine, engine->ref.loadRelaxed());
2940  }
2941  it.value().data = nullptr;
2942  }
2943  }
2944  } while (mightHaveEnginesLeftForCleanup);
2945 
2946  engineCache.clear();
2948 
2949 
2950  total_cost = 0;
2951  max_cost = min_cost;
2952 }
2953 
2954 
2956 {
2958  if (it == engineDataCache.constEnd())
2959  return nullptr;
2960 
2961  // found
2962  return it.value();
2963 }
2964 
2966 {
2967 #ifdef QFONTCACHE_DEBUG
2968  FC_DEBUG("QFontCache: inserting new engine data %p", engineData);
2969  if (engineDataCache.contains(def)) {
2970  FC_DEBUG(" QFontCache already contains engine data %p for key=(%g %g %d %d %d)",
2971  engineDataCache.value(def), def.pointSize,
2972  def.pixelSize, def.weight, def.style, def.fixedPitch);
2973  }
2974 #endif
2976 
2977  engineData->ref.ref();
2978  // Decrease now rather than waiting
2979  if (total_cost > min_cost * 2 && engineDataCache.size() >= QFONTCACHE_DECREASE_TRIGGER_LIMIT)
2980  decreaseCache();
2981 
2982  engineDataCache.insert(def, engineData);
2983  increaseCost(sizeof(QFontEngineData));
2984 }
2985 
2987 {
2989  end = engineCache.end();
2990  if (it == end) return nullptr;
2991 
2992  Q_ASSERT(it.value().data != nullptr);
2993  Q_ASSERT(key.multi == (it.value().data->type() == QFontEngine::Multi));
2994 
2995  // found... update the hitcount and timestamp
2996  updateHitCountAndTimeStamp(it.value());
2997 
2998  return it.value().data;
2999 }
3000 
3002 {
3003  value.hits++;
3004  value.timestamp = ++current_timestamp;
3005 
3006  FC_DEBUG("QFontCache: found font engine\n"
3007  " %p: timestamp %4u hits %3u ref %2d/%2d, type %d",
3008  value.data, value.timestamp, value.hits,
3009  value.data->ref.loadRelaxed(), engineCacheCount.value(value.data),
3010  value.data->type());
3011 }
3012 
3013 void QFontCache::insertEngine(const Key &key, QFontEngine *engine, bool insertMulti)
3014 {
3015  Q_ASSERT(engine != nullptr);
3016  Q_ASSERT(key.multi == (engine->type() == QFontEngine::Multi));
3017 
3018 #ifdef QFONTCACHE_DEBUG
3019  FC_DEBUG("QFontCache: inserting new engine %p, refcount %d", engine, engine->ref.loadRelaxed());
3020  if (!insertMulti && engineCache.contains(key)) {
3021  FC_DEBUG(" QFontCache already contains engine %p for key=(%g %g %d %d %d)",
3022  engineCache.value(key).data, key.def.pointSize,
3023  key.def.pixelSize, key.def.weight, key.def.style, key.def.fixedPitch);
3024  }
3025 #endif
3026  engine->ref.ref();
3027  // Decrease now rather than waiting
3028  if (total_cost > min_cost * 2 && engineCache.size() >= QFONTCACHE_DECREASE_TRIGGER_LIMIT)
3029  decreaseCache();
3030 
3031  Engine data(engine);
3032  data.timestamp = ++current_timestamp;
3033 
3034  if (insertMulti)
3036  else
3038  // only increase the cost if this is the first time we insert the engine
3039  if (++engineCacheCount[engine] == 1)
3040  increaseCost(engine->cache_cost);
3041 }
3042 
3043 void QFontCache::increaseCost(uint cost)
3044 {
3045  cost = (cost + 512) / 1024; // store cost in kb
3046  cost = cost > 0 ? cost : 1;
3047  total_cost += cost;
3048 
3049  FC_DEBUG(" COST: increased %u kb, total_cost %u kb, max_cost %u kb",
3050  cost, total_cost, max_cost);
3051 
3052  if (total_cost > max_cost) {
3053  max_cost = total_cost;
3054 
3055  if (!autoClean)
3056  return;
3057 
3058  if (timer_id == -1 || ! fast) {
3059  FC_DEBUG(" TIMER: starting fast timer (%d ms)", fast_timeout);
3060 
3061  if (timer_id != -1)
3062  killTimer(timer_id);
3063  timer_id = startTimer(fast_timeout);
3064  fast = true;
3065  }
3066  }
3067 }
3068 
3069 void QFontCache::decreaseCost(uint cost)
3070 {
3071  cost = (cost + 512) / 1024; // cost is stored in kb
3072  cost = cost > 0 ? cost : 1;
3073  Q_ASSERT(cost <= total_cost);
3074  total_cost -= cost;
3075 
3076  FC_DEBUG(" COST: decreased %u kb, total_cost %u kb, max_cost %u kb",
3077  cost, total_cost, max_cost);
3078 }
3079 
3080 void QFontCache::timerEvent(QTimerEvent *)
3081 {
3082  FC_DEBUG("QFontCache::timerEvent: performing cache maintenance (timestamp %u)",
3083  current_timestamp);
3084 
3085  if (total_cost <= max_cost && max_cost <= min_cost) {
3086  FC_DEBUG(" cache redused sufficiently, stopping timer");
3087 
3088  killTimer(timer_id);
3089  timer_id = -1;
3090  fast = false;
3091 
3092  return;
3093  }
3094  decreaseCache();
3095 }
3096 
3097 void QFontCache::decreaseCache()
3098 {
3099  // go through the cache and count up everything in use
3100  uint in_use_cost = 0;
3101 
3102  {
3103  FC_DEBUG(" SWEEP engine data:");
3104 
3105  // make sure the cost of each engine data is at least 1kb
3106  const uint engine_data_cost =
3107  sizeof(QFontEngineData) > 1024 ? sizeof(QFontEngineData) : 1024;
3108 
3111  for (; it != end; ++it) {
3112  FC_DEBUG(" %p: ref %2d", it.value(), int(it.value()->ref.loadRelaxed()));
3113 
3114  if (it.value()->ref.loadRelaxed() != 1)
3115  in_use_cost += engine_data_cost;
3116  }
3117  }
3118 
3119  {
3120  FC_DEBUG(" SWEEP engine:");
3121 
3123  end = engineCache.constEnd();
3124  for (; it != end; ++it) {
3125  FC_DEBUG(" %p: timestamp %4u hits %2u ref %2d/%2d, cost %u bytes",
3126  it.value().data, it.value().timestamp, it.value().hits,
3127  it.value().data->ref.loadRelaxed(), engineCacheCount.value(it.value().data),
3128  it.value().data->cache_cost);
3129 
3130  if (it.value().data->ref.loadRelaxed() > engineCacheCount.value(it.value().data))
3131  in_use_cost += it.value().data->cache_cost / engineCacheCount.value(it.value().data);
3132  }
3133 
3134  // attempt to make up for rounding errors
3135  in_use_cost += engineCache.size();
3136  }
3137 
3138  in_use_cost = (in_use_cost + 512) / 1024; // cost is stored in kb
3139 
3140  /*
3141  calculate the new maximum cost for the cache
3142 
3143  NOTE: in_use_cost is *not* correct due to rounding errors in the
3144  above algorithm. instead of worrying about getting the
3145  calculation correct, we are more interested in speed, and use
3146  in_use_cost as a floor for new_max_cost
3147  */
3148  uint new_max_cost = qMax(qMax(max_cost / 2, in_use_cost), min_cost);
3149 
3150  FC_DEBUG(" after sweep, in use %u kb, total %u kb, max %u kb, new max %u kb",
3151  in_use_cost, total_cost, max_cost, new_max_cost);
3152 
3153  if (autoClean) {
3154  if (new_max_cost == max_cost) {
3155  if (fast) {
3156  FC_DEBUG(" cannot shrink cache, slowing timer");
3157 
3158  if (timer_id != -1) {
3159  killTimer(timer_id);
3160  timer_id = startTimer(slow_timeout);
3161  fast = false;
3162  }
3163 
3164  return;
3165  } else if (! fast) {
3166  FC_DEBUG(" dropping into passing gear");
3167 
3168  if (timer_id != -1)
3169  killTimer(timer_id);
3170  timer_id = startTimer(fast_timeout);
3171  fast = true; }
3172  }
3173  }
3174 
3175  max_cost = new_max_cost;
3176 
3177  {
3178  FC_DEBUG(" CLEAN engine data:");
3179 
3180  // clean out all unused engine data
3182  while (it != engineDataCache.end()) {
3183  if (it.value()->ref.loadRelaxed() == 1) {
3184  FC_DEBUG(" %p", it.value());
3185  decreaseCost(sizeof(QFontEngineData));
3186  it.value()->ref.deref();
3187  delete it.value();
3189  } else {
3190  ++it;
3191  }
3192  }
3193  }
3194 
3195  FC_DEBUG(" CLEAN engine:");
3196 
3197  // clean out the engine cache just enough to get below our new max cost
3198  bool cost_decreased;
3199  do {
3200  cost_decreased = false;
3201 
3203  end = engineCache.end();
3204  // determine the oldest and least popular of the unused engines
3205  uint oldest = ~0u;
3206  uint least_popular = ~0u;
3207 
3209 
3210  for ( ; it != end; ++it) {
3211  if (it.value().data->ref.loadRelaxed() != engineCacheCount.value(it.value().data))
3212  continue;
3213 
3214  if (it.value().timestamp < oldest && it.value().hits <= least_popular) {
3215  oldest = it.value().timestamp;
3216  least_popular = it.value().hits;
3217  jt = it;
3218  }
3219  }
3220 
3221  it = jt;
3222  if (it != end) {
3223  FC_DEBUG(" %p: timestamp %4u hits %2u ref %2d/%2d, type %d",
3224  it.value().data, it.value().timestamp, it.value().hits,
3225  it.value().data->ref.loadRelaxed(), engineCacheCount.value(it.value().data),
3226  it.value().data->type());
3227 
3228  QFontEngine *fontEngine = it.value().data;
3229  // get rid of all occurrences
3230  it = engineCache.begin();
3231  while (it != engineCache.end()) {
3232  if (it.value().data == fontEngine) {
3233  fontEngine->ref.deref();
3234  it = engineCache.erase(it);
3235  } else {
3236  ++it;
3237  }
3238  }
3239  // and delete the last occurrence
3240  Q_ASSERT(fontEngine->ref.loadRelaxed() == 0);
3241  decreaseCost(fontEngine->cache_cost);
3242  delete fontEngine;
3243  engineCacheCount.remove(fontEngine);
3244 
3245  cost_decreased = true;
3246  }
3247  } while (cost_decreased && total_cost > max_cost);
3248 }
3249 
3250 
3251 #ifndef QT_NO_DEBUG_STREAM
3253 {
3254  QDebugStateSaver saver(stream);
3255  stream.nospace().noquote();
3256  stream << "QFont(";
3257 
3258  if (stream.verbosity() == QDebug::DefaultVerbosity) {
3259  stream << font.toString() << ")";
3260  return stream;
3261  }
3262 
3263  QString fontDescription;
3264  QDebug debug(&fontDescription);
3265  debug.nospace();
3266 
3267  const QFont defaultFont(new QFontPrivate);
3268 
3269  for (int property = QFont::SizeResolved; property < QFont::AllPropertiesResolved; property <<= 1) {
3270  const bool resolved = (font.resolve_mask & property) != 0;
3271  if (!resolved && stream.verbosity() == QDebug::MinimumVerbosity)
3272  continue;
3273 
3274  #define QFONT_DEBUG_SKIP_DEFAULT(prop) \
3275  if ((font.prop() == defaultFont.prop()) && stream.verbosity() == 1) \
3276  continue;
3277 
3278  QDebugStateSaver saver(debug);
3279 
3280  switch (property) {
3281  case QFont::SizeResolved:
3282  if (font.pointSizeF() >= 0)
3283  debug << font.pointSizeF() << "pt";
3284  else if (font.pixelSize() >= 0)
3285  debug << font.pixelSize() << "px";
3286  else
3287  Q_UNREACHABLE();
3288  break;
3290  QFONT_DEBUG_SKIP_DEFAULT(styleHint);
3291  debug.verbosity(1) << font.styleHint(); break;
3293  QFONT_DEBUG_SKIP_DEFAULT(styleStrategy);
3294  debug.verbosity(1) << font.styleStrategy(); break;
3295  case QFont::WeightResolved:
3296  debug.verbosity(1) << QFont::Weight(font.weight()); break;
3297  case QFont::StyleResolved:
3299  debug.verbosity(0) << font.style(); break;
3301  QFONT_DEBUG_SKIP_DEFAULT(underline);
3302  debug << "underline=" << font.underline(); break;
3304  QFONT_DEBUG_SKIP_DEFAULT(overline);
3305  debug << "overline=" << font.overline(); break;
3307  QFONT_DEBUG_SKIP_DEFAULT(strikeOut);
3308  debug << "strikeOut=" << font.strikeOut(); break;
3310  QFONT_DEBUG_SKIP_DEFAULT(fixedPitch);
3311  debug << "fixedPitch=" << font.fixedPitch(); break;
3313  QFONT_DEBUG_SKIP_DEFAULT(stretch);
3314  debug.verbosity(0) << QFont::Stretch(font.stretch()); break;
3317  debug << "kerning=" << font.kerning(); break;
3319  QFONT_DEBUG_SKIP_DEFAULT(capitalization);
3320  debug.verbosity(0) << font.capitalization(); break;
3322  QFONT_DEBUG_SKIP_DEFAULT(letterSpacing);
3323  debug << "letterSpacing=" << font.letterSpacing();
3324  debug.verbosity(0) << " (" << font.letterSpacingType() << ")";
3325  break;
3327  QFONT_DEBUG_SKIP_DEFAULT(hintingPreference);
3328  debug.verbosity(0) << font.hintingPreference(); break;
3330  QFONT_DEBUG_SKIP_DEFAULT(styleName);
3331  debug << "styleName=" << font.styleName(); break;
3332  default:
3333  continue;
3334  };
3335 
3336  #undef QFONT_DEBUG_SKIP_DEFAULT
3337 
3338  debug << ", ";
3339  }
3340 
3341  if (stream.verbosity() > QDebug::MinimumVerbosity)
3342  debug.verbosity(0) << "resolveMask=" << QFlags<QFont::ResolveProperties>(font.resolve_mask);
3343  else
3344  fontDescription.chop(2); // Last ', '
3345 
3346  stream << fontDescription << ')';
3347 
3348  return stream;
3349 }
3350 #endif
3351 
3353 
3354 #include "moc_qfont.cpp"
small capitals from c petite p scientific f u
Definition: afcover.h:88
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
xD9 x84 xD8 xAD xD9 x80 xF0 x90 xAC x9A xE0 xA7 xA6 xE0 xA7 xAA xF0 x91 x84 xA4 xF0 x91 x84 x89 xF0 x91 x84 x9B xF0 x90 x8A xAB xF0 x90 x8B x89 xE2 xB2 x9E xE2 xB2 x9F xD0 xBE xD0 x9E xF0 x90 x90 x84 xF0 x90 x90 xAC xE1 x83 x98 xE1 x83 x94 xE1 x83 x90 xE1 xB2 xBF xE2 xB0 x95 xE2 xB1 x85 xCE xBF xCE x9F xE0 xA8 xA0 xE0 xA8 xB0 xE0 xA9 xA6 Kayah xEA xA4 x8D xEA xA4 x80 Khmer xE1 xA7 xA1 xE1 xA7 xAA xE0 xBB x90 Latin Subscript xE2 x82 x92 xE2 x82 x80 xEA x93 xB3 xF0 x96 xB9 xA1 xF0 x96 xB9 x9B xF0 x96 xB9 xAF xE1 x80 x9D xE1 x80 x84 xE1 x80 x82 no script
Definition: afscript.h:271
Arabic default style
Definition: afstyles.h:94
#define value
[5]
bool ref() noexcept
Definition: qbasicatomic.h:101
bool deref() noexcept
Definition: qbasicatomic.h:102
T loadRelaxed() const noexcept
Definition: qbasicatomic.h:90
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
char * data()
Definition: qbytearray.h:516
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:84
Script
Definition: qchar.h:180
@ ScriptCount
Definition: qchar.h:373
@ Script_Common
Definition: qchar.h:183
@ Script_Latin
Definition: qchar.h:185
static QCoreApplication * instance()
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:66
operator>>(QDataStream &ds, qfloat16 &f)
Definition: qfloat16.cpp:344
operator<<(QDataStream &ds, qfloat16 f)
Definition: qfloat16.cpp:327
The QDebug class provides an output stream for debugging information.
Definition: qdebug.h:65
@ MinimumVerbosity
Definition: qdebug.h:118
@ DefaultVerbosity
Definition: qdebug.h:118
Convenience class for custom QDebug operators.
Definition: qdebug.h:176
T * data() const noexcept
Definition: qshareddata.h:171
The QFlags class provides a type-safe way of storing OR-combinations of enum values.
Definition: qflags.h:89
template< typename Enum > size_t qHash(QFlags< Enum > flags, size_t seed=0) noexcept
static void cleanup()
Definition: qfont.cpp:2866
void insertEngineData(const QFontDef &def, QFontEngineData *engineData)
Definition: qfont.cpp:2965
EngineDataCache engineDataCache
Definition: qfont_p.h:264
void clear()
Definition: qfont.cpp:2895
QFontEngine * findEngine(const Key &key)
Definition: qfont.cpp:2986
QFontEngineData * findEngineData(const QFontDef &def) const
Definition: qfont.cpp:2955
EngineCache engineCache
Definition: qfont_p.h:280
static QFontCache * instance()
Definition: qfont.cpp:2858
QFontCache()
Definition: qfont.cpp:2880
~QFontCache()
Definition: qfont.cpp:2890
void updateHitCountAndTimeStamp(Engine &value)
Definition: qfont.cpp:3001
int id() const
Definition: qfont_p.h:232
void insertEngine(const Key &key, QFontEngine *engine, bool insertMulti=false)
Definition: qfont.cpp:3013
QHash< QFontEngine *, int > engineCacheCount
Definition: qfont_p.h:281
static void parseFontName(const QString &name, QString &foundry, QString &family)
static void load(const QFontPrivate *d, int script)
QAtomicInt ref
Definition: qfont_p.h:168
QFontEngine * engines[QChar::ScriptCount]
Definition: qfont_p.h:171
const int fontCacheId
Definition: qfont_p.h:169
QFontDef fontDef
Type type() const
QAtomicInt ref
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const =0
The QFont class specifies a query for a font used for drawing text.
Definition: qfont.h:56
static QStringList substitutes(const QString &)
Definition: qfont.cpp:1939
StyleHint
Definition: qfont.h:59
void setStyle(Style style)
Definition: qfont.cpp:1136
QString family() const
Definition: qfont.cpp:821
static void initialize()
Definition: qfont.cpp:2231
StyleStrategy styleStrategy() const
Definition: qfont.cpp:1414
void setPointSize(int)
Definition: qfont.cpp:1006
static void cacheStatistics()
Definition: qfont.cpp:2249
void setOverline(bool)
Definition: qfont.cpp:1308
QString styleName() const
Definition: qfont.cpp:864
void setStrikeOut(bool)
Definition: qfont.cpp:1335
static void cleanup()
Definition: qfont.cpp:2240
bool isCopyOf(const QFont &) const
Definition: qfont.cpp:1865
int pixelSize() const
Definition: qfont.cpp:1094
bool italic() const
Definition: qfont.h:338
QFont()
Definition: qfont.cpp:689
friend class QFontPrivate
Definition: qfont.h:288
StyleHint styleHint() const
Definition: qfont.cpp:1427
bool fromString(const QString &)
Definition: qfont.cpp:2171
bool strikeOut() const
Definition: qfont.cpp:1324
size_t qHash(const QFont &font, size_t seed) noexcept
Definition: qfont.cpp:2158
bool underline() const
Definition: qfont.cpp:1271
Capitalization
Definition: qfont.h:130
@ AllLowercase
Definition: qfont.h:133
@ AllUppercase
Definition: qfont.h:132
@ MixedCase
Definition: qfont.h:131
@ SmallCaps
Definition: qfont.h:134
void setFamilies(const QStringList &)
Definition: qfont.cpp:2306
bool operator!=(const QFont &) const
Definition: qfont.cpp:1845
void setCapitalization(Capitalization)
Definition: qfont.cpp:1737
QString toString() const
Definition: qfont.cpp:2124
qreal letterSpacing() const
Definition: qfont.cpp:1633
void setWordSpacing(qreal spacing)
Definition: qfont.cpp:1702
void setFixedPitch(bool)
Definition: qfont.cpp:1362
void setFamily(const QString &)
Definition: qfont.cpp:844
void setStyleStrategy(StyleStrategy s)
Definition: qfont.cpp:1538
bool exactMatch() const
Definition: qfont.cpp:1766
QFont resolve(const QFont &) const
Definition: qfont.cpp:1874
static void insertSubstitution(const QString &, const QString &)
Definition: qfont.cpp:1956
HintingPreference hintingPreference() const
Definition: qfont.cpp:995
SpacingType
Definition: qfont.h:139
@ AbsoluteSpacing
Definition: qfont.h:141
@ PercentageSpacing
Definition: qfont.h:140
bool operator<(const QFont &) const
Definition: qfont.cpp:1810
Capitalization capitalization() const
Definition: qfont.cpp:1755
static void removeSubstitutions(const QString &)
Definition: qfont.cpp:1997
QStringList families() const
Definition: qfont.cpp:2284
Weight weight() const
Definition: qfont.cpp:1153
@ StretchResolved
Definition: qfont.h:157
@ LetterSpacingResolved
Definition: qfont.h:160
@ SizeResolved
Definition: qfont.h:148
@ OverlineResolved
Definition: qfont.h:154
@ UnderlineResolved
Definition: qfont.h:153
@ StyleHintResolved
Definition: qfont.h:149
@ StyleNameResolved
Definition: qfont.h:163
@ AllPropertiesResolved
Definition: qfont.h:165
@ StrikeOutResolved
Definition: qfont.h:155
@ KerningResolved
Definition: qfont.h:158
@ WeightResolved
Definition: qfont.h:151
@ CapitalizationResolved
Definition: qfont.h:159
@ HintingPreferenceResolved
Definition: qfont.h:162
@ FixedPitchResolved
Definition: qfont.h:156
@ WordSpacingResolved
Definition: qfont.h:161
@ StyleStrategyResolved
Definition: qfont.h:150
@ StyleResolved
Definition: qfont.h:152
@ FamiliesResolved
Definition: qfont.h:164
void setLetterSpacing(SpacingType type, qreal spacing)
Definition: qfont.cpp:1650
qreal wordSpacing() const
Definition: qfont.cpp:1683
int pointSize() const
Definition: qfont.cpp:899
void setKerning(bool)
Definition: qfont.cpp:1395
int stretch() const
Definition: qfont.cpp:1576
static QStringList substitutions()
Definition: qfont.cpp:2009
bool kerning() const
Definition: qfont.cpp:1379
QString defaultFamily() const
Definition: qfont.cpp:2265
QString key() const
Definition: qfont.cpp:2093
void setPixelSize(int)
Definition: qfont.cpp:1069
bool operator==(const QFont &) const
Definition: qfont.cpp:1782
void setHintingPreference(HintingPreference hintingPreference)
Definition: qfont.cpp:978
void setItalic(bool b)
Definition: qfont.h:343
bool fixedPitch() const
Definition: qfont.cpp:1351
void setUnderline(bool)
Definition: qfont.cpp:1282
void setStyleHint(StyleHint, StyleStrategy=PreferDefault)
Definition: qfont.cpp:1517
HintingPreference
Definition: qfont.h:88
QFont & operator=(const QFont &)
Definition: qfont.cpp:800
qreal pointSizeF() const
Definition: qfont.cpp:1055
void setStyleName(const QString &)
Definition: qfont.cpp:882
void setStretch(int)
Definition: qfont.cpp:1600
SpacingType letterSpacingType() const
Definition: qfont.cpp:1672
Stretch
Definition: qfont.h:116
Style style() const
Definition: qfont.cpp:1125
StyleStrategy
Definition: qfont.h:72
@ PreferDefault
Definition: qfont.h:73
void setPointSizeF(qreal)
Definition: qfont.cpp:1031
Weight
Definition: qfont.h:96
@ DemiBold
Definition: qfont.h:102
@ Thin
Definition: qfont.h:97
@ ExtraBold
Definition: qfont.h:104
@ Black
Definition: qfont.h:105
@ Bold
Definition: qfont.h:103
@ ExtraLight
Definition: qfont.h:98
@ Normal
Definition: qfont.h:100
@ Light
Definition: qfont.h:99
@ Medium
Definition: qfont.h:101
void setWeight(Weight weight)
Definition: qfont.cpp:1225
bool overline() const
Definition: qfont.cpp:1298
~QFont()
Definition: qfont.cpp:793
Style
Definition: qfont.h:109
@ StyleItalic
Definition: qfont.h:111
@ StyleNormal
Definition: qfont.h:110
@ StyleOblique
Definition: qfont.h:112
static void insertSubstitutions(const QString &, const QStringList &)
Definition: qfont.cpp:1978
The QFontInfo class provides general information about fonts. \inmodule QtGui.
Definition: qfontinfo.h:51
qreal pointSizeF() const
Definition: qfont.cpp:2655
int pointSize() const
Definition: qfont.cpp:2643
int pixelSize() const
Definition: qfont.cpp:2667
QString family() const
Definition: qfont.cpp:2616
bool italic() const
Definition: qfont.cpp:2679
QFontInfo & operator=(const QFontInfo &)
Definition: qfont.cpp:2597
QString styleName() const
Definition: qfont.cpp:2631
bool fixedPitch() const
Definition: qfont.cpp:2790
QFontInfo(const QFont &)
Definition: qfont.cpp:2574
QFont::StyleHint styleHint() const
Definition: qfont.cpp:2816
bool strikeOut() const
Definition: qfont.cpp:2780
bool overline() const
Definition: qfont.cpp:2767
QFont::Style style() const
Definition: qfont.cpp:2691
int weight() const
Definition: qfont.cpp:2725
~QFontInfo()
Definition: qfont.cpp:2590
bool exactMatch() const
Definition: qfont.cpp:2829
bool underline() const
Definition: qfont.cpp:2752
bool letterSpacingIsAbsolute
Definition: qfont_p.h:199
uint overline
Definition: qfont_p.h:195
~QFontPrivate()
Definition: qfont.cpp:256
uint strikeOut
Definition: qfont_p.h:196
QAtomicInt ref
Definition: qfont_p.h:189
QFontPrivate()
Definition: qfont.cpp:237
QFontDef request
Definition: qfont_p.h:190
QFontPrivate * smallCapsFontPrivate() const
Definition: qfont.cpp:302
uint underline
Definition: qfont_p.h:194
static QFontPrivate * get(const QFont &font)
Definition: qfont_p.h:208
QFontEngine * engineForScript(int script) const
Definition: qfont.cpp:272
QFixed wordSpacing
Definition: qfont_p.h:202
uint kerning
Definition: qfont_p.h:197
QFixed letterSpacing
Definition: qfont_p.h:201
void resolve(uint mask, const QFontPrivate *other)
Definition: qfont.cpp:319
QFontEngineData * engineData
Definition: qfont_p.h:191
uint capital
Definition: qfont_p.h:198
QFontPrivate * scFont
Definition: qfont_p.h:204
void alterCharForCapitalization(QChar &c) const
Definition: qfont.cpp:288
static void detachButKeepEngineData(QFont *font)
Definition: qfont.cpp:672
The QGuiApplication class manages the GUI application's control flow and main settings.
QScreen * primaryScreen
the primary (or default) screen of the application.
bool remove(const Key &key)
Definition: qhash.h:911
const_iterator constFind(const Key &key) const noexcept
Definition: qhash.h:1224
const_iterator constEnd() const noexcept
Definition: qhash.h:1162
QList< Key > keys() const
Definition: qhash.h:1029
T value(const Key &key) const noexcept
Definition: qhash.h:997
const_iterator ConstIterator
Definition: qhash.h:1202
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Definition: qhash.h:904
iterator insert(const Key &key, const T &value)
Definition: qmap.h:719
T value(const Key &key, const T &defaultValue=T()) const
Definition: qmap.h:392
iterator erase(const_iterator it)
Definition: qmap.h:650
bool contains(const Key &key) const
Definition: qmap.h:376
const_iterator constFind(const Key &key) const
Definition: qmap.h:686
void clear()
Definition: qmap.h:324
const_iterator ConstIterator
Definition: qmap.h:670
iterator begin()
Definition: qmap.h:633
iterator end()
Definition: qmap.h:637
const_iterator constBegin() const
Definition: qmap.h:635
size_type size() const
Definition: qmap.h:302
const_iterator constEnd() const
Definition: qmap.h:639
iterator replace(const Key &key, const T &value)
Definition: qmap.h:1502
const_iterator constEnd() const
Definition: qmap.h:1334
bool contains(const Key &key) const
Definition: qmap.h:1050
iterator end()
Definition: qmap.h:1332
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:943
const_iterator constBegin() const
Definition: qmap.h:1330
T value(const Key &key, const T &defaultValue=T()) const
Definition: qmap.h:1071
void clear()
Definition: qmap.h:965
iterator begin()
Definition: qmap.h:1328
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes.
Definition: qmutex.h:317
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
int startTimer(int interval, Qt::TimerType timerType=Qt::CoarseTimer)
Definition: qobject.cpp:1765
void killTimer(int id)
Definition: qobject.cpp:1838
int logicalDpiY() const
Definition: qpaintdevice.h:82
The QRecursiveMutex class provides access serialization between threads.
Definition: qmutex.h:313
The QScreen class is used to query screen properties. \inmodule QtGui.
Definition: qscreen.h:68
qreal logicalDotsPerInchY
the number of logical dots or pixels per inch in the vertical direction
Definition: qscreen.h:93
qreal logicalDotsPerInchX
the number of logical dots or pixels per inch in the horizontal direction
Definition: qscreen.h:92
The QString class provides a Unicode character string.
Definition: qstring.h:388
QByteArray toLatin1() const &
Definition: qstring.h:745
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:5092
void chop(qsizetype n)
Definition: qstring.cpp:5955
static QString fromLatin1(QByteArrayView ba)
Definition: qstring.cpp:5488
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:7672
void clear()
Definition: qstring.h:1240
QString mid(qsizetype position, qsizetype n=-1) const
Definition: qstring.cpp:4994
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:5143
bool isEmpty() const
Definition: qstring.h:1216
QString toLower() const &
Definition: qstring.h:611
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.h:1353
static QString number(int, int base=10)
Definition: qstring.cpp:7538
qsizetype length() const
Definition: qstring.h:415
The QStringList class provides a list of strings.
The QStringView class provides a unified view on UTF-16 strings with a read-only subset of the QStrin...
Definition: qstringview.h:122
QStringView trimmed() const noexcept
Definition: qstringview.h:296
The QThreadStorage class provides per-thread data storage.
The QTimerEvent class contains parameters that describe a timer event.
Definition: qcoreevent.h:367
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:95
static auto fromValue(const T &value) -> std::enable_if_t< std::is_copy_constructible_v< T >, QVariant >
Definition: qvariant.h:391
Definition: main.cpp:626
float factor
QString str
[2]
qreal spacing
QCache< int, Employee > cache
[0]
int const char * version
Definition: zlib.h:814
#define true
Definition: ftrandom.c:51
auto it unsigned count const
Definition: hb-iter.hh:848
#define bits
Definition: infblock.c:15
Q_WIDGETS_EXPORT qreal dpi(const QStyleOption *option)
@ AA_Use96Dpi
Definition: qnamespace.h:458
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION ParsedNumber< double > toDouble(QByteArrayView a) noexcept
string comma
Definition: cordic.py:8
#define QString()
Definition: parse-defines.h:51
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
[3]
#define Q_BASIC_ATOMIC_INITIALIZER(a)
#define Q_UNREACHABLE()
QList< QString > QStringList
Definition: qcontainerfwd.h:64
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
int qRound(qfloat16 d) noexcept
Definition: qfloat16.h:227
Q_GUI_EXPORT int qt_openTypeToLegacyWeight(int weight)
Definition: qfont.cpp:232
QRecursiveMutex * qt_fontdatabase_mutex()
Q_GUI_EXPORT int qt_defaultDpiX()
Definition: qfont.cpp:141
#define FC_DEBUG
Definition: qfont.cpp:74
Q_GUI_EXPORT int qt_legacyToOpenTypeWeight(int weight)
Definition: qfont.cpp:226
Q_GUI_EXPORT int qt_defaultDpi()
Definition: qfont.cpp:171
QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
#define QFONT_DEBUG_SKIP_DEFAULT(prop)
#define QFONTCACHE_MIN_COST
Definition: qfont.cpp:2853
#define QT_FONT_ENGINE_FROM_DATA(data, script)
Definition: qfont.cpp:270
Q_GUI_EXPORT int qt_defaultDpiY()
Definition: qfont.cpp:156
bool qt_is_tty_app
#define QFONTCACHE_DECREASE_TRIGGER_LIMIT
Definition: qfont.cpp:80
QHash< QString, QStringList > QFontSubst
Definition: qfont.cpp:1904
#define QFONT_WEIGHT_MIN
Definition: qfont_p.h:69
#define QFONT_WEIGHT_MAX
Definition: qfont_p.h:70
short qint16
Definition: qglobal.h:285
unsigned short quint16
Definition: qglobal.h:286
int qint32
Definition: qglobal.h:287
QT_END_INCLUDE_NAMESPACE typedef double qreal
Definition: qglobal.h:341
unsigned int uint
Definition: qglobal.h:334
unsigned char quint8
Definition: qglobal.h:284
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qWarning
Definition: qlogging.h:179
GLenum GLuint id
[6]
Definition: qopengl.h:270
GLenum type
Definition: qopengl.h:270
GLuint64 key
GLuint GLuint end
GLenum GLenum GLsizei count
GLfloat GLfloat f
GLuint GLuint GLfloat weight
GLboolean enable
GLenum const void GLbitfield fontStyle
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLboolean GLboolean g
GLint ref
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
const GLubyte * c
Definition: qopenglext.h:12701
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
Definition: qopenglext.h:6904
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLdouble s
[6]
Definition: qopenglext.h:235
GLenum GLenum GLenum GLenum mapping
Definition: qopenglext.h:10816
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
QPointF qAbs(const QPointF &p)
Definition: qscroller.cpp:119
const char property[13]
Definition: qwizard.cpp:136
QScreen * screen
[1]
Definition: main.cpp:76
std::uniform_real_distribution dist(1, 2.5)
[2]
QFileInfo fi("c:/temp/foo")
[newstuff]
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)
QStringList::Iterator it
QStringList list
[0]
constexpr int value() const
Definition: qfixed_p.h:74
constexpr static QFixed fromReal(qreal r)
Definition: qfixed_p.h:71
void setValue(int value)
Definition: qfixed_p.h:75
constexpr qreal toReal() const
Definition: qfixed_p.h:78
QFontEngine * data
Definition: qfont_p.h:274
uint hintingPreference
Definition: qfont_p.h:102
uint stretch
Definition: qfont_p.h:100
uint style
Definition: qfont_p.h:101
uint styleStrategy
Definition: qfont_p.h:99
uint fixedPitch
Definition: qfont_p.h:106
qreal pixelSize
Definition: qfont_p.h:96
uint ignorePitch
Definition: qfont_p.h:107
uint weight
Definition: qfont_p.h:105
QStringList families
Definition: qfont_p.h:90
QString styleName
Definition: qfont_p.h:91
uint fixedPitchComputed
Definition: qfont_p.h:108
bool exactMatch(const QFontDef &other) const
Definition: qfont.cpp:83
uint styleHint
Definition: qfont_p.h:104
qreal pointSize
Definition: qfont_p.h:95
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:53
FT_UInt FT_UInt FT_Vector * kerning
Definition: ttdriver.c:206