diff options
Diffstat (limited to '')
-rw-r--r-- | gfx/thebes/gfxFT2FontBase.h | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/gfx/thebes/gfxFT2FontBase.h b/gfx/thebes/gfxFT2FontBase.h new file mode 100644 index 0000000000..8575bb0666 --- /dev/null +++ b/gfx/thebes/gfxFT2FontBase.h @@ -0,0 +1,173 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef GFX_FT2FONTBASE_H +#define GFX_FT2FONTBASE_H + +#include "gfxContext.h" +#include "gfxFont.h" +#include "gfxFontEntry.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/gfx/UnscaledFontFreeType.h" +#include "nsDataHashtable.h" +#include "nsHashKeys.h" + +class gfxFT2FontEntryBase : public gfxFontEntry { + public: + explicit gfxFT2FontEntryBase(const nsACString& aName) : gfxFontEntry(aName) {} + + struct CmapCacheSlot { + CmapCacheSlot() : mCharCode(0), mGlyphIndex(0) {} + + uint32_t mCharCode; + uint32_t mGlyphIndex; + }; + + CmapCacheSlot* GetCmapCacheSlot(uint32_t aCharCode); + + static bool FaceHasTable(mozilla::gfx::SharedFTFace*, uint32_t aTableTag); + static nsresult CopyFaceTable(mozilla::gfx::SharedFTFace*, uint32_t aTableTag, + nsTArray<uint8_t>&); + + private: + enum { kNumCmapCacheSlots = 256 }; + + mozilla::UniquePtr<CmapCacheSlot[]> mCmapCache; +}; + +class gfxFT2FontBase : public gfxFont { + public: + gfxFT2FontBase( + const RefPtr<mozilla::gfx::UnscaledFontFreeType>& aUnscaledFont, + RefPtr<mozilla::gfx::SharedFTFace>&& aFTFace, gfxFontEntry* aFontEntry, + const gfxFontStyle* aFontStyle, int aLoadFlags, bool aEmbolden); + virtual ~gfxFT2FontBase(); + + uint32_t GetGlyph(uint32_t aCharCode); + bool ProvidesGetGlyph() const override { return true; } + virtual uint32_t GetGlyph(uint32_t unicode, + uint32_t variation_selector) override; + bool ProvidesGlyphWidths() const override { return true; } + int32_t GetGlyphWidth(uint16_t aGID) override; + bool GetGlyphBounds(uint16_t aGID, gfxRect* aBounds, bool aTight) override; + + FontType GetType() const override { return FONT_TYPE_FT2; } + + bool ShouldRoundXOffset(cairo_t* aCairo) const override; + + static void SetupVarCoords(FT_MM_Var* aMMVar, + const nsTArray<gfxFontVariation>& aVariations, + FT_Face aFTFace); + + FT_Face LockFTFace(); + void UnlockFTFace(); + + private: + uint32_t GetCharExtents(char aChar, gfxFloat* aWidth, + gfxRect* aBounds = nullptr); + + // Get advance (and optionally bounds) of a single glyph from FreeType, + // and return true, or return false if we failed. + bool GetFTGlyphExtents(uint16_t aGID, int32_t* aWidth, + mozilla::gfx::IntRect* aBounds = nullptr); + + protected: + void InitMetrics(); + const Metrics& GetHorizontalMetrics() override; + FT_Vector GetEmboldenStrength(FT_Face aFace); + + RefPtr<mozilla::gfx::SharedFTFace> mFTFace; + + Metrics mMetrics; + int mFTLoadFlags; + bool mEmbolden; + gfxFloat mFTSize; + + // For variation/multiple-master fonts, this will be an array of the values + // for each axis, as specified by mStyle.variationSettings (or the font's + // default for axes not present in variationSettings). Values here are in + // freetype's 16.16 fixed-point format, and clamped to the valid min/max + // range reported by the face. + nsTArray<FT_Fixed> mCoords; + + // Store cached glyph metrics for reasonably small glyph sizes. The bounds + // are stored unscaled to losslessly compress 26.6 fixed point to an int16_t. + // Larger glyphs are handled directly via GetFTGlyphExtents. + struct GlyphMetrics { + // Set the X coord to INT16_MIN to signal the bounds are invalid, or + // INT16_MAX to signal that the bounds would overflow an int16_t. + enum { INVALID = INT16_MIN, LARGE = INT16_MAX }; + + GlyphMetrics() : mAdvance(0), mX(INVALID), mY(0), mWidth(0), mHeight(0) {} + + bool HasValidBounds() const { return mX != INVALID; } + bool HasCachedBounds() const { return mX != LARGE; } + + // If the bounds can fit in an int16_t, set them. Otherwise, leave the + // bounds invalid to signal that GetFTGlyphExtents should be queried + // directly. + void SetBounds(const mozilla::gfx::IntRect& aBounds) { + if (aBounds.x > INT16_MIN && aBounds.x < INT16_MAX && + aBounds.y > INT16_MIN && aBounds.y < INT16_MAX && + aBounds.width <= UINT16_MAX && aBounds.height <= UINT16_MAX) { + mX = aBounds.x; + mY = aBounds.y; + mWidth = aBounds.width; + mHeight = aBounds.height; + } else { + mX = LARGE; + } + } + + mozilla::gfx::IntRect GetBounds() const { + return mozilla::gfx::IntRect(mX, mY, mWidth, mHeight); + } + + int32_t mAdvance; + int16_t mX; + int16_t mY; + uint16_t mWidth; + uint16_t mHeight; + }; + + const GlyphMetrics& GetCachedGlyphMetrics( + uint16_t aGID, mozilla::gfx::IntRect* aBounds = nullptr); + + mozilla::UniquePtr<nsDataHashtable<nsUint32HashKey, GlyphMetrics>> + mGlyphMetrics; +}; + +// Helper classes used for clearing out user font data when FT font +// face is destroyed. Since multiple faces may use the same data, be +// careful to assure that the data is only cleared out when all uses +// expire. The font entry object contains a refptr to FTUserFontData and +// each FT face created from that font entry contains a refptr to that +// same FTUserFontData object. + +class FTUserFontData final + : public mozilla::gfx::SharedFTFaceRefCountedData<FTUserFontData> { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FTUserFontData) + + FTUserFontData(const uint8_t* aData, uint32_t aLength) + : mFontData(aData), mLength(aLength) {} + + const uint8_t* FontData() const { return mFontData; } + + already_AddRefed<mozilla::gfx::SharedFTFace> CloneFace( + int aFaceIndex = 0) override; + + private: + ~FTUserFontData() { + if (mFontData) { + free((void*)mFontData); + } + } + + const uint8_t* mFontData; + uint32_t mLength; +}; + +#endif /* GFX_FT2FONTBASE_H */ |