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:
Lee Salzman 2019-09-16 17:07:59 +00:00
Родитель 264178a181
Коммит 286a7bbfff
9 изменённых файлов: 358 добавлений и 522 удалений

Просмотреть файл

@ -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"))) {