1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QFONT_P_H
5#define QFONT_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists for the convenience
12// of internal files. This header file may change from version to version
13// without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtGui/private/qtguiglobal_p.h>
19#include "QtGui/qfont.h"
20#include "QtCore/qbasictimer.h"
21#include "QtCore/qmap.h"
22#include "QtCore/qhash.h"
23#include "QtCore/qobject.h"
24#include "QtCore/qstringlist.h"
25#include <QtGui/qfontdatabase.h>
26#include "private/qfixed_p.h"
27#include "private/qfontdatabase_p.h"
28
29QT_BEGIN_NAMESPACE
30
31// forwards
32class QFontCache;
33class QFontEngine;
34
35#define QFONT_WEIGHT_MIN 1
36#define QFONT_WEIGHT_MAX 1000
37
38struct QFontDef
39{
40 inline QFontDef()
41 : pointSize(-1.0),
42 pixelSize(-1),
43 styleStrategy(QFont::PreferDefault),
44 stretch(QFont::AnyStretch),
45 style(QFont::StyleNormal),
46 hintingPreference(QFont::PreferDefaultHinting),
47 styleHint(QFont::AnyStyle),
48 weight(QFont::Normal),
49 fixedPitch(false),
50 ignorePitch(true),
51 fixedPitchComputed(0),
52 reserved(0)
53 {
54 }
55
56 QStringList families;
57 QString styleName;
58
59 QStringList fallBackFamilies;
60 QMap<QFont::Tag, float> variableAxisValues;
61
62 qreal pointSize;
63 qreal pixelSize;
64
65 // Note: Variable ordering matters to make sure no variable overlaps two 32-bit registers.
66 uint styleStrategy : 16;
67 uint stretch : 12; // 0-4000
68 uint style : 2;
69 uint hintingPreference : 2;
70
71 uint styleHint : 8;
72 uint weight : 10; // 1-1000
73 uint fixedPitch : 1;
74 uint ignorePitch : 1;
75 uint fixedPitchComputed : 1; // for Mac OS X only
76 uint reserved : 11; // for future extensions
77
78 bool exactMatch(const QFontDef &other) const;
79 bool operator==(const QFontDef &other) const
80 {
81 return pixelSize == other.pixelSize
82 && weight == other.weight
83 && style == other.style
84 && stretch == other.stretch
85 && styleHint == other.styleHint
86 && styleStrategy == other.styleStrategy
87 && ignorePitch == other.ignorePitch && fixedPitch == other.fixedPitch
88 && families == other.families
89 && styleName == other.styleName
90 && hintingPreference == other.hintingPreference
91 && variableAxisValues == other.variableAxisValues
92 ;
93 }
94 inline bool operator<(const QFontDef &other) const
95 {
96 if (pixelSize != other.pixelSize) return pixelSize < other.pixelSize;
97 if (weight != other.weight) return weight < other.weight;
98 if (style != other.style) return style < other.style;
99 if (stretch != other.stretch) return stretch < other.stretch;
100 if (styleHint != other.styleHint) return styleHint < other.styleHint;
101 if (styleStrategy != other.styleStrategy) return styleStrategy < other.styleStrategy;
102 if (families != other.families) return families < other.families;
103 if (styleName != other.styleName)
104 return styleName < other.styleName;
105 if (hintingPreference != other.hintingPreference) return hintingPreference < other.hintingPreference;
106
107
108 if (ignorePitch != other.ignorePitch) return ignorePitch < other.ignorePitch;
109 if (fixedPitch != other.fixedPitch) return fixedPitch < other.fixedPitch;
110 if (variableAxisValues != other.variableAxisValues) {
111 if (variableAxisValues.size() != other.variableAxisValues.size())
112 return variableAxisValues.size() < other.variableAxisValues.size();
113
114 {
115 auto it = variableAxisValues.constBegin();
116 auto jt = other.variableAxisValues.constBegin();
117 for (; it != variableAxisValues.constEnd(); ++it, ++jt) {
118 if (it.key() != jt.key())
119 return jt.key() < it.key();
120 if (it.value() != jt.value())
121 return jt.value() < it.value();
122 }
123 }
124 }
125
126 return false;
127 }
128};
129
130inline size_t qHash(const QFontDef &fd, size_t seed = 0) noexcept
131{
132 return qHashMulti(seed,
133 args: qRound64(d: fd.pixelSize*10000), // use only 4 fractional digits
134 args: fd.weight,
135 args: fd.style,
136 args: fd.stretch,
137 args: fd.styleHint,
138 args: fd.styleStrategy,
139 args: fd.ignorePitch,
140 args: fd.fixedPitch,
141 args: fd.families,
142 args: fd.styleName,
143 args: fd.hintingPreference,
144 args: fd.variableAxisValues.keys(),
145 args: fd.variableAxisValues.values());
146}
147
148class QFontEngineData
149{
150public:
151 QFontEngineData();
152 ~QFontEngineData();
153
154 QAtomicInt ref;
155 const int fontCacheId;
156
157 QFontEngine *engines[QFontDatabasePrivate::ScriptCount];
158private:
159 Q_DISABLE_COPY_MOVE(QFontEngineData)
160};
161
162
163class Q_GUI_EXPORT QFontPrivate
164{
165public:
166
167 QFontPrivate();
168 QFontPrivate(const QFontPrivate &other);
169 ~QFontPrivate();
170
171 QFontEngine *engineForScript(int script) const;
172 void alterCharForCapitalization(QChar &c) const;
173
174 QAtomicInt ref;
175 QFontDef request;
176 mutable QFontEngineData *engineData;
177 int dpi;
178
179 uint underline : 1;
180 uint overline : 1;
181 uint strikeOut : 1;
182 uint kerning : 1;
183 uint capital : 3;
184 bool letterSpacingIsAbsolute : 1;
185
186 QFixed letterSpacing;
187 QFixed wordSpacing;
188 QHash<QFont::Tag, quint32> features;
189
190 mutable QFontPrivate *scFont;
191 QFont smallCapsFont() const { return QFont(smallCapsFontPrivate()); }
192 QFontPrivate *smallCapsFontPrivate() const;
193
194 static QFontPrivate *get(const QFont &font)
195 {
196 return font.d.data();
197 }
198
199 void resolve(uint mask, const QFontPrivate *other);
200
201 static void detachButKeepEngineData(QFont *font);
202
203 void setFeature(QFont::Tag tag, quint32 value);
204 void unsetFeature(QFont::Tag tag);
205
206 void setVariableAxis(QFont::Tag tag, float value);
207 void unsetVariableAxis(QFont::Tag tag);
208 bool hasVariableAxis(QFont::Tag tag, float value) const;
209
210private:
211 QFontPrivate &operator=(const QFontPrivate &) { return *this; }
212};
213
214
215class Q_GUI_EXPORT QFontCache : public QObject
216{
217public:
218 // note: these static functions work on a per-thread basis
219 static QFontCache *instance();
220 static void cleanup();
221
222 QFontCache();
223 ~QFontCache();
224
225 int id() const { return m_id; }
226
227 void clear();
228
229 struct Key {
230 Key() : script(0), multi(0) { }
231 Key(const QFontDef &d, uchar c, bool m = 0)
232 : def(d), script(c), multi(m) { }
233
234 QFontDef def;
235 uchar script;
236 uchar multi: 1;
237
238 inline bool operator<(const Key &other) const
239 {
240 if (script != other.script) return script < other.script;
241 if (multi != other.multi) return multi < other.multi;
242 if (multi && def.fallBackFamilies.size() != other.def.fallBackFamilies.size())
243 return def.fallBackFamilies.size() < other.def.fallBackFamilies.size();
244 return def < other.def;
245 }
246 inline bool operator==(const Key &other) const
247 {
248 return script == other.script
249 && multi == other.multi
250 && (!multi || def.fallBackFamilies == other.def.fallBackFamilies)
251 && def == other.def;
252 }
253 };
254
255 // QFontEngineData cache
256 typedef QMap<QFontDef, QFontEngineData*> EngineDataCache;
257 EngineDataCache engineDataCache;
258
259 QFontEngineData *findEngineData(const QFontDef &def) const;
260 void insertEngineData(const QFontDef &def, QFontEngineData *engineData);
261
262 // QFontEngine cache
263 struct Engine {
264 Engine() : data(nullptr), timestamp(0), hits(0) { }
265 Engine(QFontEngine *d) : data(d), timestamp(0), hits(0) { }
266
267 QFontEngine *data;
268 uint timestamp;
269 uint hits;
270 };
271
272 typedef QMultiMap<Key,Engine> EngineCache;
273 EngineCache engineCache;
274 QHash<QFontEngine *, int> engineCacheCount;
275
276 QFontEngine *findEngine(const Key &key);
277
278 void updateHitCountAndTimeStamp(Engine &value);
279 void insertEngine(const Key &key, QFontEngine *engine, bool insertMulti = false);
280
281private:
282 void increaseCost(uint cost);
283 void decreaseCost(uint cost);
284 void timerEvent(QTimerEvent *event) override;
285 void decreaseCache();
286
287 static const uint min_cost;
288 uint total_cost, max_cost;
289 uint current_timestamp;
290 bool fast;
291 const bool autoClean;
292 QBasicTimer timer;
293 const int m_id;
294};
295
296Q_GUI_EXPORT int qt_defaultDpiX();
297Q_GUI_EXPORT int qt_defaultDpiY();
298Q_GUI_EXPORT int qt_defaultDpi();
299
300Q_GUI_EXPORT int qt_legacyToOpenTypeWeight(int weight);
301Q_GUI_EXPORT int qt_openTypeToLegacyWeight(int weight);
302
303QT_END_NAMESPACE
304
305#endif // QFONT_P_H
306

source code of qtbase/src/gui/text/qfont_p.h