зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1547063 - Use SharedFTFace in thebes. r=jfkthame
Differential Revision: https://phabricator.services.mozilla.com/D44494 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
264178a181
Коммит
286a7bbfff
|
@ -213,30 +213,6 @@ void gfxFT2FontBase::InitMetrics() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
|
||||
// Resolve variations from entry (descriptor) and style (property)
|
||||
AutoTArray<gfxFontVariation, 8> settings;
|
||||
mFontEntry->GetVariationsForStyle(settings, mStyle);
|
||||
SetupVarCoords(mFontEntry->GetMMVar(), settings, &mCoords);
|
||||
if (!mCoords.IsEmpty()) {
|
||||
#if MOZ_TREE_FREETYPE
|
||||
FT_Set_Var_Design_Coordinates(face, mCoords.Length(), mCoords.Elements());
|
||||
#else
|
||||
typedef FT_Error (*SetCoordsFunc)(FT_Face, FT_UInt, FT_Fixed*);
|
||||
static SetCoordsFunc setCoords;
|
||||
static bool firstTime = true;
|
||||
if (firstTime) {
|
||||
firstTime = false;
|
||||
setCoords =
|
||||
(SetCoordsFunc)dlsym(RTLD_DEFAULT, "FT_Set_Var_Design_Coordinates");
|
||||
}
|
||||
if (setCoords) {
|
||||
(*setCoords)(face, mCoords.Length(), mCoords.Elements());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
const FT_Size_Metrics& ftMetrics = face->size->metrics;
|
||||
|
||||
mMetrics.maxAscent = FLOAT_FROM_26_6(ftMetrics.ascender);
|
||||
|
@ -607,22 +583,52 @@ bool gfxFT2FontBase::SetupCairoFont(DrawTarget* aDrawTarget) {
|
|||
/*static*/
|
||||
void gfxFT2FontBase::SetupVarCoords(
|
||||
FT_MM_Var* aMMVar, const nsTArray<gfxFontVariation>& aVariations,
|
||||
nsTArray<FT_Fixed>* aCoords) {
|
||||
aCoords->TruncateLength(0);
|
||||
FT_Face aFTFace) {
|
||||
if (!aMMVar) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<FT_Fixed> coords;
|
||||
for (unsigned i = 0; i < aMMVar->num_axis; ++i) {
|
||||
aCoords->AppendElement(aMMVar->axis[i].def);
|
||||
coords.AppendElement(aMMVar->axis[i].def);
|
||||
for (const auto& v : aVariations) {
|
||||
if (aMMVar->axis[i].tag == v.mTag) {
|
||||
FT_Fixed val = v.mValue * 0x10000;
|
||||
val = std::min(val, aMMVar->axis[i].maximum);
|
||||
val = std::max(val, aMMVar->axis[i].minimum);
|
||||
(*aCoords)[i] = val;
|
||||
coords[i] = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!coords.IsEmpty()) {
|
||||
#if MOZ_TREE_FREETYPE
|
||||
FT_Set_Var_Design_Coordinates(aFTFace, coords.Length(), coords.Elements());
|
||||
#else
|
||||
typedef FT_Error (*SetCoordsFunc)(FT_Face, FT_UInt, FT_Fixed*);
|
||||
static SetCoordsFunc setCoords;
|
||||
static bool firstTime = true;
|
||||
if (firstTime) {
|
||||
firstTime = false;
|
||||
setCoords =
|
||||
(SetCoordsFunc)dlsym(RTLD_DEFAULT, "FT_Set_Var_Design_Coordinates");
|
||||
}
|
||||
if (setCoords) {
|
||||
(*setCoords)(aFTFace, coords.Length(), coords.Elements());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<SharedFTFace> FTUserFontData::CloneFace(int aFaceIndex) {
|
||||
RefPtr<SharedFTFace> face = Factory::NewSharedFTFaceFromData(
|
||||
nullptr, mFontData, mLength, aFaceIndex, this);
|
||||
if (!face ||
|
||||
(FT_Select_Charmap(face->GetFace(), FT_ENCODING_UNICODE) != FT_Err_Ok &&
|
||||
FT_Select_Charmap(face->GetFace(), FT_ENCODING_MS_SYMBOL) !=
|
||||
FT_Err_Ok)) {
|
||||
return nullptr;
|
||||
}
|
||||
return face.forget();
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ class gfxFT2FontBase : public gfxFont {
|
|||
|
||||
static void SetupVarCoords(FT_MM_Var* aMMVar,
|
||||
const nsTArray<gfxFontVariation>& aVariations,
|
||||
nsTArray<FT_Fixed>* aCoords);
|
||||
FT_Face aFTFace);
|
||||
|
||||
private:
|
||||
uint32_t GetCharExtents(char aChar, cairo_text_extents_t* aExtents);
|
||||
|
@ -67,4 +67,35 @@ class gfxFT2FontBase : public gfxFont {
|
|||
mozilla::UniquePtr<nsDataHashtable<nsUint32HashKey, int32_t>> mGlyphWidths;
|
||||
};
|
||||
|
||||
// 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 */
|
||||
|
|
|
@ -63,8 +63,6 @@ static LazyLogModule sFontInfoLog("fontInfoLog");
|
|||
#define LOG(args) MOZ_LOG(sFontInfoLog, mozilla::LogLevel::Debug, args)
|
||||
#define LOG_ENABLED() MOZ_LOG_TEST(sFontInfoLog, mozilla::LogLevel::Debug)
|
||||
|
||||
static cairo_user_data_key_t sFTUserFontDataKey;
|
||||
|
||||
static __inline void BuildKeyNameFromFontName(nsACString& aName) {
|
||||
ToLowerCase(aName);
|
||||
}
|
||||
|
@ -76,91 +74,65 @@ static __inline void BuildKeyNameFromFontName(nsACString& aName) {
|
|||
// memory long-term.
|
||||
// This may fail (resulting in a null FT_Face), e.g. if it fails to
|
||||
// allocate memory to uncompress a font from omnijar.
|
||||
class AutoFTFace {
|
||||
public:
|
||||
explicit AutoFTFace(FT2FontEntry* aFontEntry)
|
||||
: mFace(nullptr),
|
||||
mFontDataBuf(nullptr),
|
||||
mDataLength(0),
|
||||
mOwnsFace(false) {
|
||||
if (aFontEntry->mFTFace) {
|
||||
mFace = aFontEntry->mFTFace;
|
||||
return;
|
||||
}
|
||||
already_AddRefed<SharedFTFace> FT2FontEntry::GetFTFace(bool aCommit) {
|
||||
if (mFTFace) {
|
||||
return do_AddRef(mFTFace);
|
||||
}
|
||||
|
||||
NS_ASSERTION(!aFontEntry->mFilename.IsEmpty(),
|
||||
"can't use AutoFTFace for fonts without a filename");
|
||||
NS_ASSERTION(!mFilename.IsEmpty(),
|
||||
"can't use GetFTFace for fonts without a filename");
|
||||
|
||||
// A relative path (no initial "/") means this is a resource in
|
||||
// omnijar, not an installed font on the device.
|
||||
// The NS_ASSERTIONs here should never fail, as the resource must have
|
||||
// been read successfully during font-list initialization or we'd never
|
||||
// have created the font entry. The only legitimate runtime failure
|
||||
// here would be memory allocation, in which case mFace remains null.
|
||||
if (aFontEntry->mFilename[0] != '/') {
|
||||
RefPtr<nsZipArchive> reader = Omnijar::GetReader(Omnijar::Type::GRE);
|
||||
nsZipItem* item = reader->GetItem(aFontEntry->mFilename.get());
|
||||
NS_ASSERTION(item, "failed to find zip entry");
|
||||
// A relative path (no initial "/") means this is a resource in
|
||||
// omnijar, not an installed font on the device.
|
||||
// The NS_ASSERTIONs here should never fail, as the resource must have
|
||||
// been read successfully during font-list initialization or we'd never
|
||||
// have created the font entry. The only legitimate runtime failure
|
||||
// here would be memory allocation, in which case mFace remains null.
|
||||
RefPtr<SharedFTFace> face;
|
||||
if (mFilename[0] != '/') {
|
||||
RefPtr<nsZipArchive> reader = Omnijar::GetReader(Omnijar::Type::GRE);
|
||||
nsZipItem* item = reader->GetItem(mFilename.get());
|
||||
NS_ASSERTION(item, "failed to find zip entry");
|
||||
|
||||
uint32_t bufSize = item->RealSize();
|
||||
mFontDataBuf = static_cast<uint8_t*>(malloc(bufSize));
|
||||
if (mFontDataBuf) {
|
||||
nsZipCursor cursor(item, reader, mFontDataBuf, bufSize);
|
||||
cursor.Copy(&bufSize);
|
||||
NS_ASSERTION(bufSize == item->RealSize(), "error reading bundled font");
|
||||
mDataLength = bufSize;
|
||||
mFace = Factory::NewFTFaceFromData(nullptr, mFontDataBuf, bufSize,
|
||||
aFontEntry->mFTFontIndex);
|
||||
if (!mFace) {
|
||||
NS_WARNING("failed to create freetype face");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mFace = Factory::NewFTFace(nullptr, aFontEntry->mFilename.get(),
|
||||
aFontEntry->mFTFontIndex);
|
||||
if (!mFace) {
|
||||
uint32_t bufSize = item->RealSize();
|
||||
uint8_t* fontDataBuf = static_cast<uint8_t*>(malloc(bufSize));
|
||||
if (fontDataBuf) {
|
||||
nsZipCursor cursor(item, reader, fontDataBuf, bufSize);
|
||||
cursor.Copy(&bufSize);
|
||||
NS_ASSERTION(bufSize == item->RealSize(), "error reading bundled font");
|
||||
RefPtr<FTUserFontData> ufd = new FTUserFontData(fontDataBuf, bufSize);
|
||||
face = ufd->CloneFace(mFTFontIndex);
|
||||
if (!face) {
|
||||
NS_WARNING("failed to create freetype face");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (FT_Err_Ok != FT_Select_Charmap(mFace, FT_ENCODING_UNICODE) &&
|
||||
FT_Err_Ok != FT_Select_Charmap(mFace, FT_ENCODING_MS_SYMBOL)) {
|
||||
} else {
|
||||
face = Factory::NewSharedFTFace(nullptr, mFilename.get(), mFTFontIndex);
|
||||
if (!face) {
|
||||
NS_WARNING("failed to create freetype face");
|
||||
return nullptr;
|
||||
}
|
||||
if (FT_Err_Ok != FT_Select_Charmap(face->GetFace(), FT_ENCODING_UNICODE) &&
|
||||
FT_Err_Ok !=
|
||||
FT_Select_Charmap(face->GetFace(), FT_ENCODING_MS_SYMBOL)) {
|
||||
NS_WARNING("failed to select Unicode or symbol charmap");
|
||||
}
|
||||
mOwnsFace = true;
|
||||
}
|
||||
|
||||
~AutoFTFace() {
|
||||
if (mFace && mOwnsFace) {
|
||||
Factory::ReleaseFTFace(mFace);
|
||||
if (mFontDataBuf) {
|
||||
free(mFontDataBuf);
|
||||
}
|
||||
}
|
||||
if (aCommit) {
|
||||
mFTFace = face;
|
||||
}
|
||||
|
||||
operator FT_Face() { return mFace; }
|
||||
return face.forget();
|
||||
}
|
||||
|
||||
// If we 'forget' the FT_Face (used when ownership is handed over to Cairo),
|
||||
// we do -not- free the mFontDataBuf (if used); that also becomes the
|
||||
// responsibility of the new owner of the face.
|
||||
FT_Face forget() {
|
||||
NS_ASSERTION(mOwnsFace, "can't forget() when we didn't own the face");
|
||||
mOwnsFace = false;
|
||||
return mFace;
|
||||
FTUserFontData* FT2FontEntry::GetUserFontData() {
|
||||
if (mFTFace && mFTFace->GetData()) {
|
||||
return static_cast<FTUserFontData*>(mFTFace->GetData());
|
||||
}
|
||||
|
||||
const uint8_t* FontData() const { return mFontDataBuf; }
|
||||
uint32_t DataLength() const { return mDataLength; }
|
||||
|
||||
private:
|
||||
FT_Face mFace;
|
||||
uint8_t* mFontDataBuf; // Uncompressed data (for fonts stored in a JAR),
|
||||
// or null for fonts instantiated from a file.
|
||||
// If non-null, this must survive as long as the
|
||||
// FT_Face.
|
||||
uint32_t mDataLength; // Size of mFontDataBuf, if present.
|
||||
bool mOwnsFace;
|
||||
};
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* FT2FontEntry
|
||||
|
@ -173,8 +145,15 @@ class AutoFTFace {
|
|||
*/
|
||||
|
||||
cairo_scaled_font_t* FT2FontEntry::CreateScaledFont(
|
||||
const gfxFontStyle* aStyle) {
|
||||
cairo_font_face_t* cairoFace = CairoFontFace(aStyle);
|
||||
const gfxFontStyle* aStyle, RefPtr<SharedFTFace> aFace) {
|
||||
int flags = gfxPlatform::GetPlatform()->FontHintingEnabled()
|
||||
? FT_LOAD_DEFAULT
|
||||
: (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
|
||||
if (aFace->GetFace()->face_flags & FT_FACE_FLAG_TRICKY) {
|
||||
flags &= ~FT_LOAD_NO_AUTOHINT;
|
||||
}
|
||||
cairo_font_face_t* cairoFace = cairo_ft_font_face_create_for_ft_face(
|
||||
aFace->GetFace(), flags, 0, aFace.get());
|
||||
if (!cairoFace) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -206,18 +185,8 @@ cairo_scaled_font_t* FT2FontEntry::CreateScaledFont(
|
|||
|
||||
FT2FontEntry::~FT2FontEntry() {
|
||||
if (mMMVar) {
|
||||
FT_Done_MM_Var(mFTFace->glyph->library, mMMVar);
|
||||
FT_Done_MM_Var(mFTFace->GetFace()->glyph->library, mMMVar);
|
||||
}
|
||||
|
||||
// Do nothing for mFTFace here since FTFontDestroyFunc is called by cairo.
|
||||
mFTFace = nullptr;
|
||||
|
||||
#ifndef ANDROID
|
||||
if (mFontFace) {
|
||||
cairo_font_face_destroy(mFontFace);
|
||||
mFontFace = nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
gfxFontEntry* FT2FontEntry::Clone() const {
|
||||
|
@ -231,29 +200,52 @@ gfxFontEntry* FT2FontEntry::Clone() const {
|
|||
return fe;
|
||||
}
|
||||
|
||||
static cairo_user_data_key_t sFTFaceKey;
|
||||
gfxFont* FT2FontEntry::CreateFontInstance(const gfxFontStyle* aStyle) {
|
||||
RefPtr<SharedFTFace> face = GetFTFace(true);
|
||||
if (!face) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gfxFont* FT2FontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle) {
|
||||
cairo_scaled_font_t* scaledFont = CreateScaledFont(aFontStyle);
|
||||
// If variations are present, we will not use our cached mFTFace
|
||||
// but always create a new one as it will have custom variation
|
||||
// coordinates applied.
|
||||
if ((!mVariationSettings.IsEmpty() ||
|
||||
(aStyle && !aStyle->variationSettings.IsEmpty())) &&
|
||||
(face->GetFace()->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) {
|
||||
// Create a separate FT_Face because we need to apply custom
|
||||
// variation settings to it.
|
||||
RefPtr<SharedFTFace> varFace;
|
||||
if (!mFilename.IsEmpty() && mFilename[0] == '/') {
|
||||
varFace =
|
||||
Factory::NewSharedFTFace(nullptr, mFilename.get(), mFTFontIndex);
|
||||
} else {
|
||||
varFace = face->GetData()->CloneFace(mFTFontIndex);
|
||||
}
|
||||
if (varFace) {
|
||||
// Resolve variations from entry (descriptor) and style (property)
|
||||
AutoTArray<gfxFontVariation, 8> settings;
|
||||
GetVariationsForStyle(settings, aStyle ? *aStyle : gfxFontStyle());
|
||||
gfxFT2FontBase::SetupVarCoords(GetMMVar(), settings, varFace->GetFace());
|
||||
face = std::move(varFace);
|
||||
}
|
||||
}
|
||||
|
||||
cairo_scaled_font_t* scaledFont = CreateScaledFont(aStyle, face);
|
||||
if (!scaledFont) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<UnscaledFontFreeType> unscaledFont(mUnscaledFont);
|
||||
if (!unscaledFont) {
|
||||
unscaledFont =
|
||||
!mFilename.IsEmpty() && mFilename[0] == '/'
|
||||
? new UnscaledFontFreeType(mFilename.BeginReading(), mFTFontIndex)
|
||||
: new UnscaledFontFreeType(mFTFace);
|
||||
unscaledFont = !mFilename.IsEmpty() && mFilename[0] == '/'
|
||||
? new UnscaledFontFreeType(mFilename.BeginReading(),
|
||||
mFTFontIndex, mFTFace)
|
||||
: new UnscaledFontFreeType(mFTFace);
|
||||
mUnscaledFont = unscaledFont;
|
||||
}
|
||||
|
||||
cairo_font_face_t* face = cairo_scaled_font_get_font_face(scaledFont);
|
||||
FT_Face ftFace =
|
||||
static_cast<FT_Face>(cairo_font_face_get_user_data(face, &sFTFaceKey));
|
||||
|
||||
gfxFont* font = new gfxFT2Font(unscaledFont, scaledFont,
|
||||
ftFace ? ftFace : mFTFace, this, aFontStyle);
|
||||
gfxFont* font =
|
||||
new gfxFT2Font(unscaledFont, scaledFont, std::move(face), this, aStyle);
|
||||
cairo_scaled_font_destroy(scaledFont);
|
||||
return font;
|
||||
}
|
||||
|
@ -265,22 +257,17 @@ FT2FontEntry* FT2FontEntry::CreateFontEntry(
|
|||
// Ownership of aFontData is passed in here; the fontEntry must
|
||||
// retain it as long as the FT_Face needs it, and ensure it is
|
||||
// eventually deleted.
|
||||
FT_Face face = Factory::NewFTFaceFromData(nullptr, aFontData, aLength, 0);
|
||||
RefPtr<FTUserFontData> ufd = new FTUserFontData(aFontData, aLength);
|
||||
RefPtr<SharedFTFace> face = ufd->CloneFace();
|
||||
if (!face) {
|
||||
free((void*)aFontData);
|
||||
return nullptr;
|
||||
}
|
||||
if (FT_Err_Ok != FT_Select_Charmap(face, FT_ENCODING_UNICODE) &&
|
||||
FT_Err_Ok != FT_Select_Charmap(face, FT_ENCODING_MS_SYMBOL)) {
|
||||
Factory::ReleaseFTFace(face);
|
||||
free((void*)aFontData);
|
||||
return nullptr;
|
||||
}
|
||||
// Create our FT2FontEntry, which inherits the name of the userfont entry
|
||||
// as it's not guaranteed that the face has valid names (bug 737315)
|
||||
FT2FontEntry* fe = FT2FontEntry::CreateFontEntry(face, nullptr, 0, aFontName,
|
||||
aFontData, aLength);
|
||||
FT2FontEntry* fe =
|
||||
FT2FontEntry::CreateFontEntry(face->GetFace(), nullptr, 0, aFontName);
|
||||
if (fe) {
|
||||
fe->mFTFace = face;
|
||||
fe->mStyleRange = aStyle;
|
||||
fe->mWeightRange = aWeight;
|
||||
fe->mStretchRange = aStretch;
|
||||
|
@ -289,32 +276,6 @@ FT2FontEntry* FT2FontEntry::CreateFontEntry(
|
|||
return fe;
|
||||
}
|
||||
|
||||
class FTUserFontData {
|
||||
public:
|
||||
FTUserFontData(FT_Face aFace, const uint8_t* aData, uint32_t aLength)
|
||||
: mFace(aFace), mFontData(aData), mLength(aLength) {}
|
||||
|
||||
~FTUserFontData() {
|
||||
Factory::ReleaseFTFace(mFace);
|
||||
if (mFontData) {
|
||||
free((void*)mFontData);
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t* FontData() const { return mFontData; }
|
||||
uint32_t Length() const { return mLength; }
|
||||
|
||||
private:
|
||||
FT_Face mFace;
|
||||
const uint8_t* mFontData;
|
||||
uint32_t mLength;
|
||||
};
|
||||
|
||||
static void FTFontDestroyFunc(void* data) {
|
||||
FTUserFontData* userFontData = static_cast<FTUserFontData*>(data);
|
||||
delete userFontData;
|
||||
}
|
||||
|
||||
/* static */
|
||||
FT2FontEntry* FT2FontEntry::CreateFontEntry(const FontListEntry& aFLE) {
|
||||
FT2FontEntry* fe = new FT2FontEntry(aFLE.faceName());
|
||||
|
@ -368,9 +329,10 @@ static FontWeight FTFaceGetWeight(FT_Face aFace) {
|
|||
// as we don't want to keep a freetype face for every installed font
|
||||
// permanently in memory.
|
||||
/* static */
|
||||
FT2FontEntry* FT2FontEntry::CreateFontEntry(
|
||||
FT_Face aFace, const char* aFilename, uint8_t aIndex,
|
||||
const nsACString& aName, const uint8_t* aFontData, uint32_t aLength) {
|
||||
FT2FontEntry* FT2FontEntry::CreateFontEntry(FT_Face aFace,
|
||||
const char* aFilename,
|
||||
uint8_t aIndex,
|
||||
const nsACString& aName) {
|
||||
FT2FontEntry* fe = new FT2FontEntry(aName);
|
||||
fe->mStyleRange =
|
||||
SlantStyleRange(FTFaceIsItalic(aFace) ? FontSlantStyle::Italic()
|
||||
|
@ -379,22 +341,6 @@ FT2FontEntry* FT2FontEntry::CreateFontEntry(
|
|||
fe->mFilename = aFilename;
|
||||
fe->mFTFontIndex = aIndex;
|
||||
|
||||
if (aFontData) {
|
||||
fe->mFTFace = aFace;
|
||||
int flags = gfxPlatform::GetPlatform()->FontHintingEnabled()
|
||||
? FT_LOAD_DEFAULT
|
||||
: (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
|
||||
if (aFace->face_flags & FT_FACE_FLAG_TRICKY) {
|
||||
flags &= ~FT_LOAD_NO_AUTOHINT;
|
||||
}
|
||||
fe->mFontFace =
|
||||
cairo_ft_font_face_create_for_ft_face(aFace, flags, nullptr, 0);
|
||||
FTUserFontData* userFontData =
|
||||
new FTUserFontData(aFace, aFontData, aLength);
|
||||
cairo_font_face_set_user_data(fe->mFontFace, &sFTUserFontDataKey,
|
||||
userFontData, FTFontDestroyFunc);
|
||||
}
|
||||
|
||||
return fe;
|
||||
}
|
||||
|
||||
|
@ -417,76 +363,6 @@ FT2FontEntry* gfxFT2Font::GetFontEntry() {
|
|||
return static_cast<FT2FontEntry*>(mFontEntry.get());
|
||||
}
|
||||
|
||||
cairo_font_face_t* FT2FontEntry::CairoFontFace(const gfxFontStyle* aStyle) {
|
||||
// Create our basic (no-variations) mFontFace if not already present;
|
||||
// this also ensures we have mFTFace available.
|
||||
if (!mFontFace) {
|
||||
AutoFTFace face(this);
|
||||
if (!face) {
|
||||
return nullptr;
|
||||
}
|
||||
int flags = gfxPlatform::GetPlatform()->FontHintingEnabled()
|
||||
? FT_LOAD_DEFAULT
|
||||
: (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
|
||||
if (FT_Face(face)->face_flags & FT_FACE_FLAG_TRICKY) {
|
||||
flags &= ~FT_LOAD_NO_AUTOHINT;
|
||||
}
|
||||
mFontFace = cairo_ft_font_face_create_for_ft_face(face, flags, nullptr, 0);
|
||||
auto userFontData =
|
||||
new FTUserFontData(face, face.FontData(), face.DataLength());
|
||||
cairo_font_face_set_user_data(mFontFace, &sFTUserFontDataKey, userFontData,
|
||||
FTFontDestroyFunc);
|
||||
mFTFace = face.forget();
|
||||
}
|
||||
|
||||
// If variations are present, we will not use our cached mFontFace
|
||||
// but always create a new cairo_font_face_t because its FT_Face will
|
||||
// have custom variation coordinates applied.
|
||||
if ((!mVariationSettings.IsEmpty() ||
|
||||
(aStyle && !aStyle->variationSettings.IsEmpty())) &&
|
||||
(mFTFace->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) {
|
||||
int flags = gfxPlatform::GetPlatform()->FontHintingEnabled()
|
||||
? FT_LOAD_DEFAULT
|
||||
: (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
|
||||
if (mFTFace->face_flags & FT_FACE_FLAG_TRICKY) {
|
||||
flags &= ~FT_LOAD_NO_AUTOHINT;
|
||||
}
|
||||
// Resolve variations from entry (descriptor) and style (property)
|
||||
AutoTArray<gfxFontVariation, 8> settings;
|
||||
GetVariationsForStyle(settings, aStyle ? *aStyle : gfxFontStyle());
|
||||
AutoTArray<FT_Fixed, 8> coords;
|
||||
gfxFT2FontBase::SetupVarCoords(GetMMVar(), settings, &coords);
|
||||
// Create a separate FT_Face because we need to apply custom
|
||||
// variation settings to it.
|
||||
FT_Face ftFace;
|
||||
if (!mFilename.IsEmpty() && mFilename[0] == '/') {
|
||||
ftFace = Factory::NewFTFace(nullptr, mFilename.get(), mFTFontIndex);
|
||||
} else {
|
||||
auto ufd = reinterpret_cast<FTUserFontData*>(
|
||||
cairo_font_face_get_user_data(mFontFace, &sFTUserFontDataKey));
|
||||
ftFace = Factory::NewFTFaceFromData(nullptr, ufd->FontData(),
|
||||
ufd->Length(), mFTFontIndex);
|
||||
}
|
||||
// The variation coordinates will actually be applied to ftFace by
|
||||
// gfxFT2FontBase::InitMetrics, so we don't need to do it here.
|
||||
cairo_font_face_t* cairoFace = cairo_ft_font_face_create_for_ft_face(
|
||||
ftFace, flags, coords.Elements(), coords.Length());
|
||||
// Set up user data to properly release the FT_Face when the cairo face
|
||||
// is deleted.
|
||||
if (cairo_font_face_set_user_data(
|
||||
cairoFace, &sFTFaceKey, ftFace,
|
||||
(cairo_destroy_func_t)&Factory::ReleaseFTFace)) {
|
||||
// set_user_data failed! discard, and fall back to default face
|
||||
cairo_font_face_destroy(cairoFace);
|
||||
FT_Done_Face(ftFace);
|
||||
} else {
|
||||
return cairoFace;
|
||||
}
|
||||
}
|
||||
|
||||
return mFontFace;
|
||||
}
|
||||
|
||||
// Copied/modified from similar code in gfxMacPlatformFontList.mm:
|
||||
// Complex scripts will not render correctly unless Graphite or OT
|
||||
// layout tables are present.
|
||||
|
@ -560,14 +436,14 @@ nsresult FT2FontEntry::ReadCMAP(FontInfoData* aFontInfoData) {
|
|||
|
||||
nsresult FT2FontEntry::CopyFontTable(uint32_t aTableTag,
|
||||
nsTArray<uint8_t>& aBuffer) {
|
||||
AutoFTFace face(this);
|
||||
RefPtr<SharedFTFace> face = GetFTFace();
|
||||
if (!face) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
FT_Error status;
|
||||
FT_ULong len = 0;
|
||||
status = FT_Load_Sfnt_Table(face, aTableTag, 0, nullptr, &len);
|
||||
status = FT_Load_Sfnt_Table(face->GetFace(), aTableTag, 0, nullptr, &len);
|
||||
if (status != FT_Err_Ok || len == 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -576,19 +452,17 @@ nsresult FT2FontEntry::CopyFontTable(uint32_t aTableTag,
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
uint8_t* buf = aBuffer.Elements();
|
||||
status = FT_Load_Sfnt_Table(face, aTableTag, 0, buf, &len);
|
||||
status = FT_Load_Sfnt_Table(face->GetFace(), aTableTag, 0, buf, &len);
|
||||
NS_ENSURE_TRUE(status == FT_Err_Ok, NS_ERROR_FAILURE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
hb_blob_t* FT2FontEntry::GetFontTable(uint32_t aTableTag) {
|
||||
if (mFontFace) {
|
||||
if (FTUserFontData* userFontData = GetUserFontData()) {
|
||||
// if there's a cairo font face, we may be able to return a blob
|
||||
// that just wraps a range of the attached user font data
|
||||
FTUserFontData* userFontData = static_cast<FTUserFontData*>(
|
||||
cairo_font_face_get_user_data(mFontFace, &sFTUserFontDataKey));
|
||||
if (userFontData && userFontData->FontData()) {
|
||||
if (userFontData->FontData()) {
|
||||
return gfxFontUtils::GetTableFromFontData(userFontData->FontData(),
|
||||
aTableTag);
|
||||
}
|
||||
|
@ -605,9 +479,10 @@ bool FT2FontEntry::HasVariations() {
|
|||
}
|
||||
mHasVariationsInitialized = true;
|
||||
|
||||
AutoFTFace face(this);
|
||||
RefPtr<SharedFTFace> face = GetFTFace();
|
||||
if (face) {
|
||||
mHasVariations = FT_Face(face)->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS;
|
||||
mHasVariations =
|
||||
face->GetFace()->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS;
|
||||
}
|
||||
|
||||
return mHasVariations;
|
||||
|
@ -641,11 +516,11 @@ FT_MM_Var* FT2FontEntry::GetMMVar() {
|
|||
return mMMVar;
|
||||
}
|
||||
mMMVarInitialized = true;
|
||||
AutoFTFace face(this);
|
||||
RefPtr<SharedFTFace> face = GetFTFace(true);
|
||||
if (!face) {
|
||||
return nullptr;
|
||||
}
|
||||
if (FT_Err_Ok != FT_Get_MM_Var(face, &mMMVar)) {
|
||||
if (FT_Err_Ok != FT_Get_MM_Var(face->GetFace(), &mMMVar)) {
|
||||
mMMVar = nullptr;
|
||||
}
|
||||
return mMMVar;
|
||||
|
@ -1162,10 +1037,10 @@ void FT2FontEntry::CheckForBrokenFont(const nsACString& aFamilyKey) {
|
|||
// Droid Sans Arabic from certain phones, as identified by the
|
||||
// font checksum in the 'head' table
|
||||
if (aFamilyKey.EqualsLiteral("droid sans arabic")) {
|
||||
AutoFTFace face(this);
|
||||
RefPtr<SharedFTFace> face = GetFTFace();
|
||||
if (face) {
|
||||
const TT_Header* head =
|
||||
static_cast<const TT_Header*>(FT_Get_Sfnt_Table(face, ft_sfnt_head));
|
||||
const TT_Header* head = static_cast<const TT_Header*>(
|
||||
FT_Get_Sfnt_Table(face->GetFace(), ft_sfnt_head));
|
||||
if (head && head->CheckSum_Adjust == 0xe445242) {
|
||||
mIgnoreGSUB = true;
|
||||
}
|
||||
|
@ -1739,14 +1614,14 @@ searchDone:
|
|||
// from the userfont entry rather than the actual font.
|
||||
|
||||
// Ensure existence of mFTFace in the original entry
|
||||
fontEntry->CairoFontFace();
|
||||
if (!fontEntry->mFTFace) {
|
||||
RefPtr<SharedFTFace> face = fontEntry->GetFTFace(true);
|
||||
if (!face) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FT2FontEntry* fe = FT2FontEntry::CreateFontEntry(
|
||||
fontEntry->mFTFace, fontEntry->mFilename.get(), fontEntry->mFTFontIndex,
|
||||
fontEntry->Name(), nullptr);
|
||||
FT2FontEntry* fe =
|
||||
FT2FontEntry::CreateFontEntry(face->GetFace(), fontEntry->mFilename.get(),
|
||||
fontEntry->mFTFontIndex, fontEntry->Name());
|
||||
if (fe) {
|
||||
fe->mStyleRange = aStyleForEntry;
|
||||
fe->mWeightRange = aWeightForEntry;
|
||||
|
|
|
@ -21,14 +21,12 @@ class FontNameCache;
|
|||
typedef struct FT_FaceRec_* FT_Face;
|
||||
class nsZipArchive;
|
||||
class WillShutdownObserver;
|
||||
class FTUserFontData;
|
||||
|
||||
class FT2FontEntry : public gfxFontEntry {
|
||||
public:
|
||||
explicit FT2FontEntry(const nsACString& aFaceName)
|
||||
: gfxFontEntry(aFaceName),
|
||||
mFTFace(nullptr),
|
||||
mFontFace(nullptr),
|
||||
mFTFontIndex(0) {}
|
||||
: gfxFontEntry(aFaceName), mFTFontIndex(0) {}
|
||||
|
||||
~FT2FontEntry();
|
||||
|
||||
|
@ -51,22 +49,15 @@ class FT2FontEntry : public gfxFontEntry {
|
|||
// aFontData (if non-nullptr) is NS_Malloc'ed data that aFace depends on,
|
||||
// to be freed after the face is destroyed.
|
||||
// aLength is the length of aFontData.
|
||||
static FT2FontEntry* CreateFontEntry(FT_Face aFace, const char* aFilename,
|
||||
uint8_t aIndex, const nsACString& aName,
|
||||
const uint8_t* aFontData = nullptr,
|
||||
uint32_t aLength = 0);
|
||||
static FT2FontEntry* CreateFontEntry(FT_Face, const char* aFilename,
|
||||
uint8_t aIndex, const nsACString& aName);
|
||||
|
||||
gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle) override;
|
||||
|
||||
// Create (if necessary) and return the cairo_font_face for this font.
|
||||
// This may fail and return null, so caller must be prepared to handle this.
|
||||
// If a style is passed, any variationSettings in the style will be applied
|
||||
// to the resulting font face.
|
||||
cairo_font_face_t* CairoFontFace(const gfxFontStyle* aStyle = nullptr);
|
||||
gfxFont* CreateFontInstance(const gfxFontStyle* aStyle) override;
|
||||
|
||||
// Create a cairo_scaled_font for this face, with the given style.
|
||||
// This may fail and return null, so caller must be prepared to handle this.
|
||||
cairo_scaled_font_t* CreateScaledFont(const gfxFontStyle* aStyle);
|
||||
cairo_scaled_font_t* CreateScaledFont(
|
||||
const gfxFontStyle* aStyle, RefPtr<mozilla::gfx::SharedFTFace> aFace);
|
||||
|
||||
nsresult ReadCMAP(FontInfoData* aFontInfoData = nullptr) override;
|
||||
|
||||
|
@ -86,6 +77,9 @@ class FT2FontEntry : public gfxFontEntry {
|
|||
void CheckForBrokenFont(gfxFontFamily* aFamily);
|
||||
void CheckForBrokenFont(const nsACString& aFamilyKey);
|
||||
|
||||
already_AddRefed<mozilla::gfx::SharedFTFace> GetFTFace(bool aCommit = false);
|
||||
FTUserFontData* GetUserFontData();
|
||||
|
||||
FT_MM_Var* GetMMVar() override;
|
||||
|
||||
/**
|
||||
|
@ -103,8 +97,7 @@ class FT2FontEntry : public gfxFontEntry {
|
|||
void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
|
||||
FontListSizes* aSizes) const override;
|
||||
|
||||
FT_Face mFTFace;
|
||||
cairo_font_face_t* mFontFace;
|
||||
RefPtr<mozilla::gfx::SharedFTFace> mFTFace;
|
||||
|
||||
FT_MM_Var* mMMVar = nullptr;
|
||||
|
||||
|
|
|
@ -153,11 +153,12 @@ void gfxFT2Font::AddRange(const char16_t* aText, uint32_t aOffset,
|
|||
}
|
||||
|
||||
gfxFT2Font::gfxFT2Font(const RefPtr<UnscaledFontFreeType>& aUnscaledFont,
|
||||
cairo_scaled_font_t* aCairoFont, FT_Face aFTFace,
|
||||
cairo_scaled_font_t* aCairoFont,
|
||||
RefPtr<mozilla::gfx::SharedFTFace>&& aFTFace,
|
||||
FT2FontEntry* aFontEntry, const gfxFontStyle* aFontStyle)
|
||||
: gfxFT2FontBase(aUnscaledFont, aCairoFont, aFontEntry, aFontStyle),
|
||||
mCharGlyphCache(32),
|
||||
mFTFace(aFTFace) {
|
||||
mFTFace(std::move(aFTFace)) {
|
||||
NS_ASSERTION(mFontEntry,
|
||||
"Unable to find font entry for font. Something is whack.");
|
||||
// TODO: use FreeType emboldening instead of multi-strike?
|
||||
|
@ -168,12 +169,8 @@ gfxFT2Font::~gfxFT2Font() {}
|
|||
|
||||
already_AddRefed<ScaledFont> gfxFT2Font::GetScaledFont(DrawTarget* aTarget) {
|
||||
if (!mAzureScaledFont) {
|
||||
NativeFont nativeFont;
|
||||
nativeFont.mType = NativeFontType::FREETYPE_FACE;
|
||||
nativeFont.mFont = mFTFace;
|
||||
|
||||
mAzureScaledFont = Factory::CreateScaledFontForNativeFont(
|
||||
nativeFont, GetUnscaledFont(), GetAdjustedSize(), GetCairoScaledFont());
|
||||
mAzureScaledFont = Factory::CreateScaledFontForFreeTypeFont(
|
||||
GetUnscaledFont(), GetAdjustedSize(), GetCairoScaledFont(), mFTFace);
|
||||
InitializeScaledFont();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,8 @@ class FT2FontEntry;
|
|||
class gfxFT2Font : public gfxFT2FontBase {
|
||||
public: // new functions
|
||||
gfxFT2Font(const RefPtr<mozilla::gfx::UnscaledFontFreeType>& aUnscaledFont,
|
||||
cairo_scaled_font_t* aCairoFont, FT_Face aFTFace,
|
||||
cairo_scaled_font_t* aCairoFont,
|
||||
RefPtr<mozilla::gfx::SharedFTFace>&& aFTFace,
|
||||
FT2FontEntry* aFontEntry, const gfxFontStyle* aFontStyle);
|
||||
virtual ~gfxFT2Font();
|
||||
|
||||
|
@ -73,7 +74,7 @@ class gfxFT2Font : public gfxFT2FontBase {
|
|||
CharGlyphMapEntryType;
|
||||
typedef nsTHashtable<CharGlyphMapEntryType> CharGlyphMap;
|
||||
CharGlyphMap mCharGlyphCache;
|
||||
FT_Face mFTFace;
|
||||
RefPtr<mozilla::gfx::SharedFTFace> mFTFace;
|
||||
};
|
||||
|
||||
#endif /* GFX_FT2FONTS_H */
|
||||
|
|
|
@ -93,8 +93,6 @@ static const char* ToCharPtr(const FcChar8* aStr) {
|
|||
|
||||
FT_Library gfxFcPlatformFontList::sCairoFTLibrary = nullptr;
|
||||
|
||||
static cairo_user_data_key_t sFcFontlistUserFontDataKey;
|
||||
|
||||
// canonical name ==> first en name or first name if no en name
|
||||
// This is the required logic for fullname lookups as per CSS3 Fonts spec.
|
||||
static uint32_t FindCanonicalNameIndex(FcPattern* aFont,
|
||||
|
@ -251,13 +249,10 @@ gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsACString& aFaceName,
|
|||
bool aIgnoreFcCharmap)
|
||||
: gfxFontEntry(aFaceName),
|
||||
mFontPattern(aFontPattern),
|
||||
mFTFace(nullptr),
|
||||
mFTFaceInitialized(false),
|
||||
mIgnoreFcCharmap(aIgnoreFcCharmap),
|
||||
mHasVariationsInitialized(false),
|
||||
mAspect(0.0),
|
||||
mFontData(nullptr),
|
||||
mLength(0) {
|
||||
mAspect(0.0) {
|
||||
GetFontProperties(aFontPattern, &mWeightRange, &mStretchRange, &mStyleRange);
|
||||
}
|
||||
|
||||
|
@ -292,7 +287,8 @@ static FcPattern* CreatePatternForFace(FT_Face aFace) {
|
|||
return pattern;
|
||||
}
|
||||
|
||||
static FT_Face CreateFaceForPattern(FcPattern* aPattern) {
|
||||
static already_AddRefed<SharedFTFace> CreateFaceForPattern(
|
||||
FcPattern* aPattern) {
|
||||
FcChar8* filename;
|
||||
if (FcPatternGetString(aPattern, FC_FILE, 0, &filename) != FcResultMatch) {
|
||||
return nullptr;
|
||||
|
@ -301,31 +297,26 @@ static FT_Face CreateFaceForPattern(FcPattern* aPattern) {
|
|||
if (FcPatternGetInteger(aPattern, FC_INDEX, 0, &index) != FcResultMatch) {
|
||||
index = 0; // default to 0 if not found in pattern
|
||||
}
|
||||
return Factory::NewFTFace(nullptr, ToCharPtr(filename), index);
|
||||
return Factory::NewSharedFTFace(nullptr, ToCharPtr(filename), index);
|
||||
}
|
||||
|
||||
gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsACString& aFaceName,
|
||||
WeightRange aWeight,
|
||||
StretchRange aStretch,
|
||||
SlantStyleRange aStyle,
|
||||
const uint8_t* aData,
|
||||
uint32_t aLength, FT_Face aFace)
|
||||
RefPtr<SharedFTFace>&& aFace)
|
||||
: gfxFontEntry(aFaceName),
|
||||
mFTFace(aFace),
|
||||
mFTFace(std::move(aFace)),
|
||||
mFTFaceInitialized(true),
|
||||
mIgnoreFcCharmap(true),
|
||||
mHasVariationsInitialized(false),
|
||||
mAspect(0.0),
|
||||
mFontData(aData),
|
||||
mLength(aLength) {
|
||||
mAspect(0.0) {
|
||||
mWeightRange = aWeight;
|
||||
mStyleRange = aStyle;
|
||||
mStretchRange = aStretch;
|
||||
mIsDataUserFont = true;
|
||||
|
||||
mFontPattern = CreatePatternForFace(mFTFace);
|
||||
|
||||
mUserFontData = new FTUserFontData(mFTFace, mFontData);
|
||||
mFontPattern = CreatePatternForFace(mFTFace->GetFace());
|
||||
}
|
||||
|
||||
gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsACString& aFaceName,
|
||||
|
@ -335,12 +326,9 @@ gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsACString& aFaceName,
|
|||
SlantStyleRange aStyle)
|
||||
: gfxFontEntry(aFaceName),
|
||||
mFontPattern(aFontPattern),
|
||||
mFTFace(nullptr),
|
||||
mFTFaceInitialized(false),
|
||||
mHasVariationsInitialized(false),
|
||||
mAspect(0.0),
|
||||
mFontData(nullptr),
|
||||
mLength(0) {
|
||||
mAspect(0.0) {
|
||||
mWeightRange = aWeight;
|
||||
mStyleRange = aStyle;
|
||||
mStretchRange = aStretch;
|
||||
|
@ -388,7 +376,7 @@ gfxFontconfigFontEntry::~gfxFontconfigFontEntry() {
|
|||
// non-null here, so we don't need to do it again.
|
||||
if (sDoneVar) {
|
||||
MOZ_ASSERT(mFTFace, "How did mMMVar get set without a face?");
|
||||
(*sDoneVar)(mFTFace->glyph->library, mMMVar);
|
||||
(*sDoneVar)(mFTFace->GetFace()->glyph->library, mMMVar);
|
||||
} else {
|
||||
free(mMMVar);
|
||||
}
|
||||
|
@ -481,44 +469,17 @@ bool gfxFontconfigFontEntry::TestCharacterMap(uint32_t aCh) {
|
|||
|
||||
hb_blob_t* gfxFontconfigFontEntry::GetFontTable(uint32_t aTableTag) {
|
||||
// for data fonts, read directly from the font data
|
||||
if (mFontData) {
|
||||
return gfxFontUtils::GetTableFromFontData(mFontData, aTableTag);
|
||||
if (FTUserFontData* ufd = GetUserFontData()) {
|
||||
return gfxFontUtils::GetTableFromFontData(ufd->FontData(), aTableTag);
|
||||
}
|
||||
|
||||
return gfxFontEntry::GetFontTable(aTableTag);
|
||||
}
|
||||
|
||||
void gfxFontconfigFontEntry::MaybeReleaseFTFace() {
|
||||
// don't release if either HB or Gr face still exists
|
||||
if (mHBFace || mGrFace) {
|
||||
return;
|
||||
}
|
||||
// only close out FT_Face for system fonts, not for data fonts
|
||||
if (!mIsDataUserFont) {
|
||||
if (mFTFace) {
|
||||
if (mMMVar) {
|
||||
if (sDoneVar) {
|
||||
(*sDoneVar)(mFTFace->glyph->library, mMMVar);
|
||||
} else {
|
||||
free(mMMVar);
|
||||
}
|
||||
mMMVar = nullptr;
|
||||
}
|
||||
Factory::ReleaseFTFace(mFTFace);
|
||||
mFTFace = nullptr;
|
||||
}
|
||||
mFTFaceInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
void gfxFontconfigFontEntry::ForgetHBFace() {
|
||||
gfxFontEntry::ForgetHBFace();
|
||||
MaybeReleaseFTFace();
|
||||
}
|
||||
void gfxFontconfigFontEntry::ForgetHBFace() { gfxFontEntry::ForgetHBFace(); }
|
||||
|
||||
void gfxFontconfigFontEntry::ReleaseGrFace(gr_face* aFace) {
|
||||
gfxFontEntry::ReleaseGrFace(aFace);
|
||||
MaybeReleaseFTFace();
|
||||
}
|
||||
|
||||
double gfxFontconfigFontEntry::GetAspect() {
|
||||
|
@ -567,9 +528,14 @@ double gfxFontconfigFontEntry::GetAspect() {
|
|||
}
|
||||
|
||||
static void PrepareFontOptions(FcPattern* aPattern,
|
||||
cairo_font_options_t* aFontOptions) {
|
||||
cairo_font_options_t* aFontOptions,
|
||||
int* aOutLoadFlags,
|
||||
unsigned int* aOutSynthFlags) {
|
||||
NS_ASSERTION(aFontOptions, "null font options passed to PrepareFontOptions");
|
||||
|
||||
int loadFlags = FT_LOAD_DEFAULT;
|
||||
unsigned int synthFlags = 0;
|
||||
|
||||
// xxx - taken from the gfxFontconfigFonts code, needs to be reviewed
|
||||
|
||||
FcBool printing;
|
||||
|
@ -718,21 +684,63 @@ static void PrepareFontOptions(FcPattern* aPattern,
|
|||
antialias = CAIRO_ANTIALIAS_SUBPIXEL;
|
||||
}
|
||||
cairo_font_options_set_antialias(aFontOptions, antialias);
|
||||
}
|
||||
|
||||
static void ReleaseFTUserFontData(void* aData) {
|
||||
static_cast<FTUserFontData*>(aData)->Release();
|
||||
}
|
||||
FcBool bitmap;
|
||||
if (FcPatternGetBool(aPattern, FC_EMBEDDED_BITMAP, 0, &bitmap) !=
|
||||
FcResultMatch) {
|
||||
bitmap = FcFalse;
|
||||
}
|
||||
if (fc_antialias && (hint_style == CAIRO_HINT_STYLE_NONE || !bitmap)) {
|
||||
loadFlags |= FT_LOAD_NO_BITMAP;
|
||||
}
|
||||
|
||||
static cairo_user_data_key_t sFcFontlistFTFaceKey;
|
||||
int fc_lcd_filter;
|
||||
if (FcPatternGetInteger(aPattern, FC_LCD_FILTER, 0, &fc_lcd_filter) ==
|
||||
FcResultMatch) {
|
||||
cairo_lcd_filter_t lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
|
||||
switch (fc_lcd_filter) {
|
||||
case FC_LCD_NONE:
|
||||
lcd_filter = CAIRO_LCD_FILTER_NONE;
|
||||
break;
|
||||
case FC_LCD_DEFAULT:
|
||||
lcd_filter = CAIRO_LCD_FILTER_FIR5;
|
||||
break;
|
||||
case FC_LCD_LIGHT:
|
||||
lcd_filter = CAIRO_LCD_FILTER_FIR3;
|
||||
break;
|
||||
case FC_LCD_LEGACY:
|
||||
lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
|
||||
break;
|
||||
}
|
||||
cairo_font_options_set_lcd_filter(aFontOptions, lcd_filter);
|
||||
}
|
||||
|
||||
static void ReleaseFTFace(void* aData) {
|
||||
Factory::ReleaseFTFace(static_cast<FT_Face>(aData));
|
||||
FcBool autohint;
|
||||
if (FcPatternGetBool(aPattern, FC_AUTOHINT, 0, &autohint) == FcResultMatch &&
|
||||
autohint) {
|
||||
loadFlags |= FT_LOAD_FORCE_AUTOHINT;
|
||||
}
|
||||
|
||||
FcBool vertical;
|
||||
if (FcPatternGetBool(aPattern, FC_VERTICAL_LAYOUT, 0, &vertical) ==
|
||||
FcResultMatch &&
|
||||
vertical) {
|
||||
loadFlags |= FT_LOAD_VERTICAL_LAYOUT;
|
||||
}
|
||||
|
||||
FcBool embolden;
|
||||
if (FcPatternGetBool(aPattern, FC_EMBOLDEN, 0, &embolden) == FcResultMatch &&
|
||||
embolden) {
|
||||
synthFlags |= CAIRO_FT_SYNTHESIZE_BOLD;
|
||||
}
|
||||
|
||||
*aOutLoadFlags = loadFlags;
|
||||
*aOutSynthFlags = synthFlags;
|
||||
}
|
||||
|
||||
cairo_scaled_font_t* gfxFontconfigFontEntry::CreateScaledFont(
|
||||
FcPattern* aRenderPattern, gfxFloat aAdjustedSize,
|
||||
const gfxFontStyle* aStyle, FT_Face aFTFace) {
|
||||
const gfxFontStyle* aStyle, RefPtr<SharedFTFace> aFTFace) {
|
||||
if (aStyle->NeedsSyntheticBold(this)) {
|
||||
FcPatternAddBool(aRenderPattern, FC_EMBOLDEN, FcTrue);
|
||||
}
|
||||
|
@ -748,45 +756,19 @@ cairo_scaled_font_t* gfxFontconfigFontEntry::CreateScaledFont(
|
|||
FcPatternAddBool(aRenderPattern, FC_EMBEDDED_BITMAP, FcFalse);
|
||||
}
|
||||
|
||||
AutoTArray<FT_Fixed, 8> coords;
|
||||
if (HasVariations()) {
|
||||
FT_Face ftFace = GetFTFace();
|
||||
if (ftFace) {
|
||||
AutoTArray<gfxFontVariation, 8> settings;
|
||||
GetVariationsForStyle(settings, *aStyle);
|
||||
gfxFT2FontBase::SetupVarCoords(GetMMVar(), settings, &coords);
|
||||
}
|
||||
if (HasVariations() && aFTFace != mFTFace) {
|
||||
AutoTArray<gfxFontVariation, 8> settings;
|
||||
GetVariationsForStyle(settings, *aStyle);
|
||||
gfxFT2FontBase::SetupVarCoords(GetMMVar(), settings, aFTFace->GetFace());
|
||||
}
|
||||
|
||||
cairo_font_face_t* face = cairo_ft_font_face_create_for_pattern(
|
||||
aRenderPattern, coords.Elements(), coords.Length());
|
||||
cairo_font_options_t* fontOptions = cairo_font_options_create();
|
||||
int loadFlags;
|
||||
unsigned int synthFlags;
|
||||
PrepareFontOptions(aRenderPattern, fontOptions, &loadFlags, &synthFlags);
|
||||
|
||||
if (aFTFace) {
|
||||
if (cairo_font_face_set_user_data(face, &sFcFontlistFTFaceKey, aFTFace,
|
||||
ReleaseFTFace) != CAIRO_STATUS_SUCCESS) {
|
||||
NS_WARNING("Failed binding FT_Face to Cairo font face");
|
||||
cairo_font_face_destroy(face);
|
||||
Factory::ReleaseFTFace(aFTFace);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (mFontData) {
|
||||
// for data fonts, add the face/data pointer to the cairo font face
|
||||
// so that it ges deleted whenever cairo decides
|
||||
NS_ASSERTION(mFTFace, "FT_Face is null when setting user data");
|
||||
NS_ASSERTION(mUserFontData,
|
||||
"user font data is null when setting user data");
|
||||
mUserFontData.get()->AddRef();
|
||||
if (cairo_font_face_set_user_data(face, &sFcFontlistUserFontDataKey,
|
||||
mUserFontData, ReleaseFTUserFontData) !=
|
||||
CAIRO_STATUS_SUCCESS) {
|
||||
NS_WARNING("Failed binding FTUserFontData to Cairo font face");
|
||||
mUserFontData.get()->Release();
|
||||
cairo_font_face_destroy(face);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
cairo_font_face_t* face = cairo_ft_font_face_create_for_ft_face(
|
||||
aFTFace->GetFace(), loadFlags, synthFlags, aFTFace.get());
|
||||
|
||||
cairo_scaled_font_t* scaledFont = nullptr;
|
||||
|
||||
|
@ -796,9 +778,6 @@ cairo_scaled_font_t* gfxFontconfigFontEntry::CreateScaledFont(
|
|||
cairo_matrix_init_scale(&sizeMatrix, aAdjustedSize, aAdjustedSize);
|
||||
cairo_matrix_init_identity(&identityMatrix);
|
||||
|
||||
cairo_font_options_t* fontOptions = cairo_font_options_create();
|
||||
PrepareFontOptions(aRenderPattern, fontOptions);
|
||||
|
||||
scaledFont =
|
||||
cairo_scaled_font_create(face, &sizeMatrix, &identityMatrix, fontOptions);
|
||||
cairo_font_options_destroy(fontOptions);
|
||||
|
@ -892,12 +871,11 @@ void gfxFontconfigFontEntry::UnscaledFontCache::MoveToFront(size_t aIndex) {
|
|||
}
|
||||
|
||||
already_AddRefed<UnscaledFontFontconfig>
|
||||
gfxFontconfigFontEntry::UnscaledFontCache::Lookup(const char* aFile,
|
||||
gfxFontconfigFontEntry::UnscaledFontCache::Lookup(const std::string& aFile,
|
||||
uint32_t aIndex) {
|
||||
for (size_t i = 0; i < kNumEntries; i++) {
|
||||
RefPtr<UnscaledFontFontconfig> entry(mUnscaledFonts[i]);
|
||||
if (entry && !strcmp(entry->GetFile(), aFile) &&
|
||||
entry->GetIndex() == aIndex) {
|
||||
if (entry && entry->GetFile() == aFile && entry->GetIndex() == aIndex) {
|
||||
MoveToFront(i);
|
||||
return entry.forget();
|
||||
}
|
||||
|
@ -941,11 +919,6 @@ static double ChooseFontSize(gfxFontconfigFontEntry* aEntry,
|
|||
|
||||
gfxFont* gfxFontconfigFontEntry::CreateFontInstance(
|
||||
const gfxFontStyle* aFontStyle) {
|
||||
FcPattern* fontPattern = mFontPattern;
|
||||
if (!fontPattern) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsAutoRef<FcPattern> pattern(FcPatternCreate());
|
||||
if (!pattern) {
|
||||
NS_WARNING("Failed to create Fontconfig pattern for font instance");
|
||||
|
@ -955,25 +928,25 @@ gfxFont* gfxFontconfigFontEntry::CreateFontInstance(
|
|||
double size = ChooseFontSize(this, *aFontStyle);
|
||||
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size);
|
||||
|
||||
FT_Face face = mFTFace;
|
||||
if (face && face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
|
||||
// For variation fonts, we create a new FT_Face and FcPattern here
|
||||
// so that variation coordinates from the style can be applied
|
||||
// without affecting other font instances created from the same
|
||||
// entry (font resource).
|
||||
if (mFontData) {
|
||||
RefPtr<SharedFTFace> face = GetFTFace();
|
||||
if (!face) {
|
||||
NS_WARNING("Failed to get FreeType face for pattern");
|
||||
return nullptr;
|
||||
}
|
||||
if (face->GetFace()->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
|
||||
// For variation fonts, we create a new FT_Face here so that
|
||||
// variation coordinates from the style can be applied without
|
||||
// affecting other font instances created from the same entry
|
||||
// (font resource).
|
||||
if (face->GetData()) {
|
||||
// For user fonts: create a new FT_Face from the font data, and then
|
||||
// make a pattern from that.
|
||||
face = Factory::NewFTFaceFromData(nullptr, mFontData, mLength, 0);
|
||||
fontPattern = CreatePatternForFace(face);
|
||||
face = face->GetData()->CloneFace();
|
||||
} else {
|
||||
// For system fonts: create a new FT_Face and store it in a copy of
|
||||
// the original mFontPattern.
|
||||
fontPattern = FcPatternDuplicate(mFontPattern);
|
||||
face = CreateFaceForPattern(fontPattern);
|
||||
if (face) {
|
||||
FcPatternAddFTFace(fontPattern, FC_FT_FACE, face);
|
||||
} else {
|
||||
face = CreateFaceForPattern(mFontPattern);
|
||||
if (!face) {
|
||||
// I don't think CreateFaceForPattern above should ever fail,
|
||||
// but just in case let's fall back here.
|
||||
face = mFTFace;
|
||||
|
@ -983,51 +956,47 @@ gfxFont* gfxFontconfigFontEntry::CreateFontInstance(
|
|||
|
||||
PreparePattern(pattern, aFontStyle->printerFont);
|
||||
nsAutoRef<FcPattern> renderPattern(
|
||||
FcFontRenderPrepare(nullptr, pattern, fontPattern));
|
||||
if (fontPattern != mFontPattern) {
|
||||
// Discard temporary pattern used for variation support
|
||||
FcPatternDestroy(fontPattern);
|
||||
}
|
||||
FcFontRenderPrepare(nullptr, pattern, mFontPattern));
|
||||
if (!renderPattern) {
|
||||
NS_WARNING("Failed to prepare Fontconfig pattern for font instance");
|
||||
if (face != mFTFace) {
|
||||
Factory::ReleaseFTFace(face);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cairo_scaled_font_t* scaledFont = CreateScaledFont(
|
||||
renderPattern, size, aFontStyle, face != mFTFace ? face : nullptr);
|
||||
cairo_scaled_font_t* scaledFont =
|
||||
CreateScaledFont(renderPattern, size, aFontStyle, face);
|
||||
|
||||
const FcChar8* file = ToFcChar8Ptr("");
|
||||
std::string file;
|
||||
int index = 0;
|
||||
if (!mFontData) {
|
||||
if (!face->GetData()) {
|
||||
const FcChar8* fcFile;
|
||||
if (FcPatternGetString(renderPattern, FC_FILE, 0,
|
||||
const_cast<FcChar8**>(&file)) != FcResultMatch ||
|
||||
const_cast<FcChar8**>(&fcFile)) != FcResultMatch ||
|
||||
FcPatternGetInteger(renderPattern, FC_INDEX, 0, &index) !=
|
||||
FcResultMatch) {
|
||||
NS_WARNING("No file in Fontconfig pattern for font instance");
|
||||
return nullptr;
|
||||
}
|
||||
file = ToCharPtr(fcFile);
|
||||
}
|
||||
|
||||
RefPtr<UnscaledFontFontconfig> unscaledFont =
|
||||
mUnscaledFontCache.Lookup(ToCharPtr(file), index);
|
||||
mUnscaledFontCache.Lookup(file, index);
|
||||
if (!unscaledFont) {
|
||||
unscaledFont = mFontData
|
||||
? new UnscaledFontFontconfig(mFTFace)
|
||||
: new UnscaledFontFontconfig(ToCharPtr(file), index);
|
||||
unscaledFont = mFTFace->GetData() ? new UnscaledFontFontconfig(mFTFace)
|
||||
: new UnscaledFontFontconfig(
|
||||
std::move(file), index, mFTFace);
|
||||
mUnscaledFontCache.Add(unscaledFont);
|
||||
}
|
||||
|
||||
gfxFont* newFont = new gfxFontconfigFont(
|
||||
unscaledFont, scaledFont, renderPattern, size, this, aFontStyle);
|
||||
gfxFont* newFont =
|
||||
new gfxFontconfigFont(unscaledFont, scaledFont, std::move(face),
|
||||
renderPattern, size, this, aFontStyle);
|
||||
cairo_scaled_font_destroy(scaledFont);
|
||||
|
||||
return newFont;
|
||||
}
|
||||
|
||||
FT_Face gfxFontconfigFontEntry::GetFTFace() {
|
||||
const RefPtr<SharedFTFace>& gfxFontconfigFontEntry::GetFTFace() {
|
||||
if (!mFTFaceInitialized) {
|
||||
mFTFaceInitialized = true;
|
||||
mFTFace = CreateFaceForPattern(mFontPattern);
|
||||
|
@ -1035,6 +1004,13 @@ FT_Face gfxFontconfigFontEntry::GetFTFace() {
|
|||
return mFTFace;
|
||||
}
|
||||
|
||||
FTUserFontData* gfxFontconfigFontEntry::GetUserFontData() {
|
||||
if (mFTFace && mFTFace->GetData()) {
|
||||
return static_cast<FTUserFontData*>(mFTFace->GetData());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool gfxFontconfigFontEntry::HasVariations() {
|
||||
if (mHasVariationsInitialized) {
|
||||
return mHasVariations;
|
||||
|
@ -1056,9 +1032,9 @@ bool gfxFontconfigFontEntry::HasVariations() {
|
|||
mHasVariations = true;
|
||||
}
|
||||
} else {
|
||||
FT_Face face = GetFTFace();
|
||||
if (face) {
|
||||
mHasVariations = face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS;
|
||||
if (GetFTFace()) {
|
||||
mHasVariations =
|
||||
mFTFace->GetFace()->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1074,11 +1050,10 @@ FT_MM_Var* gfxFontconfigFontEntry::GetMMVar() {
|
|||
if (!sGetVar) {
|
||||
return nullptr;
|
||||
}
|
||||
FT_Face face = GetFTFace();
|
||||
if (!face) {
|
||||
if (!GetFTFace()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (FT_Err_Ok != (*sGetVar)(face, &mMMVar)) {
|
||||
if (FT_Err_Ok != (*sGetVar)(mFTFace->GetFace(), &mMMVar)) {
|
||||
mMMVar = nullptr;
|
||||
}
|
||||
return mMMVar;
|
||||
|
@ -1105,20 +1080,20 @@ nsresult gfxFontconfigFontEntry::CopyFontTable(uint32_t aTableTag,
|
|||
NS_ASSERTION(!mIsDataUserFont,
|
||||
"data fonts should be reading tables directly from memory");
|
||||
|
||||
FT_Face face = GetFTFace();
|
||||
if (!face) {
|
||||
if (!GetFTFace()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
FT_ULong length = 0;
|
||||
if (FT_Load_Sfnt_Table(face, aTableTag, 0, nullptr, &length) != 0) {
|
||||
if (FT_Load_Sfnt_Table(mFTFace->GetFace(), aTableTag, 0, nullptr, &length) !=
|
||||
0) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
if (!aBuffer.SetLength(length, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
if (FT_Load_Sfnt_Table(face, aTableTag, 0, aBuffer.Elements(), &length) !=
|
||||
0) {
|
||||
if (FT_Load_Sfnt_Table(mFTFace->GetFace(), aTableTag, 0, aBuffer.Elements(),
|
||||
&length) != 0) {
|
||||
aBuffer.Clear();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -1370,10 +1345,11 @@ void gfxFontconfigFontFamily::AddFacesToFontList(Func aAddPatternFunc) {
|
|||
|
||||
gfxFontconfigFont::gfxFontconfigFont(
|
||||
const RefPtr<UnscaledFontFontconfig>& aUnscaledFont,
|
||||
cairo_scaled_font_t* aScaledFont, FcPattern* aPattern,
|
||||
gfxFloat aAdjustedSize, gfxFontEntry* aFontEntry,
|
||||
cairo_scaled_font_t* aScaledFont, RefPtr<SharedFTFace>&& aFTFace,
|
||||
FcPattern* aPattern, gfxFloat aAdjustedSize, gfxFontEntry* aFontEntry,
|
||||
const gfxFontStyle* aFontStyle)
|
||||
: gfxFT2FontBase(aUnscaledFont, aScaledFont, aFontEntry, aFontStyle),
|
||||
mFTFace(std::move(aFTFace)),
|
||||
mPattern(aPattern) {
|
||||
mAdjustedSize = aAdjustedSize;
|
||||
}
|
||||
|
@ -1383,12 +1359,9 @@ gfxFontconfigFont::~gfxFontconfigFont() {}
|
|||
already_AddRefed<ScaledFont> gfxFontconfigFont::GetScaledFont(
|
||||
mozilla::gfx::DrawTarget* aTarget) {
|
||||
if (!mAzureScaledFont) {
|
||||
NativeFont nativeFont;
|
||||
nativeFont.mType = NativeFontType::FONTCONFIG_PATTERN;
|
||||
nativeFont.mFont = GetPattern();
|
||||
|
||||
mAzureScaledFont = Factory::CreateScaledFontForNativeFont(
|
||||
nativeFont, GetUnscaledFont(), GetAdjustedSize(), GetCairoScaledFont());
|
||||
mAzureScaledFont = Factory::CreateScaledFontForFontconfigFont(
|
||||
GetUnscaledFont(), GetAdjustedSize(), GetCairoScaledFont(), mFTFace,
|
||||
GetPattern());
|
||||
InitializeScaledFont();
|
||||
}
|
||||
|
||||
|
@ -1984,21 +1957,14 @@ gfxFontEntry* gfxFcPlatformFontList::MakePlatformFont(
|
|||
const nsACString& aFontName, WeightRange aWeightForEntry,
|
||||
StretchRange aStretchForEntry, SlantStyleRange aStyleForEntry,
|
||||
const uint8_t* aFontData, uint32_t aLength) {
|
||||
FT_Face face = Factory::NewFTFaceFromData(nullptr, aFontData, aLength, 0);
|
||||
RefPtr<FTUserFontData> ufd = new FTUserFontData(aFontData, aLength);
|
||||
RefPtr<SharedFTFace> face = ufd->CloneFace();
|
||||
if (!face) {
|
||||
free((void*)aFontData);
|
||||
return nullptr;
|
||||
}
|
||||
if (FT_Err_Ok != FT_Select_Charmap(face, FT_ENCODING_UNICODE) &&
|
||||
FT_Err_Ok != FT_Select_Charmap(face, FT_ENCODING_MS_SYMBOL)) {
|
||||
Factory::ReleaseFTFace(face);
|
||||
free((void*)aFontData);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new gfxFontconfigFontEntry(aFontName, aWeightForEntry,
|
||||
aStretchForEntry, aStyleForEntry, aFontData,
|
||||
aLength, face);
|
||||
aStretchForEntry, aStyleForEntry,
|
||||
std::move(face));
|
||||
}
|
||||
|
||||
bool gfxFcPlatformFontList::FindAndAddFamilies(
|
||||
|
@ -2267,8 +2233,7 @@ FT_Library gfxFcPlatformFontList::GetFTLibrary() {
|
|||
|
||||
FcPattern* pat =
|
||||
FcPatternBuild(0, FC_FAMILY, FcTypeString, "serif", (char*)0);
|
||||
cairo_font_face_t* face =
|
||||
cairo_ft_font_face_create_for_pattern(pat, nullptr, 0);
|
||||
cairo_font_face_t* face = cairo_ft_font_face_create_for_pattern(pat);
|
||||
FcPatternDestroy(pat);
|
||||
|
||||
cairo_matrix_t identity;
|
||||
|
|
|
@ -47,34 +47,6 @@ class nsAutoRefTraits<FcConfig> : public nsPointerRefTraits<FcConfig> {
|
|||
static void AddRef(FcConfig* ptr) { FcConfigReference(ptr); }
|
||||
};
|
||||
|
||||
// Helper classes used for clearning out user font data when cairo 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 cairo font created from that font entry contains a
|
||||
// FTUserFontDataRef with a refptr to that same FTUserFontData object.
|
||||
|
||||
class FTUserFontData final {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FTUserFontData)
|
||||
|
||||
explicit FTUserFontData(FT_Face aFace, const uint8_t* aData)
|
||||
: mFace(aFace), mFontData(aData) {}
|
||||
|
||||
const uint8_t* FontData() const { return mFontData; }
|
||||
|
||||
private:
|
||||
~FTUserFontData() {
|
||||
mozilla::gfx::Factory::ReleaseFTFace(mFace);
|
||||
if (mFontData) {
|
||||
free((void*)mFontData);
|
||||
}
|
||||
}
|
||||
|
||||
FT_Face mFace;
|
||||
const uint8_t* mFontData;
|
||||
};
|
||||
|
||||
// The names for the font entry and font classes should really
|
||||
// the common 'Fc' abbreviation but the gfxPangoFontGroup code already
|
||||
// defines versions of these, so use the verbose name for now.
|
||||
|
@ -90,8 +62,8 @@ class gfxFontconfigFontEntry : public gfxFontEntry {
|
|||
// of the font data and the FT_Face
|
||||
explicit gfxFontconfigFontEntry(const nsACString& aFaceName,
|
||||
WeightRange aWeight, StretchRange aStretch,
|
||||
SlantStyleRange aStyle, const uint8_t* aData,
|
||||
uint32_t aLength, FT_Face aFace);
|
||||
SlantStyleRange aStyle,
|
||||
RefPtr<mozilla::gfx::SharedFTFace>&& aFace);
|
||||
|
||||
// used for @font-face local system fonts with explicit patterns
|
||||
explicit gfxFontconfigFontEntry(const nsACString& aFaceName,
|
||||
|
@ -106,7 +78,8 @@ class gfxFontconfigFontEntry : public gfxFontEntry {
|
|||
nsresult ReadCMAP(FontInfoData* aFontInfoData = nullptr) override;
|
||||
bool TestCharacterMap(uint32_t aCh) override;
|
||||
|
||||
FT_Face GetFTFace();
|
||||
const RefPtr<mozilla::gfx::SharedFTFace>& GetFTFace();
|
||||
FTUserFontData* GetUserFontData();
|
||||
|
||||
FT_MM_Var* GetMMVar() override;
|
||||
|
||||
|
@ -128,26 +101,19 @@ class gfxFontconfigFontEntry : public gfxFontEntry {
|
|||
gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle) override;
|
||||
|
||||
// helper method for creating cairo font from pattern
|
||||
cairo_scaled_font_t* CreateScaledFont(FcPattern* aRenderPattern,
|
||||
gfxFloat aAdjustedSize,
|
||||
const gfxFontStyle* aStyle,
|
||||
FT_Face aFTFace);
|
||||
cairo_scaled_font_t* CreateScaledFont(
|
||||
FcPattern* aRenderPattern, gfxFloat aAdjustedSize,
|
||||
const gfxFontStyle* aStyle, RefPtr<mozilla::gfx::SharedFTFace> aFTFace);
|
||||
|
||||
// override to pull data from FTFace
|
||||
virtual nsresult CopyFontTable(uint32_t aTableTag,
|
||||
nsTArray<uint8_t>& aBuffer) override;
|
||||
|
||||
// if HB or GR faces are gone, close down the FT_Face
|
||||
void MaybeReleaseFTFace();
|
||||
|
||||
// pattern for a single face of a family
|
||||
nsCountedRef<FcPattern> mFontPattern;
|
||||
|
||||
// user font data, when needed
|
||||
RefPtr<FTUserFontData> mUserFontData;
|
||||
|
||||
// FTFace - initialized when needed
|
||||
FT_Face mFTFace;
|
||||
RefPtr<mozilla::gfx::SharedFTFace> mFTFace;
|
||||
bool mFTFaceInitialized;
|
||||
|
||||
// Whether TestCharacterMap should check the actual cmap rather than asking
|
||||
|
@ -166,14 +132,10 @@ class gfxFontconfigFontEntry : public gfxFontEntry {
|
|||
|
||||
double mAspect;
|
||||
|
||||
// data font
|
||||
const uint8_t* mFontData;
|
||||
uint32_t mLength;
|
||||
|
||||
class UnscaledFontCache {
|
||||
public:
|
||||
already_AddRefed<mozilla::gfx::UnscaledFontFontconfig> Lookup(
|
||||
const char* aFile, uint32_t aIndex);
|
||||
const std::string& aFile, uint32_t aIndex);
|
||||
|
||||
void Add(
|
||||
const RefPtr<mozilla::gfx::UnscaledFontFontconfig>& aUnscaledFont) {
|
||||
|
@ -244,7 +206,8 @@ class gfxFontconfigFont : public gfxFT2FontBase {
|
|||
public:
|
||||
gfxFontconfigFont(
|
||||
const RefPtr<mozilla::gfx::UnscaledFontFontconfig>& aUnscaledFont,
|
||||
cairo_scaled_font_t* aScaledFont, FcPattern* aPattern,
|
||||
cairo_scaled_font_t* aScaledFont,
|
||||
RefPtr<mozilla::gfx::SharedFTFace>&& aFTFace, FcPattern* aPattern,
|
||||
gfxFloat aAdjustedSize, gfxFontEntry* aFontEntry,
|
||||
const gfxFontStyle* aFontStyle);
|
||||
|
||||
|
@ -257,6 +220,7 @@ class gfxFontconfigFont : public gfxFT2FontBase {
|
|||
private:
|
||||
virtual ~gfxFontconfigFont();
|
||||
|
||||
RefPtr<mozilla::gfx::SharedFTFace> mFTFace;
|
||||
nsCountedRef<FcPattern> mPattern;
|
||||
};
|
||||
|
||||
|
|
|
@ -789,6 +789,10 @@ gfxFont::gfxFont(const RefPtr<UnscaledFont>& aUnscaledFont,
|
|||
++gFontCount;
|
||||
#endif
|
||||
|
||||
if (MOZ_UNLIKELY(StaticPrefs::gfx_text_disable_aa_AtStartup())) {
|
||||
mAntialiasOption = kAntialiasNone;
|
||||
}
|
||||
|
||||
// Turn off AA for Ahem for testing purposes when requested.
|
||||
if (MOZ_UNLIKELY(StaticPrefs::gfx_font_rendering_ahem_antialias_none() &&
|
||||
mFontEntry->FamilyName().EqualsLiteral("Ahem"))) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче