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 "nsTHashMap.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 static bool FaceHasTable(mozilla::gfx::SharedFTFace*, uint32_t aTableTag); 31 static nsresult CopyFaceTable(mozilla::gfx::SharedFTFace*, uint32_t aTableTag, 32 nsTArray<uint8_t>&); 33 34 private: 35 enum { kNumCmapCacheSlots = 256 }; 36 37 mozilla::UniquePtr<CmapCacheSlot[]> mCmapCache; 38 }; 39 40 class gfxFT2FontBase : public gfxFont { 41 public: 42 gfxFT2FontBase( 43 const RefPtr<mozilla::gfx::UnscaledFontFreeType>& aUnscaledFont, 44 RefPtr<mozilla::gfx::SharedFTFace>&& aFTFace, gfxFontEntry* aFontEntry, 45 const gfxFontStyle* aFontStyle, int aLoadFlags, bool aEmbolden); 46 virtual ~gfxFT2FontBase(); 47 48 uint32_t GetGlyph(uint32_t aCharCode); ProvidesGetGlyph()49 bool ProvidesGetGlyph() const override { return true; } 50 virtual uint32_t GetGlyph(uint32_t unicode, 51 uint32_t variation_selector) override; ProvidesGlyphWidths()52 bool ProvidesGlyphWidths() const override { return true; } 53 int32_t GetGlyphWidth(uint16_t aGID) override; 54 bool GetGlyphBounds(uint16_t aGID, gfxRect* aBounds, bool aTight) override; 55 GetType()56 FontType GetType() const override { return FONT_TYPE_FT2; } 57 58 bool ShouldRoundXOffset(cairo_t* aCairo) const override; 59 60 static void SetupVarCoords(FT_MM_Var* aMMVar, 61 const nsTArray<gfxFontVariation>& aVariations, 62 FT_Face aFTFace); 63 64 FT_Face LockFTFace(); 65 void UnlockFTFace(); 66 67 private: 68 uint32_t GetCharExtents(uint32_t aChar, gfxFloat* aWidth, 69 gfxRect* aBounds = nullptr); 70 71 // Get advance (and optionally bounds) of a single glyph from FreeType, 72 // and return true, or return false if we failed. 73 bool GetFTGlyphExtents(uint16_t aGID, int32_t* aWidth, 74 mozilla::gfx::IntRect* aBounds = nullptr); 75 76 protected: 77 void InitMetrics(); 78 const Metrics& GetHorizontalMetrics() override; 79 FT_Vector GetEmboldenStrength(FT_Face aFace); 80 81 RefPtr<mozilla::gfx::SharedFTFace> mFTFace; 82 83 Metrics mMetrics; 84 int mFTLoadFlags; 85 bool mEmbolden; 86 gfxFloat mFTSize; 87 88 // For variation/multiple-master fonts, this will be an array of the values 89 // for each axis, as specified by mStyle.variationSettings (or the font's 90 // default for axes not present in variationSettings). Values here are in 91 // freetype's 16.16 fixed-point format, and clamped to the valid min/max 92 // range reported by the face. 93 nsTArray<FT_Fixed> mCoords; 94 95 // Store cached glyph metrics for reasonably small glyph sizes. The bounds 96 // are stored unscaled to losslessly compress 26.6 fixed point to an int16_t. 97 // Larger glyphs are handled directly via GetFTGlyphExtents. 98 struct GlyphMetrics { 99 // Set the X coord to INT16_MIN to signal the bounds are invalid, or 100 // INT16_MAX to signal that the bounds would overflow an int16_t. 101 enum { INVALID = INT16_MIN, LARGE = INT16_MAX }; 102 GlyphMetricsGlyphMetrics103 GlyphMetrics() : mAdvance(0), mX(INVALID), mY(0), mWidth(0), mHeight(0) {} 104 HasValidBoundsGlyphMetrics105 bool HasValidBounds() const { return mX != INVALID; } HasCachedBoundsGlyphMetrics106 bool HasCachedBounds() const { return mX != LARGE; } 107 108 // If the bounds can fit in an int16_t, set them. Otherwise, leave the 109 // bounds invalid to signal that GetFTGlyphExtents should be queried 110 // directly. SetBoundsGlyphMetrics111 void SetBounds(const mozilla::gfx::IntRect& aBounds) { 112 if (aBounds.x > INT16_MIN && aBounds.x < INT16_MAX && 113 aBounds.y > INT16_MIN && aBounds.y < INT16_MAX && 114 aBounds.width <= UINT16_MAX && aBounds.height <= UINT16_MAX) { 115 mX = aBounds.x; 116 mY = aBounds.y; 117 mWidth = aBounds.width; 118 mHeight = aBounds.height; 119 } else { 120 mX = LARGE; 121 } 122 } 123 GetBoundsGlyphMetrics124 mozilla::gfx::IntRect GetBounds() const { 125 return mozilla::gfx::IntRect(mX, mY, mWidth, mHeight); 126 } 127 128 int32_t mAdvance; 129 int16_t mX; 130 int16_t mY; 131 uint16_t mWidth; 132 uint16_t mHeight; 133 }; 134 135 const GlyphMetrics& GetCachedGlyphMetrics( 136 uint16_t aGID, mozilla::gfx::IntRect* aBounds = nullptr); 137 138 mozilla::UniquePtr<nsTHashMap<nsUint32HashKey, GlyphMetrics>> mGlyphMetrics; 139 }; 140 141 // Helper classes used for clearing out user font data when FT font 142 // face is destroyed. Since multiple faces may use the same data, be 143 // careful to assure that the data is only cleared out when all uses 144 // expire. The font entry object contains a refptr to FTUserFontData and 145 // each FT face created from that font entry contains a refptr to that 146 // same FTUserFontData object. 147 148 class FTUserFontData final 149 : public mozilla::gfx::SharedFTFaceRefCountedData<FTUserFontData> { 150 public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FTUserFontData)151 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FTUserFontData) 152 153 FTUserFontData(const uint8_t* aData, uint32_t aLength) 154 : mFontData(aData), mLength(aLength) {} 155 FontData()156 const uint8_t* FontData() const { return mFontData; } 157 158 already_AddRefed<mozilla::gfx::SharedFTFace> CloneFace( 159 int aFaceIndex = 0) override; 160 161 private: ~FTUserFontData()162 ~FTUserFontData() { 163 if (mFontData) { 164 free((void*)mFontData); 165 } 166 } 167 168 const uint8_t* mFontData; 169 uint32_t mLength; 170 }; 171 172 #endif /* GFX_FT2FONTBASE_H */ 173