1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://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 http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://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 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #ifndef QFONTENGINE_FT_P_H
42 #define QFONTENGINE_FT_P_H
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 "qfontengine_p.h"
55
56 #ifndef QT_NO_FREETYPE
57
58 #include <ft2build.h>
59 #include FT_FREETYPE_H
60
61 #if defined(Q_WS_X11)
62 #include <private/qt_x11_p.h>
63 #endif
64
65 #include <unistd.h>
66
67 #ifndef QT_NO_FONTCONFIG
68 #include <fontconfig/fontconfig.h>
69 #endif
70
71 #include <qmutex.h>
72
73 #include <harfbuzz-shaper.h>
74
75 QT_BEGIN_NAMESPACE
76
77 class QFontEngineFTRawFont;
78
79 /*
80 * This struct represents one font file on disk (like Arial.ttf) and is shared between all the font engines
81 * that show this font file (at different pixel sizes).
82 */
83 struct QFreetypeFace
84 {
85 void computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing);
86 QFontEngine::Properties properties() const;
87 bool getSfntTable(uint tag, uchar *buffer, uint *length) const;
88
89 static QFreetypeFace *getFace(const QFontEngine::FaceId &face_id,
90 const QByteArray &fontData = QByteArray());
91 void release(const QFontEngine::FaceId &face_id);
92
93 // locks the struct for usage. Any read/write operations require locking.
lockQFreetypeFace94 void lock()
95 {
96 _lock.lock();
97 }
unlockQFreetypeFace98 void unlock()
99 {
100 _lock.unlock();
101 }
102
103 FT_Face face;
104 HB_Face hbFace;
105 #ifndef QT_NO_FONTCONFIG
106 FcCharSet *charset;
107 #endif
108 int xsize; // 26.6
109 int ysize; // 26.6
110 FT_Matrix matrix;
111 FT_CharMap unicode_map;
112 FT_CharMap symbol_map;
113
114 enum { cmapCacheSize = 0x200 };
115 glyph_t cmapCache[cmapCacheSize];
116
117 int fsType() const;
118
119 HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints);
120
121 static void addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale);
122 static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path, bool = false);
123
124 private:
125 friend class QFontEngineFT;
126 friend class QScopedPointerDeleter<QFreetypeFace>;
QFreetypeFaceQFreetypeFace127 QFreetypeFace() : _lock(QMutex::Recursive) {}
~QFreetypeFaceQFreetypeFace128 ~QFreetypeFace() {}
129 QAtomicInt ref;
130 QMutex _lock;
131 QByteArray fontData;
132 };
133
134 class Q_GUI_EXPORT QFontEngineFT : public QFontEngine
135 {
136 public:
137
138 /* we don't cache glyphs that are too large anyway, so we can make this struct rather small */
139 struct Glyph {
140 ~Glyph();
141 short linearAdvance;
142 unsigned char width;
143 unsigned char height;
144 signed char x;
145 signed char y;
146 signed char advance;
147 signed char format;
148 uchar *data;
149 unsigned int uploadedToServer : 1;
150 };
151
152 enum SubpixelAntialiasingType {
153 Subpixel_None,
154 Subpixel_RGB,
155 Subpixel_BGR,
156 Subpixel_VRGB,
157 Subpixel_VBGR
158 };
159
160 #if defined(Q_WS_X11) && !defined(QT_NO_XRENDER)
161 typedef XGlyphInfo GlyphInfo;
162 #else
163 struct GlyphInfo {
164 unsigned short width;
165 unsigned short height;
166 short x;
167 short y;
168 short xOff;
169 short yOff;
170 };
171 #endif
172
173 struct GlyphAndSubPixelPosition
174 {
GlyphAndSubPixelPositionGlyphAndSubPixelPosition175 GlyphAndSubPixelPosition(glyph_t g, QFixed spp) : glyph(g), subPixelPosition(spp) {}
176
177 bool operator==(const GlyphAndSubPixelPosition &other) const
178 {
179 return glyph == other.glyph && subPixelPosition == other.subPixelPosition;
180 }
181
182 glyph_t glyph;
183 QFixed subPixelPosition;
184 };
185
186 struct QGlyphSet
187 {
188 QGlyphSet();
189 ~QGlyphSet();
190 FT_Matrix transformationMatrix;
191 unsigned long id; // server sided id, GlyphSet for X11
192 bool outline_drawing;
193
194 void removeGlyphFromCache(glyph_t index, QFixed subPixelPosition);
195 void clear();
useFastGlyphDataQGlyphSet196 inline bool useFastGlyphData(glyph_t index, QFixed subPixelPosition) const {
197 return (index < 256 && subPixelPosition == 0);
198 }
199 inline Glyph *getGlyph(glyph_t index, QFixed subPixelPosition = 0) const;
200 void setGlyph(glyph_t index, QFixed spp, Glyph *glyph);
201
202 private:
203 mutable QHash<GlyphAndSubPixelPosition, Glyph *> glyph_data; // maps from glyph index to glyph data
204 mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256
205 mutable int fast_glyph_count;
206 };
207
208 virtual QFontEngine::FaceId faceId() const;
209 virtual QFontEngine::Properties properties() const;
210 virtual QFixed emSquareSize() const;
supportsSubPixelPositions()211 virtual bool supportsSubPixelPositions() const
212 {
213 return default_hint_style == HintLight ||
214 default_hint_style == HintNone;
215 }
216
217 virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
218 virtual int synthesized() const;
219
220 virtual QFixed ascent() const;
221 virtual QFixed descent() const;
222 virtual QFixed leading() const;
223 virtual QFixed xHeight() const;
224 virtual QFixed averageCharWidth() const;
225
226 virtual qreal maxCharWidth() const;
227 virtual qreal minLeftBearing() const;
228 virtual qreal minRightBearing() const;
229 virtual QFixed lineThickness() const;
230 virtual QFixed underlinePosition() const;
231
232 void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const;
233
type()234 inline virtual Type type() const
235 { return QFontEngine::Freetype; }
name()236 inline virtual const char *name() const
237 { return "freetype"; }
238
239 virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics);
240
241 virtual bool canRender(const QChar *string, int len);
242
243 virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
244 QPainterPath *path, QTextItem::RenderFlags flags);
245 virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,
246 QPainterPath *path, QTextItem::RenderFlags flags);
247
248 virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
249 QTextEngine::ShaperFlags flags) const;
250
251 virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
252 virtual glyph_metrics_t boundingBox(glyph_t glyph);
253 virtual glyph_metrics_t boundingBox(glyph_t glyph, const QTransform &matrix);
254
255 virtual void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const;
alphaMapForGlyph(glyph_t g)256 virtual QImage alphaMapForGlyph(glyph_t g) { return alphaMapForGlyph(g, 0); }
257 virtual QImage alphaMapForGlyph(glyph_t, QFixed);
258 virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t);
259 virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
260 QFixed subPixelPosition,
261 const QTransform &matrix,
262 QFontEngine::GlyphFormat format);
263 virtual void removeGlyphFromCache(glyph_t glyph);
264
265 virtual int glyphCount() const;
266
267 enum Scaling {
268 Scaled,
269 Unscaled
270 };
271 FT_Face lockFace(Scaling scale = Scaled) const;
272 void unlockFace() const;
273
274 FT_Face non_locked_face() const;
275
drawAntialiased()276 inline bool drawAntialiased() const { return antialias; }
invalid()277 inline bool invalid() const { return xsize == 0 && ysize == 0; }
isBitmapFont()278 inline bool isBitmapFont() const { return defaultFormat == Format_Mono; }
279
280 inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false) const
281 { return loadGlyph(&defaultGlyphSet, glyph, subPixelPosition, format, fetchMetricsOnly); }
282 Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false) const;
283
defaultGlyphs()284 QGlyphSet *defaultGlyphs() { return &defaultGlyphSet; }
defaultGlyphFormat()285 GlyphFormat defaultGlyphFormat() const { return defaultFormat; }
286
cachedGlyph(glyph_t g)287 inline Glyph *cachedGlyph(glyph_t g) const { return defaultGlyphSet.getGlyph(g, 0); }
288
289 QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix);
290 QFixed subPixelPositionForX(QFixed x);
291 bool loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs,
292 const QFixedPoint *positions,
293 GlyphFormat format = Format_Render);
294
295 #if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
draw(QPaintEngine *,qreal,qreal,const QTextItemInt &)296 virtual void draw(QPaintEngine * /*p*/, qreal /*x*/, qreal /*y*/, const QTextItemInt & /*si*/) {}
297 #endif
298
299 QFontEngineFT(const QFontDef &fd);
300 virtual ~QFontEngineFT();
301
302 bool init(FaceId faceId, bool antiaalias, GlyphFormat defaultFormat = Format_None,
303 const QByteArray &fontData = QByteArray());
304 bool init(FaceId faceId, bool antialias, GlyphFormat format,
305 QFreetypeFace *freetypeFace);
306
307 virtual HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints);
308
309 enum HintStyle {
310 HintNone,
311 HintLight,
312 HintMedium,
313 HintFull
314 };
315
316 void setDefaultHintStyle(HintStyle style);
317
318 virtual QFontEngine *cloneWithSize(qreal pixelSize) const;
319 bool initFromFontEngine(const QFontEngineFT *fontEngine);
320
defaultHintStyle()321 HintStyle defaultHintStyle() const { return default_hint_style; }
322 protected:
323
324 void freeGlyphSets();
325
326 virtual bool uploadGlyphToServer(QGlyphSet *set, uint glyphid, Glyph *g, GlyphInfo *info, int glyphDataSize) const;
327 virtual unsigned long allocateServerGlyphSet();
328 virtual void freeServerGlyphSet(unsigned long id);
329
330 QFreetypeFace *freetype;
331 int default_load_flags;
332
333
334 HintStyle default_hint_style;
335
336 bool antialias;
337 bool transform;
338 bool embolden;
339 SubpixelAntialiasingType subpixelType;
340 int lcdFilterType;
341 bool canUploadGlyphsToServer;
342 bool embeddedbitmap;
343
344 private:
345 friend class QFontEngineFTRawFont;
346
347 int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const;
348
349 GlyphFormat defaultFormat;
350 FT_Matrix matrix;
351
352 QList<QGlyphSet> transformedGlyphSets;
353 mutable QGlyphSet defaultGlyphSet;
354
355 QFontEngine::FaceId face_id;
356
357 int xsize;
358 int ysize;
359
360 mutable QFixed lbearing;
361 mutable QFixed rbearing;
362 QFixed line_thickness;
363 QFixed underline_position;
364
365 FT_Size_Metrics metrics;
366 mutable bool kerning_pairs_loaded;
367 };
368
qHash(const QFontEngineFT::GlyphAndSubPixelPosition & g)369 inline uint qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g)
370 {
371 return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt();
372 }
373
getGlyph(glyph_t index,QFixed subPixelPosition)374 inline QFontEngineFT::Glyph *QFontEngineFT::QGlyphSet::getGlyph(glyph_t index, QFixed subPixelPosition) const
375 {
376 if (useFastGlyphData(index, subPixelPosition))
377 return fast_glyph_data[index];
378 return glyph_data.value(GlyphAndSubPixelPosition(index, subPixelPosition));
379 }
380
381
382 QT_END_NAMESPACE
383
384 #endif // QT_NO_FREETYPE
385
386 #endif // QFONTENGINE_FT_P_H
387