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#ifndef QFONTENGINE_FT_P_H
40#define QFONTENGINE_FT_P_H
41//
42// W A R N I N G
43// -------------
44//
45// This file is not part of the Qt API. It exists purely as an
46// implementation detail. This header file may change from version to
47// version without notice, or even be removed.
48//
49// We mean it.
50//
51
52#include "private/qfontengine_p.h"
53
54#ifndef QT_NO_FREETYPE
55
56#include <ft2build.h>
57#include FT_FREETYPE_H
58
59
60#ifndef Q_OS_WIN
61#include <unistd.h>
62#endif
63
64#include <qmutex.h>
65
66QT_BEGIN_NAMESPACE
67
68class QFontEngineFTRawFont;
69class QFontconfigDatabase;
70
71/*
72 * This class represents one font file on disk (like Arial.ttf) and is shared between all the font engines
73 * that show this font file (at different pixel sizes).
74 */
75class QFreetypeFace
76{
77public:
78 void computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing, QFixed *scalableBitmapScaleFactor);
79 QFontEngine::Properties properties() const;
80 bool getSfntTable(uint tag, uchar *buffer, uint *length) const;
81
82 static QFreetypeFace *getFace(const QFontEngine::FaceId &face_id,
83 const QByteArray &fontData = QByteArray());
84 void release(const QFontEngine::FaceId &face_id);
85
86 // locks the struct for usage. Any read/write operations require locking.
87 void lock()
88 {
89 _lock.lock();
90 }
91 void unlock()
92 {
93 _lock.unlock();
94 }
95
96 FT_Face face;
97 int xsize; // 26.6
98 int ysize; // 26.6
99 FT_Matrix matrix;
100 FT_CharMap unicode_map;
101 FT_CharMap symbol_map;
102
103 enum { cmapCacheSize = 0x200 };
104 glyph_t cmapCache[cmapCacheSize];
105
106 int fsType() const;
107
108 int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints);
109
110 bool isScalableBitmap() const;
111
112 static void addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale);
113 static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path);
114
115private:
116 friend class QFontEngineFT;
117 friend class QtFreetypeData;
118 friend struct QScopedPointerDeleter<QFreetypeFace>;
119 QFreetypeFace() = default;
120 ~QFreetypeFace() {}
121 void cleanup();
122 QAtomicInt ref;
123 QRecursiveMutex _lock;
124 QByteArray fontData;
125
126 QFontEngine::Holder hbFace;
127};
128
129class QFontEngineFT : public QFontEngine
130{
131public:
132 struct GlyphInfo {
133 int linearAdvance;
134 unsigned short width;
135 unsigned short height;
136 short x;
137 short y;
138 short xOff;
139 short yOff;
140 };
141
142 struct GlyphAndSubPixelPosition
143 {
144 GlyphAndSubPixelPosition(glyph_t g, QFixed spp) : glyph(g), subPixelPosition(spp) {}
145
146 bool operator==(const GlyphAndSubPixelPosition &other) const
147 {
148 return glyph == other.glyph && subPixelPosition == other.subPixelPosition;
149 }
150
151 glyph_t glyph;
152 QFixed subPixelPosition;
153 };
154
155 struct QGlyphSet
156 {
157 QGlyphSet();
158 ~QGlyphSet();
159 FT_Matrix transformationMatrix;
160 bool outline_drawing;
161
162 void removeGlyphFromCache(glyph_t index, QFixed subPixelPosition);
163 void clear();
164 inline bool useFastGlyphData(glyph_t index, QFixed subPixelPosition) const {
165 return (index < 256 && subPixelPosition == 0);
166 }
167 inline Glyph *getGlyph(glyph_t index, QFixed subPixelPosition = 0) const;
168 void setGlyph(glyph_t index, QFixed spp, Glyph *glyph);
169
170 inline bool isGlyphMissing(glyph_t index) const { return missing_glyphs.contains(value: index); }
171 inline void setGlyphMissing(glyph_t index) const { missing_glyphs.insert(value: index); }
172private:
173 mutable QHash<GlyphAndSubPixelPosition, Glyph *> glyph_data; // maps from glyph index to glyph data
174 mutable QSet<glyph_t> missing_glyphs;
175 mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256
176 mutable int fast_glyph_count;
177 };
178
179 QFontEngine::FaceId faceId() const override;
180 QFontEngine::Properties properties() const override;
181 QFixed emSquareSize() const override;
182 bool supportsSubPixelPositions() const override
183 {
184 return default_hint_style == HintLight ||
185 default_hint_style == HintNone;
186 }
187
188 bool getSfntTableData(uint tag, uchar *buffer, uint *length) const override;
189 int synthesized() const override;
190
191 QFixed ascent() const override;
192 QFixed capHeight() const override;
193 QFixed descent() const override;
194 QFixed leading() const override;
195 QFixed xHeight() const override;
196 QFixed averageCharWidth() const override;
197
198 qreal maxCharWidth() const override;
199 QFixed lineThickness() const override;
200 QFixed underlinePosition() const override;
201
202 glyph_t glyphIndex(uint ucs4) const override;
203 void doKerning(QGlyphLayout *, ShaperFlags) const override;
204
205 void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) override;
206
207 bool supportsTransformation(const QTransform &transform) const override;
208
209 void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
210 QPainterPath *path, QTextItem::RenderFlags flags) override;
211 void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,
212 QPainterPath *path, QTextItem::RenderFlags flags) override;
213
214 bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
215
216 glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override;
217 glyph_metrics_t boundingBox(glyph_t glyph) override;
218 glyph_metrics_t boundingBox(glyph_t glyph, const QTransform &matrix) override;
219
220 void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const override;
221 QImage alphaMapForGlyph(glyph_t g) override { return alphaMapForGlyph(g, 0); }
222 QImage alphaMapForGlyph(glyph_t, QFixed) override;
223 QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) override;
224 QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override;
225 QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color) override;
226 glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
227 QFixed subPixelPosition,
228 const QTransform &matrix,
229 QFontEngine::GlyphFormat format) override;
230 Glyph *glyphData(glyph_t glyph, QFixed subPixelPosition,
231 GlyphFormat neededFormat, const QTransform &t) override;
232 bool hasInternalCaching() const override { return cacheEnabled; }
233 bool expectsGammaCorrectedBlending() const override;
234
235 void removeGlyphFromCache(glyph_t glyph) override;
236 int glyphMargin(QFontEngine::GlyphFormat /* format */) override { return 0; }
237
238 int glyphCount() const override;
239
240 enum Scaling {
241 Scaled,
242 Unscaled
243 };
244 FT_Face lockFace(Scaling scale = Scaled) const;
245 void unlockFace() const;
246
247 FT_Face non_locked_face() const;
248
249 inline bool drawAntialiased() const { return antialias; }
250 inline bool invalid() const { return xsize == 0 && ysize == 0; }
251 inline bool isBitmapFont() const { return defaultFormat == Format_Mono; }
252 inline bool isScalableBitmap() const { return freetype->isScalableBitmap(); }
253
254 inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false, bool disableOutlineDrawing = false) const
255 { return loadGlyph(set: cacheEnabled ? &defaultGlyphSet : nullptr, glyph, subPixelPosition, format, fetchMetricsOnly, disableOutlineDrawing); }
256 Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false, bool disableOutlineDrawing = false) const;
257 Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format, const QTransform &t, bool fetchBoundingBox = false, bool disableOutlineDrawing = false);
258
259 QGlyphSet *loadGlyphSet(const QTransform &matrix);
260
261 QFontEngineFT(const QFontDef &fd);
262 virtual ~QFontEngineFT();
263
264 bool init(FaceId faceId, bool antiaalias, GlyphFormat defaultFormat = Format_None,
265 const QByteArray &fontData = QByteArray());
266 bool init(FaceId faceId, bool antialias, GlyphFormat format,
267 QFreetypeFace *freetypeFace);
268
269 int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints) override;
270
271 void setQtDefaultHintStyle(QFont::HintingPreference hintingPreference);
272 void setDefaultHintStyle(HintStyle style) override;
273
274 QFontEngine *cloneWithSize(qreal pixelSize) const override;
275 Qt::HANDLE handle() const override;
276 bool initFromFontEngine(const QFontEngineFT *fontEngine);
277
278 HintStyle defaultHintStyle() const { return default_hint_style; }
279
280 static QFontEngineFT *create(const QFontDef &fontDef, FaceId faceId, const QByteArray &fontData = QByteArray());
281 static QFontEngineFT *create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
282
283protected:
284
285 QFreetypeFace *freetype;
286 mutable int default_load_flags;
287 HintStyle default_hint_style;
288 bool antialias;
289 bool transform;
290 bool embolden;
291 bool obliquen;
292 SubpixelAntialiasingType subpixelType;
293 int lcdFilterType;
294 bool embeddedbitmap;
295 bool cacheEnabled;
296 bool forceAutoHint;
297 bool stemDarkeningDriver;
298
299private:
300 friend class QFontEngineFTRawFont;
301 friend class QFontconfigDatabase;
302 friend class QFreeTypeFontDatabase;
303 friend class QFontEngineMultiFontConfig;
304
305 int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const;
306 bool shouldUseDesignMetrics(ShaperFlags flags) const;
307 QFixed scaledBitmapMetrics(QFixed m) const;
308 glyph_metrics_t scaledBitmapMetrics(const glyph_metrics_t &m, const QTransform &matrix) const;
309
310 GlyphFormat defaultFormat;
311 FT_Matrix matrix;
312
313 QList<QGlyphSet> transformedGlyphSets;
314 mutable QGlyphSet defaultGlyphSet;
315
316 QFontEngine::FaceId face_id;
317
318 int xsize;
319 int ysize;
320
321 QFixed line_thickness;
322 QFixed underline_position;
323
324 FT_Size_Metrics metrics;
325 mutable bool kerning_pairs_loaded;
326 QFixed scalableBitmapScaleFactor;
327};
328
329inline uint qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g)
330{
331 return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt();
332}
333
334inline QFontEngineFT::Glyph *QFontEngineFT::QGlyphSet::getGlyph(glyph_t index, QFixed subPixelPosition) const
335{
336 if (useFastGlyphData(index, subPixelPosition))
337 return fast_glyph_data[index];
338 return glyph_data.value(akey: GlyphAndSubPixelPosition(index, subPixelPosition));
339}
340
341extern FT_Library qt_getFreetype();
342
343QT_END_NAMESPACE
344
345#endif // QT_NO_FREETYPE
346
347#endif // QFONTENGINE_FT_P_H
348

source code of qtbase/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h