b=468218 @font-face { src:local() } for GTK/Pango r=roc

This commit is contained in:
Karl Tomlinson 2009-01-03 16:21:49 +13:00
Родитель 4dfe0343f6
Коммит 911b1cef22
12 изменённых файлов: 364 добавлений и 93 удалений

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

@ -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);