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 
61 QT_BEGIN_NAMESPACE
62 
63 class QPainterPath;
64 class QFontEngineGlyphCache;
65 
66 struct 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
76 enum 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 
84 typedef void (*qt_destroy_func_t) (void *user_data);
85 typedef bool (*qt_get_font_table_func_t) (void *user_data, uint tag, uchar *buffer, uint *length);
86 
87 class Q_GUI_EXPORT QFontEngine
88 {
89 public:
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;
~GlyphGlyph129         ~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 
type()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 {
FaceIdFaceId166         FaceId() : index(0), encoding(0) {}
167         QByteArray filename;
168         QByteArray uuid;
169         int index;
170         int encoding;
171     };
faceId()172     virtual FaceId faceId() const { return FaceId(); }
173     enum SynthesizedFlags {
174         SynthesizedItalic = 0x1,
175         SynthesizedBold = 0x2,
176         SynthesizedStretch = 0x4
177     };
synthesized()178     virtual int synthesized() const { return 0; }
supportsSubPixelPositions()179     virtual bool supportsSubPixelPositions() const { return false; }
180     virtual QFixed subPixelPositionForX(QFixed x) const;
181 
emSquareSize()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;
recalcAdvances(QGlyphLayout *,ShaperFlags)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);
hasInternalCaching()210     virtual bool hasInternalCaching() const { return false; }
211 
alphaMapBoundingBox(glyph_t glyph,QFixed,const QTransform & matrix,GlyphFormat)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 
canRender(uint ucs4)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;
glyphMargin(GlyphFormat format)246     virtual int glyphMargin(GlyphFormat format) { return format == Format_A32 ? 2 : 0; }
247 
cloneWithSize(qreal)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 
scriptRequiresOpenType(QChar::Script script)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     };
setDefaultHintStyle(HintStyle)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 
292 private:
293     const Type m_type;
294 
295 public:
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:
Holder()303         Holder() : ptr(nullptr), destroy_func(nullptr) {}
Holder(void * p,qt_destroy_func_t d)304         explicit Holder(void *p, qt_destroy_func_t d) : ptr(p), destroy_func(d) {}
~Holder()305         ~Holder() { if (ptr && destroy_func) destroy_func(ptr); }
Holder(Holder && other)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 
swap(Holder & other)316         void swap(Holder &other) noexcept
317         {
318             qSwap(ptr, other.ptr);
319             qSwap(destroy_func, other.destroy_func);
320         }
321 
get()322         void *get() const noexcept { return ptr; }
release()323         void *release() noexcept {
324             void *result = ptr;
325             ptr = nullptr;
326             destroy_func = nullptr;
327             return result;
328         }
reset()329         void reset() noexcept { Holder().swap(*this); }
get_deleter()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 
userData()362     inline QVariant userData() const { return m_userData; }
363 
364 protected:
365     explicit QFontEngine(Type type);
366 
367     QFixed lastRightBearing(const QGlyphLayout &glyphs, bool round = false);
368 
setUserData(const QVariant & userData)369     inline void setUserData(const QVariant &userData) { m_userData = userData; }
370     QFixed calculatedCapHeight() const;
371 
372 private:
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 
386 private:
387     QVariant m_userData;
388 
389     mutable qreal m_minLeftBearing;
390     mutable qreal m_minRightBearing;
391 
392 };
393 Q_DECLARE_TYPEINFO(QFontEngine::KernPair, Q_PRIMITIVE_TYPE);
394 
395 Q_DECLARE_OPERATORS_FOR_FLAGS(QFontEngine::ShaperFlags)
396 
397 inline 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 
402 inline uint qHash(const QFontEngine::FaceId &f, uint seed = 0)
403     noexcept(noexcept(qHash(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 
414 class QGlyph;
415 
416 
417 
418 class QFontEngineBox : public QFontEngine
419 {
420 public:
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;
minLeftBearing()440     virtual qreal minLeftBearing() const override { return 0; }
minRightBearing()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 
size()446     inline int size() const { return _size; }
447 
448 protected:
449     explicit QFontEngineBox(Type type, int size);
450 
451 private:
452     friend class QFontPrivate;
453     int _size;
454 };
455 
456 class Q_GUI_EXPORT QFontEngineMulti : public QFontEngine
457 {
458 public:
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 
fallbackFamilyCount()493     inline int fallbackFamilyCount() const { return m_fallbackFamilies.size(); }
fallbackFamilyAt(int at)494     inline QString fallbackFamilyAt(int at) const { return m_fallbackFamilies.at(at); }
495 
496     void setFallbackFamiliesList(const QStringList &fallbackFamilies);
497 
498     static uchar highByte(glyph_t glyph); // Used for determining engine
499 
engine(int at)500     inline QFontEngine *engine(int at) const
501     { Q_ASSERT(at < m_engines.size()); return m_engines.at(at); }
502 
503     void ensureEngineAt(int at);
504 
505     static QFontEngine *createMultiFontEngine(QFontEngine *fe, int script);
506 
507 protected:
508     virtual void ensureFallbackFamiliesQueried();
509     virtual bool shouldLoadFontEngineForCharacter(int at, uint ucs4) const;
510     virtual QFontEngine *loadEngine(int at);
511 
512 private:
513     QVector<QFontEngine *> m_engines;
514     QStringList m_fallbackFamilies;
515     const int m_script;
516     bool m_fallbackFamiliesQueried;
517 };
518 
519 class QTestFontEngine : public QFontEngineBox
520 {
521 public:
522     QTestFontEngine(int size);
523 };
524 
525 QT_END_NAMESPACE
526 
527 
528 
529 #endif // QFONTENGINE_P_H
530