gecko-dev/gfx/thebes/gfxFT2FontBase.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

170 строки
5.5 KiB
C
Исходник Обычный вид История

/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2012-05-21 15:12:37 +04:00
* 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);
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,
Bug 1582749 - query FreeType glyph advance and bounds at the same time. r=jfkthame Cairo would normally query both the advance and other metrics at the same time, then store them in a glyph cache sitting on each cairo_scaled_font_t any time any of the extents were queried. Each cached scaled glyph metrics would require about 150 bytes of space and could thus use a horribly large amount of memory when a lot of glyphs were being used within a scaled font. This tries to duplicate the behavior of querying and storing both advance and bounds at the same time to effectively cut the number of glyph loads in half for most cases. This should only add another 8 bytes per hash entry to store the cached bounds, thus putting us way ahead on memory usage compared to what Cairo did under the hood. Further, Cairo would keep around cairo_scaled_font_t's in a holdover cache even after there are no existing references to them and the owning gfxFonts have long since died. This gives an artificial boost in successive runs of the benchmark, while not aiding in the performance of the first run. I don't believe the extra memory use would be justified to reproduce that particular behavior, especially since our expectations are that the glyph cache for a gfxFont dies when the gfxFont itself dies from the gfxFontCache. In any case, this should at least significantly boost our glyph metrics performance on a cold start, with the caveat about the warm start case. Differential Revision: https://phabricator.services.mozilla.com/D46726 --HG-- extra : moz-landing-system : lando
2019-09-22 22:56:00 +03:00
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;
Bug 1582749 - query FreeType glyph advance and bounds at the same time. r=jfkthame Cairo would normally query both the advance and other metrics at the same time, then store them in a glyph cache sitting on each cairo_scaled_font_t any time any of the extents were queried. Each cached scaled glyph metrics would require about 150 bytes of space and could thus use a horribly large amount of memory when a lot of glyphs were being used within a scaled font. This tries to duplicate the behavior of querying and storing both advance and bounds at the same time to effectively cut the number of glyph loads in half for most cases. This should only add another 8 bytes per hash entry to store the cached bounds, thus putting us way ahead on memory usage compared to what Cairo did under the hood. Further, Cairo would keep around cairo_scaled_font_t's in a holdover cache even after there are no existing references to them and the owning gfxFonts have long since died. This gives an artificial boost in successive runs of the benchmark, while not aiding in the performance of the first run. I don't believe the extra memory use would be justified to reproduce that particular behavior, especially since our expectations are that the glyph cache for a gfxFont dies when the gfxFont itself dies from the gfxFontCache. In any case, this should at least significantly boost our glyph metrics performance on a cold start, with the caveat about the warm start case. Differential Revision: https://phabricator.services.mozilla.com/D46726 --HG-- extra : moz-landing-system : lando
2019-09-22 22:56:00 +03:00
// 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 */