1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef GFX_FT2FONTBASE_H 7 #define GFX_FT2FONTBASE_H 8 9 #include "gfxContext.h" 10 #include "gfxFont.h" 11 #include "gfxFontEntry.h" 12 #include "mozilla/gfx/2D.h" 13 #include "mozilla/gfx/UnscaledFontFreeType.h" 14 #include "nsDataHashtable.h" 15 #include "nsHashKeys.h" 16 17 class gfxFT2FontEntryBase : public gfxFontEntry { 18 public: gfxFT2FontEntryBase(const nsACString & aName)19 explicit gfxFT2FontEntryBase(const nsACString& aName) : gfxFontEntry(aName) {} 20 21 struct CmapCacheSlot { CmapCacheSlotCmapCacheSlot22 CmapCacheSlot() : mCharCode(0), mGlyphIndex(0) {} 23 24 uint32_t mCharCode; 25 uint32_t mGlyphIndex; 26 }; 27 28 CmapCacheSlot* GetCmapCacheSlot(uint32_t aCharCode); 29 30 private: 31 enum { kNumCmapCacheSlots = 256 }; 32 33 mozilla::UniquePtr<CmapCacheSlot[]> mCmapCache; 34 }; 35 36 class gfxFT2FontBase : public gfxFont { 37 public: 38 gfxFT2FontBase( 39 const RefPtr<mozilla::gfx::UnscaledFontFreeType>& aUnscaledFont, 40 RefPtr<mozilla::gfx::SharedFTFace>&& aFTFace, gfxFontEntry* aFontEntry, 41 const gfxFontStyle* aFontStyle, int aLoadFlags, bool aEmbolden); 42 virtual ~gfxFT2FontBase(); 43 44 uint32_t GetGlyph(uint32_t aCharCode); ProvidesGetGlyph()45 bool ProvidesGetGlyph() const override { return true; } 46 virtual uint32_t GetGlyph(uint32_t unicode, 47 uint32_t variation_selector) override; ProvidesGlyphWidths()48 bool ProvidesGlyphWidths() const override { return true; } 49 int32_t GetGlyphWidth(uint16_t aGID) override; 50 bool GetGlyphBounds(uint16_t aGID, gfxRect* aBounds, bool aTight) override; 51 GetType()52 FontType GetType() const override { return FONT_TYPE_FT2; } 53 54 bool ShouldRoundXOffset(cairo_t* aCairo) const override; 55 56 static void SetupVarCoords(FT_MM_Var* aMMVar, 57 const nsTArray<gfxFontVariation>& aVariations, 58 FT_Face aFTFace); 59 60 FT_Face LockFTFace(); 61 void UnlockFTFace(); 62 63 private: 64 uint32_t GetCharExtents(char aChar, gfxFloat* aWidth, 65 gfxRect* aBounds = nullptr); 66 67 // Get advance (and optionally bounds) of a single glyph from FreeType, 68 // and return true, or return false if we failed. 69 bool GetFTGlyphExtents(uint16_t aGID, int32_t* aWidth, 70 mozilla::gfx::IntRect* aBounds = nullptr); 71 72 protected: 73 void InitMetrics(); 74 const Metrics& GetHorizontalMetrics() override; 75 FT_Vector GetEmboldenStrength(FT_Face aFace); 76 77 RefPtr<mozilla::gfx::SharedFTFace> mFTFace; 78 79 Metrics mMetrics; 80 int mFTLoadFlags; 81 bool mEmbolden; 82 gfxFloat mFTSize; 83 84 // For variation/multiple-master fonts, this will be an array of the values 85 // for each axis, as specified by mStyle.variationSettings (or the font's 86 // default for axes not present in variationSettings). Values here are in 87 // freetype's 16.16 fixed-point format, and clamped to the valid min/max 88 // range reported by the face. 89 nsTArray<FT_Fixed> mCoords; 90 91 // Store cached glyph metrics for reasonably small glyph sizes. The bounds 92 // are stored unscaled to losslessly compress 26.6 fixed point to an int16_t. 93 // Larger glyphs are handled directly via GetFTGlyphExtents. 94 struct GlyphMetrics { 95 // Set the X coord to INT16_MIN to signal the bounds are invalid, or 96 // INT16_MAX to signal that the bounds would overflow an int16_t. 97 enum { INVALID = INT16_MIN, LARGE = INT16_MAX }; 98 GlyphMetricsGlyphMetrics99 GlyphMetrics() : mAdvance(0), mX(INVALID), mY(0), mWidth(0), mHeight(0) {} 100 HasValidBoundsGlyphMetrics101 bool HasValidBounds() const { return mX != INVALID; } HasCachedBoundsGlyphMetrics102 bool HasCachedBounds() const { return mX != LARGE; } 103 104 // If the bounds can fit in an int16_t, set them. Otherwise, leave the 105 // bounds invalid to signal that GetFTGlyphExtents should be queried 106 // directly. SetBoundsGlyphMetrics107 void SetBounds(const mozilla::gfx::IntRect& aBounds) { 108 if (aBounds.x > INT16_MIN && aBounds.x < INT16_MAX && 109 aBounds.y > INT16_MIN && aBounds.y < INT16_MAX && 110 aBounds.width <= UINT16_MAX && aBounds.height <= UINT16_MAX) { 111 mX = aBounds.x; 112 mY = aBounds.y; 113 mWidth = aBounds.width; 114 mHeight = aBounds.height; 115 } else { 116 mX = LARGE; 117 } 118 } 119 GetBoundsGlyphMetrics120 mozilla::gfx::IntRect GetBounds() const { 121 return mozilla::gfx::IntRect(mX, mY, mWidth, mHeight); 122 } 123 124 int32_t mAdvance; 125 int16_t mX; 126 int16_t mY; 127 uint16_t mWidth; 128 uint16_t mHeight; 129 }; 130 131 const GlyphMetrics& GetCachedGlyphMetrics( 132 uint16_t aGID, mozilla::gfx::IntRect* aBounds = nullptr); 133 134 mozilla::UniquePtr<nsDataHashtable<nsUint32HashKey, GlyphMetrics>> 135 mGlyphMetrics; 136 }; 137 138 // Helper classes used for clearing out user font data when FT font 139 // face is destroyed. Since multiple faces may use the same data, be 140 // careful to assure that the data is only cleared out when all uses 141 // expire. The font entry object contains a refptr to FTUserFontData and 142 // each FT face created from that font entry contains a refptr to that 143 // same FTUserFontData object. 144 145 class FTUserFontData final 146 : public mozilla::gfx::SharedFTFaceRefCountedData<FTUserFontData> { 147 public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FTUserFontData)148 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FTUserFontData) 149 150 FTUserFontData(const uint8_t* aData, uint32_t aLength) 151 : mFontData(aData), mLength(aLength) {} 152 FontData()153 const uint8_t* FontData() const { return mFontData; } 154 155 already_AddRefed<mozilla::gfx::SharedFTFace> CloneFace( 156 int aFaceIndex = 0) override; 157 158 private: ~FTUserFontData()159 ~FTUserFontData() { 160 if (mFontData) { 161 free((void*)mFontData); 162 } 163 } 164 165 const uint8_t* mFontData; 166 uint32_t mLength; 167 }; 168 169 #endif /* GFX_FT2FONTBASE_H */ 170