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
4#ifndef QFONTENGINE_P_H
5#define QFONTENGINE_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 purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtGui/private/qtguiglobal_p.h>
19#include "QtCore/qatomic.h"
20#include <QtCore/qvarlengtharray.h>
21#include <QtCore/qhashfunctions.h>
22#include "private/qtextengine_p.h"
23#include "private/qfont_p.h"
24
25QT_BEGIN_NAMESPACE
26
27class QPainterPath;
28class QFontEngineGlyphCache;
29
30struct QGlyphLayout;
31
32// ### this only used in getPointInOutline(), refactor it and then remove these magic numbers
33enum HB_Compat_Error {
34 Err_Ok = 0x0000,
35 Err_Not_Covered = 0xFFFF,
36 Err_Invalid_Argument = 0x1A66,
37 Err_Invalid_SubTable_Format = 0x157F,
38 Err_Invalid_SubTable = 0x1570
39};
40
41typedef void (*qt_destroy_func_t) (void *user_data);
42typedef bool (*qt_get_font_table_func_t) (void *user_data, uint tag, uchar *buffer, uint *length);
43
44class Q_GUI_EXPORT QFontEngine
45{
46public:
47 enum Type {
48 Box,
49 Multi,
50
51 // MS Windows types
52 Win,
53
54 // Apple Mac OS types
55 Mac,
56
57 // QWS types
58 Freetype,
59 QPF1,
60 QPF2,
61 Proxy,
62
63 DirectWrite,
64
65 TestFontEngine = 0x1000
66 };
67
68 enum GlyphFormat {
69 Format_None,
70 Format_Render = Format_None,
71 Format_Mono,
72 Format_A8,
73 Format_A32,
74 Format_ARGB
75 };
76
77 enum ShaperFlag {
78 DesignMetrics = 0x0002,
79 GlyphIndicesOnly = 0x0004,
80 FullStringFallback = 0x008
81 };
82 Q_DECLARE_FLAGS(ShaperFlags, ShaperFlag)
83
84 /* Used with the Freetype font engine. */
85 struct Glyph {
86 Glyph() = default;
87 ~Glyph() { delete [] data; }
88 short linearAdvance = 0;
89 unsigned short width = 0;
90 unsigned short height = 0;
91 short x = 0;
92 short y = 0;
93 short advance = 0;
94 signed char format = 0;
95 uchar *data = nullptr;
96 private:
97 Q_DISABLE_COPY(Glyph)
98 };
99
100 virtual ~QFontEngine();
101
102 inline Type type() const { return m_type; }
103
104 // all of these are in unscaled metrics if the engine supports uncsaled metrics,
105 // otherwise in design metrics
106 struct Properties {
107 QByteArray postscriptName;
108 QByteArray copyright;
109 QRectF boundingBox;
110 QFixed emSquare;
111 QFixed ascent;
112 QFixed descent;
113 QFixed leading;
114 QFixed italicAngle;
115 QFixed capHeight;
116 QFixed lineWidth;
117 };
118 virtual Properties properties() const;
119 virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics);
120 QByteArray getSfntTable(uint tag) const;
121 virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
122
123 struct FaceId {
124 FaceId() : index(0), instanceIndex(-1), encoding(0) {}
125 QByteArray filename;
126 QByteArray uuid;
127 int index;
128 int instanceIndex;
129 int encoding;
130 QMap<QFont::Tag, float> variableAxes;
131 };
132 virtual FaceId faceId() const { return FaceId(); }
133 enum SynthesizedFlags {
134 SynthesizedItalic = 0x1,
135 SynthesizedBold = 0x2,
136 SynthesizedStretch = 0x4
137 };
138 virtual int synthesized() const { return 0; }
139 inline bool supportsSubPixelPositions() const
140 {
141 return supportsHorizontalSubPixelPositions() || supportsVerticalSubPixelPositions();
142 }
143 virtual bool supportsHorizontalSubPixelPositions() const { return false; }
144 virtual bool supportsVerticalSubPixelPositions() const { return false; }
145 virtual QFixedPoint subPixelPositionFor(const QFixedPoint &position) const;
146 QFixed subPixelPositionForX(QFixed x) const
147 {
148 return subPixelPositionFor(position: QFixedPoint(x, 0)).x;
149 }
150
151 bool preferTypoLineMetrics() const;
152 bool isColorFont() const { return glyphFormat == Format_ARGB; }
153 static bool isIgnorableChar(char32_t ucs4)
154 {
155 return ucs4 == QChar::LineSeparator
156 || ucs4 == QChar::LineFeed
157 || ucs4 == QChar::CarriageReturn
158 || ucs4 == QChar::ParagraphSeparator
159 || QChar::category(ucs4) == QChar::Other_Control;
160 }
161
162 virtual QFixed emSquareSize() const { return ascent(); }
163
164 /* returns 0 as glyph index for non existent glyphs */
165 virtual glyph_t glyphIndex(uint ucs4) const = 0;
166 virtual int stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const = 0;
167 virtual void recalcAdvances(QGlyphLayout *, ShaperFlags) const {}
168 virtual void doKerning(QGlyphLayout *, ShaperFlags) const;
169
170 virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
171 QPainterPath *path, QTextItem::RenderFlags flags);
172
173 void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags,
174 QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions);
175
176 virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags);
177 void addBitmapFontToPath(qreal x, qreal y, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags);
178 /**
179 * Create a qimage with the alpha values for the glyph.
180 * Returns an image indexed_8 with index values ranging from 0=fully transparent to 255=opaque
181 */
182 // ### Refactor this into a smaller and more flexible API.
183 virtual QImage alphaMapForGlyph(glyph_t);
184 virtual QImage alphaMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition);
185 virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t);
186 virtual QImage alphaMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t);
187 virtual QImage alphaRGBMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t);
188 virtual QImage bitmapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t, const QColor &color = QColor());
189 QImage renderedPathForGlyph(glyph_t glyph, const QColor &color);
190 virtual Glyph *glyphData(glyph_t glyph, const QFixedPoint &subPixelPosition, GlyphFormat neededFormat, const QTransform &t);
191 virtual bool hasInternalCaching() const { return false; }
192
193 virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QFixedPoint &/*subPixelPosition*/, const QTransform &matrix, GlyphFormat /*format*/)
194 {
195 return boundingBox(glyph, matrix);
196 }
197
198 virtual void removeGlyphFromCache(glyph_t);
199
200 virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
201 virtual glyph_metrics_t boundingBox(glyph_t glyph) = 0;
202 virtual glyph_metrics_t boundingBox(glyph_t glyph, const QTransform &matrix);
203 glyph_metrics_t tightBoundingBox(const QGlyphLayout &glyphs);
204
205 virtual QFixed ascent() const;
206 virtual QFixed capHeight() const = 0;
207 virtual QFixed descent() const;
208 virtual QFixed leading() const;
209 virtual QFixed xHeight() const;
210 virtual QFixed averageCharWidth() const;
211
212 virtual QFixed lineThickness() const;
213 virtual QFixed underlinePosition() const;
214
215 virtual qreal maxCharWidth() const = 0;
216 virtual qreal minLeftBearing() const;
217 virtual qreal minRightBearing() const;
218
219 virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = nullptr, qreal *rightBearing = nullptr);
220
221 inline bool canRender(uint ucs4) const { return glyphIndex(ucs4) != 0; }
222 virtual bool canRender(const QChar *str, int len) const;
223
224 virtual bool supportsTransformation(const QTransform &transform) const;
225
226 virtual int glyphCount() const;
227 virtual int glyphMargin(GlyphFormat format) { return format == Format_A32 ? 2 : 0; }
228
229 virtual QFontEngine *cloneWithSize(qreal /*pixelSize*/) const { return nullptr; }
230
231 virtual Qt::HANDLE handle() const;
232
233 void *harfbuzzFont() const;
234 void *harfbuzzFace() const;
235 bool supportsScript(QChar::Script script) const;
236
237 inline static bool scriptRequiresOpenType(QChar::Script script)
238 {
239 return ((script >= QChar::Script_Syriac && script <= QChar::Script_Sinhala)
240 || script == QChar::Script_Khmer || script == QChar::Script_Nko);
241 }
242
243 virtual int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints);
244
245 void clearGlyphCache(const void *key);
246 void setGlyphCache(const void *key, QFontEngineGlyphCache *data);
247 QFontEngineGlyphCache *glyphCache(const void *key, GlyphFormat format, const QTransform &transform, const QColor &color = QColor()) const;
248
249 static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize);
250 static quint32 getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode);
251
252 static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily);
253
254 virtual bool hasUnreliableGlyphOutline() const;
255 virtual bool expectsGammaCorrectedBlending() const;
256
257 enum HintStyle {
258 HintNone,
259 HintLight,
260 HintMedium,
261 HintFull
262 };
263 virtual void setDefaultHintStyle(HintStyle) { }
264
265 enum SubpixelAntialiasingType {
266 Subpixel_None,
267 Subpixel_RGB,
268 Subpixel_BGR,
269 Subpixel_VRGB,
270 Subpixel_VBGR
271 };
272
273private:
274 const Type m_type;
275
276public:
277 QAtomicInt ref;
278 QFontDef fontDef;
279
280 class Holder { // replace by std::unique_ptr once available
281 void *ptr;
282 qt_destroy_func_t destroy_func;
283 public:
284 Holder() : ptr(nullptr), destroy_func(nullptr) {}
285 explicit Holder(void *p, qt_destroy_func_t d) : ptr(p), destroy_func(d) {}
286 ~Holder() { if (ptr && destroy_func) destroy_func(ptr); }
287 Holder(Holder &&other) noexcept
288 : ptr(std::exchange(obj&: other.ptr, new_val: nullptr)),
289 destroy_func(std::exchange(obj&: other.destroy_func, new_val: nullptr))
290 {
291 }
292 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Holder)
293
294 void swap(Holder &other) noexcept
295 {
296 qSwap(value1&: ptr, value2&: other.ptr);
297 qSwap(value1&: destroy_func, value2&: other.destroy_func);
298 }
299
300 void *get() const noexcept { return ptr; }
301 void *release() noexcept {
302 void *result = ptr;
303 ptr = nullptr;
304 destroy_func = nullptr;
305 return result;
306 }
307 void reset() noexcept { Holder().swap(other&: *this); }
308 qt_destroy_func_t get_deleter() const noexcept { return destroy_func; }
309
310 bool operator!() const noexcept { return !ptr; }
311 };
312
313 mutable Holder font_; // \ NOTE: Declared before m_glyphCaches, so font_, face_
314 mutable Holder face_; // / are destroyed _after_ m_glyphCaches is destroyed.
315
316 struct FaceData {
317 void *user_data;
318 qt_get_font_table_func_t get_font_table;
319 } faceData;
320
321 uint cache_cost; // amount of mem used in bytes by the font
322 uint fsType : 16;
323 bool symbol;
324 bool isSmoothlyScalable;
325 struct KernPair {
326 uint left_right;
327 QFixed adjust;
328
329 inline bool operator<(const KernPair &other) const
330 {
331 return left_right < other.left_right;
332 }
333 };
334 QList<KernPair> kerning_pairs;
335 void loadKerningPairs(QFixed scalingFactor);
336
337 GlyphFormat glyphFormat;
338 int m_subPixelPositionCount; // Number of positions within a single pixel for this cache
339
340protected:
341 explicit QFontEngine(Type type);
342
343 QFixed firstLeftBearing(const QGlyphLayout &glyphs);
344 QFixed lastRightBearing(const QGlyphLayout &glyphs);
345
346 QFixed calculatedCapHeight() const;
347
348 mutable QFixed m_ascent;
349 mutable QFixed m_descent;
350 mutable QFixed m_leading;
351 mutable bool m_heightMetricsQueried;
352
353 virtual void initializeHeightMetrics() const;
354 bool processHheaTable() const;
355 bool processOS2Table() const;
356
357private:
358 struct GlyphCacheEntry {
359 GlyphCacheEntry();
360 GlyphCacheEntry(const GlyphCacheEntry &);
361 ~GlyphCacheEntry();
362
363 GlyphCacheEntry &operator=(const GlyphCacheEntry &);
364
365 QExplicitlySharedDataPointer<QFontEngineGlyphCache> cache;
366 bool operator==(const GlyphCacheEntry &other) const { return cache == other.cache; }
367 };
368 typedef std::list<GlyphCacheEntry> GlyphCaches;
369 mutable QHash<const void *, GlyphCaches> m_glyphCaches;
370
371private:
372 mutable qreal m_minLeftBearing;
373 mutable qreal m_minRightBearing;
374};
375Q_DECLARE_TYPEINFO(QFontEngine::KernPair, Q_PRIMITIVE_TYPE);
376
377Q_DECLARE_OPERATORS_FOR_FLAGS(QFontEngine::ShaperFlags)
378
379inline bool operator ==(const QFontEngine::FaceId &f1, const QFontEngine::FaceId &f2)
380{
381 return f1.index == f2.index
382 && f1.encoding == f2.encoding
383 && f1.filename == f2.filename
384 && f1.uuid == f2.uuid
385 && f1.instanceIndex == f2.instanceIndex
386 && f1.variableAxes == f2.variableAxes;
387}
388
389inline size_t qHash(const QFontEngine::FaceId &f, size_t seed = 0)
390 noexcept(noexcept(qHash(key: f.filename)))
391{
392 return qHashMulti(seed, args: f.filename, args: f.uuid, args: f.index, args: f.instanceIndex, args: f.encoding, args: f.variableAxes.keys(), args: f.variableAxes.values());
393}
394
395
396class QGlyph;
397
398
399
400class QFontEngineBox : public QFontEngine
401{
402public:
403 QFontEngineBox(int size);
404 ~QFontEngineBox();
405
406 virtual glyph_t glyphIndex(uint ucs4) const override;
407 virtual int stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
408 virtual void recalcAdvances(QGlyphLayout *, ShaperFlags) const override;
409
410 void draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &si);
411 virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) override;
412
413 virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override;
414 virtual glyph_metrics_t boundingBox(glyph_t glyph) override;
415 virtual QFontEngine *cloneWithSize(qreal pixelSize) const override;
416
417 virtual QFixed ascent() const override;
418 virtual QFixed capHeight() const override;
419 virtual QFixed descent() const override;
420 virtual QFixed leading() const override;
421 virtual qreal maxCharWidth() const override;
422 virtual qreal minLeftBearing() const override { return 0; }
423 virtual qreal minRightBearing() const override { return 0; }
424 virtual QImage alphaMapForGlyph(glyph_t) override;
425
426 virtual bool canRender(const QChar *string, int len) const override;
427
428 inline int size() const { return _size; }
429
430protected:
431 explicit QFontEngineBox(Type type, int size);
432
433private:
434 friend class QFontPrivate;
435 int _size;
436};
437
438class Q_GUI_EXPORT QFontEngineMulti : public QFontEngine
439{
440public:
441 explicit QFontEngineMulti(QFontEngine *engine, int script, const QStringList &fallbackFamilies = QStringList());
442 ~QFontEngineMulti();
443
444 virtual glyph_t glyphIndex(uint ucs4) const override;
445 virtual int stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
446
447 virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override;
448 virtual glyph_metrics_t boundingBox(glyph_t glyph) override;
449
450 virtual void recalcAdvances(QGlyphLayout *, ShaperFlags) const override;
451 virtual void doKerning(QGlyphLayout *, ShaperFlags) const override;
452 virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags) override;
453 virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = nullptr, qreal *rightBearing = nullptr) override;
454
455 virtual QFixed ascent() const override;
456 virtual QFixed capHeight() const override;
457 virtual QFixed descent() const override;
458 virtual QFixed leading() const override;
459 virtual QFixed xHeight() const override;
460 virtual QFixed averageCharWidth() const override;
461 virtual QImage alphaMapForGlyph(glyph_t) override;
462 virtual QImage alphaMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition) override;
463 virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t) override;
464 virtual QImage alphaMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t) override;
465 virtual QImage alphaRGBMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t) override;
466
467 virtual QFixed lineThickness() const override;
468 virtual QFixed underlinePosition() const override;
469 virtual qreal maxCharWidth() const override;
470 virtual qreal minLeftBearing() const override;
471 virtual qreal minRightBearing() const override;
472
473 virtual bool canRender(const QChar *string, int len) const override;
474
475 inline int fallbackFamilyCount() const { return m_fallbackFamilies.size(); }
476 inline QString fallbackFamilyAt(int at) const { return m_fallbackFamilies.at(i: at); }
477
478 void setFallbackFamiliesList(const QStringList &fallbackFamilies);
479
480 static uchar highByte(glyph_t glyph); // Used for determining engine
481
482 inline QFontEngine *engine(int at) const
483 { Q_ASSERT(at < m_engines.size()); return m_engines.at(i: at); }
484
485 void ensureEngineAt(int at);
486
487 static QFontEngine *createMultiFontEngine(QFontEngine *fe, int script);
488
489protected:
490 virtual void ensureFallbackFamiliesQueried();
491 virtual bool shouldLoadFontEngineForCharacter(int at, uint ucs4) const;
492 virtual QFontEngine *loadEngine(int at);
493
494private:
495 QList<QFontEngine *> m_engines;
496 QStringList m_fallbackFamilies;
497 const int m_script;
498 bool m_fallbackFamiliesQueried;
499};
500
501class QTestFontEngine : public QFontEngineBox
502{
503public:
504 QTestFontEngine(int size);
505};
506
507QT_END_NAMESPACE
508
509
510
511#endif // QFONTENGINE_P_H
512

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtbase/src/gui/text/qfontengine_p.h