bug 998844 - part 4 - support bundled fonts on desktop Linux. r=jdaggett

This commit is contained in:
Jonathan Kew 2014-05-29 13:01:03 +01:00
parent 995d8e9e8c
commit 715446ecd5
2 changed files with 164 additions and 84 deletions

View File

@ -16,6 +16,9 @@
#include "nsILanguageAtomService.h"
#include "nsTArray.h"
#include "mozilla/Preferences.h"
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsIAtom.h"
#include "nsCRT.h"
@ -314,6 +317,9 @@ gfxFontconfigUtils::gfxFontconfigUtils()
, mFontsByFullname(50)
, mLangSupportTable(50)
, mLastConfig(nullptr)
#ifdef MOZ_BUNDLED_FONTS
, mBundledFontsInitialized(false)
#endif
{
UpdateFontListInternal();
}
@ -579,8 +585,17 @@ gfxFontconfigUtils::UpdateFontListInternal(bool aForce)
if (currentConfig == mLastConfig)
return NS_OK;
// This FcFontSet is owned by fontconfig
FcFontSet *fontSet = FcConfigGetFonts(currentConfig, FcSetSystem);
#ifdef MOZ_BUNDLED_FONTS
ActivateBundledFonts();
#endif
// These FcFontSets are owned by fontconfig
FcFontSet *fontSets[] = {
FcConfigGetFonts(currentConfig, FcSetSystem)
#ifdef MOZ_BUNDLED_FONTS
, FcConfigGetFonts(currentConfig, FcSetApplication)
#endif
};
mFontsByFamily.Clear();
mFontsByFullname.Clear();
@ -588,29 +603,35 @@ gfxFontconfigUtils::UpdateFontListInternal(bool aForce)
mAliasForMultiFonts.Clear();
// Record the existing font families
for (int f = 0; f < fontSet->nfont; ++f) {
FcPattern *font = fontSet->fonts[f];
for (unsigned fs = 0; fs < ArrayLength(fontSets); ++fs) {
FcFontSet *fontSet = fontSets[fs];
if (!fontSet) { // the application set might not exist
continue;
}
for (int f = 0; f < fontSet->nfont; ++f) {
FcPattern *font = fontSet->fonts[f];
FcChar8 *family;
for (int v = 0;
FcPatternGetString(font, FC_FAMILY, v, &family) == FcResultMatch;
++v) {
FontsByFcStrEntry *entry = mFontsByFamily.PutEntry(family);
if (entry) {
bool added = entry->AddFont(font);
FcChar8 *family;
for (int v = 0;
FcPatternGetString(font, FC_FAMILY, v, &family) == FcResultMatch;
++v) {
FontsByFcStrEntry *entry = mFontsByFamily.PutEntry(family);
if (entry) {
bool added = entry->AddFont(font);
if (!entry->mKey) {
// The reference to the font pattern keeps the pointer to
// string for the key valid. If adding the font failed
// then the entry must be removed.
if (added) {
entry->mKey = family;
} else {
mFontsByFamily.RawRemoveEntry(entry);
}
}
}
}
if (!entry->mKey) {
// The reference to the font pattern keeps the pointer to
// string for the key valid. If adding the font failed
// then the entry must be removed.
if (added) {
entry->mKey = family;
} else {
mFontsByFamily.RawRemoveEntry(entry);
}
}
}
}
}
}
// XXX we don't support all alias names.
@ -851,51 +872,62 @@ gfxFontconfigUtils::FontsByFullnameEntry::KeyEquals(KeyTypePointer aKey) const
void
gfxFontconfigUtils::AddFullnameEntries()
{
// This FcFontSet is owned by fontconfig
FcFontSet *fontSet = FcConfigGetFonts(nullptr, FcSetSystem);
// These FcFontSets are owned by fontconfig
FcFontSet *fontSets[] = {
FcConfigGetFonts(nullptr, FcSetSystem)
#ifdef MOZ_BUNDLED_FONTS
, FcConfigGetFonts(nullptr, FcSetApplication)
#endif
};
// Record the existing font families
for (int f = 0; f < fontSet->nfont; ++f) {
FcPattern *font = fontSet->fonts[f];
for (unsigned fs = 0; fs < ArrayLength(fontSets); ++fs) {
FcFontSet *fontSet = fontSets[fs];
if (!fontSet) {
continue;
}
// Record the existing font families
for (int f = 0; f < fontSet->nfont; ++f) {
FcPattern *font = fontSet->fonts[f];
int v = 0;
FcChar8 *fullname;
while (FcPatternGetString(font,
FC_FULLNAME, v, &fullname) == FcResultMatch) {
FontsByFullnameEntry *entry = mFontsByFullname.PutEntry(fullname);
if (entry) {
// entry always has space for one font, so the first AddFont
// will always succeed, and so the entry will always have a
// font from which to obtain the key.
bool added = entry->AddFont(font);
// The key may be nullptr either if this is the first font, or
// if the first font does not have a fullname property, and so
// the key is obtained from the font. Set the key in both
// cases. The check that AddFont succeeded is required for
// the second case.
if (!entry->mKey && added) {
entry->mKey = fullname;
}
}
int v = 0;
FcChar8 *fullname;
while (FcPatternGetString(font,
FC_FULLNAME, v, &fullname) == FcResultMatch) {
FontsByFullnameEntry *entry = mFontsByFullname.PutEntry(fullname);
if (entry) {
// entry always has space for one font, so the first AddFont
// will always succeed, and so the entry will always have a
// font from which to obtain the key.
bool added = entry->AddFont(font);
// The key may be nullptr either if this is the first font, or
// if the first font does not have a fullname property, and so
// the key is obtained from the font. Set the key in both
// cases. The check that AddFont succeeded is required for
// the second case.
if (!entry->mKey && added) {
entry->mKey = fullname;
}
}
++v;
}
++v;
}
// Fontconfig does not provide a fullname property for all fonts.
if (v == 0) {
nsAutoCString name;
if (!GetFullnameFromFamilyAndStyle(font, &name))
continue;
// Fontconfig does not provide a fullname property for all fonts.
if (v == 0) {
nsAutoCString name;
if (!GetFullnameFromFamilyAndStyle(font, &name))
continue;
FontsByFullnameEntry *entry =
mFontsByFullname.PutEntry(ToFcChar8(name));
if (entry) {
entry->AddFont(font);
// Either entry->mKey has been set for a previous font or it
// remains nullptr to indicate that the key is obtained from
// the first font.
}
}
FontsByFullnameEntry *entry =
mFontsByFullname.PutEntry(ToFcChar8(name));
if (entry) {
entry->AddFont(font);
// Either entry->mKey has been set for a previous font or it
// remains nullptr to indicate that the key is obtained from
// the first font.
}
}
}
}
}
@ -1009,33 +1041,44 @@ gfxFontconfigUtils::GetLangSupportEntry(const FcChar8 *aLang, bool aWithFonts)
return entry;
}
// This FcFontSet is owned by fontconfig
FcFontSet *fontSet = FcConfigGetFonts(nullptr, FcSetSystem);
// These FcFontSets are owned by fontconfig
FcFontSet *fontSets[] = {
FcConfigGetFonts(nullptr, FcSetSystem)
#ifdef MOZ_BUNDLED_FONTS
, FcConfigGetFonts(nullptr, FcSetApplication)
#endif
};
nsAutoTArray<FcPattern*,100> fonts;
for (int f = 0; f < fontSet->nfont; ++f) {
FcPattern *font = fontSet->fonts[f];
for (unsigned fs = 0; fs < ArrayLength(fontSets); ++fs) {
FcFontSet *fontSet = fontSets[fs];
if (!fontSet) {
continue;
}
for (int f = 0; f < fontSet->nfont; ++f) {
FcPattern *font = fontSet->fonts[f];
FcLangResult support = GetLangSupport(font, aLang);
FcLangResult support = GetLangSupport(font, aLang);
if (support < best) { // lower is better
best = support;
if (aWithFonts) {
fonts.Clear();
} else if (best == FcLangEqual) {
break;
}
}
if (support < best) { // lower is better
best = support;
if (aWithFonts) {
fonts.Clear();
} else if (best == FcLangEqual) {
break;
}
}
// The font list in the LangSupportEntry is expected to be used only
// when no default fonts support the language. There would be a large
// number of fonts in entries for languages using Latin script but
// these do not need to be created because default fonts already
// support these languages.
if (aWithFonts && support != FcLangDifferentLang && support == best) {
fonts.AppendElement(font);
}
// The font list in the LangSupportEntry is expected to be used only
// when no default fonts support the language. There would be a large
// number of fonts in entries for languages using Latin script but
// these do not need to be created because default fonts already
// support these languages.
if (aWithFonts && support != FcLangDifferentLang && support == best) {
fonts.AppendElement(font);
}
}
}
entry->mSupport = best;
@ -1078,3 +1121,33 @@ gfxFontconfigUtils::GetFontsForLang(const FcChar8 *aLang)
return entry->mFonts;
}
#ifdef MOZ_BUNDLED_FONTS
void
gfxFontconfigUtils::ActivateBundledFonts()
{
if (!mBundledFontsInitialized) {
mBundledFontsInitialized = true;
nsCOMPtr<nsIFile> localDir;
nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(localDir));
if (NS_FAILED(rv)) {
return;
}
if (NS_FAILED(localDir->Append(NS_LITERAL_STRING("fonts")))) {
return;
}
bool isDir;
if (NS_FAILED(localDir->IsDirectory(&isDir)) || !isDir) {
return;
}
if (NS_FAILED(localDir->GetNativePath(mBundledFontsPath))) {
return;
}
}
if (!mBundledFontsPath.IsEmpty()) {
FcConfigAppFontAddDir(nullptr, (const FcChar8*)mBundledFontsPath.get());
}
}
#endif

View File

@ -309,6 +309,13 @@ protected:
nsTArray<nsCString> mAliasForMultiFonts;
FcConfig *mLastConfig;
#ifdef MOZ_BUNDLED_FONTS
void ActivateBundledFonts();
nsCString mBundledFontsPath;
bool mBundledFontsInitialized;
#endif
};
#endif /* GFX_FONTCONFIG_UTILS_H */