Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qfontengine_ft_p.h
Go to the documentation of this file.
1// Copyright (C) 2021 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#ifndef QFONTENGINE_FT_P_H
4#define QFONTENGINE_FT_P_H
5//
6// W A R N I N G
7// -------------
8//
9// This file is not part of the Qt API. It exists purely as an
10// implementation detail. This header file may change from version to
11// version without notice, or even be removed.
12//
13// We mean it.
14//
15
16#include "private/qfontengine_p.h"
17
18#ifndef QT_NO_FREETYPE
19
20#include <ft2build.h>
21#include FT_FREETYPE_H
22#include FT_MULTIPLE_MASTERS_H
23
24#if defined(FT_COLOR_H)
25# include FT_COLOR_H
26#endif
27
28#ifndef Q_OS_WIN
29#include <unistd.h>
30#endif
31
32#include <qmutex.h>
33
34#include <string.h>
35#include <qpainterpath.h>
36
38
39class QFontEngineFTRawFont;
40class QFontconfigDatabase;
41class QColrPaintGraphRenderer;
42
43#if defined(FT_COLOR_H) && (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
44# define QFONTENGINE_FT_SUPPORT_COLRV1
45#endif
46
47/*
48 * This class represents one font file on disk (like Arial.ttf) and is shared between all the font engines
49 * that show this font file (at different pixel sizes).
50 */
51class Q_GUI_EXPORT QFreetypeFace
52{
53public:
54 void computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing, QFixed *scalableBitmapScaleFactor);
55 QFontEngine::Properties properties() const;
56 bool getSfntTable(uint tag, uchar *buffer, uint *length) const;
57
58 static QFreetypeFace *getFace(const QFontEngine::FaceId &face_id,
59 const QByteArray &fontData = QByteArray());
60 void release(const QFontEngine::FaceId &face_id);
61
62 static int getFaceIndexByStyleName(const QString &faceFileName, const QString &styleName);
63
64 // locks the struct for usage. Any read/write operations require locking.
65 void lock()
66 {
67 _lock.lock();
68 }
69 void unlock()
70 {
71 _lock.unlock();
72 }
73
74 FT_Face face;
75 FT_MM_Var *mm_var;
76 int xsize; // 26.6
77 int ysize; // 26.6
78 FT_Matrix matrix;
79 FT_CharMap unicode_map;
80 FT_CharMap symbol_map;
81
82 enum { cmapCacheSize = 0x200 };
83 glyph_t cmapCache[cmapCacheSize];
84
85 int fsType() const;
86
87 int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints);
88
89 bool isScalableBitmap() const;
90
91 static void addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale);
92 static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path);
93
94 inline QList<QFontVariableAxis> variableAxes() const
95 {
96 return variableAxisList;
97 }
98
99private:
100 friend class QFontEngineFT;
101 friend class QtFreetypeData;
102 QFreetypeFace() = default;
103 ~QFreetypeFace() {}
104 void cleanup();
105 QAtomicInt ref;
106 QRecursiveMutex _lock;
107 QByteArray fontData;
108
109 QFontEngine::Holder hbFace;
110 QList<QFontVariableAxis> variableAxisList;
111};
112
113class Q_GUI_EXPORT QFontEngineFT : public QFontEngine
114{
115public:
116 struct GlyphInfo {
117 int linearAdvance;
118 unsigned short width;
119 unsigned short height;
120 short x;
121 short y;
122 short xOff;
123 short yOff;
124 };
125
126 struct GlyphAndSubPixelPosition
127 {
128 GlyphAndSubPixelPosition(glyph_t g, const QFixedPoint spp) : glyph(g), subPixelPosition(spp) {}
129
130 bool operator==(const GlyphAndSubPixelPosition &other) const
131 {
132 return glyph == other.glyph && subPixelPosition == other.subPixelPosition;
133 }
134
135 glyph_t glyph;
136 QFixedPoint subPixelPosition;
137 };
138
139 struct QGlyphSet
140 {
141 QGlyphSet();
142 ~QGlyphSet();
143 FT_Matrix transformationMatrix;
144 bool outline_drawing;
145
146 void removeGlyphFromCache(glyph_t index, const QFixedPoint &subPixelPosition);
147 void clear();
148 inline bool useFastGlyphData(glyph_t index, const QFixedPoint &subPixelPosition) const {
149 return (index < 256 && subPixelPosition.x == 0 && subPixelPosition.y == 0);
150 }
151 inline Glyph *getGlyph(glyph_t index,
152 const QFixedPoint &subPixelPositionX = QFixedPoint()) const;
153 void setGlyph(glyph_t index, const QFixedPoint &spp, Glyph *glyph);
154
155 inline bool isGlyphMissing(glyph_t index) const { return missing_glyphs.contains(index); }
156 inline void setGlyphMissing(glyph_t index) const { missing_glyphs.insert(index); }
157private:
158 Q_DISABLE_COPY(QGlyphSet);
159 mutable QHash<GlyphAndSubPixelPosition, Glyph *> glyph_data; // maps from glyph index to glyph data
160 mutable QSet<glyph_t> missing_glyphs;
161 mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256
162 mutable int fast_glyph_count;
163 };
164
165 QFontEngine::FaceId faceId() const override;
166 QFontEngine::Properties properties() const override;
167 QFixed emSquareSize() const override;
168 bool supportsHorizontalSubPixelPositions() const override
169 {
170 return default_hint_style == HintLight ||
171 default_hint_style == HintNone;
172 }
173
174 bool supportsVerticalSubPixelPositions() const override
175 {
176 return supportsHorizontalSubPixelPositions();
177 }
178
179 bool getSfntTableData(uint tag, uchar *buffer, uint *length) const override;
180 int synthesized() const override;
181
182 void initializeHeightMetrics() const override;
183 QFixed capHeight() const override;
184 QFixed xHeight() const override;
185 QFixed averageCharWidth() const override;
186
187 qreal maxCharWidth() const override;
188 QFixed lineThickness() const override;
189 QFixed underlinePosition() const override;
190
191 glyph_t glyphIndex(uint ucs4) const override;
192 QString glyphName(glyph_t index) const override;
193 void doKerning(QGlyphLayout *, ShaperFlags) const override;
194
195 void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) override;
196
197 bool supportsTransformation(const QTransform &transform) const override;
198
199 void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
200 QPainterPath *path, QTextItem::RenderFlags flags) override;
201 void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,
202 QPainterPath *path, QTextItem::RenderFlags flags) override;
203
204 int stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
205
206 glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override;
207 glyph_metrics_t boundingBox(glyph_t glyph) override;
208 glyph_metrics_t boundingBox(glyph_t glyph, const QTransform &matrix) override;
209
210 void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const override;
211 QImage alphaMapForGlyph(glyph_t g) override { return alphaMapForGlyph(g, QFixedPoint()); }
212 QImage alphaMapForGlyph(glyph_t, const QFixedPoint &) override;
213 QImage alphaMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition, const QTransform &t) override;
214 QImage alphaRGBMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t) override;
215 QImage bitmapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t, const QColor &color) override;
216 glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
217 const QFixedPoint &subPixelPosition,
218 const QTransform &matrix,
219 QFontEngine::GlyphFormat format) override;
220 Glyph *glyphData(glyph_t glyph,
221 const QFixedPoint &subPixelPosition,
222 GlyphFormat neededFormat,
223 const QTransform &t) override;
224 bool hasInternalCaching() const override { return cacheEnabled; }
225 bool expectsGammaCorrectedBlending() const override;
226
227 void removeGlyphFromCache(glyph_t glyph) override;
228 int glyphMargin(QFontEngine::GlyphFormat /* format */) override { return 0; }
229
230 int glyphCount() const override;
231
232 QList<QFontVariableAxis> variableAxes() const override;
233
234 enum Scaling {
235 Scaled,
236 Unscaled
237 };
238 FT_Face lockFace(Scaling scale = Scaled) const;
239 void unlockFace() const;
240
241 FT_Face non_locked_face() const;
242
243 inline bool drawAntialiased() const { return antialias; }
244 inline bool invalid() const { return xsize == 0 && ysize == 0; }
245 inline bool isBitmapFont() const { return defaultFormat == Format_Mono; }
246 inline bool isScalableBitmap() const { return freetype->isScalableBitmap(); }
247
248 inline Glyph *loadGlyph(uint glyph,
249 const QFixedPoint &subPixelPosition,
250 GlyphFormat format = Format_None,
251 bool fetchMetricsOnly = false,
252 bool disableOutlineDrawing = false) const
253 {
254 return loadGlyph(cacheEnabled ? &defaultGlyphSet : nullptr,
255 glyph,
256 subPixelPosition,
257 QColor(),
258 format,
259 fetchMetricsOnly,
260 disableOutlineDrawing);
261 }
262 Glyph *loadGlyph(QGlyphSet *set,
263 uint glyph,
264 const QFixedPoint &subPixelPosition,
265 QColor color,
266 GlyphFormat = Format_None,
267 bool fetchMetricsOnly = false,
268 bool disableOutlineDrawing = false) const;
269 Glyph *loadGlyphFor(glyph_t g,
270 const QFixedPoint &subPixelPosition,
271 GlyphFormat format,
272 const QTransform &t,
273 QColor color,
274 bool fetchBoundingBox = false,
275 bool disableOutlineDrawing = false);
276
277 QGlyphSet *loadGlyphSet(const QTransform &matrix);
278
279 QFontEngineFT(const QFontDef &fd);
280 virtual ~QFontEngineFT();
281
282 bool init(FaceId faceId, bool antiaalias, GlyphFormat defaultFormat = Format_None,
283 const QByteArray &fontData = QByteArray());
284 bool init(FaceId faceId, bool antialias, GlyphFormat format,
285 QFreetypeFace *freetypeFace);
286
287 int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints) override;
288
289 void setQtDefaultHintStyle(QFont::HintingPreference hintingPreference);
290 void setDefaultHintStyle(HintStyle style) override;
291
292 QFontEngine *cloneWithSize(qreal pixelSize) const override;
293 Qt::HANDLE handle() const override;
294 bool initFromFontEngine(const QFontEngineFT *fontEngine);
295
296 HintStyle defaultHintStyle() const { return default_hint_style; }
297
298 static QFontEngineFT *create(const QFontDef &fontDef, FaceId faceId, const QByteArray &fontData = QByteArray());
299 static QFontEngineFT *create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference, const QMap<QFont::Tag, float> &variableAxisValue);
300
301protected:
302
303 QFreetypeFace *freetype;
304 mutable int default_load_flags;
305 HintStyle default_hint_style;
306 bool antialias;
307 bool transform;
308 bool embolden;
309 bool obliquen;
310 SubpixelAntialiasingType subpixelType;
311 int lcdFilterType;
312 bool embeddedbitmap;
313 bool cacheEnabled;
314 bool forceAutoHint;
315 bool stemDarkeningDriver;
316
317private:
318 friend class QFontEngineFTRawFont;
319 friend class QFontconfigDatabase;
320 friend class QFreeTypeFontDatabase;
321 friend class QFontEngineMultiFontConfig;
322
323 int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const;
324 bool shouldUseDesignMetrics(ShaperFlags flags) const;
325 QFixed scaledBitmapMetrics(QFixed m) const;
326 glyph_metrics_t scaledBitmapMetrics(const glyph_metrics_t &m, const QTransform &matrix) const;
327
328#if defined(QFONTENGINE_FT_SUPPORT_COLRV1)
329 Glyph *loadColrv1Glyph(QGlyphSet *set,
330 Glyph *g,
331 uint glyph,
332 const QColor &color,
333 bool fetchMetricsOnly) const;
334
335 bool traverseColr1(FT_OpaquePaint paint,
336 QSet<QPair<FT_Byte *, FT_Bool> > *loops,
337 QColor foregroundColor,
338 FT_Color *palette,
339 ushort paletteCount,
340 QColrPaintGraphRenderer *paintGraphRenderer) const;
341 mutable glyph_t colrv1_bounds_cache_id = 0;
342 mutable QRect colrv1_bounds_cache;
343#endif // QFONTENGINE_FT_SUPPORT_COLRV1
344
345 GlyphFormat defaultFormat;
346 FT_Matrix matrix;
347
348 struct TransformedGlyphSets {
349 enum { nSets = 10 };
350 QGlyphSet *sets[nSets];
351
352 QGlyphSet *findSet(const QTransform &matrix, const QFontDef &fontDef);
353 TransformedGlyphSets() { std::fill(&sets[0], &sets[nSets], nullptr); }
354 ~TransformedGlyphSets() { qDeleteAll(&sets[0], &sets[nSets]); }
355 private:
356 void moveToFront(int i);
357 Q_DISABLE_COPY(TransformedGlyphSets);
358 };
359 TransformedGlyphSets transformedGlyphSets;
360 mutable QGlyphSet defaultGlyphSet;
361
362 QFontEngine::FaceId face_id;
363
364 int xsize;
365 int ysize;
366
367 QFixed line_thickness;
368 QFixed underline_position;
369
370 FT_Size_Metrics metrics;
371 mutable bool kerning_pairs_loaded;
372 QFixed scalableBitmapScaleFactor;
373};
374
375
376inline size_t qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g, size_t seed = 0)
377{
378 return qHashMulti(seed,
379 g.glyph,
380 g.subPixelPosition.x.value(),
381 g.subPixelPosition.y.value());
382}
383
384inline QFontEngineFT::Glyph *QFontEngineFT::QGlyphSet::getGlyph(glyph_t index,
385 const QFixedPoint &subPixelPosition) const
386{
387 if (useFastGlyphData(index, subPixelPosition))
388 return fast_glyph_data[index];
389 return glyph_data.value(GlyphAndSubPixelPosition(index, subPixelPosition));
390}
391
392Q_GUI_EXPORT FT_Library qt_getFreetype();
393
394QT_END_NAMESPACE
395
396#endif // QT_NO_FREETYPE
397
398#endif // QFONTENGINE_FT_P_H
\inmodule QtCore
QHash< QFontEngine::FaceId, QFreetypeFace * > faces
QList< QFreetypeFace * > staleFaces
QHash< FaceStyle, int > faceIndices
static const QFontEngine::HintStyle ftInitialDefaultHintStyle
#define FLOOR(x)
static QFontEngine::SubpixelAntialiasingType subpixelAntialiasingTypeHint()
static FT_Matrix QTransformToFTMatrix(const QTransform &matrix)
static void transformBoundingBox(int *left, int *top, int *right, int *bottom, FT_Matrix *matrix)
static void convertRGBToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr)
QtFreetypeData * qt_getFreetypeData()
static bool calculateActualItalic(QFreetypeFace *freetypeFace, FT_Face face, QFontEngine::FaceId faceId)
#define CEIL(x)
static bool is2dRotation(const QTransform &t)
static QImage alphaMapFromGlyphData(QFontEngineFT::Glyph *glyph, QFontEngine::GlyphFormat glyphFormat)
static QFontEngineFT::Glyph emptyGlyph
QByteArray qt_fontdata_from_index(int)
size_t qHash(const QtFreetypeData::FaceStyle &style, size_t seed)
static bool ft_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length)
void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path)
static int computeFaceIndex(const QString &faceFileName, const QString &styleName)
bool operator==(const QtFreetypeData::FaceStyle &style1, const QtFreetypeData::FaceStyle &style2)
FT_Library qt_getFreetype()
static FT_UShort calculateActualWeight(QFreetypeFace *freetypeFace, FT_Face face, QFontEngine::FaceId faceId)
#define GLYPH2PATH_DEBUG
static void convertRGBToARGB_V(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr)
static void scaleOutline(FT_Face face, FT_GlyphSlot g, FT_Fixed x_scale, FT_Fixed y_scale)
static void dont_delete(void *)
#define ROUND(x)
static bool areMetricsTooLarge(const QFontEngineFT::GlyphInfo &info)
#define TRUNC(x)
#define QT_MAX_CACHED_GLYPH_SIZE
constexpr size_t qHash(const QSize &s, size_t seed=0) noexcept
Definition qsize.h:191
FaceStyle(QString faceFileName, QString styleName)