/src/qtbase/src/gui/text/qfont_p.h
Line | Count | Source |
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 | | |
29 | | QT_BEGIN_NAMESPACE |
30 | | |
31 | | // forwards |
32 | | class QFontCache; |
33 | | class QFontEngine; |
34 | | |
35 | 0 | #define QFONT_WEIGHT_MIN 1 |
36 | 0 | #define QFONT_WEIGHT_MAX 1000 |
37 | | |
38 | | struct QFontDef |
39 | | { |
40 | | inline QFontDef() |
41 | 2.56M | : pointSize(-1.0), |
42 | 2.56M | pixelSize(-1), |
43 | 2.56M | styleStrategy(QFont::PreferDefault), |
44 | 2.56M | stretch(QFont::AnyStretch), |
45 | 2.56M | style(QFont::StyleNormal), |
46 | 2.56M | hintingPreference(QFont::PreferDefaultHinting), |
47 | 2.56M | styleHint(QFont::AnyStyle), |
48 | 2.56M | weight(QFont::Normal), |
49 | 2.56M | fixedPitch(false), |
50 | 2.56M | ignorePitch(true), |
51 | 2.56M | fixedPitchComputed(0), |
52 | 2.56M | reserved(0) |
53 | 2.56M | { |
54 | 2.56M | } |
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 | 0 | { |
81 | 0 | return pixelSize == other.pixelSize |
82 | 0 | && weight == other.weight |
83 | 0 | && style == other.style |
84 | 0 | && stretch == other.stretch |
85 | 0 | && styleHint == other.styleHint |
86 | 0 | && styleStrategy == other.styleStrategy |
87 | 0 | && ignorePitch == other.ignorePitch && fixedPitch == other.fixedPitch |
88 | 0 | && families == other.families |
89 | 0 | && styleName == other.styleName |
90 | 0 | && hintingPreference == other.hintingPreference |
91 | 0 | && variableAxisValues == other.variableAxisValues |
92 | 0 | ; |
93 | 0 | } |
94 | | inline bool operator<(const QFontDef &other) const |
95 | 0 | { |
96 | 0 | if (pixelSize != other.pixelSize) return pixelSize < other.pixelSize; |
97 | 0 | if (weight != other.weight) return weight < other.weight; |
98 | 0 | if (style != other.style) return style < other.style; |
99 | 0 | if (stretch != other.stretch) return stretch < other.stretch; |
100 | 0 | if (styleHint != other.styleHint) return styleHint < other.styleHint; |
101 | 0 | if (styleStrategy != other.styleStrategy) return styleStrategy < other.styleStrategy; |
102 | 0 | if (families != other.families) return families < other.families; |
103 | 0 | if (styleName != other.styleName) |
104 | 0 | return styleName < other.styleName; |
105 | 0 | if (hintingPreference != other.hintingPreference) return hintingPreference < other.hintingPreference; |
106 | | |
107 | | |
108 | 0 | if (ignorePitch != other.ignorePitch) return ignorePitch < other.ignorePitch; |
109 | 0 | if (fixedPitch != other.fixedPitch) return fixedPitch < other.fixedPitch; |
110 | 0 | if (variableAxisValues != other.variableAxisValues) { |
111 | 0 | if (variableAxisValues.size() != other.variableAxisValues.size()) |
112 | 0 | return variableAxisValues.size() < other.variableAxisValues.size(); |
113 | | |
114 | 0 | { |
115 | 0 | auto it = variableAxisValues.constBegin(); |
116 | 0 | auto jt = other.variableAxisValues.constBegin(); |
117 | 0 | for (; it != variableAxisValues.constEnd(); ++it, ++jt) { |
118 | 0 | if (it.key() != jt.key()) |
119 | 0 | return jt.key() < it.key(); |
120 | 0 | if (it.value() != jt.value()) |
121 | 0 | return jt.value() < it.value(); |
122 | 0 | } |
123 | 0 | } |
124 | 0 | } |
125 | | |
126 | 0 | return false; |
127 | 0 | } |
128 | | }; |
129 | | |
130 | | inline size_t qHash(const QFontDef &fd, size_t seed = 0) noexcept |
131 | 0 | { |
132 | 0 | return qHashMulti(seed, |
133 | 0 | qRound64(fd.pixelSize*10000), // use only 4 fractional digits |
134 | 0 | fd.weight, |
135 | 0 | fd.style, |
136 | 0 | fd.stretch, |
137 | 0 | fd.styleHint, |
138 | 0 | fd.styleStrategy, |
139 | 0 | fd.ignorePitch, |
140 | 0 | fd.fixedPitch, |
141 | 0 | fd.families, |
142 | 0 | fd.styleName, |
143 | 0 | fd.hintingPreference, |
144 | 0 | fd.variableAxisValues.keys(), |
145 | 0 | fd.variableAxisValues.values()); |
146 | 0 | } |
147 | | |
148 | | class QFontEngineData |
149 | | { |
150 | | public: |
151 | | QFontEngineData(); |
152 | | ~QFontEngineData(); |
153 | | |
154 | | QAtomicInt ref; |
155 | | const int fontCacheId; |
156 | | |
157 | | QFontEngine *engines[QFontDatabasePrivate::ScriptCount]; |
158 | | private: |
159 | | Q_DISABLE_COPY_MOVE(QFontEngineData) |
160 | | }; |
161 | | |
162 | | |
163 | | class Q_GUI_EXPORT QFontPrivate |
164 | | { |
165 | | public: |
166 | | enum class EngineQueryOption { |
167 | | Default = 0, |
168 | | IgnoreSmallCapsEngine = 0x1, |
169 | | }; |
170 | | Q_DECLARE_FLAGS(EngineQueryOptions, EngineQueryOption) |
171 | | |
172 | | QFontPrivate(); |
173 | | QFontPrivate(const QFontPrivate &other); |
174 | | QFontPrivate &operator=(const QFontPrivate &) = delete; |
175 | | ~QFontPrivate(); |
176 | | |
177 | | QFontEngine *engineForScript(int script) const; |
178 | | QFontEngine *engineForCharacter(char32_t c, EngineQueryOptions opt = {}) const; |
179 | | void alterCharForCapitalization(QChar &c) const; |
180 | | |
181 | | QAtomicInt ref; |
182 | | QFontDef request; |
183 | | mutable QFontEngineData *engineData; |
184 | | int dpi; |
185 | | |
186 | | uint underline : 1; |
187 | | uint overline : 1; |
188 | | uint strikeOut : 1; |
189 | | uint kerning : 1; |
190 | | uint capital : 3; |
191 | | bool letterSpacingIsAbsolute : 1; |
192 | | |
193 | | QFixed letterSpacing; |
194 | | QFixed wordSpacing; |
195 | | QMap<QFont::Tag, quint32> features; |
196 | | |
197 | | mutable QFontPrivate *scFont; |
198 | 0 | QFont smallCapsFont() const { return QFont(smallCapsFontPrivate()); } |
199 | | QFontPrivate *smallCapsFontPrivate() const; |
200 | | |
201 | | static QFontPrivate *get(const QFont &font) |
202 | 0 | { |
203 | 0 | return font.d.data(); |
204 | 0 | } |
205 | | |
206 | | void resolve(uint mask, const QFontPrivate *other); |
207 | | |
208 | | static void detachButKeepEngineData(QFont *font); |
209 | | |
210 | | void setFeature(QFont::Tag tag, quint32 value); |
211 | | void unsetFeature(QFont::Tag tag); |
212 | | |
213 | | void setVariableAxis(QFont::Tag tag, float value); |
214 | | void unsetVariableAxis(QFont::Tag tag); |
215 | | bool hasVariableAxis(QFont::Tag tag, float value) const; |
216 | | }; |
217 | 0 | Q_DECLARE_OPERATORS_FOR_FLAGS(QFontPrivate::EngineQueryOptions) Unexecuted instantiation: operator|(QFontPrivate::EngineQueryOption, QFontPrivate::EngineQueryOption) Unexecuted instantiation: operator|(QFontPrivate::EngineQueryOption, QFlags<QFontPrivate::EngineQueryOption>) Unexecuted instantiation: operator&(QFontPrivate::EngineQueryOption, QFontPrivate::EngineQueryOption) Unexecuted instantiation: operator&(QFontPrivate::EngineQueryOption, QFlags<QFontPrivate::EngineQueryOption>) Unexecuted instantiation: operator^(QFontPrivate::EngineQueryOption, QFontPrivate::EngineQueryOption) Unexecuted instantiation: operator^(QFontPrivate::EngineQueryOption, QFlags<QFontPrivate::EngineQueryOption>) Unexecuted instantiation: operator|(QFontPrivate::EngineQueryOption, int) |
218 | 0 |
|
219 | 0 |
|
220 | 0 | class Q_GUI_EXPORT QFontCache : public QObject |
221 | 0 | { |
222 | 0 | public: |
223 | 0 | // note: these static functions work on a per-thread basis |
224 | 0 | static QFontCache *instance(); |
225 | 0 | static void cleanup(); |
226 | 0 |
|
227 | 0 | QFontCache(); |
228 | 0 | ~QFontCache(); |
229 | 0 |
|
230 | 0 | int id() const { return m_id; } |
231 | | |
232 | | void clear(); |
233 | | |
234 | | struct Key { |
235 | 0 | Key() : script(0), multi(0) { } |
236 | | Key(const QFontDef &d, uchar c, bool m = 0) |
237 | 0 | : def(d), script(c), multi(m) { } |
238 | | |
239 | | QFontDef def; |
240 | | uchar script; |
241 | | uchar multi: 1; |
242 | | |
243 | | inline bool operator<(const Key &other) const |
244 | 0 | { |
245 | 0 | if (script != other.script) return script < other.script; |
246 | 0 | if (multi != other.multi) return multi < other.multi; |
247 | 0 | if (multi && def.fallBackFamilies.size() != other.def.fallBackFamilies.size()) |
248 | 0 | return def.fallBackFamilies.size() < other.def.fallBackFamilies.size(); |
249 | 0 | return def < other.def; |
250 | 0 | } |
251 | | inline bool operator==(const Key &other) const |
252 | 0 | { |
253 | 0 | return script == other.script |
254 | 0 | && multi == other.multi |
255 | 0 | && (!multi || def.fallBackFamilies == other.def.fallBackFamilies) |
256 | 0 | && def == other.def; |
257 | 0 | } |
258 | | }; |
259 | | |
260 | | // QFontEngineData cache |
261 | | typedef QMap<QFontDef, QFontEngineData*> EngineDataCache; |
262 | | EngineDataCache engineDataCache; |
263 | | |
264 | | QFontEngineData *findEngineData(const QFontDef &def) const; |
265 | | void insertEngineData(const QFontDef &def, QFontEngineData *engineData); |
266 | | |
267 | | // QFontEngine cache |
268 | | struct Engine { |
269 | 0 | Engine() : data(nullptr), timestamp(0), hits(0) { } |
270 | 0 | Engine(QFontEngine *d) : data(d), timestamp(0), hits(0) { } |
271 | | |
272 | | QFontEngine *data; |
273 | | uint timestamp; |
274 | | uint hits; |
275 | | }; |
276 | | |
277 | | typedef QMultiMap<Key,Engine> EngineCache; |
278 | | EngineCache engineCache; |
279 | | QHash<QFontEngine *, int> engineCacheCount; |
280 | | |
281 | | QFontEngine *findEngine(const Key &key); |
282 | | |
283 | | void updateHitCountAndTimeStamp(Engine &value); |
284 | | void insertEngine(const Key &key, QFontEngine *engine, bool insertMulti = false); |
285 | | |
286 | | private: |
287 | | void increaseCost(uint cost); |
288 | | void decreaseCost(uint cost); |
289 | | void timerEvent(QTimerEvent *event) override; |
290 | | void decreaseCache(); |
291 | | |
292 | | static const uint min_cost; |
293 | | uint total_cost, max_cost; |
294 | | uint current_timestamp; |
295 | | bool fast; |
296 | | const bool autoClean; |
297 | | QBasicTimer timer; |
298 | | const int m_id; |
299 | | }; |
300 | | |
301 | | Q_GUI_EXPORT QPoint qt_defaultDpis(); |
302 | | Q_GUI_EXPORT int qt_defaultDpiX(); |
303 | | Q_GUI_EXPORT int qt_defaultDpiY(); |
304 | | Q_GUI_EXPORT int qt_defaultDpi(); |
305 | | |
306 | | Q_GUI_EXPORT int qt_legacyToOpenTypeWeight(int weight); |
307 | | Q_GUI_EXPORT int qt_openTypeToLegacyWeight(int weight); |
308 | | |
309 | | QT_END_NAMESPACE |
310 | | |
311 | | #endif // QFONT_P_H |