Bug 1432552 - patch 2 - Linux font back-end implementation of getVariationInstances. r=dholbert

This commit is contained in:
Jonathan Kew 2018-01-29 13:24:11 +00:00
parent 9de316c207
commit c70ab6cef4
2 changed files with 103 additions and 25 deletions

View File

@ -360,8 +360,37 @@ gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName,
mIgnoreFcCharmap = true;
}
typedef FT_Error (*GetVarFunc)(FT_Face, FT_MM_Var**);
typedef FT_Error (*DoneVarFunc)(FT_Library, FT_MM_Var*);
static GetVarFunc sGetVar;
static DoneVarFunc sDoneVar;
static bool sInitializedVarFuncs = false;
static void
InitializeVarFuncs()
{
if (sInitializedVarFuncs) {
return;
}
sInitializedVarFuncs = true;
sGetVar = (GetVarFunc)dlsym(RTLD_DEFAULT, "FT_Get_MM_Var");
sDoneVar = (DoneVarFunc)dlsym(RTLD_DEFAULT, "FT_Done_MM_Var");
}
gfxFontconfigFontEntry::~gfxFontconfigFontEntry()
{
if (mMMVar) {
// Prior to freetype 2.9, there was no specific function to free the
// FT_MM_Var record, and the docs just said to use free().
// InitializeVarFuncs must have been called in order for mMMVar to be
// 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);
} else {
free(mMMVar);
}
}
}
nsresult
@ -469,6 +498,14 @@ gfxFontconfigFontEntry::MaybeReleaseFTFace()
// 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;
}
@ -1017,31 +1054,36 @@ gfxFontconfigFontEntry::HasVariations()
return false;
}
FT_MM_Var*
gfxFontconfigFontEntry::GetMMVar()
{
if (mMMVarInitialized) {
return mMMVar;
}
mMMVarInitialized = true;
InitializeVarFuncs();
if (!sGetVar) {
return nullptr;
}
FT_Face face = GetFTFace();
if (!face) {
return nullptr;
}
if (FT_Err_Ok != (*sGetVar)(face, &mMMVar)) {
mMMVar = nullptr;
}
return mMMVar;
}
void
gfxFontconfigFontEntry::GetVariationAxes(nsTArray<gfxFontVariationAxis>& aAxes)
{
MOZ_ASSERT(aAxes.IsEmpty());
FT_Face face = GetFTFace();
if (!face) {
return;
}
typedef FT_Error (*GetVarFunc)(FT_Face, FT_MM_Var**);
static GetVarFunc getVar;
typedef FT_Error (*DoneVarFunc)(FT_Library, FT_MM_Var*);
static DoneVarFunc doneVar;
static bool firstTime = true;
if (firstTime) {
firstTime = false;
getVar = (GetVarFunc)dlsym(RTLD_DEFAULT, "FT_Get_MM_Var");
doneVar = (DoneVarFunc)dlsym(RTLD_DEFAULT, "FT_Done_MM_Var");
}
if (!getVar) {
return;
}
FT_MM_Var* mmVar;
if (FT_Err_Ok != (*getVar)(face, &mmVar)) {
FT_MM_Var* mmVar = GetMMVar();
if (!mmVar) {
return;
}
aAxes.SetCapacity(mmVar->num_axis);
for (unsigned i = 0; i < mmVar->num_axis; i++) {
const auto& a = mmVar->axis[i];
gfxFontVariationAxis axis;
@ -1052,13 +1094,40 @@ gfxFontconfigFontEntry::GetVariationAxes(nsTArray<gfxFontVariationAxis>& aAxes)
axis.mName.Assign(NS_ConvertUTF8toUTF16(a.name));
aAxes.AppendElement(axis);
}
// Prior to freetype 2.9, there was no specific function to free the FT_MM_Var,
// and the docs just said to use free().
if (doneVar) {
(*doneVar)(face->glyph->library, mmVar);
} else {
free(mmVar);
}
void
gfxFontconfigFontEntry::GetVariationInstances(
nsTArray<gfxFontVariationInstance>& aInstances)
{
MOZ_ASSERT(aInstances.IsEmpty());
FT_MM_Var* mmVar = GetMMVar();
if (!mmVar) {
return;
}
hb_blob_t* nameTable = GetFontTable(TRUETYPE_TAG('n','a','m','e'));
if (!nameTable) {
return;
}
aInstances.SetCapacity(mmVar->num_namedstyles);
for (unsigned i = 0; i < mmVar->num_namedstyles; i++) {
const auto& ns = mmVar->namedstyle[i];
gfxFontVariationInstance inst;
nsresult rv =
gfxFontUtils::ReadCanonicalName(nameTable, ns.strid, inst.mName);
if (NS_FAILED(rv)) {
continue;
}
inst.mValues.SetCapacity(mmVar->num_axis);
for (unsigned j = 0; j < mmVar->num_axis; j++) {
gfxFontVariationValue value;
value.mAxis = mmVar->axis[j].tag;
value.mValue = ns.coords[j] / 65536.0;
inst.mValues.AppendElement(value);
}
aInstances.AppendElement(inst);
}
hb_blob_destroy(nameTable);
}
nsresult

View File

@ -18,6 +18,7 @@
#include "ft2build.h"
#include FT_FREETYPE_H
#include FT_TRUETYPE_TABLES_H
#include FT_MULTIPLE_MASTERS_H
#include <cairo.h>
#include <cairo-ft.h>
@ -115,8 +116,11 @@ public:
FT_Face GetFTFace();
FT_MM_Var* GetMMVar();
bool HasVariations() override;
void GetVariationAxes(nsTArray<gfxFontVariationAxis>& aAxes) override;
void GetVariationInstances(nsTArray<gfxFontVariationInstance>& aInstances) override;
hb_blob_t* GetFontTable(uint32_t aTableTag) override;
@ -188,6 +192,11 @@ protected:
};
UnscaledFontCache mUnscaledFontCache;
// Because of FreeType bug 52955, we keep the FT_MM_Var struct when it is
// first loaded, rather than releasing it and re-fetching it as needed.
FT_MM_Var* mMMVar = nullptr;
bool mMMVarInitialized = false;
};
class gfxFontconfigFontFamily : public gfxFontFamily {