gecko-dev/gfx/thebes/gfxFT2FontBase.h

185 lines
6.1 KiB
C++

/* -*- 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 "nsTHashMap.h"
#include "nsHashKeys.h"
class gfxFT2FontBase;
class gfxFT2FontEntryBase : public gfxFontEntry {
public:
explicit gfxFT2FontEntryBase(const nsACString& aName) : gfxFontEntry(aName) {}
uint32_t GetGlyph(uint32_t aCharCode, gfxFT2FontBase* aFont);
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 };
struct CmapCacheSlot {
CmapCacheSlot() : mCharCode(0), mGlyphIndex(0) {}
uint32_t mCharCode;
uint32_t mGlyphIndex;
};
mozilla::UniquePtr<CmapCacheSlot[]> mCmapCache GUARDED_BY(mLock);
};
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) {
auto* entry = static_cast<gfxFT2FontEntryBase*>(mFontEntry.get());
return entry->GetGlyph(aCharCode, this);
}
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 {
return GetCachedGlyphMetrics(aGID).mAdvance;
}
bool GetGlyphBounds(uint16_t aGID, gfxRect* aBounds,
bool aTight) const 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() const;
void UnlockFTFace() const;
private:
uint32_t GetCharExtents(uint32_t 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) const;
protected:
void InitMetrics();
const Metrics& GetHorizontalMetrics() const override { return mMetrics; }
FT_Vector GetEmboldenStrength(FT_Face aFace) const;
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) const;
mutable mozilla::UniquePtr<nsTHashMap<nsUint32HashKey, GlyphMetrics>>
mGlyphMetrics GUARDED_BY(mLock);
};
// 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 */