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