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 virtual ~QFontEngine();
127
128 inline Type type() const { return m_type; }
129
130 // all of these are in unscaled metrics if the engine supports uncsaled metrics,
131 // otherwise in design metrics
132 struct Properties {
133 QByteArray postscriptName;
134 QByteArray copyright;
135 QRectF boundingBox;
136 QFixed emSquare;
137 QFixed ascent;
138 QFixed descent;
139 QFixed leading;
140 QFixed italicAngle;
141 QFixed capHeight;
142 QFixed lineWidth;
143 };
144 virtual Properties properties() const;
145 virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics);
146 QByteArray getSfntTable(uint tag) const;
147 virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
148
149 struct FaceId {
150 FaceId() : index(0), encoding(0) {}
151 QByteArray filename;
152 QByteArray uuid;
153 int index;
154 int encoding;
155 };
156 virtual FaceId faceId() const { return FaceId(); }
157 enum SynthesizedFlags {
158 SynthesizedItalic = 0x1,
159 SynthesizedBold = 0x2,
160 SynthesizedStretch = 0x4
161 };
162 virtual int synthesized() const { return 0; }
163 virtual bool supportsSubPixelPositions() const { return false; }
164 virtual QFixed subPixelPositionForX(QFixed x) const;
165
166 virtual QFixed emSquareSize() const { return ascent(); }
167
168 /* returns 0 as glyph index for non existent glyphs */
169 virtual glyph_t glyphIndex(uint ucs4) const = 0;
170 virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const = 0;
171 virtual void recalcAdvances(QGlyphLayout *, ShaperFlags) const {}
172 virtual void doKerning(QGlyphLayout *, ShaperFlags) const;
173
174 virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
175 QPainterPath *path, QTextItem::RenderFlags flags);
176
177 void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags,
178 QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions);
179
180 virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags);
181 void addBitmapFontToPath(qreal x, qreal y, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags);
182 /**
183 * Create a qimage with the alpha values for the glyph.
184 * Returns an image indexed_8 with index values ranging from 0=fully transparent to 255=opaque
185 */
186 // ### Refactor this into a smaller and more flexible API.
187 virtual QImage alphaMapForGlyph(glyph_t);
188 virtual QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition);
189 virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t);
190 virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
191 virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
192 virtual QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color = QColor());
193 virtual QImage *lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition,
194 GlyphFormat neededFormat,
195 const QTransform &t = QTransform(),
196 QPoint *offset = nullptr);
197 virtual void unlockAlphaMapForGlyph();
198 virtual bool hasInternalCaching() const { return false; }
199
200 virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed /*subPixelPosition*/, const QTransform &matrix, GlyphFormat /*format*/)
201 {
202 return boundingBox(glyph, matrix);
203 }
204
205 virtual void removeGlyphFromCache(glyph_t);
206
207 virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) = 0;
208 virtual glyph_metrics_t boundingBox(glyph_t glyph) = 0;
209 virtual glyph_metrics_t boundingBox(glyph_t glyph, const QTransform &matrix);
210 glyph_metrics_t tightBoundingBox(const QGlyphLayout &glyphs);
211
212 virtual QFixed ascent() const = 0;
213 virtual QFixed capHeight() const = 0;
214 virtual QFixed descent() const = 0;
215 virtual QFixed leading() const = 0;
216 virtual QFixed xHeight() const;
217 virtual QFixed averageCharWidth() const;
218
219 virtual QFixed lineThickness() const;
220 virtual QFixed underlinePosition() const;
221
222 virtual qreal maxCharWidth() const = 0;
223 virtual qreal minLeftBearing() const;
224 virtual qreal minRightBearing() const;
225
226 virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = nullptr, qreal *rightBearing = nullptr);
227
228 inline bool canRender(uint ucs4) const { return glyphIndex(ucs4) != 0; }
229 virtual bool canRender(const QChar *str, int len) const;
230
231 virtual bool supportsTransformation(const QTransform &transform) const;
232
233 virtual int glyphCount() const;
234 virtual int glyphMargin(GlyphFormat format) { return format == Format_A32 ? 2 : 0; }
235
236 virtual QFontEngine *cloneWithSize(qreal /*pixelSize*/) const { return nullptr; }
237
238 virtual Qt::HANDLE handle() const;
239
240 void *harfbuzzFont() const;
241 void *harfbuzzFace() const;
242 bool supportsScript(QChar::Script script) const;
243
244 inline static bool scriptRequiresOpenType(QChar::Script script)
245 {
246 return ((script >= QChar::Script_Syriac && script <= QChar::Script_Sinhala)
247 || script == QChar::Script_Khmer || script == QChar::Script_Nko);
248 }
249
250 virtual int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints);
251
252 void clearGlyphCache(const void *key);
253 void setGlyphCache(const void *key, QFontEngineGlyphCache *data);
254 QFontEngineGlyphCache *glyphCache(const void *key, GlyphFormat format, const QTransform &transform, const QColor &color = QColor()) const;
255
256 static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize);
257 static quint32 getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode);
258
259 static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily);
260
261 virtual bool hasUnreliableGlyphOutline() const;
262 virtual bool expectsGammaCorrectedBlending() const;
263
264 enum HintStyle {
265 HintNone,
266 HintLight,
267 HintMedium,
268 HintFull
269 };
270 virtual void setDefaultHintStyle(HintStyle) { }
271
272 enum SubpixelAntialiasingType {
273 Subpixel_None,
274 Subpixel_RGB,
275 Subpixel_BGR,
276 Subpixel_VRGB,
277 Subpixel_VBGR
278 };
279
280private:
281 const Type m_type;
282
283public:
284 QAtomicInt ref;
285 QFontDef fontDef;
286
287 class Holder { // replace by std::unique_ptr once available
288 void *ptr;
289 qt_destroy_func_t destroy_func;
290 public:
291 Holder() : ptr(nullptr), destroy_func(nullptr) {}
292 explicit Holder(void *p, qt_destroy_func_t d) : ptr(p), destroy_func(d) {}
293 ~Holder() { if (ptr && destroy_func) destroy_func(ptr); }
294 Holder(Holder &&other) noexcept
295 : ptr(other.ptr),
296 destroy_func(other.destroy_func)
297 {
298 other.ptr = nullptr;
299 other.destroy_func = nullptr;
300 }
301 Holder &operator=(Holder &&other) noexcept
302 { swap(other); return *this; }
303
304 void swap(Holder &other) noexcept
305 {
306 qSwap(ptr, other.ptr);
307 qSwap(destroy_func, other.destroy_func);
308 }
309
310 void *get() const noexcept { return ptr; }
311 void *release() noexcept {
312 void *result = ptr;
313 ptr = nullptr;
314 destroy_func = nullptr;
315 return result;
316 }
317 void reset() noexcept { Holder().swap(*this); }
318 qt_destroy_func_t get_deleter() const noexcept { return destroy_func; }
319
320 bool operator!() const noexcept { return !ptr; }
321 };
322
323 mutable Holder font_; // \ NOTE: Declared before m_glyphCaches, so font_, face_
324 mutable Holder face_; // / are destroyed _after_ m_glyphCaches is destroyed.
325
326 struct FaceData {
327 void *user_data;
328 qt_get_font_table_func_t get_font_table;
329 } faceData;
330
331 uint cache_cost; // amount of mem used in bytes by the font
332 uint fsType : 16;
333 bool symbol;
334 bool isSmoothlyScalable;
335 struct KernPair {
336 uint left_right;
337 QFixed adjust;
338
339 inline bool operator<(const KernPair &other) const
340 {
341 return left_right < other.left_right;
342 }
343 };
344 QVector<KernPair> kerning_pairs;
345 void loadKerningPairs(QFixed scalingFactor);
346
347 GlyphFormat glyphFormat;
348 QImage currentlyLockedAlphaMap;
349 int m_subPixelPositionCount; // Number of positions within a single pixel for this cache
350
351 inline QVariant userData() const { return m_userData; }
352
353protected:
354 explicit QFontEngine(Type type);
355
356 QFixed lastRightBearing(const QGlyphLayout &glyphs, bool round = false);
357
358 inline void setUserData(const QVariant &userData) { m_userData = userData; }
359 QFixed calculatedCapHeight() const;
360
361private:
362 struct GlyphCacheEntry {
363 GlyphCacheEntry();
364 GlyphCacheEntry(const GlyphCacheEntry &);
365 ~GlyphCacheEntry();
366
367 GlyphCacheEntry &operator=(const GlyphCacheEntry &);
368
369 QExplicitlySharedDataPointer<QFontEngineGlyphCache> cache;
370 bool operator==(const GlyphCacheEntry &other) const { return cache == other.cache; }
371 };
372 typedef std::list<GlyphCacheEntry> GlyphCaches;
373 mutable QHash<const void *, GlyphCaches> m_glyphCaches;
374
375private:
376 QVariant m_userData;
377
378 mutable qreal m_minLeftBearing;
379 mutable qreal m_minRightBearing;
380
381};
382Q_DECLARE_TYPEINFO(QFontEngine::KernPair, Q_PRIMITIVE_TYPE);
383
384Q_DECLARE_OPERATORS_FOR_FLAGS(QFontEngine::ShaperFlags)
385
386inline bool operator ==(const QFontEngine::FaceId &f1, const QFontEngine::FaceId &f2)
387{
388 return f1.index == f2.index && f1.encoding == f2.encoding && f1.filename == f2.filename && f1.uuid == f2.uuid;
389}
390
391inline uint qHash(const QFontEngine::FaceId &f, uint seed = 0)
392 noexcept(noexcept(qHash(f.filename)))
393{
394 QtPrivate::QHashCombine hash;
395 seed = hash(seed, f.filename);
396 seed = hash(seed, f.uuid);
397 seed = hash(seed, f.index);
398 seed = hash(seed, f.encoding);
399 return seed;
400}
401
402
403class QGlyph;
404
405
406
407class QFontEngineBox : public QFontEngine
408{
409public:
410 QFontEngineBox(int size);
411 ~QFontEngineBox();
412
413 virtual glyph_t glyphIndex(uint ucs4) const override;
414 virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
415 virtual void recalcAdvances(QGlyphLayout *, ShaperFlags) const override;
416
417 void draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &si);
418 virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) override;
419
420 virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override;
421 virtual glyph_metrics_t boundingBox(glyph_t glyph) override;
422 virtual QFontEngine *cloneWithSize(qreal pixelSize) const override;
423
424 virtual QFixed ascent() const override;
425 virtual QFixed capHeight() const override;
426 virtual QFixed descent() const override;
427 virtual QFixed leading() const override;
428 virtual qreal maxCharWidth() const override;
429 virtual qreal minLeftBearing() const override { return 0; }
430 virtual qreal minRightBearing() const override { return 0; }
431 virtual QImage alphaMapForGlyph(glyph_t) override;
432
433 virtual bool canRender(const QChar *string, int len) const override;
434
435 inline int size() const { return _size; }
436
437protected:
438 explicit QFontEngineBox(Type type, int size);
439
440private:
441 friend class QFontPrivate;
442 int _size;
443};
444
445class Q_GUI_EXPORT QFontEngineMulti : public QFontEngine
446{
447public:
448 explicit QFontEngineMulti(QFontEngine *engine, int script, const QStringList &fallbackFamilies = QStringList());
449 ~QFontEngineMulti();
450
451 virtual glyph_t glyphIndex(uint ucs4) const override;
452 virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
453
454 virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override;
455 virtual glyph_metrics_t boundingBox(glyph_t glyph) override;
456
457 virtual void recalcAdvances(QGlyphLayout *, ShaperFlags) const override;
458 virtual void doKerning(QGlyphLayout *, ShaperFlags) const override;
459 virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags) override;
460 virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = nullptr, qreal *rightBearing = nullptr) override;
461
462 virtual QFixed ascent() const override;
463 virtual QFixed capHeight() const override;
464 virtual QFixed descent() const override;
465 virtual QFixed leading() const override;
466 virtual QFixed xHeight() const override;
467 virtual QFixed averageCharWidth() const override;
468 virtual QImage alphaMapForGlyph(glyph_t) override;
469 virtual QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) override;
470 virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t) override;
471 virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override;
472 virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override;
473
474 virtual QFixed lineThickness() const override;
475 virtual QFixed underlinePosition() const override;
476 virtual qreal maxCharWidth() const override;
477 virtual qreal minLeftBearing() const override;
478 virtual qreal minRightBearing() const override;
479
480 virtual bool canRender(const QChar *string, int len) const override;
481
482 inline int fallbackFamilyCount() const { return m_fallbackFamilies.size(); }
483 inline QString fallbackFamilyAt(int at) const { return m_fallbackFamilies.at(at); }
484
485 void setFallbackFamiliesList(const QStringList &fallbackFamilies);
486
487 static uchar highByte(glyph_t glyph); // Used for determining engine
488
489 inline QFontEngine *engine(int at) const
490 { Q_ASSERT(at < m_engines.size()); return m_engines.at(at); }
491
492 void ensureEngineAt(int at);
493
494 static QFontEngine *createMultiFontEngine(QFontEngine *fe, int script);
495
496protected:
497 virtual void ensureFallbackFamiliesQueried();
498 virtual bool shouldLoadFontEngineForCharacter(int at, uint ucs4) const;
499 virtual QFontEngine *loadEngine(int at);
500
501private:
502 QVector<QFontEngine *> m_engines;
503 QStringList m_fallbackFamilies;
504 const int m_script;
505 bool m_fallbackFamiliesQueried;
506};
507
508class QTestFontEngine : public QFontEngineBox
509{
510public:
511 QTestFontEngine(int size);
512};
513
514QT_END_NAMESPACE
515
516
517
518#endif // QFONTENGINE_P_H
519