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