зеркало из https://github.com/mozilla/pjs.git
b=458169 @font-face { src: url() } for Linux. r=roc
This commit is contained in:
Родитель
17b7625229
Коммит
ba399becc8
|
@ -1615,7 +1615,6 @@ public:
|
|||
void ComputeRanges(nsTArray<gfxTextRange>& mRanges, const PRUnichar *aString, PRUint32 begin, PRUint32 end);
|
||||
|
||||
gfxUserFontSet* GetUserFontSet();
|
||||
void SetUserFontSet(gfxUserFontSet *aUserFontSet);
|
||||
|
||||
// With downloadable fonts, the composition of the font group can change as fonts are downloaded
|
||||
// for each change in state of the user font set, the generation value is bumped to avoid picking up
|
||||
|
@ -1623,6 +1622,8 @@ public:
|
|||
// with no @font-face rule, this always returns 0.
|
||||
PRUint64 GetGeneration();
|
||||
|
||||
// If there is a user font set, check to see whether the font list or any
|
||||
// caches need updating.
|
||||
virtual void UpdateFontList() { }
|
||||
|
||||
protected:
|
||||
|
@ -1634,6 +1635,10 @@ protected:
|
|||
gfxUserFontSet* mUserFontSet;
|
||||
PRUint64 mCurrGeneration; // track the current user font set generation, rebuild font list if needed
|
||||
|
||||
// Used for construction/destruction. Not intended to change the font set
|
||||
// as invalidation of font lists and caches is not considered.
|
||||
void SetUserFontSet(gfxUserFontSet *aUserFontSet);
|
||||
|
||||
// Init this font group's font metrics. If there no bad fonts, you don't need to call this.
|
||||
// But if there are one or more bad fonts which have bad underline offset,
|
||||
// you should call this with the *first* bad font.
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#include "nsAutoRef.h"
|
||||
|
||||
#include <pango/pango.h>
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
// Control when we bypass Pango
|
||||
// Enable this to use FreeType to glyph-convert 8bit-only textruns, but use Pango
|
||||
|
@ -58,6 +57,9 @@
|
|||
//#define ENABLE_FAST_PATH_ALWAYS
|
||||
|
||||
class gfxFcPangoFontSet;
|
||||
class gfxProxyFontEntry;
|
||||
typedef struct _FcPattern FcPattern;
|
||||
typedef struct FT_FaceRec_* FT_Face;
|
||||
|
||||
class THEBES_API gfxPangoFontGroup : public gfxFontGroup {
|
||||
public:
|
||||
|
@ -76,8 +78,16 @@ public:
|
|||
|
||||
virtual gfxFont *GetFontAt(PRInt32 i);
|
||||
|
||||
virtual void UpdateFontList();
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
// Used for @font-face { src: url(); }
|
||||
static gfxFontEntry *NewFontEntry(const gfxProxyFontEntry &aProxyEntry,
|
||||
nsISupports *aLoader,
|
||||
const PRUint8 *aFontData,
|
||||
PRUint32 aLength);
|
||||
|
||||
// Interfaces used internally
|
||||
// (but public so that they can be accessed from non-member functions):
|
||||
|
||||
|
@ -136,7 +146,7 @@ protected:
|
|||
const gchar *aUTF8, PRUint32 aUTF8Length);
|
||||
#endif
|
||||
|
||||
void GetFcFamilies(nsStringArray *aFcFamilyList,
|
||||
void GetFcFamilies(nsTArray<nsString> *aFcFamilyList,
|
||||
const nsACString& aLangGroup);
|
||||
|
||||
// @param aLang [in] language to use for pref fonts and system font
|
||||
|
|
|
@ -61,6 +61,7 @@ class gfxFontGroup;
|
|||
struct gfxFontStyle;
|
||||
class gfxUserFontSet;
|
||||
class gfxFontEntry;
|
||||
class gfxProxyFontEntry;
|
||||
class nsIURI;
|
||||
|
||||
// pref lang id's for font prefs
|
||||
|
@ -192,15 +193,24 @@ public:
|
|||
|
||||
|
||||
/**
|
||||
* Look up a local platform font using the full font face name (needed to support @font-face src local() )
|
||||
* Look up a local platform font using the full font face name.
|
||||
* (Needed to support @font-face src local().)
|
||||
* Ownership of the returned gfxFontEntry is passed to the caller,
|
||||
* who must either AddRef() or delete.
|
||||
*/
|
||||
virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName) { return nsnull; }
|
||||
|
||||
/**
|
||||
* Activate a platform font (needed to support @font-face src url() )
|
||||
*
|
||||
* Activate a platform font. (Needed to support @font-face src url().)
|
||||
* aFontData must persist as long as a reference is held to aLoader.
|
||||
* Ownership of the returned gfxFontEntry is passed to the caller,
|
||||
* who must either AddRef() or delete.
|
||||
*/
|
||||
virtual gfxFontEntry* MakePlatformFont(const gfxFontEntry *aProxyEntry, const PRUint8 *aFontData, PRUint32 aLength) { return nsnull; }
|
||||
virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
nsISupports *aLoader,
|
||||
const PRUint8 *aFontData,
|
||||
PRUint32 aLength)
|
||||
{ return nsnull; }
|
||||
|
||||
/**
|
||||
* Whether to allow downloadable fonts via @font-face rules
|
||||
|
|
|
@ -88,6 +88,24 @@ public:
|
|||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet);
|
||||
|
||||
#ifdef MOZ_PANGO
|
||||
/**
|
||||
* Activate a platform font (needed to support @font-face src url() )
|
||||
*
|
||||
*/
|
||||
virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
nsISupports *aLoader,
|
||||
const PRUint8 *aFontData,
|
||||
PRUint32 aLength);
|
||||
|
||||
/**
|
||||
* Check whether format is supported on a platform or not (if unclear,
|
||||
* returns true).
|
||||
*/
|
||||
virtual PRBool IsFontFormatSupported(nsIURI *aFontURI,
|
||||
PRUint32 aFormatFlags);
|
||||
#endif
|
||||
|
||||
#ifndef MOZ_PANGO
|
||||
FontFamily *FindFontFamily(const nsAString& aName);
|
||||
FontEntry *FindFontEntry(const nsAString& aFamilyName, const gfxFontStyle& aFontStyle);
|
||||
|
|
|
@ -71,7 +71,10 @@ public:
|
|||
|
||||
gfxFontEntry* LookupLocalFont(const nsAString& aFontName);
|
||||
|
||||
gfxFontEntry* MakePlatformFont(const gfxFontEntry *aProxyEntry, const PRUint8 *aFontData, PRUint32 aLength);
|
||||
virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
nsISupports *aLoader,
|
||||
const PRUint8 *aFontData,
|
||||
PRUint32 aLength);
|
||||
|
||||
PRBool IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags);
|
||||
|
||||
|
|
|
@ -193,6 +193,12 @@ public:
|
|||
PRUint32 aItalicStyle = 0,
|
||||
gfxSparseBitSet *aUnicodeRanges = nsnull);
|
||||
|
||||
// Whether there is a face with this family name
|
||||
PRBool HasFamily(const nsAString& aFamilyName) const
|
||||
{
|
||||
return GetFamily(aFamilyName) != nsnull;
|
||||
}
|
||||
|
||||
// lookup a font entry for a given style, returns null if not loaded
|
||||
gfxFontEntry *FindFontEntry(const nsAString& aName,
|
||||
const gfxFontStyle& aFontStyle, PRBool& aNeedsBold);
|
||||
|
@ -201,7 +207,7 @@ public:
|
|||
// aDownloadStatus == NS_OK ==> download succeeded, error otherwise
|
||||
// returns true if platform font creation sucessful (or local()
|
||||
// reference was next in line)
|
||||
PRBool OnLoadComplete(gfxFontEntry *aFontToLoad,
|
||||
PRBool OnLoadComplete(gfxFontEntry *aFontToLoad, nsISupports *aLoader,
|
||||
const PRUint8 *aFontData, PRUint32 aLength,
|
||||
nsresult aDownloadStatus);
|
||||
|
||||
|
@ -217,6 +223,8 @@ protected:
|
|||
// increment the generation on font load
|
||||
void IncrementGeneration();
|
||||
|
||||
gfxMixedFontFamily *GetFamily(const nsAString& aName) const;
|
||||
|
||||
// remove family
|
||||
void RemoveFamily(const nsAString& aFamilyName);
|
||||
|
||||
|
@ -235,6 +243,7 @@ class gfxProxyFontEntry : public gfxFontEntry {
|
|||
|
||||
public:
|
||||
gfxProxyFontEntry(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
|
||||
gfxMixedFontFamily *aFamily,
|
||||
PRUint32 aWeight,
|
||||
PRUint32 aStretch,
|
||||
PRUint32 aItalicStyle,
|
||||
|
|
|
@ -86,7 +86,10 @@ public:
|
|||
/**
|
||||
* Activate a platform font (needed to support @font-face src url() )
|
||||
*/
|
||||
virtual gfxFontEntry* MakePlatformFont(const gfxFontEntry *aProxyEntry, const PRUint8 *aFontData, PRUint32 aLength);
|
||||
virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
nsISupports *aLoader,
|
||||
const PRUint8 *aFontData,
|
||||
PRUint32 aLength);
|
||||
|
||||
/**
|
||||
* Check whether format is supported on a platform or not (if unclear, returns true)
|
||||
|
|
|
@ -63,18 +63,28 @@ gfxFontconfigUtils::Shutdown() {
|
|||
NS_IF_RELEASE(gLangService);
|
||||
}
|
||||
|
||||
/* static */ PRUint8
|
||||
gfxFontconfigUtils::FcSlantToThebesStyle(int aFcSlant)
|
||||
{
|
||||
switch (aFcSlant) {
|
||||
case FC_SLANT_ITALIC:
|
||||
return FONT_STYLE_ITALIC;
|
||||
case FC_SLANT_OBLIQUE:
|
||||
return FONT_STYLE_OBLIQUE;
|
||||
default:
|
||||
return FONT_STYLE_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ PRUint8
|
||||
gfxFontconfigUtils::GetThebesStyle(FcPattern *aPattern)
|
||||
{
|
||||
int slant;
|
||||
if (FcPatternGetInteger(aPattern, FC_SLANT, 0, &slant) == FcResultMatch) {
|
||||
if (slant == FC_SLANT_ITALIC)
|
||||
return FONT_STYLE_ITALIC;
|
||||
if (slant == FC_SLANT_OBLIQUE)
|
||||
return FONT_STYLE_OBLIQUE;
|
||||
if (FcPatternGetInteger(aPattern, FC_SLANT, 0, &slant) != FcResultMatch) {
|
||||
return FONT_STYLE_NORMAL;
|
||||
}
|
||||
|
||||
return FONT_STYLE_NORMAL;
|
||||
return FcSlantToThebesStyle(slant);
|
||||
}
|
||||
|
||||
/* static */ int
|
||||
|
@ -209,10 +219,8 @@ GuessFcWeight(const gfxFontStyle& aFontStyle)
|
|||
static void
|
||||
AddString(FcPattern *aPattern, const char *object, const char *aString)
|
||||
{
|
||||
// Cast from signed chars used in nsString to unsigned in fontconfig
|
||||
const FcChar8 *fcString = gfxFontconfigUtils::ToFcChar8(aString);
|
||||
// and cast away the const for fontconfig, that will merely make a copy.
|
||||
FcPatternAddString(aPattern, object, const_cast<FcChar8*>(fcString));
|
||||
FcPatternAddString(aPattern, object,
|
||||
gfxFontconfigUtils::ToFcChar8(aString));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -229,7 +237,7 @@ AddLangGroup(FcPattern *aPattern, const nsACString& aLangGroup)
|
|||
|
||||
|
||||
nsReturnRef<FcPattern>
|
||||
gfxFontconfigUtils::NewPattern(const nsStringArray& aFamilies,
|
||||
gfxFontconfigUtils::NewPattern(const nsTArray<nsString>& aFamilies,
|
||||
const gfxFontStyle& aFontStyle,
|
||||
const char *aLang)
|
||||
{
|
||||
|
@ -245,8 +253,8 @@ gfxFontconfigUtils::NewPattern(const nsStringArray& aFamilies,
|
|||
AddString(pattern, FC_LANG, aLang);
|
||||
}
|
||||
|
||||
for (PRInt32 i = 0; i < aFamilies.Count(); ++i) {
|
||||
NS_ConvertUTF16toUTF8 family(*aFamilies[i]);
|
||||
for (PRUint32 i = 0; i < aFamilies.Length(); ++i) {
|
||||
NS_ConvertUTF16toUTF8 family(aFamilies[i]);
|
||||
AddString(pattern, FC_FAMILY, family.get());
|
||||
}
|
||||
|
||||
|
@ -785,16 +793,23 @@ CompareLangString(const FcChar8 *aLangA, const FcChar8 *aLangB) {
|
|||
FcLangResult
|
||||
gfxFontconfigUtils::GetLangSupport(FcPattern *aFont, const FcChar8 *aLang)
|
||||
{
|
||||
// When fontconfig builds a pattern for the font, it will set a single
|
||||
// LangSet property value for the font. That value may be removed and
|
||||
// additional string values may be added through FcConfigSubsitute with
|
||||
// FcMatchScan. Values that are neither LangSet nor string are considered
|
||||
// errors in fontconfig sort and match functions.
|
||||
// When fontconfig builds a pattern for a system font, it will set a
|
||||
// single LangSet property value for the font. That value may be removed
|
||||
// and additional string values may be added through FcConfigSubsitute
|
||||
// with FcMatchScan. Values that are neither LangSet nor string are
|
||||
// considered errors in fontconfig sort and match functions.
|
||||
//
|
||||
// If no string nor LangSet value is found, then either the font is a
|
||||
// system font and the LangSet has been removed through FcConfigSubsitute,
|
||||
// or the font is a web font and its language support is unknown.
|
||||
// Returning FcLangDifferentLang for these fonts ensures that this font
|
||||
// will not be assumed to satisfy the language, and so language will be
|
||||
// prioritized in sorting fallback fonts.
|
||||
FcValue value;
|
||||
FcLangResult best = FcLangDifferentLang;
|
||||
int v = 0;
|
||||
while (FcPatternGet(aFont, FC_LANG, v, &value) == FcResultMatch) {
|
||||
++v;
|
||||
for (int v = 0;
|
||||
FcPatternGet(aFont, FC_LANG, v, &value) == FcResultMatch;
|
||||
++v) {
|
||||
|
||||
FcLangResult support;
|
||||
switch (value.type) {
|
||||
|
@ -805,8 +820,8 @@ gfxFontconfigUtils::GetLangSupport(FcPattern *aFont, const FcChar8 *aLang)
|
|||
support = CompareLangString(value.u.s, aLang);
|
||||
break;
|
||||
default:
|
||||
// error
|
||||
return FcLangEqual;
|
||||
// error. continue to see if there is a useful value.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (support < best) { // lower is better
|
||||
|
@ -816,11 +831,6 @@ gfxFontconfigUtils::GetLangSupport(FcPattern *aFont, const FcChar8 *aLang)
|
|||
}
|
||||
}
|
||||
|
||||
// A missing FC_LANG property is considered a match in fontconfig sort
|
||||
// and match functions.
|
||||
if (v == 0)
|
||||
return FcLangEqual;
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
|
|
|
@ -125,6 +125,7 @@ public:
|
|||
return reinterpret_cast<const char*>(aChar8Ptr);
|
||||
}
|
||||
|
||||
static PRUint8 FcSlantToThebesStyle(int aFcSlant);
|
||||
static PRUint8 GetThebesStyle(FcPattern *aPattern); // slant
|
||||
static PRUint16 GetThebesWeight(FcPattern *aPattern);
|
||||
|
||||
|
@ -135,8 +136,8 @@ public:
|
|||
// This doesn't consider which faces exist, and so initializes the pattern
|
||||
// using a guessed weight, and doesn't consider sizeAdjust.
|
||||
static nsReturnRef<FcPattern>
|
||||
NewPattern(const nsStringArray& aFamilies, const gfxFontStyle& aFontStyle,
|
||||
const char *aLang);
|
||||
NewPattern(const nsTArray<nsString>& aFamilies,
|
||||
const gfxFontStyle& aFontStyle, const char *aLang);
|
||||
|
||||
/**
|
||||
* @param aLangGroup [in] a Mozilla langGroup.
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "gfxPlatformGtk.h"
|
||||
#include "gfxPangoFonts.h"
|
||||
#include "gfxFontconfigUtils.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
|
||||
#include <freetype/tttables.h>
|
||||
|
||||
|
@ -97,22 +98,368 @@ static cairo_scaled_font_t *CreateScaledFont(FcPattern *aPattern);
|
|||
static PangoFontMap *gPangoFontMap;
|
||||
static PangoFontMap *GetPangoFontMap();
|
||||
|
||||
static FT_Library gFTLibrary;
|
||||
static nsILanguageAtomService* gLangService;
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
class nsAutoRefTraits<PangoFont> : public gfxGObjectRefTraits<PangoFont> { };
|
||||
|
||||
// stub class until fuller implementation is flushed out
|
||||
class gfxPangoFontEntry : public gfxFontEntry {
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
class nsAutoRefTraits<PangoCoverage>
|
||||
: public nsPointerRefTraits<PangoCoverage> {
|
||||
public:
|
||||
gfxPangoFontEntry(const nsAString& aName)
|
||||
: gfxFontEntry(aName)
|
||||
{ }
|
||||
|
||||
~gfxPangoFontEntry() {}
|
||||
|
||||
static void Release(PangoCoverage *aPtr) { pango_coverage_unref(aPtr); }
|
||||
static void AddRef(PangoCoverage *aPtr) { pango_coverage_ref(aPtr); }
|
||||
};
|
||||
|
||||
|
||||
// FC_FAMILYLANG and FC_FULLNAME were introduced in fontconfig-2.2.97
|
||||
// and so fontconfig-2.3.0 (2005).
|
||||
#ifndef FC_FAMILYLANG
|
||||
#define FC_FAMILYLANG "familylang"
|
||||
#endif
|
||||
#ifndef FC_FULLNAME
|
||||
#define FC_FULLNAME "fullname"
|
||||
#endif
|
||||
|
||||
// Rounding and truncation functions for a FreeType fixed point number
|
||||
// (FT26Dot6) stored in a 32bit integer with high 26 bits for the integer
|
||||
// part and low 6 bits for the fractional part.
|
||||
#define FLOAT_FROM_26_6(x) ((x) / 64.0)
|
||||
#define FLOAT_FROM_16_16(x) ((x) / 65536.0)
|
||||
#define ROUND_26_6_TO_INT(x) ((x) >= 0 ? ((32 + (x)) >> 6) \
|
||||
: -((32 - (x)) >> 6))
|
||||
// aScale is intended for a 16.16 x/y_scale of an FT_Size_Metrics
|
||||
static inline FT_Long
|
||||
ScaleRoundDesignUnits(FT_Short aDesignMetric, FT_Fixed aScale)
|
||||
{
|
||||
FT_Long fixed26dot6 = FT_MulFix(aDesignMetric, aScale);
|
||||
return ROUND_26_6_TO_INT(fixed26dot6);
|
||||
}
|
||||
|
||||
// A namespace for @font-face family names in FcPatterns so that fontconfig
|
||||
// aliases do not pick up families from @font-face rules and so that
|
||||
// fontconfig rules can distinguish between web fonts and platform fonts.
|
||||
// http://lists.freedesktop.org/archives/fontconfig/2008-November/003037.html
|
||||
#define FONT_FACE_FAMILY_PREFIX "@font-face:"
|
||||
|
||||
/**
|
||||
* gfxFcFontEntry:
|
||||
*
|
||||
* An abstract class for objects in a gfxUserFontSet that can provide an
|
||||
* FcPattern* handle to a font face.
|
||||
*
|
||||
* Separate implementations of this class support local fonts from src:local()
|
||||
* and web fonts from src:url().
|
||||
*/
|
||||
|
||||
class gfxFcFontEntry : public gfxFontEntry {
|
||||
public:
|
||||
FcPattern *GetPattern()
|
||||
{
|
||||
if (!mPattern) {
|
||||
InitPattern();
|
||||
}
|
||||
return mPattern;
|
||||
}
|
||||
|
||||
protected:
|
||||
gfxFcFontEntry(const gfxProxyFontEntry &aProxyEntry)
|
||||
// store the family name
|
||||
: gfxFontEntry(aProxyEntry.mFamily->Name())
|
||||
{
|
||||
mItalic = aProxyEntry.mItalic;
|
||||
mWeight = aProxyEntry.mWeight;
|
||||
mStretch = aProxyEntry.mStretch;
|
||||
}
|
||||
|
||||
// Initializes mPattern.
|
||||
virtual void InitPattern() = 0;
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
void
|
||||
gfxFcFontEntry::AdjustPatternToCSS()
|
||||
{
|
||||
int fontWeight = -1;
|
||||
FcPatternGetInteger(mPattern, FC_WEIGHT, 0, &fontWeight);
|
||||
int cssWeight = gfxFontconfigUtils::FcWeightForBaseWeight(mWeight);
|
||||
if (cssWeight != fontWeight) {
|
||||
FcPatternDel(mPattern, FC_WEIGHT);
|
||||
FcPatternAddInteger(mPattern, FC_WEIGHT, cssWeight);
|
||||
}
|
||||
|
||||
int fontSlant;
|
||||
FcResult res = FcPatternGetInteger(mPattern, 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,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
/**
|
||||
* gfxDownloadedFcFontEntry:
|
||||
*
|
||||
* An implementation of gfxFcFontEntry for web fonts from src:url().
|
||||
*/
|
||||
|
||||
class gfxDownloadedFcFontEntry : public gfxFcFontEntry {
|
||||
public:
|
||||
// This takes ownership of the face.
|
||||
gfxDownloadedFcFontEntry(const gfxProxyFontEntry &aProxyEntry,
|
||||
nsISupports *aLoader, FT_Face aFace)
|
||||
: gfxFcFontEntry(aProxyEntry), mLoader(aLoader), mFace(aFace)
|
||||
{
|
||||
NS_PRECONDITION(aFace != NULL, "aFace is NULL!");
|
||||
}
|
||||
|
||||
virtual ~gfxDownloadedFcFontEntry();
|
||||
|
||||
// Returns a PangoCoverage owned by the FontEntry. The caller must add a
|
||||
// reference if it wishes to keep the PangoCoverage longer than the
|
||||
// lifetime of the FontEntry.
|
||||
PangoCoverage *GetPangoCoverage();
|
||||
|
||||
protected:
|
||||
virtual void InitPattern();
|
||||
|
||||
// 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
|
||||
// format that Pango understands. A reference is kept here so that it can
|
||||
// be shared by multiple PangoFonts (of different sizes).
|
||||
nsAutoRef<PangoCoverage> mPangoCoverage;
|
||||
};
|
||||
|
||||
// A property for recording gfxDownloadedFcFontEntrys on FcPatterns.
|
||||
static const char *kFontEntryFcProp = "-moz-font-entry";
|
||||
|
||||
static FcBool AddDownloadedFontEntry(FcPattern *aPattern,
|
||||
gfxDownloadedFcFontEntry *aFontEntry)
|
||||
{
|
||||
FcValue value;
|
||||
value.type = FcTypeFTFace; // void* field of union
|
||||
value.u.f = aFontEntry;
|
||||
|
||||
return FcPatternAdd(aPattern, kFontEntryFcProp, value, FcFalse);
|
||||
}
|
||||
|
||||
static FcBool DelDownloadedFontEntry(FcPattern *aPattern)
|
||||
{
|
||||
return FcPatternDel(aPattern, kFontEntryFcProp);
|
||||
}
|
||||
|
||||
static gfxDownloadedFcFontEntry *GetDownloadedFontEntry(FcPattern *aPattern)
|
||||
{
|
||||
FcValue value;
|
||||
if (FcPatternGet(aPattern, kFontEntryFcProp, 0, &value) != FcResultMatch)
|
||||
return nsnull;
|
||||
|
||||
if (value.type != FcTypeFTFace) {
|
||||
NS_NOTREACHED("Wrong type for -moz-font-entry font property");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return static_cast<gfxDownloadedFcFontEntry*>(value.u.f);
|
||||
}
|
||||
|
||||
gfxDownloadedFcFontEntry::~gfxDownloadedFcFontEntry()
|
||||
{
|
||||
if (mPattern) {
|
||||
// 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);
|
||||
}
|
||||
FT_Done_Face(mFace);
|
||||
}
|
||||
|
||||
typedef FcPattern* (*QueryFaceFunction)(const FT_Face face,
|
||||
const FcChar8 *file, int id,
|
||||
FcBlanks *blanks);
|
||||
|
||||
static QueryFaceFunction
|
||||
GetFcFreeTypeQueryFace()
|
||||
{
|
||||
PRLibrary *lib = nsnull;
|
||||
PRFuncPtr result =
|
||||
PR_FindFunctionSymbolAndLibrary("FcFreeTypeQueryFace", &lib);
|
||||
if (lib) {
|
||||
PR_UnloadLibrary(lib);
|
||||
}
|
||||
|
||||
return reinterpret_cast<QueryFaceFunction>(result);
|
||||
}
|
||||
|
||||
void
|
||||
gfxDownloadedFcFontEntry::InitPattern()
|
||||
{
|
||||
static QueryFaceFunction sQueryFacePtr = GetFcFreeTypeQueryFace();
|
||||
|
||||
// FcFreeTypeQueryFace is the same function used to construct patterns for
|
||||
// system fonts and so is the preferred function to use for this purpose.
|
||||
// This will set up the langset property, which helps with sorting, and
|
||||
// the foundry, fullname, and fontversion properties, which properly
|
||||
// identify the font to fontconfig rules. However, FcFreeTypeQueryFace is
|
||||
// available only from fontconfig-2.4.2 (December 2006). (CentOS 5.0 has
|
||||
// fontconfig-2.4.1.)
|
||||
if (sQueryFacePtr) {
|
||||
// The "file" argument cannot be NULL (in fontconfig-2.6.0 at least).
|
||||
// The dummy file passed here is removed below.
|
||||
//
|
||||
// When fontconfig scans the system fonts, FcConfigGetBlanks(NULL) is
|
||||
// passed as the "blanks" argument, which provides that unexpectedly
|
||||
// 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)
|
||||
// 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
|
||||
// ISO Latin-1) encoding".
|
||||
return;
|
||||
|
||||
// These properties don't make sense for this face without a file.
|
||||
FcPatternDel(mPattern, FC_FILE);
|
||||
FcPatternDel(mPattern, FC_INDEX);
|
||||
|
||||
} else {
|
||||
// Do the minimum necessary to construct a pattern for sorting.
|
||||
|
||||
// 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.
|
||||
if (!charset || FcCharSetCount(charset) == 0)
|
||||
return;
|
||||
|
||||
mPattern.own(FcPatternCreate());
|
||||
FcPatternAddCharSet(mPattern, FC_CHARSET, charset);
|
||||
|
||||
// FC_PIXEL_SIZE can be important for font selection of fixed-size
|
||||
// fonts.
|
||||
if (!(mFace->face_flags & FT_FACE_FLAG_SCALABLE)) {
|
||||
for (FT_Int i = 0; i < mFace->num_fixed_sizes; ++i) {
|
||||
#if HAVE_FT_BITMAP_SIZE_Y_PPEM
|
||||
double size = FLOAT_FROM_26_6(mFace->available_sizes[i].y_ppem);
|
||||
#else
|
||||
double size = mFace->available_sizes[i].height;
|
||||
#endif
|
||||
FcPatternAddDouble (mPattern, FC_PIXEL_SIZE, size);
|
||||
}
|
||||
|
||||
// Not sure whether this is important;
|
||||
// imitating FcFreeTypeQueryFace:
|
||||
FcPatternAddBool (mPattern, FC_ANTIALIAS, FcFalse);
|
||||
}
|
||||
|
||||
// Setting up the FC_LANGSET property is very difficult with the APIs
|
||||
// available prior to FcFreeTypeQueryFace. Having no FC_LANGSET
|
||||
// property seems better than having a property with an empty LangSet.
|
||||
// With no FC_LANGSET property, fontconfig sort functions will
|
||||
// consider this face to have the same priority as (otherwise equal)
|
||||
// faces that have support for the primary requested language, but
|
||||
// will not consider any language to have been satisfied (and so will
|
||||
// continue to look for a face with language support in fallback
|
||||
// fonts).
|
||||
}
|
||||
|
||||
FcPatternAddFTFace(mPattern, FC_FT_FACE, mFace);
|
||||
AddDownloadedFontEntry(mPattern, this);
|
||||
|
||||
AdjustPatternToCSS();
|
||||
}
|
||||
|
||||
static PangoCoverage *NewPangoCoverage(FcPattern *aFont)
|
||||
{
|
||||
// This uses g_slice_alloc which will abort on OOM rather than return NULL.
|
||||
PangoCoverage *coverage = pango_coverage_new();
|
||||
|
||||
FcCharSet *charset;
|
||||
if (FcPatternGetCharSet(aFont, FC_CHARSET, 0, &charset) != FcResultMatch)
|
||||
return coverage; // empty
|
||||
|
||||
FcChar32 base;
|
||||
FcChar32 map[FC_CHARSET_MAP_SIZE];
|
||||
FcChar32 next;
|
||||
for (base = FcCharSetFirstPage(charset, map, &next);
|
||||
base != FC_CHARSET_DONE;
|
||||
base = FcCharSetNextPage(charset, map, &next)) {
|
||||
for (PRUint32 i = 0; i < FC_CHARSET_MAP_SIZE; ++i) {
|
||||
PRUint32 offset = 0;
|
||||
FcChar32 bitmap = map[i];
|
||||
for (; bitmap; bitmap >>= 1) {
|
||||
if (bitmap & 1) {
|
||||
pango_coverage_set(coverage, base + offset,
|
||||
PANGO_COVERAGE_EXACT);
|
||||
}
|
||||
++offset;
|
||||
}
|
||||
base += 32;
|
||||
}
|
||||
}
|
||||
return coverage;
|
||||
}
|
||||
|
||||
PangoCoverage *
|
||||
gfxDownloadedFcFontEntry::GetPangoCoverage()
|
||||
{
|
||||
if (!mPangoCoverage) {
|
||||
mPangoCoverage.own(NewPangoCoverage(mPattern));
|
||||
}
|
||||
return mPangoCoverage;
|
||||
}
|
||||
|
||||
/*
|
||||
* gfxFcFont
|
||||
*
|
||||
|
@ -148,7 +495,7 @@ protected:
|
|||
PRPackedBool mHasMetrics;
|
||||
|
||||
gfxFcFont(cairo_scaled_font_t *aCairoFont,
|
||||
gfxPangoFontEntry *aFontEntry, const gfxFontStyle *aFontStyle);
|
||||
gfxFontEntry *aFontEntry, const gfxFontStyle *aFontStyle);
|
||||
|
||||
virtual PRBool SetupCairoFont(gfxContext *aContext);
|
||||
|
||||
|
@ -171,6 +518,11 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
FT_Face get()
|
||||
{
|
||||
return mFace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extents for a simple character representable by a single glyph.
|
||||
* The return value is the glyph id of that glyph or zero if no such glyph
|
||||
|
@ -212,6 +564,7 @@ struct gfxPangoFcFont {
|
|||
PangoFcFont parent_instance;
|
||||
|
||||
FcPattern *mRequestedPattern;
|
||||
PangoCoverage *mCoverage;
|
||||
gfxFcFont *mGfxFont;
|
||||
|
||||
static nsReturnRef<PangoFont>
|
||||
|
@ -238,7 +591,7 @@ struct gfxPangoFcFont {
|
|||
FcPatternReference(aRequestedPattern);
|
||||
font->mRequestedPattern = aRequestedPattern;
|
||||
|
||||
// pango_fc_font::get_coverage wants a FcFontMap. (PangoFcFontMap
|
||||
// PangoFcFont::get_coverage wants an FcFontMap. (PangoFcFontMap
|
||||
// usually sets this after calling PangoFcFontMap::create_font().)
|
||||
PangoFcFont *fc_font = &font->parent_instance;
|
||||
fc_font->fontmap = GetPangoFontMap();
|
||||
|
@ -315,6 +668,8 @@ gfx_pango_fc_font_finalize(GObject *object)
|
|||
|
||||
if (self->mRequestedPattern)
|
||||
FcPatternDestroy(self->mRequestedPattern);
|
||||
if (self->mCoverage)
|
||||
pango_coverage_unref(self->mCoverage);
|
||||
NS_IF_RELEASE(self->mGfxFont);
|
||||
|
||||
// The parent class removes the reference to parent_instance->fontmap.
|
||||
|
@ -322,6 +677,33 @@ gfx_pango_fc_font_finalize(GObject *object)
|
|||
G_OBJECT_CLASS(gfx_pango_fc_font_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static PangoCoverage *
|
||||
gfx_pango_fc_font_get_coverage(PangoFont *font, PangoLanguage *lang)
|
||||
{
|
||||
gfxPangoFcFont *self = GFX_PANGO_FC_FONT(font);
|
||||
|
||||
// The coverage is requested often enough that it is worth holding a
|
||||
// reference on the font.
|
||||
if (!self->mCoverage) {
|
||||
FcPattern *pattern = self->parent_instance.font_pattern;
|
||||
gfxDownloadedFcFontEntry *downloadedFontEntry =
|
||||
GetDownloadedFontEntry(pattern);
|
||||
// The parent class implementation requires the font pattern to have
|
||||
// a file and caches results against that filename. This is not
|
||||
// suitable for web fonts.
|
||||
if (!downloadedFontEntry) {
|
||||
self->mCoverage =
|
||||
PANGO_FONT_CLASS(gfx_pango_fc_font_parent_class)->
|
||||
get_coverage(font, lang);
|
||||
} else {
|
||||
self->mCoverage =
|
||||
pango_coverage_ref(downloadedFontEntry->GetPangoCoverage());
|
||||
}
|
||||
}
|
||||
|
||||
return pango_coverage_ref(self->mCoverage);
|
||||
}
|
||||
|
||||
static PangoFontDescription *
|
||||
gfx_pango_fc_font_describe(PangoFont *font)
|
||||
{
|
||||
|
@ -464,11 +846,7 @@ gfx_pango_fc_font_class_init (gfxPangoFcFontClass *klass)
|
|||
|
||||
object_class->finalize = gfx_pango_fc_font_finalize;
|
||||
|
||||
#if 0
|
||||
// This will need overriding for user fonts to defeat the PangoFcFontMap
|
||||
// caching, unless each user font is guaranteed to have a unique filename.
|
||||
font_class->get_coverage = gfx_pango_fc_font_get_coverage;
|
||||
#endif
|
||||
// describe is called on errors in pango_shape.
|
||||
font_class->describe = gfx_pango_fc_font_describe;
|
||||
font_class->get_glyph_extents = gfx_pango_fc_font_get_glyph_extents;
|
||||
|
@ -529,8 +907,9 @@ class gfxFcPangoFontSet {
|
|||
public:
|
||||
THEBES_INLINE_DECL_REFCOUNTING(gfxFcPangoFontSet)
|
||||
|
||||
explicit gfxFcPangoFontSet(FcPattern *aPattern)
|
||||
: mSortPattern(aPattern),
|
||||
explicit gfxFcPangoFontSet(FcPattern *aPattern,
|
||||
gfxUserFontSet *aUserFontSet)
|
||||
: mSortPattern(aPattern), mUserFontSet(aUserFontSet),
|
||||
mFcFontSet(SortPreferredFonts()), mFcFontsTrimmed(0),
|
||||
mHaveFallbackFonts(PR_FALSE)
|
||||
{
|
||||
|
@ -584,6 +963,8 @@ public:
|
|||
private:
|
||||
// The requested pattern
|
||||
nsCountedRef<FcPattern> mSortPattern;
|
||||
// Fonts from @font-face rules
|
||||
nsRefPtr<gfxUserFontSet> mUserFontSet;
|
||||
// A (trimmed) list of font patterns and PangoFonts that is built up as
|
||||
// required.
|
||||
nsTArray<FontEntry> mFonts;
|
||||
|
@ -602,6 +983,40 @@ private:
|
|||
PRPackedBool mHaveFallbackFonts;
|
||||
};
|
||||
|
||||
// Find the FcPattern for an @font-face font suitable for CSS family |aFamily|
|
||||
// and style |aStyle| properties.
|
||||
static FcPattern *
|
||||
FindFontPattern(gfxUserFontSet *mUserFontSet,
|
||||
const nsACString &aFamily, PRUint8 aStyle, PRUint16 aWeight)
|
||||
{
|
||||
// Convert to UTF16
|
||||
NS_ConvertUTF8toUTF16 utf16Family(aFamily);
|
||||
|
||||
// needsBold is not used here. Instead synthetic bold is enabled through
|
||||
// FcFontRenderPrepare when the weight in the requested pattern is
|
||||
// compared against the weight in the font pattern.
|
||||
PRBool needsBold;
|
||||
|
||||
gfxFontStyle style;
|
||||
style.style = aStyle;
|
||||
style.weight = aWeight;
|
||||
|
||||
gfxFcFontEntry *fontEntry = static_cast<gfxFcFontEntry*>
|
||||
(mUserFontSet->FindFontEntry(utf16Family, style, needsBold));
|
||||
|
||||
// Accept synthetic oblique for italic and oblique.
|
||||
if (!fontEntry && aStyle != FONT_STYLE_NORMAL) {
|
||||
style.style = FONT_STYLE_NORMAL;
|
||||
fontEntry = static_cast<gfxFcFontEntry*>
|
||||
(mUserFontSet->FindFontEntry(utf16Family, style, needsBold));
|
||||
}
|
||||
|
||||
if (!fontEntry)
|
||||
return NULL;
|
||||
|
||||
return fontEntry->GetPattern();
|
||||
}
|
||||
|
||||
typedef FcBool (*FcPatternRemoveFunction)(FcPattern *p, const char *object,
|
||||
int id);
|
||||
|
||||
|
@ -619,7 +1034,6 @@ GetFcPatternRemove()
|
|||
}
|
||||
|
||||
// FcPatternRemove is available in fontconfig-2.3.0 (2005)
|
||||
// CentOS 5 has fontconfig-2.4.1
|
||||
static FcBool
|
||||
moz_FcPatternRemove(FcPattern *p, const char *object, int id)
|
||||
{
|
||||
|
@ -740,10 +1154,42 @@ gfxFcPangoFontSet::SortPreferredFonts()
|
|||
for (int v = 0;
|
||||
FcPatternGetString(mSortPattern,
|
||||
FC_FAMILY, v, &family) == FcResultMatch; ++v) {
|
||||
const nsTArray< nsCountedRef<FcPattern> >& familyFonts =
|
||||
utils->GetFontsForFamily(family);
|
||||
nsAutoTArray<nsCountedRef<FcPattern>,1> userFont;
|
||||
const nsTArray< nsCountedRef<FcPattern> > *familyFonts = nsnull;
|
||||
|
||||
if (familyFonts.Length() == 0) {
|
||||
if (mUserFontSet) {
|
||||
// Have some @font-face definitions
|
||||
|
||||
nsDependentCString cFamily(gfxFontconfigUtils::ToCString(family));
|
||||
NS_NAMED_LITERAL_CSTRING(userPrefix, FONT_FACE_FAMILY_PREFIX);
|
||||
|
||||
if (StringBeginsWith(cFamily, userPrefix)) {
|
||||
// This is an @font-face family.
|
||||
familyFonts = &userFont;
|
||||
|
||||
// Trim off the prefix
|
||||
nsDependentCSubstring cssFamily(cFamily, userPrefix.Length());
|
||||
|
||||
PRUint8 thebesStyle =
|
||||
gfxFontconfigUtils::FcSlantToThebesStyle(requestedSlant);
|
||||
PRUint16 thebesWeight =
|
||||
gfxFontconfigUtils::GetThebesWeight(mSortPattern);
|
||||
|
||||
FcPattern *fontPattern =
|
||||
FindFontPattern(mUserFontSet, cssFamily,
|
||||
thebesStyle, thebesWeight);
|
||||
|
||||
if (fontPattern) {
|
||||
userFont.AppendElement(fontPattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!familyFonts) {
|
||||
familyFonts = &utils->GetFontsForFamily(family);
|
||||
}
|
||||
|
||||
if (familyFonts->Length() == 0) {
|
||||
// There are no fonts matching this family, so there is not point
|
||||
// in searching for this family in the FontSort.
|
||||
//
|
||||
|
@ -771,10 +1217,13 @@ gfxFcPangoFontSet::SortPreferredFonts()
|
|||
entry->mKey = family; // initialize new entry
|
||||
}
|
||||
|
||||
for (PRUint32 f = 0; f < familyFonts.Length(); ++f) {
|
||||
FcPattern *font = familyFonts[f];
|
||||
for (PRUint32 f = 0; f < familyFonts->Length(); ++f) {
|
||||
FcPattern *font = familyFonts->ElementAt(f);
|
||||
|
||||
if (!SlantIsAcceptable(font, requestedSlant))
|
||||
// User fonts are already filtered by slant (but not size) in
|
||||
// mUserFontSet->FindFontEntry().
|
||||
if (familyFonts != &userFont &&
|
||||
!SlantIsAcceptable(font, requestedSlant))
|
||||
continue;
|
||||
if (requestedSize != -1.0 && !SizeIsAcceptable(font, requestedSize))
|
||||
continue;
|
||||
|
@ -1334,6 +1783,16 @@ gfx_pango_font_map_class_init(gfxPangoFontMapClass *klass)
|
|||
** gfxPangoFontGroup
|
||||
**/
|
||||
|
||||
struct FamilyCallbackData {
|
||||
FamilyCallbackData(nsTArray<nsString> *aFcFamilyList,
|
||||
gfxUserFontSet *aUserFontSet)
|
||||
: mFcFamilyList(aFcFamilyList), mUserFontSet(aUserFontSet)
|
||||
{
|
||||
}
|
||||
nsTArray<nsString> *mFcFamilyList;
|
||||
const gfxUserFontSet *mUserFontSet;
|
||||
};
|
||||
|
||||
static int
|
||||
FFRECountHyphens (const nsAString &aFFREName)
|
||||
{
|
||||
|
@ -1347,17 +1806,51 @@ FFRECountHyphens (const nsAString &aFFREName)
|
|||
}
|
||||
|
||||
static PRBool
|
||||
FontCallback (const nsAString& fontName, const nsACString& genericName,
|
||||
void *closure)
|
||||
FamilyCallback (const nsAString& fontName, const nsACString& genericName,
|
||||
void *closure)
|
||||
{
|
||||
nsStringArray *sa = static_cast<nsStringArray*>(closure);
|
||||
FamilyCallbackData *data = static_cast<FamilyCallbackData*>(closure);
|
||||
nsTArray<nsString> *list = data->mFcFamilyList;
|
||||
|
||||
// We ignore prefs that have three hypens since they are X style prefs.
|
||||
if (genericName.Length() && FFRECountHyphens(fontName) >= 3)
|
||||
return PR_TRUE;
|
||||
|
||||
if (sa->IndexOf(fontName) < 0) {
|
||||
sa->AppendString(fontName);
|
||||
if (!list->Contains(fontName)) {
|
||||
// The family properties of FcPatterns for @font-face fonts have a
|
||||
// namespace to identify them among system fonts. (see
|
||||
// FONT_FACE_FAMILY_PREFIX.) The CSS family name can match either the
|
||||
// @font-face family or the system font family so both names are added
|
||||
// here.
|
||||
//
|
||||
// http://www.w3.org/TR/2002/WD-css3-webfonts-20020802 required
|
||||
// looking for locally-installed fonts matching requested properties
|
||||
// before checking the src descriptor in @font-face rules.
|
||||
// http://www.w3.org/TR/2008/REC-CSS2-20080411/fonts.html#algorithm
|
||||
// also only checks src descriptors if there is no local font matching
|
||||
// the requested properties.
|
||||
//
|
||||
// Similarly "Editor's Draft 27 June 2008"
|
||||
// http://dev.w3.org/csswg/css3-fonts/#font-matching says "The user
|
||||
// agent attempts to find the family name among fonts available on the
|
||||
// system and then among fonts defined via @font-face rules."
|
||||
// However, this is contradicted by "if [the name from the font-family
|
||||
// descriptor] is the same as a font family available in a given
|
||||
// user's environment, it effectively hides the underlying font for
|
||||
// documents that use the stylesheet."
|
||||
//
|
||||
// Windows and Mac code currently prioritizes fonts from @font-face
|
||||
// rules. The order of families here reflects the priorities on those
|
||||
// platforms.
|
||||
const gfxUserFontSet *userFontSet = data->mUserFontSet;
|
||||
if (genericName.Length() == 0 &&
|
||||
userFontSet && userFontSet->HasFamily(fontName)) {
|
||||
nsAutoString userFontName =
|
||||
NS_LITERAL_STRING(FONT_FACE_FAMILY_PREFIX) + fontName;
|
||||
list->AppendElement(userFontName);
|
||||
}
|
||||
|
||||
list->AppendElement(fontName);
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
|
@ -1384,13 +1877,14 @@ gfxPangoFontGroup::Copy(const gfxFontStyle *aStyle)
|
|||
|
||||
// An array of family names suitable for fontconfig
|
||||
void
|
||||
gfxPangoFontGroup::GetFcFamilies(nsStringArray *aFcFamilyList,
|
||||
gfxPangoFontGroup::GetFcFamilies(nsTArray<nsString> *aFcFamilyList,
|
||||
const nsACString& aLangGroup)
|
||||
{
|
||||
FamilyCallbackData data(aFcFamilyList, mUserFontSet);
|
||||
// Leave non-existing fonts in the list so that fontconfig can get the
|
||||
// best match.
|
||||
ForEachFontInternal(mFamilies, aLangGroup, PR_TRUE, PR_FALSE,
|
||||
FontCallback, aFcFamilyList);
|
||||
FamilyCallback, &data);
|
||||
}
|
||||
|
||||
PangoFont *
|
||||
|
@ -1419,6 +1913,21 @@ gfxPangoFontGroup::GetFontAt(PRInt32 i) {
|
|||
return mFonts[0];
|
||||
}
|
||||
|
||||
void
|
||||
gfxPangoFontGroup::UpdateFontList()
|
||||
{
|
||||
if (!mUserFontSet)
|
||||
return;
|
||||
|
||||
PRUint64 newGeneration = mUserFontSet->GetGeneration();
|
||||
if (newGeneration == mCurrGeneration)
|
||||
return;
|
||||
|
||||
mFonts[0] = NULL;
|
||||
mFontSets.Clear();
|
||||
mCurrGeneration = newGeneration;
|
||||
}
|
||||
|
||||
already_AddRefed<gfxFcPangoFontSet>
|
||||
gfxPangoFontGroup::MakeFontSet(PangoLanguage *aLang, gfxFloat aSizeAdjustFactor,
|
||||
nsAutoRef<FcPattern> *aMatchPattern)
|
||||
|
@ -1440,7 +1949,7 @@ gfxPangoFontGroup::MakeFontSet(PangoLanguage *aLang, gfxFloat aSizeAdjustFactor,
|
|||
}
|
||||
}
|
||||
|
||||
nsStringArray fcFamilyList;
|
||||
nsAutoTArray<nsString, 20> fcFamilyList;
|
||||
GetFcFamilies(&fcFamilyList,
|
||||
langGroup ? nsDependentCString(langGroup) : mStyle.langGroup);
|
||||
|
||||
|
@ -1452,7 +1961,8 @@ gfxPangoFontGroup::MakeFontSet(PangoLanguage *aLang, gfxFloat aSizeAdjustFactor,
|
|||
|
||||
PrepareSortPattern(pattern, mStyle.size, aSizeAdjustFactor);
|
||||
|
||||
nsRefPtr<gfxFcPangoFontSet> fontset = new gfxFcPangoFontSet(pattern);
|
||||
nsRefPtr<gfxFcPangoFontSet> fontset =
|
||||
new gfxFcPangoFontSet(pattern, mUserFontSet);
|
||||
|
||||
if (aMatchPattern)
|
||||
aMatchPattern->steal(pattern);
|
||||
|
@ -1494,7 +2004,7 @@ gfxPangoFontGroup::GetFontSet(PangoLanguage *aLang)
|
|||
cairo_user_data_key_t gfxFcFont::sGfxFontKey;
|
||||
|
||||
gfxFcFont::gfxFcFont(cairo_scaled_font_t *aCairoFont,
|
||||
gfxPangoFontEntry *aFontEntry,
|
||||
gfxFontEntry *aFontEntry,
|
||||
const gfxFontStyle *aFontStyle)
|
||||
: gfxFont(aFontEntry, aFontStyle),
|
||||
mCairoFont(aCairoFont),
|
||||
|
@ -1523,9 +2033,61 @@ gfxPangoFontGroup::Shutdown()
|
|||
gPangoFontMap = NULL;
|
||||
}
|
||||
|
||||
// Resetting gFTLibrary in case this is wanted again after a
|
||||
// cairo_debug_reset_static_data.
|
||||
gFTLibrary = NULL;
|
||||
|
||||
NS_IF_RELEASE(gLangService);
|
||||
}
|
||||
|
||||
static FT_Library
|
||||
GetFTLibrary()
|
||||
{
|
||||
if (!gFTLibrary) {
|
||||
// Use cairo's FT_Library so that cairo takes care of shutdown of the
|
||||
// FT_Library after it has destroyed its font_faces, and FT_Done_Face
|
||||
// has been called on each FT_Face, at least until this bug is fixed:
|
||||
// https://bugs.freedesktop.org/show_bug.cgi?id=18857
|
||||
//
|
||||
// Cairo's FT_Library can be obtained from any cairo_scaled_font. The
|
||||
// font properties requested here are chosen to get an FT_Face that is
|
||||
// likely to be also used elsewhere.
|
||||
gfxFontStyle style;
|
||||
nsRefPtr<gfxPangoFontGroup> fontGroup =
|
||||
new gfxPangoFontGroup(NS_LITERAL_STRING("sans-serif"),
|
||||
&style, nsnull);
|
||||
|
||||
gfxFcFont *font = static_cast<gfxFcFont*>(fontGroup->GetFontAt(0));
|
||||
if (!font)
|
||||
return NULL;
|
||||
|
||||
LockedFTFace face(font);
|
||||
if (!face.get())
|
||||
return NULL;
|
||||
|
||||
gFTLibrary = face.get()->glyph->library;
|
||||
}
|
||||
|
||||
return gFTLibrary;
|
||||
}
|
||||
|
||||
/* static */ gfxFontEntry *
|
||||
gfxPangoFontGroup::NewFontEntry(const gfxProxyFontEntry &aProxyEntry,
|
||||
nsISupports *aLoader,
|
||||
const PRUint8 *aFontData, PRUint32 aLength)
|
||||
{
|
||||
// Using face_index = 0 for the first face in the font, as we have no
|
||||
// other information. FT_New_Memory_Face checks for a NULL FT_Library.
|
||||
FT_Face face;
|
||||
FT_Error error =
|
||||
FT_New_Memory_Face(GetFTLibrary(), aFontData, aLength, 0, &face);
|
||||
if (error != 0)
|
||||
return nsnull;
|
||||
|
||||
return new gfxDownloadedFcFontEntry(aProxyEntry, aLoader, face);
|
||||
}
|
||||
|
||||
|
||||
static double
|
||||
GetPixelSize(FcPattern *aPattern)
|
||||
{
|
||||
|
@ -1575,36 +2137,38 @@ gfxFcFont::GetOrMakeFont(FcPattern *aPattern)
|
|||
gfxFontStyle fontStyle(style, weight, size, langGroup, 0.0,
|
||||
PR_TRUE, PR_FALSE);
|
||||
|
||||
FcChar8 *fc_file; // unsigned char
|
||||
const char *file; // signed for Mozilla string APIs
|
||||
nsRefPtr<gfxFontEntry> fe;
|
||||
FcChar8 *fc_file;
|
||||
if (FcPatternGetString(aPattern,
|
||||
FC_FILE, 0, &fc_file) == FcResultMatch) {
|
||||
file = gfxFontconfigUtils::ToCString(fc_file);
|
||||
int index;
|
||||
if (FcPatternGetInteger(aPattern,
|
||||
FC_INDEX, 0, &index) != FcResultMatch) {
|
||||
// cairo won't know what to do with this pattern.
|
||||
NS_NOTREACHED("No index in pattern for font face from file");
|
||||
index = 0;
|
||||
}
|
||||
|
||||
// Get a unique name for the font face data from the file and id.
|
||||
nsAutoString name;
|
||||
AppendUTF8toUTF16(gfxFontconfigUtils::ToCString(fc_file), name);
|
||||
if (index != 0) {
|
||||
name.AppendLiteral("/");
|
||||
name.AppendInt(index);
|
||||
}
|
||||
|
||||
fe = new gfxFontEntry(name);
|
||||
} else {
|
||||
// cairo won't know which font to open without a file.
|
||||
// (We don't create fonts from an FT_Face.)
|
||||
NS_NOTREACHED("Fonts without a file are not supported");
|
||||
static const char *noFile = "NO FILE";
|
||||
file = noFile;
|
||||
}
|
||||
int index;
|
||||
if (FcPatternGetInteger(aPattern, FC_INDEX, 0, &index)
|
||||
!= FcResultMatch) {
|
||||
// cairo won't know what to do here either.
|
||||
NS_NOTREACHED("No index in pattern");
|
||||
index = 0;
|
||||
}
|
||||
// Get a unique face name from the file and id.
|
||||
nsAutoString name;
|
||||
AppendUTF8toUTF16(file, name);
|
||||
if (index != 0) {
|
||||
name.AppendLiteral("/");
|
||||
name.AppendInt(index);
|
||||
fe = GetDownloadedFontEntry(aPattern);
|
||||
if (!fe) {
|
||||
// cairo won't know which font to open without a file.
|
||||
// (We don't create fonts from an FT_Face.)
|
||||
NS_NOTREACHED("Fonts without a file is not a web font!?");
|
||||
fe = new gfxFontEntry(nsString());
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<gfxPangoFontEntry> fe = new gfxPangoFontEntry(name);
|
||||
|
||||
// Note that the unique face in the name/fe and the gfxFontStyle are
|
||||
// Note that a file/index pair (or FT_Face) and the gfxFontStyle are
|
||||
// not necessarily enough to provide a key that will describe a unique
|
||||
// font. cairoFont contains information from aPattern, which is a
|
||||
// fully resolved pattern from FcFontRenderPrepare.
|
||||
|
@ -1664,7 +2228,7 @@ gfxPangoFontGroup::GetBaseFontSet()
|
|||
FcPatternDel(pattern, FC_PIXEL_SIZE);
|
||||
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size);
|
||||
|
||||
fontSet = new gfxFcPangoFontSet(pattern);
|
||||
fontSet = new gfxFcPangoFontSet(pattern, mUserFontSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1725,21 +2289,6 @@ LockedFTFace::GetCharExtents(char aChar,
|
|||
return gid;
|
||||
}
|
||||
|
||||
// rounding and truncation functions for a Freetype fixed point number
|
||||
// (FT26Dot6) stored in a 32bit integer with high 26 bits for the integer
|
||||
// part and low 6 bits for the fractional part.
|
||||
#define FLOAT_FROM_26_6(x) ((x) / 64.0)
|
||||
#define FLOAT_FROM_16_16(x) ((x) / 65536.0)
|
||||
#define ROUND_26_6_TO_INT(x) ((x) >= 0 ? ((32 + (x)) >> 6) \
|
||||
: -((32 - (x)) >> 6))
|
||||
// aScale is intended for a 16.16 x/y_scale of an FT_Size_Metrics
|
||||
static inline FT_Long
|
||||
ScaleRoundDesignUnits(FT_Short aDesignMetric, FT_Fixed aScale)
|
||||
{
|
||||
FT_Long fixed26dot6 = FT_MulFix(aDesignMetric, aScale);
|
||||
return ROUND_26_6_TO_INT(fixed26dot6);
|
||||
}
|
||||
|
||||
// Snap a line to pixels while keeping the center and size of the line as
|
||||
// close to the original position as possible.
|
||||
//
|
||||
|
@ -2131,11 +2680,41 @@ gfxPangoFontGroup::InitTextRun(gfxTextRun *aTextRun, const gchar *aUTF8Text,
|
|||
#endif
|
||||
}
|
||||
|
||||
static void ReleaseDownloadedFontEntry(void *data)
|
||||
{
|
||||
gfxDownloadedFcFontEntry *downloadedFontEntry =
|
||||
static_cast<gfxDownloadedFcFontEntry*>(data);
|
||||
NS_RELEASE(downloadedFontEntry);
|
||||
}
|
||||
|
||||
// This will fetch an existing scaled_font if one exists.
|
||||
static cairo_scaled_font_t *
|
||||
CreateScaledFont(FcPattern *aPattern)
|
||||
{
|
||||
cairo_font_face_t *face = cairo_ft_font_face_create_for_pattern(aPattern);
|
||||
|
||||
// If the face is created from a web font entry, hold a reference to the
|
||||
// font entry to keep the font face data.
|
||||
gfxDownloadedFcFontEntry *downloadedFontEntry =
|
||||
GetDownloadedFontEntry(aPattern);
|
||||
if (downloadedFontEntry &&
|
||||
cairo_font_face_status(face) == CAIRO_STATUS_SUCCESS) {
|
||||
static cairo_user_data_key_t sFontEntryKey;
|
||||
|
||||
// Check whether this is a new cairo face
|
||||
void *currentEntry =
|
||||
cairo_font_face_get_user_data(face, &sFontEntryKey);
|
||||
if (!currentEntry) {
|
||||
NS_ADDREF(downloadedFontEntry);
|
||||
cairo_font_face_set_user_data(face, &sFontEntryKey,
|
||||
downloadedFontEntry,
|
||||
ReleaseDownloadedFontEntry);
|
||||
} else {
|
||||
NS_ASSERTION(currentEntry == downloadedFontEntry,
|
||||
"Unexpected cairo font face!");
|
||||
}
|
||||
}
|
||||
|
||||
double size = GetPixelSize(aPattern);
|
||||
|
||||
cairo_matrix_t fontMatrix;
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#ifdef MOZ_PANGO
|
||||
#include "gfxPangoFonts.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
#else
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
@ -283,6 +284,40 @@ gfxPlatformGtk::CreateFontGroup(const nsAString &aFamilies,
|
|||
return new gfxPangoFontGroup(aFamilies, aStyle, aUserFontSet);
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxPlatformGtk::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
nsISupports *aLoader,
|
||||
const PRUint8 *aFontData, PRUint32 aLength)
|
||||
{
|
||||
// Just being consistent with other platforms.
|
||||
// This will mean that only fonts in SFNT formats will be accepted.
|
||||
if (!gfxFontUtils::ValidateSFNTHeaders(aFontData, aLength))
|
||||
return nsnull;
|
||||
|
||||
return gfxPangoFontGroup::NewFontEntry(*aProxyEntry, aLoader,
|
||||
aFontData, aLength);
|
||||
}
|
||||
|
||||
PRBool
|
||||
gfxPlatformGtk::IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags)
|
||||
{
|
||||
// reject based on format flags
|
||||
if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_EOT | gfxUserFontSet::FLAG_FORMAT_SVG)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Pango doesn't apply features from AAT TrueType extensions.
|
||||
// Assume that if this is the only SFNT format specified,
|
||||
// then AAT extensions are required for complex script support.
|
||||
if ((aFormatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT)
|
||||
&& !(aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_OPENTYPE | gfxUserFontSet::FLAG_FORMAT_TRUETYPE))) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// otherwise, return true
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -129,7 +129,9 @@ gfxPlatformMac::LookupLocalFont(const nsAString& aFontName)
|
|||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxPlatformMac::MakePlatformFont(const gfxFontEntry *aProxyEntry, const PRUint8 *aFontData, PRUint32 aLength)
|
||||
gfxPlatformMac::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
nsISupports *aLoader,
|
||||
const PRUint8 *aFontData, PRUint32 aLength)
|
||||
{
|
||||
return gfxQuartzFontCache::SharedFontCache()->MakePlatformFont(aProxyEntry, aFontData, aLength);
|
||||
}
|
||||
|
|
|
@ -59,11 +59,13 @@ static PRUint64 sFontSetGeneration = LL_INIT(0, 0);
|
|||
// TODO: support for unicode ranges not yet implemented
|
||||
|
||||
gfxProxyFontEntry::gfxProxyFontEntry(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
|
||||
gfxMixedFontFamily *aFamily,
|
||||
PRUint32 aWeight,
|
||||
PRUint32 aStretch,
|
||||
PRUint32 aItalicStyle,
|
||||
gfxSparseBitSet *aUnicodeRanges)
|
||||
: gfxFontEntry(NS_LITERAL_STRING("Proxy")), mIsLoading(PR_FALSE)
|
||||
: gfxFontEntry(NS_LITERAL_STRING("Proxy")), mIsLoading(PR_FALSE),
|
||||
mFamily(aFamily)
|
||||
{
|
||||
mIsProxy = PR_TRUE;
|
||||
mSrcList = aFontFaceSrcList;
|
||||
|
@ -149,10 +151,9 @@ gfxUserFontSet::AddFontFace(const nsAString& aFamilyName,
|
|||
// construct a new face and add it into the family
|
||||
if (family) {
|
||||
gfxProxyFontEntry *proxyEntry =
|
||||
new gfxProxyFontEntry(aFontFaceSrcList, aWeight, aStretch,
|
||||
aItalicStyle, aUnicodeRanges);
|
||||
new gfxProxyFontEntry(aFontFaceSrcList, family, aWeight, aStretch,
|
||||
aItalicStyle, aUnicodeRanges);
|
||||
family->AddFontEntry(proxyEntry);
|
||||
proxyEntry->mFamily = family;
|
||||
#ifdef PR_LOGGING
|
||||
if (LOG_ENABLED()) {
|
||||
LOG(("userfonts (%p) added (%s) with style: %s weight: %d stretch: %d",
|
||||
|
@ -170,12 +171,7 @@ gfxUserFontSet::FindFontEntry(const nsAString& aName,
|
|||
const gfxFontStyle& aFontStyle,
|
||||
PRBool& aNeedsBold)
|
||||
{
|
||||
nsAutoString key(aName);
|
||||
ToLowerCase(key);
|
||||
|
||||
PRBool found;
|
||||
|
||||
gfxMixedFontFamily *family = mFontFamilies.GetWeak(key, &found);
|
||||
gfxMixedFontFamily *family = GetFamily(aName);
|
||||
|
||||
// no user font defined for this name
|
||||
if (!family)
|
||||
|
@ -209,7 +205,8 @@ gfxUserFontSet::FindFontEntry(const nsAString& aName,
|
|||
|
||||
|
||||
PRBool
|
||||
gfxUserFontSet::OnLoadComplete(gfxFontEntry *aFontToLoad,
|
||||
gfxUserFontSet::OnLoadComplete(gfxFontEntry *aFontToLoad,
|
||||
nsISupports *aLoader,
|
||||
const PRUint8 *aFontData, PRUint32 aLength,
|
||||
nsresult aDownloadStatus)
|
||||
{
|
||||
|
@ -223,7 +220,8 @@ gfxUserFontSet::OnLoadComplete(gfxFontEntry *aFontToLoad,
|
|||
// download successful, make platform font using font data
|
||||
if (NS_SUCCEEDED(aDownloadStatus)) {
|
||||
gfxFontEntry *fe =
|
||||
gfxPlatform::GetPlatform()->MakePlatformFont(pe, aFontData, aLength);
|
||||
gfxPlatform::GetPlatform()->MakePlatformFont(pe, aLoader,
|
||||
aFontData, aLength);
|
||||
if (fe) {
|
||||
pe->mFamily->ReplaceFontEntry(pe, fe);
|
||||
IncrementGeneration();
|
||||
|
@ -393,6 +391,16 @@ gfxUserFontSet::IncrementGeneration()
|
|||
}
|
||||
|
||||
|
||||
gfxMixedFontFamily*
|
||||
gfxUserFontSet::GetFamily(const nsAString& aFamilyName) const
|
||||
{
|
||||
nsAutoString key(aFamilyName);
|
||||
ToLowerCase(key);
|
||||
|
||||
return mFontFamilies.GetWeak(key);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gfxUserFontSet::RemoveFamily(const nsAString& aFamilyName)
|
||||
{
|
||||
|
|
|
@ -783,7 +783,8 @@ public:
|
|||
};
|
||||
|
||||
gfxFontEntry*
|
||||
gfxWindowsPlatform::MakePlatformFont(const gfxFontEntry *aProxyEntry,
|
||||
gfxWindowsPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
nsISupports *aLoader,
|
||||
const PRUint8 *aFontData, PRUint32 aLength)
|
||||
{
|
||||
// if calls aren't available, bail
|
||||
|
|
|
@ -2,44 +2,43 @@
|
|||
# can't use file:/// URLs because of cross-directory access restrictions
|
||||
# on file: URLs.
|
||||
|
||||
# numerous tests are marked as failing on Linux due to bug 458169
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) != download-1.html download-1-notref.html
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == download-2.html download-2-ref.html
|
||||
HTTP(..) != download-1.html download-1-notref.html
|
||||
HTTP(..) == download-2.html download-2-ref.html
|
||||
HTTP(..) != download-2.html about:blank
|
||||
HTTP(..) == fallback-to-system-1.html fallback-to-system-1-ref.html
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == name-override-simple-1.html name-override-simple-1-ref.html
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) != name-override-simple-1.html download-1-notref.html
|
||||
HTTP(..) == name-override-simple-1.html name-override-simple-1-ref.html
|
||||
HTTP(..) != name-override-simple-1.html download-1-notref.html
|
||||
fails HTTP(..) == name-override-1.html name-override-1-ref.html
|
||||
HTTP(..) == multiple-descriptor-1.html multiple-descriptor-1-ref.html
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) != multiple-descriptor-1.html multiple-descriptor-1-notref.html
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == src-list-1.html src-list-1-ref.html
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == src-list-2.html src-list-2-ref.html
|
||||
HTTP(..) != multiple-descriptor-1.html multiple-descriptor-1-notref.html
|
||||
HTTP(..) == src-list-1.html src-list-1-ref.html
|
||||
HTTP(..) == src-list-2.html src-list-2-ref.html
|
||||
fails HTTP(..) == src-list-format-1.html src-list-format-1-ref.html # bug 465452
|
||||
fails HTTP(..) == src-list-format-2.html src-list-format-2-ref.html # bug 465452
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == src-list-format-3.html src-list-format-3-ref.html
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == src-list-format-4.html src-list-format-1-ref.html
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == src-list-format-5.html src-list-format-2-ref.html
|
||||
HTTP(..) == src-list-format-3.html src-list-format-3-ref.html
|
||||
HTTP(..) == src-list-format-4.html src-list-format-1-ref.html
|
||||
HTTP(..) == src-list-format-5.html src-list-format-2-ref.html
|
||||
fails HTTP(..) == src-list-format-6.html src-list-format-3-ref.html # bug 465452
|
||||
# FIXME: The behavior here is neither mandated nor specified by the spec, but
|
||||
# it really ought to be.
|
||||
HTTP(..) == order-1.html order-1-ref.html
|
||||
fails HTTP(..) == order-2.html order-2-ref.html # bug 465414
|
||||
fails HTTP(..) == order-3.html order-3-ref.html # bug 465414
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == multiple-in-family-1.html multiple-in-family-1-ref.html
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == multiple-in-family-1b.html multiple-in-family-1-ref.html
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) != multiple-in-family-1.html multiple-in-family-1-notref.html
|
||||
HTTP(..) == multiple-in-family-1.html multiple-in-family-1-ref.html
|
||||
HTTP(..) == multiple-in-family-1b.html multiple-in-family-1-ref.html
|
||||
HTTP(..) != multiple-in-family-1.html multiple-in-family-1-notref.html
|
||||
HTTP(..) == prop-order-over-rule-order-1a.html prop-order-over-rule-order-2a.html
|
||||
HTTP(..) == prop-order-over-rule-order-1b.html prop-order-over-rule-order-2b.html
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) != prop-order-over-rule-order-1a.html prop-order-over-rule-order-1b.html
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == cross-iframe-1.html cross-iframe-1-ref.html
|
||||
HTTP(..) != prop-order-over-rule-order-1a.html prop-order-over-rule-order-1b.html
|
||||
HTTP(..) == cross-iframe-1.html cross-iframe-1-ref.html
|
||||
|
||||
# Dynamic changes
|
||||
skip-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == enable-sheet-1.html enable-sheet-1-ref.html
|
||||
HTTP(..) == enable-sheet-1.html enable-sheet-1-ref.html
|
||||
# we need to skip these because of the bug that's causing order-2.html to fail
|
||||
skip HTTP(..) == enable-sheet-2.html multiple-in-family-1-ref.html
|
||||
skip HTTP(..) == enable-sheet-3.html multiple-in-family-1-ref.html
|
||||
HTTP(..) == enable-sheet-4.html enable-sheet-4-ref.html
|
||||
skip-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == enable-sheet-5.html enable-sheet-4-ref.html
|
||||
HTTP(..) == enable-sheet-5.html enable-sheet-4-ref.html
|
||||
skip HTTP(..) == enable-sheet-6.html multiple-in-family-1-ref.html
|
||||
skip HTTP(..) == enable-sheet-7.html multiple-in-family-1-ref.html
|
||||
HTTP(..) == disable-sheet-1.html disable-sheet-1-ref.html
|
||||
|
@ -47,13 +46,13 @@ HTTP(..) == disable-sheet-1.html disable-sheet-1-ref.html
|
|||
# enable-sheet{2,3,6,7}) because I don't know how to detect test
|
||||
# completion for those cases.
|
||||
HTTP(..) == disable-sheet-4.html disable-sheet-4-ref.html
|
||||
skip-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == disable-sheet-5.html disable-sheet-4-ref.html
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == sheet-set-base-1.html sheet-set-base-1-ref.html
|
||||
skip-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == sheet-set-switch-1.html sheet-set-switch-1-ref.html
|
||||
skip-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == insert-rule-1.html insert-rule-1-ref.html
|
||||
HTTP(..) == disable-sheet-5.html disable-sheet-4-ref.html
|
||||
HTTP(..) == sheet-set-base-1.html sheet-set-base-1-ref.html
|
||||
HTTP(..) == sheet-set-switch-1.html sheet-set-switch-1-ref.html
|
||||
HTTP(..) == insert-rule-1.html insert-rule-1-ref.html
|
||||
HTTP(..) == delete-rule-1.html delete-rule-1-ref.html
|
||||
skip-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == media-query-add-1.html media-query-add-1-ref.html
|
||||
skip-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == media-query-remove-1.html media-query-remove-1-ref.html
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) != media-query-add-1-ref.html media-query-remove-1-ref.html
|
||||
HTTP(..) == media-query-add-1.html media-query-add-1-ref.html
|
||||
HTTP(..) == media-query-remove-1.html media-query-remove-1-ref.html
|
||||
HTTP(..) != media-query-add-1-ref.html media-query-remove-1-ref.html
|
||||
|
||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == ahem-metrics-1.html ahem-metrics-1-ref.html
|
||||
HTTP(..) == ahem-metrics-1.html ahem-metrics-1-ref.html
|
||||
|
|
|
@ -116,7 +116,7 @@ nsFontFaceLoader::OnStreamComplete(nsIStreamLoader* aLoader,
|
|||
PRBool fontUpdate;
|
||||
|
||||
// whether an error occurred or not, notify the user font set of the completion
|
||||
fontUpdate = mLoaderContext->mUserFontSet->OnLoadComplete(mFontEntry,
|
||||
fontUpdate = mLoaderContext->mUserFontSet->OnLoadComplete(mFontEntry, aLoader,
|
||||
aString, aStringLen,
|
||||
aStatus);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче