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

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