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