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 #ifndef QFONTENGINE_FT_P_H 40 #define QFONTENGINE_FT_P_H 41 // 42 // W A R N I N G 43 // ------------- 44 // 45 // This file is not part of the Qt API. It exists purely as an 46 // implementation detail. This header file may change from version to 47 // version without notice, or even be removed. 48 // 49 // We mean it. 50 // 51 52 #include "private/qfontengine_p.h" 53 54 #ifndef QT_NO_FREETYPE 55 56 #include <ft2build.h> 57 #include FT_FREETYPE_H 58 59 60 #ifndef Q_OS_WIN 61 #include <unistd.h> 62 #endif 63 64 #include <qmutex.h> 65 66 QT_BEGIN_NAMESPACE 67 68 class QFontEngineFTRawFont; 69 class QFontconfigDatabase; 70 71 /* 72 * This class represents one font file on disk (like Arial.ttf) and is shared between all the font engines 73 * that show this font file (at different pixel sizes). 74 */ 75 class QFreetypeFace 76 { 77 public: 78 void computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing, QFixed *scalableBitmapScaleFactor); 79 QFontEngine::Properties properties() const; 80 bool getSfntTable(uint tag, uchar *buffer, uint *length) const; 81 82 static QFreetypeFace *getFace(const QFontEngine::FaceId &face_id, 83 const QByteArray &fontData = QByteArray()); 84 void release(const QFontEngine::FaceId &face_id); 85 86 // locks the struct for usage. Any read/write operations require locking. lock()87 void lock() 88 { 89 _lock.lock(); 90 } unlock()91 void unlock() 92 { 93 _lock.unlock(); 94 } 95 96 FT_Face face; 97 int xsize; // 26.6 98 int ysize; // 26.6 99 FT_Matrix matrix; 100 FT_CharMap unicode_map; 101 FT_CharMap symbol_map; 102 103 enum { cmapCacheSize = 0x200 }; 104 glyph_t cmapCache[cmapCacheSize]; 105 106 int fsType() const; 107 108 int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints); 109 110 bool isScalableBitmap() const; 111 112 static void addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale); 113 static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path); 114 115 private: 116 friend class QFontEngineFT; 117 friend class QtFreetypeData; 118 friend struct QScopedPointerDeleter<QFreetypeFace>; 119 QFreetypeFace() = default; 120 ~QFreetypeFace() {} 121 void cleanup(); 122 QAtomicInt ref; 123 QRecursiveMutex _lock; 124 QByteArray fontData; 125 126 QFontEngine::Holder hbFace; 127 }; 128 129 class QFontEngineFT : public QFontEngine 130 { 131 public: 132 struct GlyphInfo { 133 int linearAdvance; 134 unsigned short width; 135 unsigned short height; 136 short x; 137 short y; 138 short xOff; 139 short yOff; 140 }; 141 142 struct GlyphAndSubPixelPosition 143 { 144 GlyphAndSubPixelPosition(glyph_t g, QFixed spp) : glyph(g), subPixelPosition(spp) {} 145 146 bool operator==(const GlyphAndSubPixelPosition &other) const 147 { 148 return glyph == other.glyph && subPixelPosition == other.subPixelPosition; 149 } 150 151 glyph_t glyph; 152 QFixed subPixelPosition; 153 }; 154 155 struct QGlyphSet 156 { 157 QGlyphSet(); 158 ~QGlyphSet(); 159 FT_Matrix transformationMatrix; 160 bool outline_drawing; 161 162 void removeGlyphFromCache(glyph_t index, QFixed subPixelPosition); 163 void clear(); 164 inline bool useFastGlyphData(glyph_t index, QFixed subPixelPosition) const { 165 return (index < 256 && subPixelPosition == 0); 166 } 167 inline Glyph *getGlyph(glyph_t index, QFixed subPixelPosition = 0) const; 168 void setGlyph(glyph_t index, QFixed spp, Glyph *glyph); 169 170 inline bool isGlyphMissing(glyph_t index) const { return missing_glyphs.contains(index); } 171 inline void setGlyphMissing(glyph_t index) const { missing_glyphs.insert(index); } 172 private: 173 mutable QHash<GlyphAndSubPixelPosition, Glyph *> glyph_data; // maps from glyph index to glyph data 174 mutable QSet<glyph_t> missing_glyphs; 175 mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256 176 mutable int fast_glyph_count; 177 }; 178 179 QFontEngine::FaceId faceId() const override; 180 QFontEngine::Properties properties() const override; 181 QFixed emSquareSize() const override; 182 bool supportsSubPixelPositions() const override 183 { 184 return default_hint_style == HintLight || 185 default_hint_style == HintNone; 186 } 187 188 bool getSfntTableData(uint tag, uchar *buffer, uint *length) const override; 189 int synthesized() const override; 190 191 QFixed ascent() const override; 192 QFixed capHeight() const override; 193 QFixed descent() const override; 194 QFixed leading() const override; 195 QFixed xHeight() const override; 196 QFixed averageCharWidth() const override; 197 198 qreal maxCharWidth() const override; 199 QFixed lineThickness() const override; 200 QFixed underlinePosition() const override; 201 202 glyph_t glyphIndex(uint ucs4) const override; 203 void doKerning(QGlyphLayout *, ShaperFlags) const override; 204 205 void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) override; 206 207 bool supportsTransformation(const QTransform &transform) const override; 208 209 void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, 210 QPainterPath *path, QTextItem::RenderFlags flags) override; 211 void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, 212 QPainterPath *path, QTextItem::RenderFlags flags) override; 213 214 bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override; 215 216 glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override; 217 glyph_metrics_t boundingBox(glyph_t glyph) override; 218 glyph_metrics_t boundingBox(glyph_t glyph, const QTransform &matrix) override; 219 220 void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const override; 221 QImage alphaMapForGlyph(glyph_t g) override { return alphaMapForGlyph(g, 0); } 222 QImage alphaMapForGlyph(glyph_t, QFixed) override; 223 QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) override; 224 QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override; 225 QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color) override; 226 glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, 227 QFixed subPixelPosition, 228 const QTransform &matrix, 229 QFontEngine::GlyphFormat format) override; 230 Glyph *glyphData(glyph_t glyph, QFixed subPixelPosition, 231 GlyphFormat neededFormat, const QTransform &t) override; 232 bool hasInternalCaching() const override { return cacheEnabled; } 233 bool expectsGammaCorrectedBlending() const override; 234 235 void removeGlyphFromCache(glyph_t glyph) override; 236 int glyphMargin(QFontEngine::GlyphFormat /* format */) override { return 0; } 237 238 int glyphCount() const override; 239 240 enum Scaling { 241 Scaled, 242 Unscaled 243 }; 244 FT_Face lockFace(Scaling scale = Scaled) const; 245 void unlockFace() const; 246 247 FT_Face non_locked_face() const; 248 249 inline bool drawAntialiased() const { return antialias; } 250 inline bool invalid() const { return xsize == 0 && ysize == 0; } 251 inline bool isBitmapFont() const { return defaultFormat == Format_Mono; } 252 inline bool isScalableBitmap() const { return freetype->isScalableBitmap(); } 253 254 inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false, bool disableOutlineDrawing = false) const 255 { return loadGlyph(cacheEnabled ? &defaultGlyphSet : nullptr, glyph, subPixelPosition, format, fetchMetricsOnly, disableOutlineDrawing); } 256 Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false, bool disableOutlineDrawing = false) const; 257 Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format, const QTransform &t, bool fetchBoundingBox = false, bool disableOutlineDrawing = false); 258 259 QGlyphSet *loadGlyphSet(const QTransform &matrix); 260 261 QFontEngineFT(const QFontDef &fd); 262 virtual ~QFontEngineFT(); 263 264 bool init(FaceId faceId, bool antiaalias, GlyphFormat defaultFormat = Format_None, 265 const QByteArray &fontData = QByteArray()); 266 bool init(FaceId faceId, bool antialias, GlyphFormat format, 267 QFreetypeFace *freetypeFace); 268 269 int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints) override; 270 271 void setQtDefaultHintStyle(QFont::HintingPreference hintingPreference); 272 void setDefaultHintStyle(HintStyle style) override; 273 274 QFontEngine *cloneWithSize(qreal pixelSize) const override; 275 Qt::HANDLE handle() const override; 276 bool initFromFontEngine(const QFontEngineFT *fontEngine); 277 278 HintStyle defaultHintStyle() const { return default_hint_style; } 279 280 static QFontEngineFT *create(const QFontDef &fontDef, FaceId faceId, const QByteArray &fontData = QByteArray()); 281 static QFontEngineFT *create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); 282 283 protected: 284 285 QFreetypeFace *freetype; 286 mutable int default_load_flags; 287 HintStyle default_hint_style; 288 bool antialias; 289 bool transform; 290 bool embolden; 291 bool obliquen; 292 SubpixelAntialiasingType subpixelType; 293 int lcdFilterType; 294 bool embeddedbitmap; 295 bool cacheEnabled; 296 bool forceAutoHint; 297 bool stemDarkeningDriver; 298 299 private: 300 friend class QFontEngineFTRawFont; 301 friend class QFontconfigDatabase; 302 friend class QFreeTypeFontDatabase; 303 friend class QFontEngineMultiFontConfig; 304 305 int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const; 306 bool shouldUseDesignMetrics(ShaperFlags flags) const; 307 QFixed scaledBitmapMetrics(QFixed m) const; 308 glyph_metrics_t scaledBitmapMetrics(const glyph_metrics_t &m, const QTransform &matrix) const; 309 310 GlyphFormat defaultFormat; 311 FT_Matrix matrix; 312 313 QList<QGlyphSet> transformedGlyphSets; 314 mutable QGlyphSet defaultGlyphSet; 315 316 QFontEngine::FaceId face_id; 317 318 int xsize; 319 int ysize; 320 321 QFixed line_thickness; 322 QFixed underline_position; 323 324 FT_Size_Metrics metrics; 325 mutable bool kerning_pairs_loaded; 326 QFixed scalableBitmapScaleFactor; 327 }; 328 329 inline uint qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g) 330 { 331 return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt(); 332 } 333 334 inline QFontEngineFT::Glyph *QFontEngineFT::QGlyphSet::getGlyph(glyph_t index, QFixed subPixelPosition) const 335 { 336 if (useFastGlyphData(index, subPixelPosition)) 337 return fast_glyph_data[index]; 338 return glyph_data.value(GlyphAndSubPixelPosition(index, subPixelPosition)); 339 } 340 341 extern FT_Library qt_getFreetype(); 342 343 QT_END_NAMESPACE 344 345 #endif // QT_NO_FREETYPE 346 347 #endif // QFONTENGINE_FT_P_H 348