зеркало из https://github.com/mozilla/gecko-dev.git
b=468218 @font-face { src:local() } for GTK/Pango r=roc
This commit is contained in:
Родитель
4dfe0343f6
Коммит
911b1cef22
|
@ -82,6 +82,9 @@ public:
|
|||
|
||||
static void Shutdown();
|
||||
|
||||
// Used for @font-face { src: local(); }
|
||||
static gfxFontEntry *NewFontEntry(const gfxProxyFontEntry &aProxyEntry,
|
||||
const nsAString &aFullname);
|
||||
// Used for @font-face { src: url(); }
|
||||
static gfxFontEntry *NewFontEntry(const gfxProxyFontEntry &aProxyEntry,
|
||||
nsISupports *aLoader,
|
||||
|
|
|
@ -198,7 +198,9 @@ public:
|
|||
* Ownership of the returned gfxFontEntry is passed to the caller,
|
||||
* who must either AddRef() or delete.
|
||||
*/
|
||||
virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName) { return nsnull; }
|
||||
virtual gfxFontEntry* LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFontName)
|
||||
{ return nsnull; }
|
||||
|
||||
/**
|
||||
* Activate a platform font. (Needed to support @font-face src url().)
|
||||
|
|
|
@ -89,6 +89,13 @@ public:
|
|||
gfxUserFontSet *aUserFontSet);
|
||||
|
||||
#ifdef MOZ_PANGO
|
||||
/**
|
||||
* Look up a local platform font using the full font face name (needed to
|
||||
* support @font-face src local() )
|
||||
*/
|
||||
virtual gfxFontEntry* LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFontName);
|
||||
|
||||
/**
|
||||
* Activate a platform font (needed to support @font-face src url() )
|
||||
*
|
||||
|
|
|
@ -69,7 +69,8 @@ public:
|
|||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet);
|
||||
|
||||
gfxFontEntry* LookupLocalFont(const nsAString& aFontName);
|
||||
virtual gfxFontEntry* LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFontName);
|
||||
|
||||
virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
nsISupports *aLoader,
|
||||
|
|
|
@ -81,7 +81,8 @@ public:
|
|||
/**
|
||||
* Look up a local platform font using the full font face name (needed to support @font-face src local() )
|
||||
*/
|
||||
virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName);
|
||||
virtual gfxFontEntry* LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFontName);
|
||||
|
||||
/**
|
||||
* Activate a platform font (needed to support @font-face src url() )
|
||||
|
|
|
@ -265,6 +265,7 @@ gfxFontconfigUtils::gfxFontconfigUtils()
|
|||
: mLastConfig(NULL)
|
||||
{
|
||||
mFontsByFamily.Init(50);
|
||||
mFontsByFullname.Init(50);
|
||||
mLangSupportTable.Init(20);
|
||||
UpdateFontListInternal();
|
||||
}
|
||||
|
@ -537,6 +538,7 @@ gfxFontconfigUtils::UpdateFontListInternal(PRBool aForce)
|
|||
FcFontSet *fontSet = FcConfigGetFonts(currentConfig, FcSetSystem);
|
||||
|
||||
mFontsByFamily.Clear();
|
||||
mFontsByFullname.Clear();
|
||||
mLangSupportTable.Clear();
|
||||
mAliasForMultiFonts.Clear();
|
||||
|
||||
|
@ -753,7 +755,7 @@ gfxFontconfigUtils::ResolveFontName(const nsAString& aFontName,
|
|||
PRBool
|
||||
gfxFontconfigUtils::IsExistingFamily(const nsCString& aFamilyName)
|
||||
{
|
||||
return mFontsByFamily.GetEntry(ToFcChar8(aFamilyName.get())) != nsnull;
|
||||
return mFontsByFamily.GetEntry(ToFcChar8(aFamilyName)) != nsnull;
|
||||
}
|
||||
|
||||
const nsTArray< nsCountedRef<FcPattern> >&
|
||||
|
@ -767,6 +769,114 @@ gfxFontconfigUtils::GetFontsForFamily(const FcChar8 *aFamilyName)
|
|||
return entry->GetFonts();
|
||||
}
|
||||
|
||||
// Fontconfig only provides a fullname property for fonts in formats with SFNT
|
||||
// wrappers. For other font formats (including PCF and PS Type 1), a fullname
|
||||
// must be generated from the family and style properties. Only the first
|
||||
// family and style is checked, but that should be OK, as I don't expect
|
||||
// non-SFNT fonts to have multiple families or styles.
|
||||
PRBool
|
||||
gfxFontconfigUtils::GetFullnameFromFamilyAndStyle(FcPattern *aFont,
|
||||
nsACString *aFullname)
|
||||
{
|
||||
FcChar8 *family;
|
||||
if (FcPatternGetString(aFont, FC_FAMILY, 0, &family) != FcResultMatch)
|
||||
return PR_FALSE;
|
||||
|
||||
aFullname->Truncate();
|
||||
aFullname->Append(ToCString(family));
|
||||
|
||||
FcChar8 *style;
|
||||
if (FcPatternGetString(aFont, FC_STYLE, 0, &style) == FcResultMatch &&
|
||||
strcmp(ToCString(style), "Regular") != 0) {
|
||||
aFullname->Append(' ');
|
||||
aFullname->Append(ToCString(style));
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
gfxFontconfigUtils::FontsByFullnameEntry::KeyEquals(KeyTypePointer aKey) const
|
||||
{
|
||||
const FcChar8 *key = mKey;
|
||||
// If mKey is NULL, key comes from the style and family of the first font.
|
||||
nsCAutoString fullname;
|
||||
if (!key) {
|
||||
NS_ASSERTION(mFonts.Length(), "No font in FontsByFullnameEntry!");
|
||||
GetFullnameFromFamilyAndStyle(mFonts[0], &fullname);
|
||||
|
||||
key = ToFcChar8(fullname);
|
||||
}
|
||||
|
||||
return FcStrCmpIgnoreCase(aKey, key) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontconfigUtils::AddFullnameEntries()
|
||||
{
|
||||
// This FcFontSet is owned by fontconfig
|
||||
FcFontSet *fontSet = FcConfigGetFonts(NULL, FcSetSystem);
|
||||
|
||||
// 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.
|
||||
PRBool added = entry->AddFont(font);
|
||||
// The key may be NULL 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;
|
||||
}
|
||||
|
||||
// Fontconfig does not provide a fullname property for all fonts.
|
||||
if (v == 0) {
|
||||
nsCAutoString 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 NULL to indicate that the key is obtained from the
|
||||
// first font.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const nsTArray< nsCountedRef<FcPattern> >&
|
||||
gfxFontconfigUtils::GetFontsForFullname(const FcChar8 *aFullname)
|
||||
{
|
||||
if (mFontsByFullname.Count() == 0) {
|
||||
AddFullnameEntries();
|
||||
}
|
||||
|
||||
FontsByFullnameEntry *entry = mFontsByFullname.GetEntry(aFullname);
|
||||
|
||||
if (!entry)
|
||||
return mEmptyPatternArray;
|
||||
|
||||
return entry->GetFonts();
|
||||
}
|
||||
|
||||
static FcLangResult
|
||||
CompareLangString(const FcChar8 *aLangA, const FcChar8 *aLangB) {
|
||||
FcLangResult result = FcLangDifferentLang;
|
||||
|
|
|
@ -105,6 +105,9 @@ public:
|
|||
const nsTArray< nsCountedRef<FcPattern> >&
|
||||
GetFontsForFamily(const FcChar8 *aFamilyName);
|
||||
|
||||
const nsTArray< nsCountedRef<FcPattern> >&
|
||||
GetFontsForFullname(const FcChar8 *aFullname);
|
||||
|
||||
// Returns the best support that any font offers for |aLang|.
|
||||
FcLangResult GetBestLangSupport(const FcChar8 *aLang);
|
||||
// Returns the fonts offering this best level of support.
|
||||
|
@ -120,6 +123,10 @@ public:
|
|||
{
|
||||
return reinterpret_cast<const FcChar8*>(aCharPtr);
|
||||
}
|
||||
static const FcChar8 *ToFcChar8(const nsCString& aCString)
|
||||
{
|
||||
return ToFcChar8(aCString.get());
|
||||
}
|
||||
static const char *ToCString(const FcChar8 *aChar8Ptr)
|
||||
{
|
||||
return reinterpret_cast<const char*>(aChar8Ptr);
|
||||
|
@ -133,6 +140,9 @@ public:
|
|||
// Returns a precise FC_WEIGHT from CSS weight |aBaseWeight|.
|
||||
static int FcWeightForBaseWeight(PRInt8 aBaseWeight);
|
||||
|
||||
static PRBool GetFullnameFromFamilyAndStyle(FcPattern *aFont,
|
||||
nsACString *aFullname);
|
||||
|
||||
// This doesn't consider which faces exist, and so initializes the pattern
|
||||
// using a guessed weight, and doesn't consider sizeAdjust.
|
||||
static nsReturnRef<FcPattern>
|
||||
|
@ -185,7 +195,7 @@ public:
|
|||
class DepFcStrEntry : public FcStrEntryBase {
|
||||
public:
|
||||
// When constructing a new entry in the hashtable, the key is left
|
||||
// blank. The caller of PutEntry() must fill in mKey when NULL. This
|
||||
// NULL. The caller of PutEntry() must fill in mKey when NULL. This
|
||||
// provides a mechanism for the caller of PutEntry() to determine
|
||||
// whether the entry has been initialized.
|
||||
DepFcStrEntry(KeyTypePointer aName)
|
||||
|
@ -218,7 +228,7 @@ public:
|
|||
: mKey(toCopy.mKey) { }
|
||||
|
||||
PRBool KeyEquals(KeyTypePointer aKey) const {
|
||||
return FcStrCmpIgnoreCase(aKey, ToFcChar8(mKey.get())) == 0;
|
||||
return FcStrCmpIgnoreCase(aKey, ToFcChar8(mKey)) == 0;
|
||||
}
|
||||
|
||||
PRBool IsKeyInitialized() { return !mKey.IsVoid(); }
|
||||
|
@ -247,6 +257,41 @@ protected:
|
|||
nsTArray< nsCountedRef<FcPattern> > mFonts;
|
||||
};
|
||||
|
||||
// FontsByFullnameEntry is similar to FontsByFcStrEntry (used for
|
||||
// mFontsByFamily) except for two differences:
|
||||
//
|
||||
// * The font does not always contain a single string for the fullname, so
|
||||
// the key is sometimes a combination of family and style.
|
||||
//
|
||||
// * There is usually only one font.
|
||||
class FontsByFullnameEntry : public DepFcStrEntry {
|
||||
public:
|
||||
// When constructing a new entry in the hashtable, the key is left
|
||||
// NULL. The caller of PutEntry() is must fill in mKey when adding
|
||||
// the first font if the key is not derived from the family and style.
|
||||
// If the key is derived from family and style, a font must be added.
|
||||
FontsByFullnameEntry(KeyTypePointer aName)
|
||||
: DepFcStrEntry(aName) { }
|
||||
|
||||
FontsByFullnameEntry(const FontsByFullnameEntry& toCopy)
|
||||
: DepFcStrEntry(toCopy), mFonts(toCopy.mFonts) { }
|
||||
|
||||
PRBool KeyEquals(KeyTypePointer aKey) const;
|
||||
|
||||
PRBool AddFont(FcPattern *aFont) {
|
||||
return mFonts.AppendElement(aFont) != nsnull;
|
||||
}
|
||||
const nsTArray< nsCountedRef<FcPattern> >& GetFonts() {
|
||||
return mFonts;
|
||||
}
|
||||
|
||||
// Don't memmove the nsAutoTArray.
|
||||
enum { ALLOW_MEMMOVE = PR_FALSE };
|
||||
private:
|
||||
// There is usually only one font, but sometimes more.
|
||||
nsAutoTArray<nsCountedRef<FcPattern>,1> mFonts;
|
||||
};
|
||||
|
||||
class LangSupportEntry : public CopiedFcStrEntry {
|
||||
public:
|
||||
LangSupportEntry(KeyTypePointer aName)
|
||||
|
@ -267,10 +312,18 @@ protected:
|
|||
const nsACString& aLangGroup);
|
||||
nsresult UpdateFontListInternal(PRBool aForce = PR_FALSE);
|
||||
|
||||
void AddFullnameEntries();
|
||||
|
||||
LangSupportEntry *GetLangSupportEntry(const FcChar8 *aLang,
|
||||
PRBool aWithFonts);
|
||||
|
||||
// mFontsByFamily and mFontsByFullname contain entries only for families
|
||||
// and fullnames for which there are fonts.
|
||||
nsTHashtable<FontsByFcStrEntry> mFontsByFamily;
|
||||
nsTHashtable<FontsByFullnameEntry> mFontsByFullname;
|
||||
// mLangSupportTable contains an entry for each language that has been
|
||||
// looked up through GetLangSupportEntry, even when the language is not
|
||||
// supported.
|
||||
nsTHashtable<LangSupportEntry> mLangSupportTable;
|
||||
const nsTArray< nsCountedRef<FcPattern> > mEmptyPatternArray;
|
||||
|
||||
|
|
|
@ -148,21 +148,39 @@ ScaleRoundDesignUnits(FT_Short aDesignMetric, FT_Fixed aScale)
|
|||
/**
|
||||
* gfxFcFontEntry:
|
||||
*
|
||||
* An abstract class for objects in a gfxUserFontSet that can provide an
|
||||
* FcPattern* handle to a font face.
|
||||
* An abstract class for objects in a gfxUserFontSet that can provide
|
||||
* FcPattern* handles to fonts.
|
||||
*
|
||||
* Separate implementations of this class support local fonts from src:local()
|
||||
* and web fonts from src:url().
|
||||
*/
|
||||
|
||||
// There is a one-to-one correspondence between gfxFcFontEntry objects and
|
||||
// @font-face rules, but sometimes a one-to-many correspondence between font
|
||||
// entries and font patterns.
|
||||
//
|
||||
// http://www.w3.org/TR/2002/WD-css3-webfonts-20020802#font-descriptions
|
||||
// provided a font-size descriptor to specify the sizes supported by the face,
|
||||
// but the "Editor's Draft 27 June 2008"
|
||||
// http://dev.w3.org/csswg/css3-fonts/#font-resources does not provide such a
|
||||
// descriptor, and Mozilla does not recognize such a descriptor.
|
||||
//
|
||||
// Font face names used in src:local() also do not usually specify a size.
|
||||
//
|
||||
// PCF format fonts have each size in a different file, and each of these
|
||||
// files is referenced by its own pattern, but really these are each
|
||||
// different sizes of one face with one name.
|
||||
//
|
||||
// Multiple patterns in an entry also effectively deals with a set of
|
||||
// PostScript Type 1 font files that all have the same face name but are in
|
||||
// several files because of the limit on the number of glyphs in a Type 1 font
|
||||
// file. (e.g. Computer Modern.)
|
||||
|
||||
class gfxFcFontEntry : public gfxFontEntry {
|
||||
public:
|
||||
FcPattern *GetPattern()
|
||||
const nsTArray< nsCountedRef<FcPattern> >& GetPatterns()
|
||||
{
|
||||
if (!mPattern) {
|
||||
InitPattern();
|
||||
}
|
||||
return mPattern;
|
||||
return mPatterns;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -175,76 +193,90 @@ protected:
|
|||
mStretch = aProxyEntry.mStretch;
|
||||
}
|
||||
|
||||
// Initializes mPattern.
|
||||
virtual void InitPattern() = 0;
|
||||
// Helper function to change a pattern so that it matches the CSS style
|
||||
// descriptors and so gets properly sorted in font selection. This also
|
||||
// avoids synthetic style effects being added by the renderer when the
|
||||
// style of the font itself does not match the descriptor provided by the
|
||||
// author.
|
||||
void AdjustPatternToCSS(FcPattern *aPattern);
|
||||
|
||||
// Helper function to be called from InitPattern() to change the pattern
|
||||
// so that it matches the CSS style descriptors and so gets properly
|
||||
// sorted in font selection. This also avoids synthetic style effects
|
||||
// being added by the renderer when the style of the font itself does not
|
||||
// match the descriptor provided by the author.
|
||||
void AdjustPatternToCSS();
|
||||
|
||||
nsCountedRef<FcPattern> mPattern;
|
||||
nsAutoTArray<nsCountedRef<FcPattern>,1> mPatterns;
|
||||
};
|
||||
|
||||
void
|
||||
gfxFcFontEntry::AdjustPatternToCSS()
|
||||
gfxFcFontEntry::AdjustPatternToCSS(FcPattern *aPattern)
|
||||
{
|
||||
int fontWeight = -1;
|
||||
FcPatternGetInteger(mPattern, FC_WEIGHT, 0, &fontWeight);
|
||||
FcPatternGetInteger(aPattern, FC_WEIGHT, 0, &fontWeight);
|
||||
int cssWeight = gfxFontconfigUtils::FcWeightForBaseWeight(mWeight);
|
||||
if (cssWeight != fontWeight) {
|
||||
FcPatternDel(mPattern, FC_WEIGHT);
|
||||
FcPatternAddInteger(mPattern, FC_WEIGHT, cssWeight);
|
||||
FcPatternDel(aPattern, FC_WEIGHT);
|
||||
FcPatternAddInteger(aPattern, FC_WEIGHT, cssWeight);
|
||||
}
|
||||
|
||||
int fontSlant;
|
||||
FcResult res = FcPatternGetInteger(mPattern, FC_SLANT, 0, &fontSlant);
|
||||
FcResult res = FcPatternGetInteger(aPattern, FC_SLANT, 0, &fontSlant);
|
||||
// gfxFontEntry doesn't understand the difference between oblique
|
||||
// and italic.
|
||||
if (res != FcResultMatch ||
|
||||
IsItalic() != (fontSlant != FC_SLANT_ROMAN)) {
|
||||
FcPatternDel(mPattern, FC_SLANT);
|
||||
FcPatternAddInteger(mPattern, FC_SLANT,
|
||||
FcPatternDel(aPattern, FC_SLANT);
|
||||
FcPatternAddInteger(aPattern, FC_SLANT,
|
||||
IsItalic() ? FC_SLANT_OBLIQUE : FC_SLANT_ROMAN);
|
||||
}
|
||||
|
||||
// Ensure that there is a fullname property (if there is a family
|
||||
// property) so that fontconfig rules can identify the real name of the
|
||||
// font, because the family property will be replaced.
|
||||
FcChar8 *fullname;
|
||||
FcChar8 *fontFamily;
|
||||
if (FcPatternGetString(mPattern,
|
||||
FC_FULLNAME, 0, &fullname) == FcResultNoMatch &&
|
||||
FcPatternGetString(mPattern,
|
||||
FC_FAMILY, 0, &fontFamily) == FcResultMatch) {
|
||||
// Construct fullname from family and style
|
||||
nsCAutoString fullname(gfxFontconfigUtils::ToCString(fontFamily));
|
||||
FcChar8 *fontStyle;
|
||||
if (FcPatternGetString(mPattern,
|
||||
FC_STYLE, 0, &fontStyle) == FcResultMatch) {
|
||||
const char *style = gfxFontconfigUtils::ToCString(fontStyle);
|
||||
if (strcmp(style, "Regular") != 0) {
|
||||
fullname.Append(' ');
|
||||
fullname.Append(style);
|
||||
}
|
||||
FcChar8 *unused;
|
||||
if (FcPatternGetString(aPattern,
|
||||
FC_FULLNAME, 0, &unused) == FcResultNoMatch) {
|
||||
nsCAutoString fullname;
|
||||
if (gfxFontconfigUtils::GetFullnameFromFamilyAndStyle(aPattern,
|
||||
&fullname)) {
|
||||
FcPatternAddString(aPattern, FC_FULLNAME,
|
||||
gfxFontconfigUtils::ToFcChar8(fullname));
|
||||
}
|
||||
|
||||
FcPatternAddString(mPattern, FC_FULLNAME,
|
||||
gfxFontconfigUtils::ToFcChar8(fullname.get()));
|
||||
}
|
||||
|
||||
nsCAutoString family;
|
||||
family.Append(FONT_FACE_FAMILY_PREFIX);
|
||||
AppendUTF16toUTF8(Name(), family);
|
||||
|
||||
FcPatternDel(mPattern, FC_FAMILY);
|
||||
FcPatternDel(mPattern, FC_FAMILYLANG);
|
||||
FcPatternAddString(mPattern, FC_FAMILY,
|
||||
gfxFontconfigUtils::ToFcChar8(family.get()));
|
||||
FcPatternDel(aPattern, FC_FAMILY);
|
||||
FcPatternDel(aPattern, FC_FAMILYLANG);
|
||||
FcPatternAddString(aPattern, FC_FAMILY,
|
||||
gfxFontconfigUtils::ToFcChar8(family));
|
||||
}
|
||||
|
||||
/**
|
||||
* gfxLocalFcFontEntry:
|
||||
*
|
||||
* An implementation of gfxFcFontEntry for local fonts from src:local().
|
||||
*/
|
||||
|
||||
class gfxLocalFcFontEntry : public gfxFcFontEntry {
|
||||
public:
|
||||
gfxLocalFcFontEntry(const gfxProxyFontEntry &aProxyEntry,
|
||||
const nsTArray< nsCountedRef<FcPattern> >& aPatterns)
|
||||
: gfxFcFontEntry(aProxyEntry)
|
||||
{
|
||||
if (!mPatterns.SetCapacity(aPatterns.Length()))
|
||||
return; // OOM
|
||||
|
||||
for (PRUint32 i = 0; i < aPatterns.Length(); ++i) {
|
||||
FcPattern *pattern = FcPatternDuplicate(aPatterns.ElementAt(i));
|
||||
if (!pattern)
|
||||
return; // OOM
|
||||
|
||||
AdjustPatternToCSS(pattern);
|
||||
|
||||
mPatterns.AppendElement();
|
||||
mPatterns[i].own(pattern);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* gfxDownloadedFcFontEntry:
|
||||
*
|
||||
|
@ -259,6 +291,7 @@ public:
|
|||
: gfxFcFontEntry(aProxyEntry), mLoader(aLoader), mFace(aFace)
|
||||
{
|
||||
NS_PRECONDITION(aFace != NULL, "aFace is NULL!");
|
||||
InitPattern();
|
||||
}
|
||||
|
||||
virtual ~gfxDownloadedFcFontEntry();
|
||||
|
@ -274,7 +307,7 @@ protected:
|
|||
// mLoader holds a reference to memory used by mFace.
|
||||
nsCOMPtr<nsISupports> mLoader;
|
||||
FT_Face mFace;
|
||||
// mPangoCoverage is the charset property of mPattern translated to a
|
||||
// mPangoCoverage is the charset property of the pattern translated to a
|
||||
// format that Pango understands. A reference is kept here so that it can
|
||||
// be shared by multiple PangoFonts (of different sizes).
|
||||
nsAutoRef<PangoCoverage> mPangoCoverage;
|
||||
|
@ -314,11 +347,13 @@ static gfxDownloadedFcFontEntry *GetDownloadedFontEntry(FcPattern *aPattern)
|
|||
|
||||
gfxDownloadedFcFontEntry::~gfxDownloadedFcFontEntry()
|
||||
{
|
||||
if (mPattern) {
|
||||
if (mPatterns.Length() != 0) {
|
||||
// Remove back reference to this font entry and the face in case
|
||||
// anyone holds a reference to the pattern.
|
||||
DelDownloadedFontEntry(mPattern);
|
||||
FcPatternDel(mPattern, FC_FT_FACE);
|
||||
NS_ASSERTION(mPatterns.Length() == 1,
|
||||
"More than one pattern in gfxDownloadedFcFontEntry!");
|
||||
DelDownloadedFontEntry(mPatterns[0]);
|
||||
FcPatternDel(mPatterns[0], FC_FT_FACE);
|
||||
}
|
||||
FT_Done_Face(mFace);
|
||||
}
|
||||
|
@ -344,6 +379,7 @@ void
|
|||
gfxDownloadedFcFontEntry::InitPattern()
|
||||
{
|
||||
static QueryFaceFunction sQueryFacePtr = GetFcFreeTypeQueryFace();
|
||||
FcPattern *pattern;
|
||||
|
||||
// FcFreeTypeQueryFace is the same function used to construct patterns for
|
||||
// system fonts and so is the preferred function to use for this purpose.
|
||||
|
@ -361,10 +397,9 @@ gfxDownloadedFcFontEntry::InitPattern()
|
|||
// blank glyphs are elided. Here, however, we pass NULL for "blanks",
|
||||
// effectively assuming that, if the font has a blank glyph, then the
|
||||
// author intends any associated character to be rendered blank.
|
||||
mPattern.own((*sQueryFacePtr)(mFace,
|
||||
gfxFontconfigUtils::ToFcChar8(""), 0,
|
||||
NULL));
|
||||
if (!mPattern)
|
||||
pattern =
|
||||
(*sQueryFacePtr)(mFace, gfxFontconfigUtils::ToFcChar8(""), 0, NULL);
|
||||
if (!pattern)
|
||||
// Either OOM, or fontconfig chose to skip this font because it
|
||||
// has "no encoded characters", which I think means "BDF and PCF
|
||||
// fonts which are not in Unicode (or the effectively equivalent
|
||||
|
@ -372,8 +407,8 @@ gfxDownloadedFcFontEntry::InitPattern()
|
|||
return;
|
||||
|
||||
// These properties don't make sense for this face without a file.
|
||||
FcPatternDel(mPattern, FC_FILE);
|
||||
FcPatternDel(mPattern, FC_INDEX);
|
||||
FcPatternDel(pattern, FC_FILE);
|
||||
FcPatternDel(pattern, FC_INDEX);
|
||||
|
||||
} else {
|
||||
// Do the minimum necessary to construct a pattern for sorting.
|
||||
|
@ -381,12 +416,12 @@ gfxDownloadedFcFontEntry::InitPattern()
|
|||
// FC_CHARSET is vital to determine which characters are supported.
|
||||
nsAutoRef<FcCharSet> charset(FcFreeTypeCharSet(mFace, NULL));
|
||||
// If there are no characters then assume we don't know how to read
|
||||
// this font and leave mPattern NULL.
|
||||
// this font.
|
||||
if (!charset || FcCharSetCount(charset) == 0)
|
||||
return;
|
||||
|
||||
mPattern.own(FcPatternCreate());
|
||||
FcPatternAddCharSet(mPattern, FC_CHARSET, charset);
|
||||
pattern = FcPatternCreate();
|
||||
FcPatternAddCharSet(pattern, FC_CHARSET, charset);
|
||||
|
||||
// FC_PIXEL_SIZE can be important for font selection of fixed-size
|
||||
// fonts.
|
||||
|
@ -397,12 +432,12 @@ gfxDownloadedFcFontEntry::InitPattern()
|
|||
#else
|
||||
double size = mFace->available_sizes[i].height;
|
||||
#endif
|
||||
FcPatternAddDouble (mPattern, FC_PIXEL_SIZE, size);
|
||||
FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size);
|
||||
}
|
||||
|
||||
// Not sure whether this is important;
|
||||
// imitating FcFreeTypeQueryFace:
|
||||
FcPatternAddBool (mPattern, FC_ANTIALIAS, FcFalse);
|
||||
FcPatternAddBool (pattern, FC_ANTIALIAS, FcFalse);
|
||||
}
|
||||
|
||||
// Setting up the FC_LANGSET property is very difficult with the APIs
|
||||
|
@ -416,10 +451,14 @@ gfxDownloadedFcFontEntry::InitPattern()
|
|||
// fonts).
|
||||
}
|
||||
|
||||
FcPatternAddFTFace(mPattern, FC_FT_FACE, mFace);
|
||||
AddDownloadedFontEntry(mPattern, this);
|
||||
AdjustPatternToCSS(pattern);
|
||||
|
||||
AdjustPatternToCSS();
|
||||
FcPatternAddFTFace(pattern, FC_FT_FACE, mFace);
|
||||
AddDownloadedFontEntry(pattern, this);
|
||||
|
||||
// There is never more than one pattern
|
||||
mPatterns.AppendElement();
|
||||
mPatterns[0].own(pattern);
|
||||
}
|
||||
|
||||
static PangoCoverage *NewPangoCoverage(FcPattern *aFont)
|
||||
|
@ -456,8 +495,10 @@ static PangoCoverage *NewPangoCoverage(FcPattern *aFont)
|
|||
PangoCoverage *
|
||||
gfxDownloadedFcFontEntry::GetPangoCoverage()
|
||||
{
|
||||
NS_ASSERTION(mPatterns.Length() != 0,
|
||||
"Can't get coverage without a pattern!");
|
||||
if (!mPangoCoverage) {
|
||||
mPangoCoverage.own(NewPangoCoverage(mPattern));
|
||||
mPangoCoverage.own(NewPangoCoverage(mPatterns[0]));
|
||||
}
|
||||
return mPangoCoverage;
|
||||
}
|
||||
|
@ -987,8 +1028,8 @@ private:
|
|||
|
||||
// Find the FcPattern for an @font-face font suitable for CSS family |aFamily|
|
||||
// and style |aStyle| properties.
|
||||
static FcPattern *
|
||||
FindFontPattern(gfxUserFontSet *mUserFontSet,
|
||||
static const nsTArray< nsCountedRef<FcPattern> >*
|
||||
FindFontPatterns(gfxUserFontSet *mUserFontSet,
|
||||
const nsACString &aFamily, PRUint8 aStyle, PRUint16 aWeight)
|
||||
{
|
||||
// Convert to UTF16
|
||||
|
@ -1016,7 +1057,7 @@ FindFontPattern(gfxUserFontSet *mUserFontSet,
|
|||
if (!fontEntry)
|
||||
return NULL;
|
||||
|
||||
return fontEntry->GetPattern();
|
||||
return &fontEntry->GetPatterns();
|
||||
}
|
||||
|
||||
typedef FcBool (*FcPatternRemoveFunction)(FcPattern *p, const char *object,
|
||||
|
@ -1156,9 +1197,10 @@ gfxFcPangoFontSet::SortPreferredFonts()
|
|||
for (int v = 0;
|
||||
FcPatternGetString(mSortPattern,
|
||||
FC_FAMILY, v, &family) == FcResultMatch; ++v) {
|
||||
nsAutoTArray<nsCountedRef<FcPattern>,1> userFont;
|
||||
const nsTArray< nsCountedRef<FcPattern> > *familyFonts = nsnull;
|
||||
|
||||
// Is this an @font-face family?
|
||||
PRBool isUserFont = PR_FALSE;
|
||||
if (mUserFontSet) {
|
||||
// Have some @font-face definitions
|
||||
|
||||
|
@ -1166,8 +1208,7 @@ gfxFcPangoFontSet::SortPreferredFonts()
|
|||
NS_NAMED_LITERAL_CSTRING(userPrefix, FONT_FACE_FAMILY_PREFIX);
|
||||
|
||||
if (StringBeginsWith(cFamily, userPrefix)) {
|
||||
// This is an @font-face family.
|
||||
familyFonts = &userFont;
|
||||
isUserFont = PR_TRUE;
|
||||
|
||||
// Trim off the prefix
|
||||
nsDependentCSubstring cssFamily(cFamily, userPrefix.Length());
|
||||
|
@ -1177,22 +1218,17 @@ gfxFcPangoFontSet::SortPreferredFonts()
|
|||
PRUint16 thebesWeight =
|
||||
gfxFontconfigUtils::GetThebesWeight(mSortPattern);
|
||||
|
||||
FcPattern *fontPattern =
|
||||
FindFontPattern(mUserFontSet, cssFamily,
|
||||
thebesStyle, thebesWeight);
|
||||
|
||||
if (fontPattern) {
|
||||
userFont.AppendElement(fontPattern);
|
||||
}
|
||||
familyFonts = FindFontPatterns(mUserFontSet, cssFamily,
|
||||
thebesStyle, thebesWeight);
|
||||
}
|
||||
}
|
||||
|
||||
if (!familyFonts) {
|
||||
if (!isUserFont) {
|
||||
familyFonts = &utils->GetFontsForFamily(family);
|
||||
}
|
||||
|
||||
if (familyFonts->Length() == 0) {
|
||||
// There are no fonts matching this family, so there is not point
|
||||
if (!familyFonts || familyFonts->Length() == 0) {
|
||||
// There are no fonts matching this family, so there is no point
|
||||
// in searching for this family in the FontSort.
|
||||
//
|
||||
// Perhaps the original pattern should be retained for
|
||||
|
@ -1224,8 +1260,7 @@ gfxFcPangoFontSet::SortPreferredFonts()
|
|||
|
||||
// User fonts are already filtered by slant (but not size) in
|
||||
// mUserFontSet->FindFontEntry().
|
||||
if (familyFonts != &userFont &&
|
||||
!SlantIsAcceptable(font, requestedSlant))
|
||||
if (!isUserFont && !SlantIsAcceptable(font, requestedSlant))
|
||||
continue;
|
||||
if (requestedSize != -1.0 && !SizeIsAcceptable(font, requestedSize))
|
||||
continue;
|
||||
|
@ -2060,6 +2095,54 @@ gfxPangoFontGroup::Shutdown()
|
|||
NS_IF_RELEASE(gLangService);
|
||||
}
|
||||
|
||||
/* static */ gfxFontEntry *
|
||||
gfxPangoFontGroup::NewFontEntry(const gfxProxyFontEntry &aProxyEntry,
|
||||
const nsAString& aFullname)
|
||||
{
|
||||
gfxFontconfigUtils *utils = gfxFontconfigUtils::GetFontconfigUtils();
|
||||
if (!utils)
|
||||
return nsnull;
|
||||
|
||||
// The font face name from @font-face { src: local() } is not well
|
||||
// defined.
|
||||
//
|
||||
// On MS Windows, this name gets compared with
|
||||
// ENUMLOGFONTEXW::elfFullName, which for OpenType fonts seems to be the
|
||||
// full font name from the name table. For CFF OpenType fonts this is the
|
||||
// same as the PostScript name, but for TrueType fonts it is usually
|
||||
// different.
|
||||
//
|
||||
// On Mac, the font face name is compared with the PostScript name, even
|
||||
// for TrueType fonts.
|
||||
//
|
||||
// Fontconfig only records the full font names, so the behavior here
|
||||
// follows that on MS Windows. However, to provide the possibility
|
||||
// of aliases to compensate for variations, the font face name is passed
|
||||
// through FcConfigSubstitute.
|
||||
|
||||
nsAutoRef<FcPattern> pattern(FcPatternCreate());
|
||||
if (!pattern)
|
||||
return nsnull;
|
||||
|
||||
NS_ConvertUTF16toUTF8 fullname(aFullname);
|
||||
FcPatternAddString(pattern, FC_FULLNAME,
|
||||
gfxFontconfigUtils::ToFcChar8(fullname));
|
||||
FcConfigSubstitute(NULL, pattern, FcMatchPattern);
|
||||
|
||||
FcChar8 *name;
|
||||
for (int v = 0;
|
||||
FcPatternGetString(pattern, FC_FULLNAME, v, &name) == FcResultMatch;
|
||||
++v) {
|
||||
const nsTArray< nsCountedRef<FcPattern> >& fonts =
|
||||
utils->GetFontsForFullname(name);
|
||||
|
||||
if (fonts.Length() != 0)
|
||||
return new gfxLocalFcFontEntry(aProxyEntry, fonts);
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
static FT_Library
|
||||
GetFTLibrary()
|
||||
{
|
||||
|
|
|
@ -284,6 +284,13 @@ gfxPlatformGtk::CreateFontGroup(const nsAString &aFamilies,
|
|||
return new gfxPangoFontGroup(aFamilies, aStyle, aUserFontSet);
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxPlatformGtk::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFontName)
|
||||
{
|
||||
return gfxPangoFontGroup::NewFontEntry(*aProxyEntry, aFontName);
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxPlatformGtk::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
nsISupports *aLoader,
|
||||
|
|
|
@ -123,7 +123,8 @@ gfxPlatformMac::CreateFontGroup(const nsAString &aFamilies,
|
|||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxPlatformMac::LookupLocalFont(const nsAString& aFontName)
|
||||
gfxPlatformMac::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFontName)
|
||||
{
|
||||
return gfxQuartzFontCache::SharedFontCache()->LookupLocalFont(aFontName);
|
||||
}
|
||||
|
|
|
@ -289,7 +289,9 @@ gfxUserFontSet::LoadNext(gfxProxyFontEntry *aProxyEntry)
|
|||
// src local ==> lookup and load
|
||||
|
||||
if (currSrc.mIsLocal) {
|
||||
gfxFontEntry *fe = gfxPlatform::GetPlatform()->LookupLocalFont(currSrc.mLocalName);
|
||||
gfxFontEntry *fe =
|
||||
gfxPlatform::GetPlatform()->LookupLocalFont(aProxyEntry,
|
||||
currSrc.mLocalName);
|
||||
if (fe) {
|
||||
aProxyEntry->mFamily->ReplaceFontEntry(aProxyEntry, fe);
|
||||
IncrementGeneration();
|
||||
|
|
|
@ -619,7 +619,8 @@ FindFullName(nsStringHashKey::KeyType aKey,
|
|||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxWindowsPlatform::LookupLocalFont(const nsAString& aFontName)
|
||||
gfxWindowsPlatform::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFontName)
|
||||
{
|
||||
// walk over list of names
|
||||
FullFontNameSearch data(aFontName);
|
||||
|
|
Загрузка…
Ссылка в новой задаче