зеркало из https://github.com/mozilla/gecko-dev.git
Bug 493280: restructure Windows font management based on cross-platform font-list classes. r=jdaggett sr=roc
This commit is contained in:
Родитель
cf2eca0586
Коммит
27f23b384f
|
@ -204,12 +204,12 @@ protected: // new functions
|
|||
PRBool mEnableKerning;
|
||||
|
||||
void GetPrefFonts(const char *aLangGroup,
|
||||
nsTArray<nsRefPtr<FontEntry> >& aFontEntryList);
|
||||
void GetCJKPrefFonts(nsTArray<nsRefPtr<FontEntry> >& aFontEntryList);
|
||||
nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList);
|
||||
void GetCJKPrefFonts(nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList);
|
||||
void FamilyListToArrayList(const nsString& aFamilies,
|
||||
const nsCString& aLangGroup,
|
||||
nsTArray<nsRefPtr<FontEntry> > *aFontEntryList);
|
||||
already_AddRefed<gfxFT2Font> WhichFontSupportsChar(const nsTArray<nsRefPtr<FontEntry> >& aFontEntryList,
|
||||
nsTArray<nsRefPtr<gfxFontEntry> > *aFontEntryList);
|
||||
already_AddRefed<gfxFT2Font> WhichFontSupportsChar(const nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList,
|
||||
PRUint32 aCh);
|
||||
already_AddRefed<gfxFont> WhichPrefFontSupportsChar(PRUint32 aCh);
|
||||
already_AddRefed<gfxFont> WhichSystemFontSupportsChar(PRUint32 aCh);
|
||||
|
|
|
@ -165,6 +165,7 @@ public:
|
|||
mIsProxy(PR_FALSE), mIsValid(PR_TRUE),
|
||||
mIsBadUnderlineFont(PR_FALSE), mIsUserFont(PR_FALSE),
|
||||
mStandardFace(aIsStandardFace),
|
||||
mSymbolFont(PR_FALSE),
|
||||
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
||||
mCmapInitialized(PR_FALSE), mUserFontData(nsnull),
|
||||
mFamily(aFamily)
|
||||
|
@ -176,6 +177,7 @@ public:
|
|||
mIsValid(aEntry.mIsValid), mIsBadUnderlineFont(aEntry.mIsBadUnderlineFont),
|
||||
mIsUserFont(aEntry.mIsUserFont),
|
||||
mStandardFace(aEntry.mStandardFace),
|
||||
mSymbolFont(aEntry.mSymbolFont),
|
||||
mWeight(aEntry.mWeight), mCmapInitialized(aEntry.mCmapInitialized),
|
||||
mCharacterMap(aEntry.mCharacterMap), mUserFontData(aEntry.mUserFontData),
|
||||
mFamily(aEntry.mFamily)
|
||||
|
@ -186,13 +188,14 @@ public:
|
|||
// unique name for the face, *not* the family
|
||||
const nsString& Name() const { return mName; }
|
||||
|
||||
PRUint16 Weight() { return mWeight; }
|
||||
PRInt16 Stretch() { return mStretch; }
|
||||
PRUint16 Weight() const { return mWeight; }
|
||||
PRInt16 Stretch() const { return mStretch; }
|
||||
|
||||
PRBool IsUserFont() { return mIsUserFont; }
|
||||
PRBool IsFixedPitch() { return mFixedPitch; }
|
||||
PRBool IsItalic() { return mItalic; }
|
||||
PRBool IsBold() { return mWeight >= 600; } // bold == weights 600 and above
|
||||
PRBool IsUserFont() const { return mIsUserFont; }
|
||||
PRBool IsFixedPitch() const { return mFixedPitch; }
|
||||
PRBool IsItalic() const { return mItalic; }
|
||||
PRBool IsBold() const { return mWeight >= 600; } // bold == weights 600 and above
|
||||
PRBool IsSymbolFont() const { return mSymbolFont; }
|
||||
|
||||
inline PRBool HasCharacter(PRUint32 ch) {
|
||||
if (mCharacterMap.test(ch))
|
||||
|
@ -204,6 +207,13 @@ public:
|
|||
virtual PRBool TestCharacterMap(PRUint32 aCh);
|
||||
virtual nsresult ReadCMAP();
|
||||
|
||||
virtual PRBool MatchesGenericFamily(const nsACString& aGeneric) const {
|
||||
return PR_TRUE;
|
||||
}
|
||||
virtual PRBool SupportsLangGroup(const nsACString& aLangGroup) const {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
const nsString& FamilyName();
|
||||
|
||||
nsString mName;
|
||||
|
@ -215,6 +225,7 @@ public:
|
|||
PRPackedBool mIsBadUnderlineFont : 1;
|
||||
PRPackedBool mIsUserFont : 1;
|
||||
PRPackedBool mStandardFace : 1;
|
||||
PRPackedBool mSymbolFont : 1;
|
||||
|
||||
PRUint16 mWeight;
|
||||
PRInt16 mStretch;
|
||||
|
@ -235,6 +246,7 @@ protected:
|
|||
mIsBadUnderlineFont(PR_FALSE),
|
||||
mIsUserFont(PR_FALSE),
|
||||
mStandardFace(PR_FALSE),
|
||||
mSymbolFont(PR_FALSE),
|
||||
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
||||
mCmapInitialized(PR_FALSE),
|
||||
mUserFontData(nsnull),
|
||||
|
|
|
@ -57,246 +57,7 @@
|
|||
// exceptions. use gfxSparseBitSet instead?
|
||||
#include <bitset>
|
||||
|
||||
/**
|
||||
* List of different types of fonts we support on Windows.
|
||||
* These can generally be lumped in to 3 categories where we have to
|
||||
* do special things: Really old fonts bitmap and vector fonts (device
|
||||
* and raster), Type 1 fonts, and TrueType/OpenType fonts.
|
||||
*
|
||||
* This list is sorted in order from least prefered to most prefered.
|
||||
* We prefer Type1 fonts over OpenType fonts to avoid falling back to
|
||||
* things like Arial (opentype) when you ask for Helvetica (type1)
|
||||
**/
|
||||
enum gfxWindowsFontType {
|
||||
GFX_FONT_TYPE_UNKNOWN = 0,
|
||||
GFX_FONT_TYPE_DEVICE,
|
||||
GFX_FONT_TYPE_RASTER,
|
||||
GFX_FONT_TYPE_TRUETYPE,
|
||||
GFX_FONT_TYPE_PS_OPENTYPE,
|
||||
GFX_FONT_TYPE_TT_OPENTYPE,
|
||||
GFX_FONT_TYPE_TYPE1
|
||||
};
|
||||
|
||||
/**
|
||||
* FontFamily is a class that describes one of the fonts on the users system. It holds
|
||||
* each FontEntry (maps more directly to a font face) which holds font type, charset info
|
||||
* and character map info.
|
||||
*/
|
||||
class FontEntry;
|
||||
class FontFamily : public gfxFontFamily
|
||||
{
|
||||
public:
|
||||
FontFamily(const nsAString& aName) :
|
||||
gfxFontFamily(aName), mIsBadUnderlineFontFamily(PR_FALSE) { }
|
||||
|
||||
FontEntry *FindFontEntry(const gfxFontStyle& aFontStyle);
|
||||
|
||||
private:
|
||||
friend class gfxWindowsPlatform;
|
||||
|
||||
void FindStyleVariations();
|
||||
|
||||
static int CALLBACK FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
const NEWTEXTMETRICEXW *nmetrics,
|
||||
DWORD fontType, LPARAM data);
|
||||
|
||||
protected:
|
||||
PRBool FindWeightsForStyle(gfxFontEntry* aFontsForWeights[],
|
||||
PRBool anItalic, PRInt16 aStretch);
|
||||
|
||||
public:
|
||||
PRPackedBool mIsBadUnderlineFontFamily;
|
||||
};
|
||||
|
||||
class FontEntry : public gfxFontEntry
|
||||
{
|
||||
public:
|
||||
FontEntry(const nsAString& aFaceName, gfxWindowsFontType aFontType,
|
||||
PRBool aItalic, PRUint16 aWeight, gfxUserFontData *aUserFontData) :
|
||||
gfxFontEntry(aFaceName), mFontType(aFontType),
|
||||
mForceGDI(PR_FALSE), mUnknownCMAP(PR_FALSE),
|
||||
mUnicodeFont(PR_FALSE), mSymbolFont(PR_FALSE),
|
||||
mCharset(), mUnicodeRanges()
|
||||
{
|
||||
mUserFontData = aUserFontData;
|
||||
mItalic = aItalic;
|
||||
mWeight = aWeight;
|
||||
if (IsType1())
|
||||
mForceGDI = PR_TRUE;
|
||||
mIsUserFont = aUserFontData != nsnull;
|
||||
}
|
||||
|
||||
FontEntry(const FontEntry& aFontEntry) :
|
||||
gfxFontEntry(aFontEntry),
|
||||
mWindowsFamily(aFontEntry.mWindowsFamily),
|
||||
mWindowsPitch(aFontEntry.mWindowsPitch),
|
||||
mFontType(aFontEntry.mFontType),
|
||||
mForceGDI(aFontEntry.mForceGDI),
|
||||
mUnknownCMAP(aFontEntry.mUnknownCMAP),
|
||||
mUnicodeFont(aFontEntry.mUnicodeFont),
|
||||
mSymbolFont(aFontEntry.mSymbolFont),
|
||||
mCharset(aFontEntry.mCharset),
|
||||
mUnicodeRanges(aFontEntry.mUnicodeRanges)
|
||||
{
|
||||
|
||||
}
|
||||
static void InitializeFontEmbeddingProcs();
|
||||
|
||||
// create a font entry from downloaded font data
|
||||
static FontEntry* LoadFont(const gfxProxyFontEntry &aProxyEntry,
|
||||
const PRUint8 *aFontData,
|
||||
PRUint32 aLength);
|
||||
|
||||
// create a font entry for a font with a given name
|
||||
static FontEntry* CreateFontEntry(const nsAString& aName,
|
||||
gfxWindowsFontType aFontType,
|
||||
PRBool aItalic, PRUint16 aWeight,
|
||||
gfxUserFontData* aUserFontData,
|
||||
HDC hdc = 0, LOGFONTW *aLogFont = nsnull);
|
||||
|
||||
// create a font entry for a font referenced by its fullname
|
||||
static FontEntry* LoadLocalFont(const gfxProxyFontEntry &aProxyEntry,
|
||||
const nsAString& aFullname);
|
||||
|
||||
static void FillLogFont(LOGFONTW *aLogFont, const nsAString& aName,
|
||||
gfxWindowsFontType aFontType, PRBool aItalic,
|
||||
PRUint16 aWeight, gfxFloat aSize);
|
||||
|
||||
static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics,
|
||||
DWORD fontType)
|
||||
{
|
||||
gfxWindowsFontType feType;
|
||||
if (metrics.ntmFlags & NTM_TYPE1)
|
||||
feType = GFX_FONT_TYPE_TYPE1;
|
||||
else if (metrics.ntmFlags & NTM_PS_OPENTYPE)
|
||||
feType = GFX_FONT_TYPE_PS_OPENTYPE;
|
||||
else if (metrics.ntmFlags & NTM_TT_OPENTYPE)
|
||||
feType = GFX_FONT_TYPE_TT_OPENTYPE;
|
||||
else if (fontType == TRUETYPE_FONTTYPE)
|
||||
feType = GFX_FONT_TYPE_TRUETYPE;
|
||||
else if (fontType == RASTER_FONTTYPE)
|
||||
feType = GFX_FONT_TYPE_RASTER;
|
||||
else if (fontType == DEVICE_FONTTYPE)
|
||||
feType = GFX_FONT_TYPE_DEVICE;
|
||||
else
|
||||
feType = GFX_FONT_TYPE_UNKNOWN;
|
||||
|
||||
return feType;
|
||||
}
|
||||
|
||||
PRBool IsType1() const {
|
||||
return (mFontType == GFX_FONT_TYPE_TYPE1);
|
||||
}
|
||||
|
||||
PRBool IsTrueType() const {
|
||||
return (mFontType == GFX_FONT_TYPE_TRUETYPE ||
|
||||
mFontType == GFX_FONT_TYPE_PS_OPENTYPE ||
|
||||
mFontType == GFX_FONT_TYPE_TT_OPENTYPE);
|
||||
}
|
||||
|
||||
PRBool IsCrappyFont() const {
|
||||
/* return if it is a bitmap not a unicode font */
|
||||
return (!mUnicodeFont || mSymbolFont || IsType1());
|
||||
}
|
||||
|
||||
PRBool MatchesGenericFamily(const nsACString& aGeneric) const {
|
||||
if (aGeneric.IsEmpty())
|
||||
return PR_TRUE;
|
||||
|
||||
// Japanese 'Mincho' fonts do not belong to FF_MODERN even if
|
||||
// they are fixed pitch because they have variable stroke width.
|
||||
if (mWindowsFamily == FF_ROMAN && mWindowsPitch & FIXED_PITCH) {
|
||||
return aGeneric.EqualsLiteral("monospace");
|
||||
}
|
||||
|
||||
// Japanese 'Gothic' fonts do not belong to FF_SWISS even if
|
||||
// they are variable pitch because they have constant stroke width.
|
||||
if (mWindowsFamily == FF_MODERN && mWindowsPitch & VARIABLE_PITCH) {
|
||||
return aGeneric.EqualsLiteral("sans-serif");
|
||||
}
|
||||
|
||||
// All other fonts will be grouped correctly using family...
|
||||
switch (mWindowsFamily) {
|
||||
case FF_DONTCARE:
|
||||
return PR_TRUE;
|
||||
case FF_ROMAN:
|
||||
return aGeneric.EqualsLiteral("serif");
|
||||
case FF_SWISS:
|
||||
return aGeneric.EqualsLiteral("sans-serif");
|
||||
case FF_MODERN:
|
||||
return aGeneric.EqualsLiteral("monospace");
|
||||
case FF_SCRIPT:
|
||||
return aGeneric.EqualsLiteral("cursive");
|
||||
case FF_DECORATIVE:
|
||||
return aGeneric.EqualsLiteral("fantasy");
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool SupportsLangGroup(const nsACString& aLangGroup) const {
|
||||
if (aLangGroup.IsEmpty())
|
||||
return PR_TRUE;
|
||||
|
||||
PRInt16 bit = -1;
|
||||
|
||||
/* map our langgroup names in to Windows charset bits */
|
||||
if (aLangGroup.EqualsLiteral("x-western")) {
|
||||
bit = ANSI_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("ja")) {
|
||||
bit = SHIFTJIS_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("ko")) {
|
||||
bit = HANGEUL_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("ko-XXX")) {
|
||||
bit = JOHAB_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("zh-CN")) {
|
||||
bit = GB2312_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("zh-TW")) {
|
||||
bit = CHINESEBIG5_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("el")) {
|
||||
bit = GREEK_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("tr")) {
|
||||
bit = TURKISH_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("he")) {
|
||||
bit = HEBREW_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("ar")) {
|
||||
bit = ARABIC_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("x-baltic")) {
|
||||
bit = BALTIC_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("x-cyrillic")) {
|
||||
bit = RUSSIAN_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("th")) {
|
||||
bit = THAI_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("x-central-euro")) {
|
||||
bit = EASTEUROPE_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("x-symbol")) {
|
||||
bit = SYMBOL_CHARSET;
|
||||
}
|
||||
|
||||
if (bit != -1)
|
||||
return mCharset[bit];
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool SupportsRange(PRUint8 range) {
|
||||
return mUnicodeRanges[range];
|
||||
}
|
||||
|
||||
PRBool TestCharacterMap(PRUint32 aCh);
|
||||
|
||||
PRUint8 mWindowsFamily;
|
||||
PRUint8 mWindowsPitch;
|
||||
|
||||
gfxWindowsFontType mFontType;
|
||||
PRPackedBool mForceGDI : 1;
|
||||
PRPackedBool mUnknownCMAP : 1;
|
||||
PRPackedBool mUnicodeFont : 1;
|
||||
PRPackedBool mSymbolFont : 1;
|
||||
|
||||
std::bitset<256> mCharset;
|
||||
std::bitset<128> mUnicodeRanges;
|
||||
};
|
||||
class GDIFontEntry;
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
|
@ -306,7 +67,7 @@ public:
|
|||
|
||||
class gfxWindowsFont : public gfxFont {
|
||||
public:
|
||||
gfxWindowsFont(FontEntry *aFontEntry, const gfxFontStyle *aFontStyle,
|
||||
gfxWindowsFont(gfxFontEntry *aFontEntry, const gfxFontStyle *aFontStyle,
|
||||
cairo_antialias_t anAntialiasOption = CAIRO_ANTIALIAS_DEFAULT);
|
||||
virtual ~gfxWindowsFont();
|
||||
|
||||
|
@ -336,10 +97,10 @@ public:
|
|||
};
|
||||
|
||||
PRBool IsValid() { GetMetrics(); return mIsValid; }
|
||||
FontEntry *GetFontEntry();
|
||||
GDIFontEntry *GetFontEntry();
|
||||
|
||||
static already_AddRefed<gfxWindowsFont>
|
||||
GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle,
|
||||
GetOrMakeFont(gfxFontEntry *aFontEntry, const gfxFontStyle *aStyle,
|
||||
PRBool aNeedsBold = PR_FALSE);
|
||||
|
||||
protected:
|
||||
|
@ -390,28 +151,26 @@ public:
|
|||
return mGenericFamily;
|
||||
}
|
||||
|
||||
const nsTArray<nsRefPtr<FontEntry> >& GetFontList() const {
|
||||
return mFontEntries;
|
||||
}
|
||||
PRUint32 FontListLength() const {
|
||||
return mFontEntries.Length();
|
||||
}
|
||||
|
||||
FontEntry *GetFontEntryAt(PRInt32 i) {
|
||||
return mFontEntries[i];
|
||||
}
|
||||
|
||||
virtual gfxWindowsFont *GetFontAt(PRInt32 i);
|
||||
|
||||
void GroupFamilyListToArrayList(nsTArray<nsRefPtr<FontEntry> > *list,
|
||||
void GroupFamilyListToArrayList(nsTArray<nsRefPtr<gfxFontEntry> > *list,
|
||||
nsTArray<PRPackedBool> *aNeedsBold);
|
||||
void FamilyListToArrayList(const nsString& aFamilies,
|
||||
const nsCString& aLangGroup,
|
||||
nsTArray<nsRefPtr<FontEntry> > *list);
|
||||
nsTArray<nsRefPtr<gfxFontEntry> > *list);
|
||||
|
||||
void UpdateFontList();
|
||||
virtual void UpdateFontList();
|
||||
virtual gfxFloat GetUnderlineOffset();
|
||||
|
||||
gfxWindowsFont* GetFontAt(PRInt32 aFontIndex) {
|
||||
// If it turns out to be hard for all clients that cache font
|
||||
// groups to call UpdateFontList at appropriate times, we could
|
||||
// instead consider just calling UpdateFontList from someplace
|
||||
// more central (such as here).
|
||||
NS_ASSERTION(!mUserFontSet || mCurrGeneration == GetGeneration(),
|
||||
"Whoever was caching this font group should have "
|
||||
"called UpdateFontList on it");
|
||||
|
||||
return static_cast<gfxWindowsFont*>(static_cast<gfxFont*>(mFonts[aFontIndex]));
|
||||
}
|
||||
|
||||
protected:
|
||||
void InitFontList();
|
||||
|
@ -423,14 +182,19 @@ protected:
|
|||
already_AddRefed<gfxFont> WhichPrefFontSupportsChar(PRUint32 aCh);
|
||||
already_AddRefed<gfxFont> WhichSystemFontSupportsChar(PRUint32 aCh);
|
||||
|
||||
already_AddRefed<gfxWindowsFont> WhichFontSupportsChar(const nsTArray<nsRefPtr<FontEntry> >& fonts, PRUint32 ch);
|
||||
void GetPrefFonts(const char *aLangGroup, nsTArray<nsRefPtr<FontEntry> >& array);
|
||||
void GetCJKPrefFonts(nsTArray<nsRefPtr<FontEntry> >& array);
|
||||
already_AddRefed<gfxWindowsFont> WhichFontSupportsChar(const nsTArray<nsRefPtr<gfxFontEntry> >& fonts, PRUint32 ch);
|
||||
void GetPrefFonts(const char *aLangGroup, nsTArray<nsRefPtr<gfxFontEntry> >& array);
|
||||
void GetCJKPrefFonts(nsTArray<nsRefPtr<gfxFontEntry> >& array);
|
||||
|
||||
static PRBool FindWindowsFont(const nsAString& aName,
|
||||
const nsACString& aGenericName,
|
||||
void *closure);
|
||||
|
||||
PRBool HasFont(gfxFontEntry *aFontEntry);
|
||||
|
||||
private:
|
||||
|
||||
nsCString mGenericFamily;
|
||||
nsTArray<nsRefPtr<FontEntry> > mFontEntries;
|
||||
nsTArray<PRPackedBool> mFontNeedsBold;
|
||||
|
||||
const char *mItemLangGroup; // used by pref-lang handling code
|
||||
|
|
|
@ -61,7 +61,7 @@ typedef struct FT_LibraryRec_ *FT_Library;
|
|||
|
||||
#include <windows.h>
|
||||
|
||||
class THEBES_API gfxWindowsPlatform : public gfxPlatform, private gfxFontInfoLoader {
|
||||
class THEBES_API gfxWindowsPlatform : public gfxPlatform {
|
||||
public:
|
||||
gfxWindowsPlatform();
|
||||
virtual ~gfxWindowsPlatform();
|
||||
|
@ -69,6 +69,8 @@ public:
|
|||
return (gfxWindowsPlatform*) gfxPlatform::GetPlatform();
|
||||
}
|
||||
|
||||
virtual gfxPlatformFontList* CreatePlatformFontList();
|
||||
|
||||
already_AddRefed<gfxASurface> CreateOffscreenSurface(const gfxIntSize& size,
|
||||
gfxASurface::gfxImageFormat imageFormat);
|
||||
|
||||
|
@ -104,8 +106,6 @@ public:
|
|||
|
||||
nsresult UpdateFontList();
|
||||
|
||||
void GetFontFamilyList(nsTArray<nsRefPtr<FontFamily> >& aFamilyArray);
|
||||
|
||||
nsresult ResolveFontName(const nsAString& aFontName,
|
||||
FontResolverCallback aCallback,
|
||||
void *aClosure, PRBool& aAborted);
|
||||
|
@ -134,32 +134,17 @@ public:
|
|||
*/
|
||||
virtual PRBool IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags);
|
||||
|
||||
/* Given a string and a font we already have find the font that
|
||||
* supports the most code points and most closely resembles aFont
|
||||
*
|
||||
* this involves looking at the fonts on your machine and seeing which
|
||||
* code points they support as well as looking at things like the font
|
||||
* family, style, weight, etc.
|
||||
*/
|
||||
already_AddRefed<gfxFont>
|
||||
FindFontForChar(PRUint32 aCh, gfxFont *aFont);
|
||||
|
||||
/* Find a FontFamily/FontEntry object that represents a font on your system given a name */
|
||||
FontFamily *FindFontFamily(const nsAString& aName);
|
||||
FontEntry *FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle);
|
||||
gfxFontFamily *FindFontFamily(const nsAString& aName);
|
||||
gfxFontEntry *FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle);
|
||||
|
||||
PRBool GetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> > *array);
|
||||
void SetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> >& array);
|
||||
PRBool GetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<gfxFontEntry> > *array);
|
||||
void SetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<gfxFontEntry> >& array);
|
||||
|
||||
void ClearPrefFonts() { mPrefFonts.Clear(); }
|
||||
|
||||
typedef nsDataHashtable<nsStringHashKey, nsRefPtr<FontFamily> > FontTable;
|
||||
|
||||
#ifdef MOZ_FT2_FONTS
|
||||
FT_Library GetFTLibrary();
|
||||
private:
|
||||
void AppendFacesFromFontFile(const PRUnichar *aFileName);
|
||||
void FindFonts();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
@ -170,59 +155,10 @@ protected:
|
|||
private:
|
||||
void Init();
|
||||
|
||||
void InitBadUnderlineList();
|
||||
|
||||
static int CALLBACK FontEnumProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
const NEWTEXTMETRICEXW *metrics,
|
||||
DWORD fontType, LPARAM data);
|
||||
static int CALLBACK FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
const NEWTEXTMETRICEXW *nmetrics,
|
||||
DWORD fontType, LPARAM data);
|
||||
|
||||
static PLDHashOperator FontGetStylesProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontFamily>& aFontFamily,
|
||||
void* userArg);
|
||||
|
||||
static PLDHashOperator FontGetCMapDataProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontFamily>& aFontFamily,
|
||||
void* userArg);
|
||||
|
||||
static int CALLBACK FontResolveProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
const NEWTEXTMETRICEXW *metrics,
|
||||
DWORD fontType, LPARAM data);
|
||||
|
||||
static PLDHashOperator HashEnumFunc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontFamily>& aData,
|
||||
void* userArg);
|
||||
|
||||
static PLDHashOperator FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontFamily>& aFontFamily,
|
||||
void* userArg);
|
||||
|
||||
virtual qcms_profile* GetPlatformCMSOutputProfile();
|
||||
|
||||
static int PrefChangedCallback(const char*, void*);
|
||||
|
||||
// gfxFontInfoLoader overrides, used to load in font cmaps
|
||||
virtual void InitLoader();
|
||||
virtual PRBool RunLoader();
|
||||
virtual void FinishLoader();
|
||||
|
||||
FontTable mFonts;
|
||||
FontTable mFontAliases;
|
||||
FontTable mFontSubstitutes;
|
||||
nsTArray<nsString> mNonExistingFonts;
|
||||
|
||||
// when system-wide font lookup fails for a character, cache it to skip future searches
|
||||
gfxSparseBitSet mCodepointsWithNoFonts;
|
||||
|
||||
nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<FontEntry> > > mPrefFonts;
|
||||
|
||||
// data used as part of the font cmap loading process
|
||||
nsTArray<nsRefPtr<FontFamily> > mFontFamilies;
|
||||
PRUint32 mStartIndex;
|
||||
PRUint32 mIncrement;
|
||||
PRUint32 mNumFamilies;
|
||||
// TODO: unify this with mPrefFonts (NB: holds families, not fonts) in gfxPlatformFontList
|
||||
nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<gfxFontEntry> > > mPrefFonts;
|
||||
};
|
||||
|
||||
#endif /* GFX_WINDOWS_PLATFORM_H */
|
||||
|
|
|
@ -56,10 +56,13 @@ CPPSRCS += gfxFT2Fonts.cpp \
|
|||
gfxFT2FontBase.cpp \
|
||||
gfxFT2Utils.cpp \
|
||||
gfxDDrawSurface.cpp \
|
||||
gfxFT2FontList.cpp \
|
||||
$(NULL)
|
||||
EXTRA_DSO_LDOPTS += ddraw.lib
|
||||
else
|
||||
CPPSRCS += gfxWindowsFonts.cpp
|
||||
CPPSRCS += gfxWindowsFonts.cpp \
|
||||
gfxGDIFontList.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
CPPSRCS += gfxPDFSurface.cpp
|
||||
|
|
|
@ -0,0 +1,286 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stuart Parmenter <stuart@mozilla.com>
|
||||
* Masayuki Nakano <masayuki@d-toybox.com>
|
||||
* Mats Palmgren <mats.palmgren@bredband.net>
|
||||
* John Daggett <jdaggett@mozilla.com>
|
||||
* Jonathan Kew <jfkthame@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "gfxFT2FontList.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
#include "gfxFontUtils.h"
|
||||
|
||||
#include "ft2build.h"
|
||||
#include FT_FREETYPE_H
|
||||
#include "gfxFT2Fonts.h"
|
||||
|
||||
#include "nsIPref.h" // for pref changes callback notification
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIWindowsRegKey.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#define ROUND(x) floor((x) + 0.5)
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo *gFontInfoLog = PR_NewLogModule("fontInfoLog");
|
||||
#endif /* PR_LOGGING */
|
||||
|
||||
#define LOG(args) PR_LOG(gFontInfoLog, PR_LOG_DEBUG, args)
|
||||
#define LOG_ENABLED() PR_LOG_TEST(gFontInfoLog, PR_LOG_DEBUG)
|
||||
|
||||
static __inline void
|
||||
BuildKeyNameFromFontName(nsAString &aName)
|
||||
{
|
||||
if (aName.Length() >= LF_FACESIZE)
|
||||
aName.Truncate(LF_FACESIZE - 1);
|
||||
ToLowerCase(aName);
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* gfxFT2FontList
|
||||
*
|
||||
*/
|
||||
|
||||
// For Mobile, we use gfxFT2Fonts, and we build the font list by directly scanning
|
||||
// the system's Fonts directory for OpenType and TrueType files.
|
||||
//
|
||||
// FontEntry is currently defined in gfxFT2Fonts.h, but will probably be moved here
|
||||
// as part of the Freetype/Linux font restructuring for Harfbuzz integration.
|
||||
//
|
||||
// TODO: investigate startup performance - we might be able to improve by avoiding
|
||||
// the creation of FT_Faces here, and just reading names directly from the file;
|
||||
// or even consider caching a mapping from font family name to (list of) filenames,
|
||||
// so that we don't have to scan all the files before we can do any font lookups.
|
||||
|
||||
gfxFT2FontList::gfxFT2FontList()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
gfxFT2FontList::AppendFacesFromFontFile(const PRUnichar *aFileName)
|
||||
{
|
||||
char fileName[MAX_PATH];
|
||||
WideCharToMultiByte(CP_ACP, 0, aFileName, -1, fileName, MAX_PATH, NULL, NULL);
|
||||
FT_Library ftLibrary = gfxWindowsPlatform::GetPlatform()->GetFTLibrary();
|
||||
FT_Face dummy;
|
||||
if (FT_Err_Ok == FT_New_Face(ftLibrary, fileName, -1, &dummy)) {
|
||||
for (FT_Long i = 0; i < dummy->num_faces; i++) {
|
||||
FT_Face face;
|
||||
if (FT_Err_Ok != FT_New_Face(ftLibrary, fileName, i, &face))
|
||||
continue;
|
||||
|
||||
FontEntry* fe = FontEntry::CreateFontEntryFromFace(face);
|
||||
if (fe) {
|
||||
NS_ConvertUTF8toUTF16 name(face->family_name);
|
||||
BuildKeyNameFromFontName(name);
|
||||
gfxFontFamily *family = mFontFamilies.GetWeak(name);
|
||||
if (!family) {
|
||||
family = new gfxFontFamily(name);
|
||||
mFontFamilies.Put(name, family);
|
||||
}
|
||||
family->AddFontEntry(fe);
|
||||
family->SetHasStyles(PR_TRUE);
|
||||
#ifdef PR_LOGGING
|
||||
if (LOG_ENABLED()) {
|
||||
LOG(("(fontinit) added (%s) to family (%s)"
|
||||
" with style: %s weight: %d stretch: %d",
|
||||
NS_ConvertUTF16toUTF8(fe->Name()).get(),
|
||||
NS_ConvertUTF16toUTF8(family->Name()).get(),
|
||||
fe->IsItalic() ? "italic" : "normal",
|
||||
fe->Weight(), fe->Stretch()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
FT_Done_Face(dummy);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxFT2FontList::FindFonts()
|
||||
{
|
||||
nsTArray<nsString> searchPaths(3);
|
||||
nsTArray<nsString> fontPatterns(3);
|
||||
fontPatterns.AppendElement(NS_LITERAL_STRING("\\*.ttf"));
|
||||
fontPatterns.AppendElement(NS_LITERAL_STRING("\\*.ttc"));
|
||||
fontPatterns.AppendElement(NS_LITERAL_STRING("\\*.otf"));
|
||||
wchar_t pathBuf[256];
|
||||
SHGetSpecialFolderPathW(0, pathBuf, CSIDL_WINDOWS, 0);
|
||||
searchPaths.AppendElement(pathBuf);
|
||||
SHGetSpecialFolderPathW(0, pathBuf, CSIDL_FONTS, 0);
|
||||
searchPaths.AppendElement(pathBuf);
|
||||
nsCOMPtr<nsIFile> resDir;
|
||||
NS_GetSpecialDirectory(NS_APP_RES_DIR, getter_AddRefs(resDir));
|
||||
if (resDir) {
|
||||
resDir->Append(NS_LITERAL_STRING("fonts"));
|
||||
nsAutoString resPath;
|
||||
resDir->GetPath(resPath);
|
||||
searchPaths.AppendElement(resPath);
|
||||
}
|
||||
WIN32_FIND_DATAW results;
|
||||
for (PRUint32 i = 0; i < searchPaths.Length(); i++) {
|
||||
const nsString& path(searchPaths[i]);
|
||||
for (PRUint32 j = 0; j < fontPatterns.Length(); j++) {
|
||||
nsAutoString pattern(path);
|
||||
pattern.Append(fontPatterns[j]);
|
||||
HANDLE handle = FindFirstFileExW(pattern.get(),
|
||||
FindExInfoStandard,
|
||||
&results,
|
||||
FindExSearchNameMatch,
|
||||
NULL,
|
||||
0);
|
||||
PRBool moreFiles = handle != INVALID_HANDLE_VALUE;
|
||||
while (moreFiles) {
|
||||
nsAutoString filePath(path);
|
||||
filePath.AppendLiteral("\\");
|
||||
filePath.Append(results.cFileName);
|
||||
AppendFacesFromFontFile(static_cast<const PRUnichar*>(filePath.get()));
|
||||
moreFiles = FindNextFile(handle, &results);
|
||||
}
|
||||
if (handle != INVALID_HANDLE_VALUE)
|
||||
FindClose(handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxFT2FontList::InitFontList()
|
||||
{
|
||||
mFontFamilies.Clear();
|
||||
mOtherFamilyNames.Clear();
|
||||
mOtherFamilyNamesInitialized = PR_FALSE;
|
||||
mPrefFonts.Clear();
|
||||
CancelLoader();
|
||||
|
||||
// initialize ranges of characters for which system-wide font search should be skipped
|
||||
mCodepointsWithNoFonts.reset();
|
||||
mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls
|
||||
mCodepointsWithNoFonts.SetRange(0x7f,0x9f); // C1 controls
|
||||
|
||||
FindFonts();
|
||||
|
||||
InitBadUnderlineList();
|
||||
}
|
||||
|
||||
struct FullFontNameSearch {
|
||||
FullFontNameSearch(const nsAString& aFullName)
|
||||
: mFullName(aFullName), mFontEntry(nsnull)
|
||||
{ }
|
||||
|
||||
nsString mFullName;
|
||||
gfxFontEntry *mFontEntry;
|
||||
};
|
||||
|
||||
// callback called for each family name, based on the assumption that the
|
||||
// first part of the full name is the family name
|
||||
static PLDHashOperator
|
||||
FindFullName(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFontFamily,
|
||||
void* userArg)
|
||||
{
|
||||
FullFontNameSearch *data = reinterpret_cast<FullFontNameSearch*>(userArg);
|
||||
|
||||
// does the family name match up to the length of the family name?
|
||||
const nsString& family = aFontFamily->Name();
|
||||
|
||||
nsString fullNameFamily;
|
||||
data->mFullName.Left(fullNameFamily, family.Length());
|
||||
|
||||
// if so, iterate over faces in this family to see if there is a match
|
||||
if (family.Equals(fullNameFamily)) {
|
||||
nsTArray<nsRefPtr<gfxFontEntry> >& fontList = aFontFamily->GetFontList();
|
||||
int index, len = fontList.Length();
|
||||
for (index = 0; index < len; index++) {
|
||||
if (fontList[index]->Name().Equals(data->mFullName)) {
|
||||
data->mFontEntry = fontList[index];
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxFT2FontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFontName)
|
||||
{
|
||||
// walk over list of names
|
||||
FullFontNameSearch data(aFontName);
|
||||
|
||||
mFontFamilies.Enumerate(FindFullName, &data);
|
||||
|
||||
return data.mFontEntry;
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxFT2FontList::GetDefaultFont(const gfxFontStyle* aStyle, PRBool& aNeedsBold)
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
HGDIOBJ hGDI = ::GetStockObject(SYSTEM_FONT);
|
||||
LOGFONTW logFont;
|
||||
if (hGDI && ::GetObjectW(hGDI, sizeof(logFont), &logFont)) {
|
||||
nsAutoString resolvedName;
|
||||
if (ResolveFontName(nsDependentString(logFont.lfFaceName), resolvedName)) {
|
||||
return FindFontForFamily(resolvedName, aStyle, aNeedsBold);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* TODO: what about Qt or other platforms that may use this? */
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxFT2FontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const PRUint8 *aFontData,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
// The FT2 font needs the font data to persist, so we do NOT free it here
|
||||
// but instead pass ownership to the font entry.
|
||||
// Deallocation will happen later, when the font face is destroyed.
|
||||
return FontEntry::CreateFontEntry(*aProxyEntry, aFontData, aLength);
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stuart Parmenter <stuart@mozilla.com>
|
||||
* Masayuki Nakano <masayuki@d-toybox.com>
|
||||
* John Daggett <jdaggett@mozilla.com>
|
||||
* Jonathan Kew <jfkthame@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef GFX_FT2FONTLIST_H
|
||||
#define GFX_FT2FONTLIST_H
|
||||
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "gfxPlatformFontList.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <bitset>
|
||||
|
||||
class gfxFT2FontList : public gfxPlatformFontList
|
||||
{
|
||||
public:
|
||||
gfxFT2FontList();
|
||||
|
||||
virtual gfxFontEntry* GetDefaultFont(const gfxFontStyle* aStyle,
|
||||
PRBool& aNeedsBold);
|
||||
|
||||
virtual gfxFontEntry* LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFontName);
|
||||
|
||||
virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const PRUint8 *aFontData,
|
||||
PRUint32 aLength);
|
||||
|
||||
protected:
|
||||
virtual void InitFontList();
|
||||
|
||||
void AppendFacesFromFontFile(const PRUnichar *aFileName);
|
||||
void FindFonts();
|
||||
};
|
||||
|
||||
#endif /* GFX_FT2FONTLIST_H */
|
|
@ -47,6 +47,7 @@
|
|||
#endif
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#define gfxToolkitPlatform gfxWindowsPlatform
|
||||
#include "gfxFT2FontList.h"
|
||||
#endif
|
||||
#include "gfxTypes.h"
|
||||
#include "gfxFT2Fonts.h"
|
||||
|
@ -485,7 +486,7 @@ AddFontNameToArray(const nsAString& aName,
|
|||
void
|
||||
gfxFT2FontGroup::FamilyListToArrayList(const nsString& aFamilies,
|
||||
const nsCString& aLangGroup,
|
||||
nsTArray<nsRefPtr<FontEntry> > *aFontEntryList)
|
||||
nsTArray<nsRefPtr<gfxFontEntry> > *aFontEntryList)
|
||||
{
|
||||
nsAutoTArray<nsString, 15> fonts;
|
||||
ForEachFont(aFamilies, aLangGroup, AddFontNameToArray, &fonts);
|
||||
|
@ -493,15 +494,15 @@ gfxFT2FontGroup::FamilyListToArrayList(const nsString& aFamilies,
|
|||
PRUint32 len = fonts.Length();
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
const nsString& str = fonts[i];
|
||||
nsRefPtr<FontEntry> fe = gfxToolkitPlatform::GetPlatform()->FindFontEntry(str, mStyle);
|
||||
nsRefPtr<gfxFontEntry> fe = (gfxToolkitPlatform::GetPlatform()->FindFontEntry(str, mStyle));
|
||||
aFontEntryList->AppendElement(fe);
|
||||
}
|
||||
}
|
||||
|
||||
void gfxFT2FontGroup::GetPrefFonts(const char *aLangGroup, nsTArray<nsRefPtr<FontEntry> >& aFontEntryList) {
|
||||
void gfxFT2FontGroup::GetPrefFonts(const char *aLangGroup, nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList) {
|
||||
NS_ASSERTION(aLangGroup, "aLangGroup is null");
|
||||
gfxToolkitPlatform *platform = gfxToolkitPlatform::GetPlatform();
|
||||
nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
|
||||
nsAutoTArray<nsRefPtr<gfxFontEntry>, 5> fonts;
|
||||
/* this lookup has to depend on weight and style */
|
||||
nsCAutoString key(aLangGroup);
|
||||
key.Append("-");
|
||||
|
@ -532,7 +533,7 @@ static PRInt32 GetCJKLangGroupIndex(const char *aLangGroup) {
|
|||
}
|
||||
|
||||
// this function assigns to the array passed in.
|
||||
void gfxFT2FontGroup::GetCJKPrefFonts(nsTArray<nsRefPtr<FontEntry> >& aFontEntryList) {
|
||||
void gfxFT2FontGroup::GetCJKPrefFonts(nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList) {
|
||||
gfxToolkitPlatform *platform = gfxToolkitPlatform::GetPlatform();
|
||||
|
||||
nsCAutoString key("x-internal-cjk-");
|
||||
|
@ -622,13 +623,13 @@ void gfxFT2FontGroup::GetCJKPrefFonts(nsTArray<nsRefPtr<FontEntry> >& aFontEntry
|
|||
}
|
||||
|
||||
already_AddRefed<gfxFT2Font>
|
||||
gfxFT2FontGroup::WhichFontSupportsChar(const nsTArray<nsRefPtr<FontEntry> >& aFontEntryList, PRUint32 aCh)
|
||||
gfxFT2FontGroup::WhichFontSupportsChar(const nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList, PRUint32 aCh)
|
||||
{
|
||||
for (PRUint32 i = 0; i < aFontEntryList.Length(); i++) {
|
||||
nsRefPtr<FontEntry> fe = aFontEntryList[i];
|
||||
gfxFontEntry *fe = aFontEntryList[i].get();
|
||||
if (fe->HasCharacter(aCh)) {
|
||||
nsRefPtr<gfxFT2Font> font =
|
||||
gfxFT2Font::GetOrMakeFont(fe, &mStyle);
|
||||
gfxFT2Font::GetOrMakeFont(static_cast<FontEntry*>(fe), &mStyle);
|
||||
return font.forget();
|
||||
}
|
||||
}
|
||||
|
@ -644,7 +645,7 @@ gfxFT2FontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
|
|||
nsRefPtr<gfxFT2Font> selectedFont;
|
||||
|
||||
// check out the style's language group
|
||||
nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
|
||||
nsAutoTArray<nsRefPtr<gfxFontEntry>, 5> fonts;
|
||||
GetPrefFonts(mStyle.langGroup.get(), fonts);
|
||||
selectedFont = WhichFontSupportsChar(fonts, aCh);
|
||||
|
||||
|
@ -658,7 +659,7 @@ gfxFT2FontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
|
|||
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: CJK"));
|
||||
}
|
||||
|
||||
nsAutoTArray<nsRefPtr<FontEntry>, 15> fonts;
|
||||
nsAutoTArray<nsRefPtr<gfxFontEntry>, 15> fonts;
|
||||
GetCJKPrefFonts(fonts);
|
||||
selectedFont = WhichFontSupportsChar(fonts, aCh);
|
||||
} else {
|
||||
|
@ -666,7 +667,7 @@ gfxFT2FontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
|
|||
if (langGroup) {
|
||||
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: %s", langGroup));
|
||||
|
||||
nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
|
||||
nsAutoTArray<nsRefPtr<gfxFontEntry>, 5> fonts;
|
||||
GetPrefFonts(langGroup, fonts);
|
||||
selectedFont = WhichFontSupportsChar(fonts, aCh);
|
||||
}
|
||||
|
@ -684,12 +685,22 @@ gfxFT2FontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
|
|||
already_AddRefed<gfxFont>
|
||||
gfxFT2FontGroup::WhichSystemFontSupportsChar(PRUint32 aCh)
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
FontEntry *fe = static_cast<FontEntry*>
|
||||
(gfxPlatformFontList::PlatformFontList()->FindFontForChar(aCh, GetFontAt(0)));
|
||||
if (fe) {
|
||||
nsRefPtr<gfxFT2Font> f = gfxFT2Font::GetOrMakeFont(fe, &mStyle);
|
||||
nsRefPtr<gfxFont> font = f.get();
|
||||
return font.forget();
|
||||
}
|
||||
#else
|
||||
nsRefPtr<gfxFont> selectedFont;
|
||||
nsRefPtr<gfxFT2Font> refFont = GetFontAt(0);
|
||||
gfxToolkitPlatform *platform = gfxToolkitPlatform::GetPlatform();
|
||||
selectedFont = platform->FindFontForChar(aCh, refFont);
|
||||
if (selectedFont)
|
||||
return selectedFont.forget();
|
||||
#endif
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
@ -881,7 +892,8 @@ CreateScaledFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle)
|
|||
already_AddRefed<gfxFT2Font>
|
||||
gfxFT2Font::GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle)
|
||||
{
|
||||
FontEntry *fe = gfxToolkitPlatform::GetPlatform()->FindFontEntry(aName, *aStyle);
|
||||
FontEntry *fe = static_cast<FontEntry*>
|
||||
(gfxToolkitPlatform::GetPlatform()->FindFontEntry(aName, *aStyle));
|
||||
if (!fe) {
|
||||
NS_WARNING("Failed to find font entry for font!");
|
||||
return nsnull;
|
||||
|
|
|
@ -0,0 +1,961 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stuart Parmenter <stuart@mozilla.com>
|
||||
* Masayuki Nakano <masayuki@d-toybox.com>
|
||||
* Mats Palmgren <mats.palmgren@bredband.net>
|
||||
* John Daggett <jdaggett@mozilla.com>
|
||||
* Jonathan Kew <jfkthame@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "gfxGDIFontList.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
#include "gfxFontUtils.h"
|
||||
#include "gfxWindowsFonts.h"
|
||||
|
||||
#include "nsIPref.h" // for pref changes callback notification
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIWindowsRegKey.h"
|
||||
|
||||
#define ROUND(x) floor((x) + 0.5)
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo *gFontInfoLog = PR_NewLogModule("fontInfoLog");
|
||||
#endif /* PR_LOGGING */
|
||||
|
||||
#define LOG(args) PR_LOG(gFontInfoLog, PR_LOG_DEBUG, args)
|
||||
#define LOG_ENABLED() PR_LOG_TEST(gFontInfoLog, PR_LOG_DEBUG)
|
||||
|
||||
// font info loader constants
|
||||
static const PRUint32 kDelayBeforeLoadingFonts = 8 * 1000; // 8secs
|
||||
static const PRUint32 kIntervalBetweenLoadingFonts = 150; // 150ms
|
||||
|
||||
static __inline void
|
||||
BuildKeyNameFromFontName(nsAString &aName)
|
||||
{
|
||||
if (aName.Length() >= LF_FACESIZE)
|
||||
aName.Truncate(LF_FACESIZE - 1);
|
||||
ToLowerCase(aName);
|
||||
}
|
||||
|
||||
// Implementation of gfxPlatformFontList for Win32 GDI,
|
||||
// using GDI font enumeration APIs to get the list of fonts
|
||||
|
||||
// from t2embapi.h, included in Platform SDK 6.1 but not 6.0
|
||||
|
||||
#ifndef __t2embapi__
|
||||
|
||||
#define TTLOAD_PRIVATE 0x00000001
|
||||
#define LICENSE_PREVIEWPRINT 0x0004
|
||||
#define E_NONE 0x0000L
|
||||
|
||||
typedef unsigned long( WINAPIV *READEMBEDPROC ) ( void*, void*, const unsigned long );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short usStructSize; // size in bytes of structure client should set to sizeof(TTLOADINFO)
|
||||
unsigned short usRefStrSize; // size in wide characters of pusRefStr including NULL terminator
|
||||
unsigned short *pusRefStr; // reference or actual string.
|
||||
}TTLOADINFO;
|
||||
|
||||
LONG WINAPI TTLoadEmbeddedFont
|
||||
(
|
||||
HANDLE* phFontReference, // on completion, contains handle to identify embedded font installed
|
||||
// on system
|
||||
ULONG ulFlags, // flags specifying the request
|
||||
ULONG* pulPrivStatus, // on completion, contains the embedding status
|
||||
ULONG ulPrivs, // allows for the reduction of licensing privileges
|
||||
ULONG* pulStatus, // on completion, may contain status flags for request
|
||||
READEMBEDPROC lpfnReadFromStream, // callback function for doc/disk reads
|
||||
LPVOID lpvReadStream, // the input stream tokin
|
||||
LPWSTR szWinFamilyName, // the new 16 bit windows family name can be NULL
|
||||
LPSTR szMacFamilyName, // the new 8 bit mac family name can be NULL
|
||||
TTLOADINFO* pTTLoadInfo // optional security
|
||||
);
|
||||
|
||||
#endif // __t2embapi__
|
||||
|
||||
typedef LONG( WINAPI *TTLoadEmbeddedFontProc ) (HANDLE* phFontReference, ULONG ulFlags, ULONG* pulPrivStatus, ULONG ulPrivs, ULONG* pulStatus,
|
||||
READEMBEDPROC lpfnReadFromStream, LPVOID lpvReadStream, LPWSTR szWinFamilyName,
|
||||
LPSTR szMacFamilyName, TTLOADINFO* pTTLoadInfo);
|
||||
|
||||
typedef LONG( WINAPI *TTDeleteEmbeddedFontProc ) (HANDLE hFontReference, ULONG ulFlags, ULONG* pulStatus);
|
||||
|
||||
|
||||
static TTLoadEmbeddedFontProc TTLoadEmbeddedFontPtr = nsnull;
|
||||
static TTDeleteEmbeddedFontProc TTDeleteEmbeddedFontPtr = nsnull;
|
||||
|
||||
class WinUserFontData : public gfxUserFontData {
|
||||
public:
|
||||
WinUserFontData(HANDLE aFontRef, PRBool aIsCFF)
|
||||
: mFontRef(aFontRef), mIsCFF(aIsCFF)
|
||||
{ }
|
||||
|
||||
virtual ~WinUserFontData()
|
||||
{
|
||||
if (mIsCFF) {
|
||||
RemoveFontMemResourceEx(mFontRef);
|
||||
} else {
|
||||
ULONG pulStatus;
|
||||
TTDeleteEmbeddedFontPtr(mFontRef, 0, &pulStatus);
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE mFontRef;
|
||||
PRPackedBool mIsCFF;
|
||||
};
|
||||
|
||||
BYTE
|
||||
FontTypeToOutPrecision(PRUint8 fontType)
|
||||
{
|
||||
BYTE ret;
|
||||
switch (fontType) {
|
||||
case GFX_FONT_TYPE_TT_OPENTYPE:
|
||||
case GFX_FONT_TYPE_TRUETYPE:
|
||||
ret = OUT_TT_ONLY_PRECIS;
|
||||
break;
|
||||
case GFX_FONT_TYPE_PS_OPENTYPE:
|
||||
ret = OUT_PS_ONLY_PRECIS;
|
||||
break;
|
||||
case GFX_FONT_TYPE_TYPE1:
|
||||
ret = OUT_OUTLINE_PRECIS;
|
||||
break;
|
||||
case GFX_FONT_TYPE_RASTER:
|
||||
ret = OUT_RASTER_PRECIS;
|
||||
break;
|
||||
case GFX_FONT_TYPE_DEVICE:
|
||||
ret = OUT_DEVICE_PRECIS;
|
||||
break;
|
||||
default:
|
||||
ret = OUT_DEFAULT_PRECIS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* GDIFontEntry
|
||||
*
|
||||
*/
|
||||
|
||||
GDIFontEntry::GDIFontEntry(const nsAString& aFaceName, gfxWindowsFontType aFontType,
|
||||
PRBool aItalic, PRUint16 aWeight, gfxUserFontData *aUserFontData) :
|
||||
gfxFontEntry(aFaceName), mFontType(aFontType),
|
||||
mForceGDI(PR_FALSE), mUnknownCMAP(PR_FALSE),
|
||||
mUnicodeFont(PR_FALSE),
|
||||
mCharset(), mUnicodeRanges()
|
||||
{
|
||||
mUserFontData = aUserFontData;
|
||||
mItalic = aItalic;
|
||||
mWeight = aWeight;
|
||||
if (IsType1())
|
||||
mForceGDI = PR_TRUE;
|
||||
mIsUserFont = aUserFontData != nsnull;
|
||||
InitLogFont(aFaceName, aFontType);
|
||||
}
|
||||
|
||||
nsresult
|
||||
GDIFontEntry::ReadCMAP()
|
||||
{
|
||||
// attempt this once, if errors occur leave a blank cmap
|
||||
if (mCmapInitialized)
|
||||
return NS_OK;
|
||||
mCmapInitialized = PR_TRUE;
|
||||
|
||||
const PRUint32 kCmapTag = TRUETYPE_TAG('c','m','a','p');
|
||||
nsAutoTArray<PRUint8,16384> buffer;
|
||||
if (GetFontTable(kCmapTag, buffer) != NS_OK)
|
||||
return NS_ERROR_FAILURE;
|
||||
PRUint8 *cmap = buffer.Elements();
|
||||
|
||||
PRPackedBool unicodeFont = PR_FALSE, symbolFont = PR_FALSE;
|
||||
nsresult rv = gfxFontUtils::ReadCMAP(cmap, buffer.Length(),
|
||||
mCharacterMap, unicodeFont, symbolFont);
|
||||
mUnicodeFont = unicodeFont;
|
||||
mSymbolFont = symbolFont;
|
||||
|
||||
PR_LOG(gFontInfoLog, PR_LOG_DEBUG, ("(fontinit-cmap) psname: %s, size: %d\n",
|
||||
NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize()));
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GDIFontEntry::GetFontTable(PRUint32 aTableTag, nsTArray<PRUint8>& aBuffer)
|
||||
{
|
||||
AutoDC dc;
|
||||
AutoSelectFont font(dc.GetDC(), &mLogFont);
|
||||
if (font.IsValid()) {
|
||||
PRInt32 tableSize = ::GetFontData(dc.GetDC(), NS_SWAP32(aTableTag), 0, NULL, NULL);
|
||||
if (tableSize != GDI_ERROR) {
|
||||
if (aBuffer.SetLength(tableSize)) {
|
||||
::GetFontData(dc.GetDC(), NS_SWAP32(aTableTag), 0, aBuffer.Elements(), tableSize);
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
GDIFontEntry::FillLogFont(LOGFONTW *aLogFont, PRBool aItalic,
|
||||
PRUint16 aWeight, gfxFloat aSize)
|
||||
{
|
||||
memcpy(aLogFont, &mLogFont, sizeof(LOGFONTW));
|
||||
|
||||
aLogFont->lfHeight = (LONG)-ROUND(aSize);
|
||||
|
||||
if (aLogFont->lfHeight == 0)
|
||||
aLogFont->lfHeight = -1;
|
||||
|
||||
// always force lfItalic if we want it. Font selection code will
|
||||
// do its best to give us an italic font entry, but if no face exists
|
||||
// it may give us a regular one based on weight. Windows should
|
||||
// do fake italic for us in that case.
|
||||
aLogFont->lfItalic = aItalic;
|
||||
aLogFont->lfWeight = aWeight;
|
||||
}
|
||||
|
||||
PRBool
|
||||
GDIFontEntry::TestCharacterMap(PRUint32 aCh)
|
||||
{
|
||||
if (ReadCMAP() != NS_OK) {
|
||||
// Type1 fonts aren't necessarily Unicode but
|
||||
// this is the best guess we can make here
|
||||
mUnicodeFont = IsType1();
|
||||
|
||||
// For fonts where we failed to read the character map,
|
||||
// we can take a slow path to look up glyphs character by character
|
||||
mUnknownCMAP = PR_TRUE;
|
||||
}
|
||||
|
||||
if (mUnknownCMAP) {
|
||||
if (aCh > 0xFFFF)
|
||||
return PR_FALSE;
|
||||
|
||||
// previous code was using the group style
|
||||
gfxFontStyle fakeStyle;
|
||||
if (mItalic)
|
||||
fakeStyle.style = FONT_STYLE_ITALIC;
|
||||
fakeStyle.weight = mWeight * 100;
|
||||
|
||||
nsRefPtr<gfxWindowsFont> font =
|
||||
gfxWindowsFont::GetOrMakeFont(this, &fakeStyle);
|
||||
if (!font->IsValid())
|
||||
return PR_FALSE;
|
||||
|
||||
HDC dc = GetDC((HWND)nsnull);
|
||||
SetGraphicsMode(dc, GM_ADVANCED);
|
||||
HFONT hfont = font->GetHFONT();
|
||||
HFONT oldFont = (HFONT)SelectObject(dc, hfont);
|
||||
|
||||
PRUnichar str[1] = { (PRUnichar)aCh };
|
||||
WORD glyph[1];
|
||||
|
||||
PRBool hasGlyph = PR_FALSE;
|
||||
if (IsType1()) {
|
||||
// Type1 fonts and uniscribe APIs don't get along. ScriptGetCMap will return E_HANDLE
|
||||
DWORD ret = GetGlyphIndicesW(dc, str, 1, glyph, GGI_MARK_NONEXISTING_GLYPHS);
|
||||
if (ret != GDI_ERROR && glyph[0] != 0xFFFF)
|
||||
hasGlyph = PR_TRUE;
|
||||
} else {
|
||||
// ScriptGetCMap works better than GetGlyphIndicesW for things like bitmap/vector fonts
|
||||
HRESULT rv = ScriptGetCMap(dc, font->ScriptCache(), str, 1, 0, glyph);
|
||||
if (rv == S_OK)
|
||||
hasGlyph = PR_TRUE;
|
||||
}
|
||||
|
||||
SelectObject(dc, oldFont);
|
||||
ReleaseDC(NULL, dc);
|
||||
|
||||
if (hasGlyph) {
|
||||
mCharacterMap.set(aCh);
|
||||
return PR_TRUE;
|
||||
}
|
||||
} else {
|
||||
// font had a cmap so simply check that
|
||||
return mCharacterMap.test(aCh);
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
GDIFontEntry::InitLogFont(const nsAString& aName,
|
||||
gfxWindowsFontType aFontType)
|
||||
{
|
||||
#define CLIP_TURNOFF_FONTASSOCIATION 0x40
|
||||
|
||||
mLogFont.lfHeight = -1;
|
||||
|
||||
// Fill in logFont structure
|
||||
mLogFont.lfWidth = 0;
|
||||
mLogFont.lfEscapement = 0;
|
||||
mLogFont.lfOrientation = 0;
|
||||
mLogFont.lfUnderline = FALSE;
|
||||
mLogFont.lfStrikeOut = FALSE;
|
||||
mLogFont.lfCharSet = DEFAULT_CHARSET;
|
||||
mLogFont.lfOutPrecision = FontTypeToOutPrecision(aFontType);
|
||||
mLogFont.lfClipPrecision = CLIP_TURNOFF_FONTASSOCIATION;
|
||||
mLogFont.lfQuality = DEFAULT_QUALITY;
|
||||
mLogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
|
||||
// always force lfItalic if we want it. Font selection code will
|
||||
// do its best to give us an italic font entry, but if no face exists
|
||||
// it may give us a regular one based on weight. Windows should
|
||||
// do fake italic for us in that case.
|
||||
mLogFont.lfItalic = mItalic;
|
||||
mLogFont.lfWeight = mWeight;
|
||||
|
||||
int len = PR_MIN(aName.Length(), LF_FACESIZE - 1);
|
||||
memcpy(&mLogFont.lfFaceName, nsPromiseFlatString(aName).get(), len * 2);
|
||||
mLogFont.lfFaceName[len] = '\0';
|
||||
}
|
||||
|
||||
GDIFontEntry*
|
||||
GDIFontEntry::CreateFontEntry(const nsAString& aName, gfxWindowsFontType aFontType,
|
||||
PRBool aItalic, PRUint16 aWeight,
|
||||
gfxUserFontData* aUserFontData)
|
||||
{
|
||||
// jtdfix - need to set charset, unicode ranges, pitch/family
|
||||
|
||||
GDIFontEntry *fe = new GDIFontEntry(aName, aFontType, aItalic, aWeight,
|
||||
aUserFontData);
|
||||
|
||||
// ReadCMAP may change the values of mUnicodeFont and mSymbolFont
|
||||
if (NS_FAILED(fe->ReadCMAP())) {
|
||||
// Type1 fonts aren't necessarily Unicode but
|
||||
// this is the best guess we can make here
|
||||
if (fe->IsType1())
|
||||
fe->mUnicodeFont = PR_TRUE;
|
||||
else
|
||||
fe->mUnicodeFont = PR_FALSE;
|
||||
|
||||
// For fonts where we failed to read the character map,
|
||||
// we can take a slow path to look up glyphs character by character
|
||||
fe->mUnknownCMAP = PR_TRUE;
|
||||
}
|
||||
|
||||
return fe;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* GDIFontFamily
|
||||
*
|
||||
*/
|
||||
|
||||
int CALLBACK
|
||||
GDIFontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
const NEWTEXTMETRICEXW *nmetrics,
|
||||
DWORD fontType, LPARAM data)
|
||||
{
|
||||
const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
|
||||
LOGFONTW logFont = lpelfe->elfLogFont;
|
||||
GDIFontFamily *ff = reinterpret_cast<GDIFontFamily*>(data);
|
||||
|
||||
// Some fonts claim to support things > 900, but we don't so clamp the sizes
|
||||
logFont.lfWeight = PR_MAX(PR_MIN(logFont.lfWeight, 900), 100);
|
||||
|
||||
gfxWindowsFontType feType = GDIFontEntry::DetermineFontType(metrics, fontType);
|
||||
|
||||
GDIFontEntry *fe = nsnull;
|
||||
for (PRUint32 i = 0; i < ff->mAvailableFonts.Length(); ++i) {
|
||||
fe = static_cast<GDIFontEntry*>(ff->mAvailableFonts[i].get());
|
||||
if (feType > fe->mFontType) {
|
||||
// if the new type is better than the old one, remove the old entries
|
||||
ff->mAvailableFonts.RemoveElementAt(i);
|
||||
--i;
|
||||
} else if (feType < fe->mFontType) {
|
||||
// otherwise if the new type is worse, skip it
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < ff->mAvailableFonts.Length(); ++i) {
|
||||
fe = static_cast<GDIFontEntry*>(ff->mAvailableFonts[i].get());
|
||||
// check if we already know about this face
|
||||
if (fe->mWeight == logFont.lfWeight &&
|
||||
fe->mItalic == (logFont.lfItalic == 0xFF)) {
|
||||
// update the charset bit here since this could be different
|
||||
fe->mCharset[metrics.tmCharSet] = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
fe = GDIFontEntry::CreateFontEntry(ff->mName, feType, (logFont.lfItalic == 0xFF),
|
||||
(PRUint16) (logFont.lfWeight), nsnull);
|
||||
if (!fe)
|
||||
return 1;
|
||||
|
||||
ff->mAvailableFonts.AppendElement(fe);
|
||||
|
||||
// mark the charset bit
|
||||
fe->mCharset[metrics.tmCharSet] = 1;
|
||||
|
||||
fe->mWindowsFamily = logFont.lfPitchAndFamily & 0xF0;
|
||||
fe->mWindowsPitch = logFont.lfPitchAndFamily & 0x0F;
|
||||
|
||||
if (nmetrics->ntmFontSig.fsUsb[0] != 0x00000000 &&
|
||||
nmetrics->ntmFontSig.fsUsb[1] != 0x00000000 &&
|
||||
nmetrics->ntmFontSig.fsUsb[2] != 0x00000000 &&
|
||||
nmetrics->ntmFontSig.fsUsb[3] != 0x00000000) {
|
||||
|
||||
// set the unicode ranges
|
||||
PRUint32 x = 0;
|
||||
for (PRUint32 i = 0; i < 4; ++i) {
|
||||
DWORD range = nmetrics->ntmFontSig.fsUsb[i];
|
||||
for (PRUint32 k = 0; k < 32; ++k) {
|
||||
fe->mUnicodeRanges[x++] = (range & (1 << k)) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (LOG_ENABLED()) {
|
||||
LOG(("(fontinit) added (%s) to family (%s)"
|
||||
" with style: %s weight: %d stretch: %d",
|
||||
NS_ConvertUTF16toUTF8(fe->Name()).get(),
|
||||
NS_ConvertUTF16toUTF8(ff->Name()).get(),
|
||||
(logFont.lfItalic == 0xff) ? "italic" : "normal",
|
||||
logFont.lfWeight, fe->Stretch()));
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
GDIFontFamily::FindStyleVariations()
|
||||
{
|
||||
if (mHasStyles)
|
||||
return;
|
||||
mHasStyles = PR_TRUE;
|
||||
|
||||
HDC hdc = GetDC(nsnull);
|
||||
SetGraphicsMode(hdc, GM_ADVANCED);
|
||||
|
||||
LOGFONTW logFont;
|
||||
memset(&logFont, 0, sizeof(LOGFONTW));
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
logFont.lfPitchAndFamily = 0;
|
||||
PRUint32 l = PR_MIN(mName.Length(), LF_FACESIZE - 1);
|
||||
memcpy(logFont.lfFaceName,
|
||||
nsPromiseFlatString(mName).get(),
|
||||
l * sizeof(PRUnichar));
|
||||
logFont.lfFaceName[l] = 0;
|
||||
|
||||
EnumFontFamiliesExW(hdc, &logFont,
|
||||
(FONTENUMPROCW)GDIFontFamily::FamilyAddStylesProc,
|
||||
(LPARAM)this, 0);
|
||||
#ifdef DEBUG
|
||||
if (mAvailableFonts.Length() == 0) {
|
||||
char msgBuf[256];
|
||||
(void)sprintf(msgBuf, "no styles available in family \"%s\"",
|
||||
NS_ConvertUTF16toUTF8(mName).get());
|
||||
NS_ASSERTION(mAvailableFonts.Length() != 0, msgBuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
ReleaseDC(nsnull, hdc);
|
||||
|
||||
if (mIsBadUnderlineFamily)
|
||||
SetBadUnderlineFonts();
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* gfxGDIFontList
|
||||
*
|
||||
*/
|
||||
|
||||
gfxGDIFontList::gfxGDIFontList()
|
||||
{
|
||||
mFontSubstitutes.Init(50);
|
||||
|
||||
InitializeFontEmbeddingProcs();
|
||||
}
|
||||
|
||||
static void
|
||||
RemoveCharsetFromFontSubstitute(nsAString &aName)
|
||||
{
|
||||
PRInt32 comma = aName.FindChar(PRUnichar(','));
|
||||
if (comma >= 0)
|
||||
aName.Truncate(comma);
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxGDIFontList::GetFontSubstitutes()
|
||||
{
|
||||
// Create the list of FontSubstitutes
|
||||
nsCOMPtr<nsIWindowsRegKey> regKey = do_CreateInstance("@mozilla.org/windows-registry-key;1");
|
||||
if (!regKey)
|
||||
return NS_ERROR_FAILURE;
|
||||
NS_NAMED_LITERAL_STRING(kFontSubstitutesKey, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes");
|
||||
|
||||
nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
|
||||
kFontSubstitutesKey, nsIWindowsRegKey::ACCESS_READ);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
PRUint32 count;
|
||||
rv = regKey->GetValueCount(&count);
|
||||
if (NS_FAILED(rv) || count == 0)
|
||||
return rv;
|
||||
for (PRUint32 i = 0; i < count; i++) {
|
||||
nsAutoString substituteName;
|
||||
rv = regKey->GetValueName(i, substituteName);
|
||||
if (NS_FAILED(rv) || substituteName.IsEmpty() || substituteName.CharAt(1) == PRUnichar('@'))
|
||||
continue;
|
||||
PRUint32 valueType;
|
||||
rv = regKey->GetValueType(substituteName, &valueType);
|
||||
if (NS_FAILED(rv) || valueType != nsIWindowsRegKey::TYPE_STRING)
|
||||
continue;
|
||||
nsAutoString actualFontName;
|
||||
rv = regKey->ReadStringValue(substituteName, actualFontName);
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
RemoveCharsetFromFontSubstitute(substituteName);
|
||||
BuildKeyNameFromFontName(substituteName);
|
||||
RemoveCharsetFromFontSubstitute(actualFontName);
|
||||
BuildKeyNameFromFontName(actualFontName);
|
||||
gfxFontFamily *ff;
|
||||
if (!actualFontName.IsEmpty() && (ff = mFontFamilies.GetWeak(actualFontName))) {
|
||||
mFontSubstitutes.Put(substituteName, ff);
|
||||
} else {
|
||||
mNonExistingFonts.AppendElement(substituteName);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
gfxGDIFontList::InitFontList()
|
||||
{
|
||||
gfxFontCache *fc = gfxFontCache::GetCache();
|
||||
if (fc)
|
||||
fc->AgeAllGenerations();
|
||||
|
||||
mFontFamilies.Clear();
|
||||
mOtherFamilyNames.Clear();
|
||||
mOtherFamilyNamesInitialized = PR_FALSE;
|
||||
mPrefFonts.Clear();
|
||||
mFontSubstitutes.Clear();
|
||||
mNonExistingFonts.Clear();
|
||||
CancelLoader();
|
||||
|
||||
// initialize ranges of characters for which system-wide font search should be skipped
|
||||
mCodepointsWithNoFonts.reset();
|
||||
mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls
|
||||
mCodepointsWithNoFonts.SetRange(0x7f,0x9f); // C1 controls
|
||||
|
||||
// iterate over available families
|
||||
LOGFONTW logfont;
|
||||
memset(&logfont, 0, sizeof(logfont));
|
||||
logfont.lfCharSet = DEFAULT_CHARSET;
|
||||
|
||||
AutoDC hdc;
|
||||
int result = EnumFontFamiliesExW(hdc.GetDC(), &logfont,
|
||||
(FONTENUMPROCW)&EnumFontFamExProc,
|
||||
0, 0);
|
||||
|
||||
GetFontSubstitutes();
|
||||
|
||||
InitBadUnderlineList();
|
||||
|
||||
StartLoader(kDelayBeforeLoadingFonts, kIntervalBetweenLoadingFonts);
|
||||
}
|
||||
|
||||
int CALLBACK
|
||||
gfxGDIFontList::EnumFontFamExProc(ENUMLOGFONTEXW *lpelfe,
|
||||
NEWTEXTMETRICEXW *lpntme,
|
||||
DWORD fontType,
|
||||
LPARAM lParam)
|
||||
{
|
||||
const LOGFONTW& lf = lpelfe->elfLogFont;
|
||||
|
||||
if (lf.lfFaceName[0] == '@') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
nsAutoString name(lf.lfFaceName);
|
||||
BuildKeyNameFromFontName(name);
|
||||
|
||||
gfxGDIFontList *fontList = PlatformFontList();
|
||||
|
||||
if (!fontList->mFontFamilies.GetWeak(name)) {
|
||||
nsRefPtr<gfxFontFamily> family = new GDIFontFamily(nsDependentString(lf.lfFaceName));
|
||||
fontList->mFontFamilies.Put(name, family);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxGDIFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFullname)
|
||||
{
|
||||
LOGFONTW logFont;
|
||||
memset(&logFont, 0, sizeof(LOGFONTW));
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
PRUint32 namelen = PR_MIN(aFullname.Length(), LF_FACESIZE - 1);
|
||||
::memcpy(logFont.lfFaceName,
|
||||
nsPromiseFlatString(aFullname).get(),
|
||||
namelen * sizeof(PRUnichar));
|
||||
logFont.lfFaceName[namelen] = 0;
|
||||
|
||||
AutoDC dc;
|
||||
::SetGraphicsMode(dc.GetDC(), GM_ADVANCED);
|
||||
|
||||
AutoSelectFont font(dc.GetDC(), &logFont);
|
||||
if (!font.IsValid())
|
||||
return nsnull;
|
||||
|
||||
// fetch fullname from name table (Windows takes swapped tag order)
|
||||
const PRUint32 kNameTag = NS_SWAP32(TRUETYPE_TAG('n','a','m','e'));
|
||||
nsAutoString fullName;
|
||||
|
||||
{
|
||||
DWORD len = ::GetFontData(dc.GetDC(), kNameTag, 0, nsnull, 0);
|
||||
if (len == GDI_ERROR || len == 0) // not a truetype font --
|
||||
return nsnull; // so just ignore
|
||||
|
||||
nsAutoTArray<PRUint8,1024> nameData;
|
||||
if (!nameData.AppendElements(len))
|
||||
return nsnull;
|
||||
PRUint8 *nameTable = nameData.Elements();
|
||||
|
||||
DWORD newLen = ::GetFontData(dc.GetDC(), kNameTag, 0, nameTable, len);
|
||||
if (newLen != len)
|
||||
return nsnull;
|
||||
|
||||
nsresult rv;
|
||||
rv = gfxFontUtils::ReadCanonicalName(nameData,
|
||||
gfxFontUtils::NAME_ID_FULL,
|
||||
fullName);
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// reject if different from canonical fullname
|
||||
if (!aFullname.Equals(fullName))
|
||||
return nsnull;
|
||||
|
||||
// create a new font entry
|
||||
PRUint16 w = (aProxyEntry->mWeight == 0 ? 400 : aProxyEntry->mWeight);
|
||||
PRBool isCFF = PR_FALSE; // jtdfix -- need to determine this
|
||||
|
||||
gfxFontEntry *fe = GDIFontEntry::CreateFontEntry(aFullname,
|
||||
gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/,
|
||||
PRUint32(aProxyEntry->mItalic ? FONT_STYLE_ITALIC : FONT_STYLE_NORMAL),
|
||||
w, nsnull);
|
||||
|
||||
if (!fe)
|
||||
return fe;
|
||||
|
||||
fe->mIsUserFont = PR_TRUE;
|
||||
return fe;
|
||||
}
|
||||
|
||||
void gfxGDIFontList::InitializeFontEmbeddingProcs()
|
||||
{
|
||||
HMODULE fontlib = LoadLibraryW(L"t2embed.dll");
|
||||
if (!fontlib)
|
||||
return;
|
||||
TTLoadEmbeddedFontPtr = (TTLoadEmbeddedFontProc) GetProcAddress(fontlib, "TTLoadEmbeddedFont");
|
||||
TTDeleteEmbeddedFontPtr = (TTDeleteEmbeddedFontProc) GetProcAddress(fontlib, "TTDeleteEmbeddedFont");
|
||||
}
|
||||
|
||||
// used to control stream read by Windows TTLoadEmbeddedFont API
|
||||
|
||||
class EOTFontStreamReader {
|
||||
public:
|
||||
EOTFontStreamReader(const PRUint8 *aFontData, PRUint32 aLength, PRUint8 *aEOTHeader,
|
||||
PRUint32 aEOTHeaderLen, FontDataOverlay *aNameOverlay)
|
||||
: mCurrentChunk(0), mChunkOffset(0)
|
||||
{
|
||||
NS_ASSERTION(aFontData, "null font data ptr passed in");
|
||||
NS_ASSERTION(aEOTHeader, "null EOT header ptr passed in");
|
||||
NS_ASSERTION(aNameOverlay, "null name overlay struct passed in");
|
||||
|
||||
if (aNameOverlay->overlaySrc) {
|
||||
mNumChunks = 4;
|
||||
// 0 : EOT header
|
||||
mDataChunks[0].mData = aEOTHeader;
|
||||
mDataChunks[0].mLength = aEOTHeaderLen;
|
||||
// 1 : start of font data to overlayDest
|
||||
mDataChunks[1].mData = aFontData;
|
||||
mDataChunks[1].mLength = aNameOverlay->overlayDest;
|
||||
// 2 : overlay data
|
||||
mDataChunks[2].mData = aFontData + aNameOverlay->overlaySrc;
|
||||
mDataChunks[2].mLength = aNameOverlay->overlaySrcLen;
|
||||
// 3 : rest of font data
|
||||
mDataChunks[3].mData = aFontData + aNameOverlay->overlayDest + aNameOverlay->overlaySrcLen;
|
||||
mDataChunks[3].mLength = aLength - aNameOverlay->overlayDest - aNameOverlay->overlaySrcLen;
|
||||
} else {
|
||||
mNumChunks = 2;
|
||||
// 0 : EOT header
|
||||
mDataChunks[0].mData = aEOTHeader;
|
||||
mDataChunks[0].mLength = aEOTHeaderLen;
|
||||
// 1 : font data
|
||||
mDataChunks[1].mData = aFontData;
|
||||
mDataChunks[1].mLength = aLength;
|
||||
}
|
||||
}
|
||||
|
||||
~EOTFontStreamReader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
struct FontDataChunk {
|
||||
const PRUint8 *mData;
|
||||
PRUint32 mLength;
|
||||
};
|
||||
|
||||
PRUint32 mNumChunks;
|
||||
FontDataChunk mDataChunks[4];
|
||||
PRUint32 mCurrentChunk;
|
||||
PRUint32 mChunkOffset;
|
||||
|
||||
unsigned long Read(void *outBuffer, const unsigned long aBytesToRead)
|
||||
{
|
||||
PRUint32 bytesLeft = aBytesToRead; // bytes left in the out buffer
|
||||
PRUint8 *out = static_cast<PRUint8*> (outBuffer);
|
||||
|
||||
while (mCurrentChunk < mNumChunks && bytesLeft) {
|
||||
FontDataChunk& currentChunk = mDataChunks[mCurrentChunk];
|
||||
PRUint32 bytesToCopy = PR_MIN(bytesLeft,
|
||||
currentChunk.mLength - mChunkOffset);
|
||||
memcpy(out, currentChunk.mData + mChunkOffset, bytesToCopy);
|
||||
bytesLeft -= bytesToCopy;
|
||||
mChunkOffset += bytesToCopy;
|
||||
out += bytesToCopy;
|
||||
|
||||
NS_ASSERTION(mChunkOffset <= currentChunk.mLength, "oops, buffer overrun");
|
||||
|
||||
if (mChunkOffset == currentChunk.mLength) {
|
||||
mCurrentChunk++;
|
||||
mChunkOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return aBytesToRead - bytesLeft;
|
||||
}
|
||||
|
||||
static unsigned long ReadEOTStream(void *aReadStream, void *outBuffer,
|
||||
const unsigned long aBytesToRead)
|
||||
{
|
||||
EOTFontStreamReader *eotReader =
|
||||
static_cast<EOTFontStreamReader*> (aReadStream);
|
||||
return eotReader->Read(outBuffer, aBytesToRead);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
gfxFontEntry*
|
||||
gfxGDIFontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const PRUint8 *aFontData,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
// MakePlatformFont is responsible for deleting the font data with NS_Free
|
||||
// so we set up a stack object to ensure it is freed even if we take an
|
||||
// early exit
|
||||
struct FontDataDeleter {
|
||||
FontDataDeleter(const PRUint8 *aFontData)
|
||||
: mFontData(aFontData) { }
|
||||
~FontDataDeleter() { NS_Free((void*)mFontData); }
|
||||
const PRUint8 *mFontData;
|
||||
};
|
||||
FontDataDeleter autoDelete(aFontData);
|
||||
|
||||
// if calls aren't available, bail
|
||||
if (!TTLoadEmbeddedFontPtr || !TTDeleteEmbeddedFontPtr)
|
||||
return nsnull;
|
||||
|
||||
PRBool isCFF = gfxFontUtils::IsCffFont(aFontData);
|
||||
|
||||
nsresult rv;
|
||||
HANDLE fontRef = nsnull;
|
||||
PRBool isEmbedded = PR_FALSE;
|
||||
|
||||
nsAutoString uniqueName;
|
||||
rv = gfxFontUtils::MakeUniqueUserFontName(uniqueName);
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
|
||||
// for TTF fonts, first try using the t2embed library
|
||||
if (!isCFF) {
|
||||
// TrueType-style glyphs, use EOT library
|
||||
nsAutoTArray<PRUint8,2048> eotHeader;
|
||||
PRUint8 *buffer;
|
||||
PRUint32 eotlen;
|
||||
|
||||
isEmbedded = PR_TRUE;
|
||||
PRUint32 nameLen = PR_MIN(uniqueName.Length(), LF_FACESIZE - 1);
|
||||
nsPromiseFlatString fontName(Substring(uniqueName, 0, nameLen));
|
||||
|
||||
FontDataOverlay overlayNameData = {0, 0, 0};
|
||||
|
||||
rv = gfxFontUtils::MakeEOTHeader(aFontData, aLength, &eotHeader,
|
||||
&overlayNameData);
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
|
||||
// load in embedded font data
|
||||
eotlen = eotHeader.Length();
|
||||
buffer = reinterpret_cast<PRUint8*> (eotHeader.Elements());
|
||||
|
||||
PRInt32 ret;
|
||||
ULONG privStatus, pulStatus;
|
||||
EOTFontStreamReader eotReader(aFontData, aLength, buffer, eotlen,
|
||||
&overlayNameData);
|
||||
|
||||
ret = TTLoadEmbeddedFontPtr(&fontRef, TTLOAD_PRIVATE, &privStatus,
|
||||
LICENSE_PREVIEWPRINT, &pulStatus,
|
||||
EOTFontStreamReader::ReadEOTStream,
|
||||
&eotReader, (PRUnichar*)(fontName.get()), 0, 0);
|
||||
if (ret != E_NONE)
|
||||
fontRef = nsnull;
|
||||
}
|
||||
|
||||
// load CFF fonts or fonts that failed with t2embed loader
|
||||
if (fontRef == nsnull) {
|
||||
// Postscript-style glyphs, swizzle name table, load directly
|
||||
nsTArray<PRUint8> newFontData;
|
||||
|
||||
isEmbedded = PR_FALSE;
|
||||
rv = gfxFontUtils::RenameFont(uniqueName, aFontData, aLength, &newFontData);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
|
||||
DWORD numFonts = 0;
|
||||
|
||||
PRUint8 *fontData = reinterpret_cast<PRUint8*> (newFontData.Elements());
|
||||
PRUint32 fontLength = newFontData.Length();
|
||||
NS_ASSERTION(fontData, "null font data after renaming");
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ms533942(VS.85).aspx
|
||||
// "A font that is added by AddFontMemResourceEx is always private
|
||||
// to the process that made the call and is not enumerable."
|
||||
fontRef = AddFontMemResourceEx(fontData, fontLength,
|
||||
0 /* reserved */, &numFonts);
|
||||
if (!fontRef)
|
||||
return nsnull;
|
||||
|
||||
// only load fonts with a single face contained in the data
|
||||
if (fontRef && numFonts != 1) {
|
||||
RemoveFontMemResourceEx(fontRef);
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// make a new font entry using the unique name
|
||||
WinUserFontData *winUserFontData = new WinUserFontData(fontRef, isCFF);
|
||||
PRUint16 w = (aProxyEntry->mWeight == 0 ? 400 : aProxyEntry->mWeight);
|
||||
|
||||
GDIFontEntry *fe = GDIFontEntry::CreateFontEntry(uniqueName,
|
||||
gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/,
|
||||
PRUint32(aProxyEntry->mItalic ? FONT_STYLE_ITALIC : FONT_STYLE_NORMAL),
|
||||
w, winUserFontData);
|
||||
|
||||
if (!fe)
|
||||
return fe;
|
||||
|
||||
fe->mIsUserFont = PR_TRUE;
|
||||
|
||||
// Uniscribe doesn't place CFF fonts loaded privately via AddFontMemResourceEx
|
||||
if (isCFF)
|
||||
fe->mForceGDI = PR_TRUE;
|
||||
|
||||
return fe;
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxGDIFontList::GetDefaultFont(const gfxFontStyle* aStyle, PRBool& aNeedsBold)
|
||||
{
|
||||
// this really shouldn't fail to find a font....
|
||||
HGDIOBJ hGDI = ::GetStockObject(DEFAULT_GUI_FONT);
|
||||
LOGFONTW logFont;
|
||||
if (hGDI && ::GetObjectW(hGDI, sizeof(logFont), &logFont)) {
|
||||
nsAutoString resolvedName;
|
||||
if (ResolveFontName(nsDependentString(logFont.lfFaceName), resolvedName)) {
|
||||
return FindFontForFamily(resolvedName, aStyle, aNeedsBold);
|
||||
}
|
||||
}
|
||||
|
||||
// ...but just in case, try another approach as well
|
||||
NONCLIENTMETRICSW ncm;
|
||||
ncm.cbSize = sizeof(ncm);
|
||||
BOOL status = ::SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
|
||||
sizeof(ncm), &ncm, 0);
|
||||
if (status) {
|
||||
nsAutoString resolvedName;
|
||||
if (ResolveFontName(nsDependentString(ncm.lfMessageFont.lfFaceName), resolvedName)) {
|
||||
return FindFontForFamily(resolvedName, aStyle, aNeedsBold);
|
||||
}
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
gfxGDIFontList::ResolveFontName(const nsAString& aFontName, nsAString& aResolvedFontName)
|
||||
{
|
||||
nsAutoString keyName(aFontName);
|
||||
BuildKeyNameFromFontName(keyName);
|
||||
|
||||
nsRefPtr<gfxFontFamily> ff;
|
||||
if (mFontSubstitutes.Get(keyName, &ff)) {
|
||||
aResolvedFontName = ff->Name();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
if (mNonExistingFonts.Contains(keyName))
|
||||
return PR_FALSE;
|
||||
|
||||
if (gfxPlatformFontList::ResolveFontName(aFontName, aResolvedFontName))
|
||||
return PR_TRUE;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
|
@ -0,0 +1,353 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stuart Parmenter <stuart@mozilla.com>
|
||||
* Masayuki Nakano <masayuki@d-toybox.com>
|
||||
* John Daggett <jdaggett@mozilla.com>
|
||||
* Jonathan Kew <jfkthame@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef GFX_GDIFONTLIST_H
|
||||
#define GFX_GDIFONTLIST_H
|
||||
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "gfxPlatformFontList.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <bitset>
|
||||
|
||||
class AutoDC // get the global device context, and auto-release it on destruction
|
||||
{
|
||||
public:
|
||||
AutoDC() {
|
||||
mDC = ::GetDC(NULL);
|
||||
}
|
||||
|
||||
~AutoDC() {
|
||||
::ReleaseDC(NULL, mDC);
|
||||
}
|
||||
|
||||
HDC GetDC() {
|
||||
return mDC;
|
||||
}
|
||||
|
||||
private:
|
||||
HDC mDC;
|
||||
};
|
||||
|
||||
class AutoSelectFont // select a font into the given DC, and auto-restore
|
||||
{
|
||||
public:
|
||||
AutoSelectFont(HDC aDC, LOGFONTW *aLogFont) {
|
||||
mFont = ::CreateFontIndirectW(aLogFont);
|
||||
if (mFont) {
|
||||
mDC = aDC;
|
||||
mOldFont = (HFONT)::SelectObject(aDC, mFont);
|
||||
} else {
|
||||
mOldFont = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
AutoSelectFont(HDC aDC, HFONT aFont) {
|
||||
mDC = aDC;
|
||||
mFont = aFont;
|
||||
mOldFont = (HFONT)::SelectObject(aDC, aFont);
|
||||
}
|
||||
|
||||
~AutoSelectFont() {
|
||||
if (mOldFont) {
|
||||
::SelectObject(mDC, mOldFont);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool IsValid() const {
|
||||
return mFont != NULL;
|
||||
}
|
||||
|
||||
HFONT GetFont() const {
|
||||
return mFont;
|
||||
}
|
||||
|
||||
private:
|
||||
HDC mDC;
|
||||
HFONT mFont;
|
||||
HFONT mOldFont;
|
||||
};
|
||||
|
||||
/**
|
||||
* List of different types of fonts we support on Windows.
|
||||
* These can generally be lumped in to 3 categories where we have to
|
||||
* do special things: Really old fonts bitmap and vector fonts (device
|
||||
* and raster), Type 1 fonts, and TrueType/OpenType fonts.
|
||||
*
|
||||
* This list is sorted in order from least prefered to most prefered.
|
||||
* We prefer Type1 fonts over OpenType fonts to avoid falling back to
|
||||
* things like Arial (opentype) when you ask for Helvetica (type1)
|
||||
**/
|
||||
enum gfxWindowsFontType {
|
||||
GFX_FONT_TYPE_UNKNOWN = 0,
|
||||
GFX_FONT_TYPE_DEVICE,
|
||||
GFX_FONT_TYPE_RASTER,
|
||||
GFX_FONT_TYPE_TRUETYPE,
|
||||
GFX_FONT_TYPE_PS_OPENTYPE,
|
||||
GFX_FONT_TYPE_TT_OPENTYPE,
|
||||
GFX_FONT_TYPE_TYPE1
|
||||
};
|
||||
|
||||
// A single member of a font family (i.e. a single face, such as Times Italic)
|
||||
// represented as a LOGFONT that will resolve to the correct face.
|
||||
// This replaces FontEntry from gfxWindowsFonts.h/cpp.
|
||||
class GDIFontEntry : public gfxFontEntry
|
||||
{
|
||||
public:
|
||||
LPLOGFONTW GetLogFont() { return &mLogFont; }
|
||||
|
||||
nsresult ReadCMAP();
|
||||
|
||||
void FillLogFont(LOGFONTW *aLogFont, PRBool aItalic,
|
||||
PRUint16 aWeight, gfxFloat aSize);
|
||||
|
||||
static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics,
|
||||
DWORD fontType)
|
||||
{
|
||||
gfxWindowsFontType feType;
|
||||
if (metrics.ntmFlags & NTM_TYPE1)
|
||||
feType = GFX_FONT_TYPE_TYPE1;
|
||||
else if (metrics.ntmFlags & NTM_PS_OPENTYPE)
|
||||
feType = GFX_FONT_TYPE_PS_OPENTYPE;
|
||||
else if (metrics.ntmFlags & NTM_TT_OPENTYPE)
|
||||
feType = GFX_FONT_TYPE_TT_OPENTYPE;
|
||||
else if (fontType == TRUETYPE_FONTTYPE)
|
||||
feType = GFX_FONT_TYPE_TRUETYPE;
|
||||
else if (fontType == RASTER_FONTTYPE)
|
||||
feType = GFX_FONT_TYPE_RASTER;
|
||||
else if (fontType == DEVICE_FONTTYPE)
|
||||
feType = GFX_FONT_TYPE_DEVICE;
|
||||
else
|
||||
feType = GFX_FONT_TYPE_UNKNOWN;
|
||||
|
||||
return feType;
|
||||
}
|
||||
|
||||
PRBool IsType1() const {
|
||||
return (mFontType == GFX_FONT_TYPE_TYPE1);
|
||||
}
|
||||
|
||||
PRBool IsTrueType() const {
|
||||
return (mFontType == GFX_FONT_TYPE_TRUETYPE ||
|
||||
mFontType == GFX_FONT_TYPE_PS_OPENTYPE ||
|
||||
mFontType == GFX_FONT_TYPE_TT_OPENTYPE);
|
||||
}
|
||||
|
||||
PRBool IsCrappyFont() const {
|
||||
/* return if it is a bitmap not a unicode font */
|
||||
return (!mUnicodeFont || IsSymbolFont() || IsType1());
|
||||
}
|
||||
|
||||
PRBool MatchesGenericFamily(const nsACString& aGeneric) const {
|
||||
if (aGeneric.IsEmpty())
|
||||
return PR_TRUE;
|
||||
|
||||
// Japanese 'Mincho' fonts do not belong to FF_MODERN even if
|
||||
// they are fixed pitch because they have variable stroke width.
|
||||
if (mWindowsFamily == FF_ROMAN && mWindowsPitch & FIXED_PITCH) {
|
||||
return aGeneric.EqualsLiteral("monospace");
|
||||
}
|
||||
|
||||
// Japanese 'Gothic' fonts do not belong to FF_SWISS even if
|
||||
// they are variable pitch because they have constant stroke width.
|
||||
if (mWindowsFamily == FF_MODERN && mWindowsPitch & VARIABLE_PITCH) {
|
||||
return aGeneric.EqualsLiteral("sans-serif");
|
||||
}
|
||||
|
||||
// All other fonts will be grouped correctly using family...
|
||||
switch (mWindowsFamily) {
|
||||
case FF_DONTCARE:
|
||||
return PR_TRUE;
|
||||
case FF_ROMAN:
|
||||
return aGeneric.EqualsLiteral("serif");
|
||||
case FF_SWISS:
|
||||
return aGeneric.EqualsLiteral("sans-serif");
|
||||
case FF_MODERN:
|
||||
return aGeneric.EqualsLiteral("monospace");
|
||||
case FF_SCRIPT:
|
||||
return aGeneric.EqualsLiteral("cursive");
|
||||
case FF_DECORATIVE:
|
||||
return aGeneric.EqualsLiteral("fantasy");
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool SupportsLangGroup(const nsACString& aLangGroup) const {
|
||||
if (aLangGroup.IsEmpty())
|
||||
return PR_TRUE;
|
||||
|
||||
PRInt16 bit = -1;
|
||||
|
||||
/* map our langgroup names in to Windows charset bits */
|
||||
if (aLangGroup.EqualsLiteral("x-western")) {
|
||||
bit = ANSI_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("ja")) {
|
||||
bit = SHIFTJIS_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("ko")) {
|
||||
bit = HANGEUL_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("ko-XXX")) {
|
||||
bit = JOHAB_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("zh-CN")) {
|
||||
bit = GB2312_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("zh-TW")) {
|
||||
bit = CHINESEBIG5_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("el")) {
|
||||
bit = GREEK_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("tr")) {
|
||||
bit = TURKISH_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("he")) {
|
||||
bit = HEBREW_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("ar")) {
|
||||
bit = ARABIC_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("x-baltic")) {
|
||||
bit = BALTIC_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("x-cyrillic")) {
|
||||
bit = RUSSIAN_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("th")) {
|
||||
bit = THAI_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("x-central-euro")) {
|
||||
bit = EASTEUROPE_CHARSET;
|
||||
} else if (aLangGroup.EqualsLiteral("x-symbol")) {
|
||||
bit = SYMBOL_CHARSET;
|
||||
}
|
||||
|
||||
if (bit != -1)
|
||||
return mCharset[bit];
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool SupportsRange(PRUint8 range) {
|
||||
return mUnicodeRanges[range];
|
||||
}
|
||||
|
||||
PRBool TestCharacterMap(PRUint32 aCh);
|
||||
|
||||
// create a font entry for a font with a given name
|
||||
static GDIFontEntry* CreateFontEntry(const nsAString& aName,
|
||||
gfxWindowsFontType aFontType,
|
||||
PRBool aItalic, PRUint16 aWeight,
|
||||
gfxUserFontData* aUserFontData);
|
||||
|
||||
// create a font entry for a font referenced by its fullname
|
||||
static GDIFontEntry* LoadLocalFont(const gfxProxyFontEntry &aProxyEntry,
|
||||
const nsAString& aFullname);
|
||||
|
||||
PRUint8 mWindowsFamily;
|
||||
PRUint8 mWindowsPitch;
|
||||
|
||||
gfxWindowsFontType mFontType;
|
||||
PRPackedBool mForceGDI : 1;
|
||||
PRPackedBool mUnknownCMAP : 1;
|
||||
PRPackedBool mUnicodeFont : 1;
|
||||
|
||||
std::bitset<256> mCharset;
|
||||
std::bitset<128> mUnicodeRanges;
|
||||
|
||||
protected:
|
||||
friend class gfxWindowsFont;
|
||||
|
||||
GDIFontEntry(const nsAString& aFaceName, gfxWindowsFontType aFontType,
|
||||
PRBool aItalic, PRUint16 aWeight, gfxUserFontData *aUserFontData);
|
||||
|
||||
void InitLogFont(const nsAString& aName, gfxWindowsFontType aFontType);
|
||||
|
||||
virtual nsresult GetFontTable(PRUint32 aTableTag, nsTArray<PRUint8>& aBuffer);
|
||||
|
||||
LOGFONTW mLogFont;
|
||||
};
|
||||
|
||||
// a single font family, referencing one or more faces
|
||||
class GDIFontFamily : public gfxFontFamily
|
||||
{
|
||||
public:
|
||||
GDIFontFamily(nsAString &aName) :
|
||||
gfxFontFamily(aName) {}
|
||||
|
||||
virtual void FindStyleVariations();
|
||||
|
||||
private:
|
||||
static int CALLBACK FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
const NEWTEXTMETRICEXW *nmetrics,
|
||||
DWORD fontType, LPARAM data);
|
||||
};
|
||||
|
||||
class gfxGDIFontList : public gfxPlatformFontList {
|
||||
public:
|
||||
static gfxGDIFontList* PlatformFontList() {
|
||||
return static_cast<gfxGDIFontList*>(sPlatformFontList);
|
||||
}
|
||||
|
||||
virtual gfxFontEntry* GetDefaultFont(const gfxFontStyle* aStyle, PRBool& aNeedsBold);
|
||||
|
||||
virtual gfxFontEntry* LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFontName);
|
||||
|
||||
virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const PRUint8 *aFontData, PRUint32 aLength);
|
||||
|
||||
virtual PRBool ResolveFontName(const nsAString& aFontName,
|
||||
nsAString& aResolvedFontName);
|
||||
|
||||
private:
|
||||
friend class gfxWindowsPlatform;
|
||||
|
||||
gfxGDIFontList();
|
||||
|
||||
void InitializeFontEmbeddingProcs();
|
||||
|
||||
// initialize font lists
|
||||
virtual void InitFontList();
|
||||
|
||||
nsresult GetFontSubstitutes();
|
||||
|
||||
static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXW *lpelfe,
|
||||
NEWTEXTMETRICEXW *lpntme,
|
||||
DWORD fontType,
|
||||
LPARAM lParam);
|
||||
|
||||
typedef nsDataHashtable<nsStringHashKey, nsRefPtr<gfxFontFamily> > FontTable;
|
||||
|
||||
FontTable mFontSubstitutes;
|
||||
nsTArray<nsString> mNonExistingFonts;
|
||||
};
|
||||
|
||||
#endif /* GFX_GDIFONTLIST_H */
|
|
@ -92,7 +92,7 @@ protected:
|
|||
class gfxMacPlatformFontList : public gfxPlatformFontList {
|
||||
public:
|
||||
static gfxMacPlatformFontList* PlatformFontList() {
|
||||
return (gfxMacPlatformFontList*)sPlatformFontList;
|
||||
return static_cast<gfxMacPlatformFontList*>(sPlatformFontList);
|
||||
}
|
||||
|
||||
static PRInt32 AppleWeightToCSSWeight(PRInt32 aAppleWeight);
|
||||
|
@ -104,7 +104,7 @@ public:
|
|||
virtual gfxFontEntry* LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFontName);
|
||||
|
||||
virtual gfxFontEntry* MakePlatformFont(const gfxFontEntry *aProxyEntry,
|
||||
virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const PRUint8 *aFontData, PRUint32 aLength);
|
||||
|
||||
void ClearPrefFonts() { mPrefFonts.Clear(); }
|
||||
|
|
|
@ -106,7 +106,12 @@ static NSString* GetNSStringForString(const nsAString& aSrc)
|
|||
length:aSrc.Length()];
|
||||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo *gFontInfoLog = PR_NewLogModule("fontInfoLog");
|
||||
#endif /* PR_LOGGING */
|
||||
|
||||
#define LOG(args) PR_LOG(gFontInfoLog, PR_LOG_DEBUG, args)
|
||||
#define LOG_ENABLED() PR_LOG_TEST(gFontInfoLog, PR_LOG_DEBUG)
|
||||
|
||||
/* MacOSFontEntry */
|
||||
#pragma mark-
|
||||
|
@ -394,9 +399,6 @@ gfxMacFontFamily::FindStyleVariations()
|
|||
|
||||
PRInt32 cssWeight = gfxMacPlatformFontList::AppleWeightToCSSWeight(appKitWeight) * 100;
|
||||
|
||||
PR_LOG(gFontInfoLog, PR_LOG_DEBUG, ("(fontinit) family: %s, psname: %s, face: %s, apple-weight: %d, css-weight: %d, macTraits: %8.8x\n",
|
||||
[family UTF8String], [psname UTF8String], [facename UTF8String], appKitWeight, cssWeight, macTraits));
|
||||
|
||||
// make a nsString
|
||||
nsAutoString postscriptFontName;
|
||||
GetStringForNSString(psname, postscriptFontName);
|
||||
|
@ -429,6 +431,19 @@ gfxMacFontFamily::FindStyleVariations()
|
|||
fontEntry->mFixedPitch = PR_TRUE;
|
||||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (LOG_ENABLED()) {
|
||||
LOG(("(fontinit) added (%s) to family (%s)"
|
||||
" with style: %s weight: %d stretch: %d"
|
||||
" (apple-weight: %d macTraits: %8.8x)",
|
||||
NS_ConvertUTF16toUTF8(fontEntry->Name()).get(),
|
||||
NS_ConvertUTF16toUTF8(Name()).get(),
|
||||
fontEntry->IsItalic() ? "italic" : "normal",
|
||||
cssWeight, fontEntry->Stretch(),
|
||||
appKitWeight, macTraits));
|
||||
}
|
||||
#endif
|
||||
|
||||
// insert into font entry array of family
|
||||
AddFontEntry(fontEntry);
|
||||
}
|
||||
|
@ -578,9 +593,13 @@ gfxMacPlatformFontList::InitFontList()
|
|||
mOtherFamilyNames.Clear();
|
||||
mOtherFamilyNamesInitialized = PR_FALSE;
|
||||
mPrefFonts.Clear();
|
||||
mCodepointsWithNoFonts.reset();
|
||||
CancelLoader();
|
||||
|
||||
// initialize ranges of characters for which system-wide font search should be skipped
|
||||
mCodepointsWithNoFonts.reset();
|
||||
mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls
|
||||
mCodepointsWithNoFonts.SetRange(0x7f,0x9f); // C1 controls
|
||||
|
||||
// iterate over available families
|
||||
NSEnumerator *families = [[sFontManager availableFontFamilies]
|
||||
objectEnumerator]; // returns "canonical", non-localized family name
|
||||
|
@ -622,15 +641,10 @@ gfxMacPlatformFontList::InitFontList()
|
|||
SetFixedPitch(NS_LITERAL_STRING("Monaco"));
|
||||
}
|
||||
|
||||
// initialize ranges of characters for which system-wide font search should be skipped
|
||||
mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls
|
||||
mCodepointsWithNoFonts.SetRange(0x7f,0x9f); // C1 controls
|
||||
|
||||
InitBadUnderlineList();
|
||||
|
||||
// start the delayed cmap loader
|
||||
StartLoader(kDelayBeforeLoadingCmaps, kIntervalBetweenLoadingCmaps);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -754,7 +768,7 @@ gfxMacPlatformFontList::AppleWeightToCSSWeight(PRInt32 aAppleWeight)
|
|||
|
||||
gfxFontEntry*
|
||||
gfxMacPlatformFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFontName)
|
||||
const nsAString& aFontName)
|
||||
{
|
||||
NSString *faceName = GetNSStringForString(aFontName);
|
||||
|
||||
|
@ -817,7 +831,7 @@ public:
|
|||
};
|
||||
|
||||
gfxFontEntry*
|
||||
gfxMacPlatformFontList::MakePlatformFont(const gfxFontEntry *aProxyEntry,
|
||||
gfxMacPlatformFontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const PRUint8 *aFontData,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
|
@ -825,6 +839,17 @@ gfxMacPlatformFontList::MakePlatformFont(const gfxFontEntry *aProxyEntry,
|
|||
|
||||
NS_ASSERTION(aFontData, "MakePlatformFont called with null data");
|
||||
|
||||
// MakePlatformFont is responsible for deleting the font data with NS_Free
|
||||
// so we set up a stack object to ensure it is freed even if we take an
|
||||
// early exit
|
||||
struct FontDataDeleter {
|
||||
FontDataDeleter(const PRUint8 *aFontData)
|
||||
: mFontData(aFontData) { }
|
||||
~FontDataDeleter() { NS_Free((void*)mFontData); }
|
||||
const PRUint8 *mFontData;
|
||||
};
|
||||
FontDataDeleter autoDelete(aFontData);
|
||||
|
||||
ATSFontRef fontRef;
|
||||
ATSFontContainerRef containerRef;
|
||||
|
||||
|
@ -844,11 +869,9 @@ gfxMacPlatformFontList::MakePlatformFont(const gfxFontEntry *aProxyEntry,
|
|||
if (err != noErr) {
|
||||
#if DEBUG
|
||||
char warnBuf[1024];
|
||||
const gfxProxyFontEntry *proxyEntry =
|
||||
static_cast<const gfxProxyFontEntry*> (aProxyEntry);
|
||||
sprintf(warnBuf, "downloaded font error, ATSFontActivateFromMemory err: %d for (%s)",
|
||||
PRInt32(err),
|
||||
NS_ConvertUTF16toUTF8(proxyEntry->mFamily->Name()).get());
|
||||
NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get());
|
||||
NS_WARNING(warnBuf);
|
||||
#endif
|
||||
return nsnull;
|
||||
|
@ -860,11 +883,9 @@ gfxMacPlatformFontList::MakePlatformFont(const gfxFontEntry *aProxyEntry,
|
|||
if (err != noErr) {
|
||||
#if DEBUG
|
||||
char warnBuf[1024];
|
||||
const gfxProxyFontEntry *proxyEntry =
|
||||
static_cast<const gfxProxyFontEntry*> (aProxyEntry);
|
||||
sprintf(warnBuf, "downloaded font error, ATSFontFindFromContainer err: %d for (%s)",
|
||||
PRInt32(err),
|
||||
NS_ConvertUTF16toUTF8(proxyEntry->mFamily->Name()).get());
|
||||
NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get());
|
||||
NS_WARNING(warnBuf);
|
||||
#endif
|
||||
::ATSFontDeactivate(containerRef, NULL, kATSOptionFlagsDefault);
|
||||
|
@ -880,10 +901,8 @@ gfxMacPlatformFontList::MakePlatformFont(const gfxFontEntry *aProxyEntry,
|
|||
} else {
|
||||
#ifdef DEBUG
|
||||
char warnBuf[1024];
|
||||
const gfxProxyFontEntry *proxyEntry =
|
||||
static_cast<const gfxProxyFontEntry*> (aProxyEntry);
|
||||
sprintf(warnBuf, "ATSFontGetPostScriptName err = %d for (%s), retries = %d", (PRInt32)err,
|
||||
NS_ConvertUTF16toUTF8(proxyEntry->mFamily->Name()).get(), retryCount);
|
||||
NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get(), retryCount);
|
||||
NS_WARNING(warnBuf);
|
||||
#endif
|
||||
::ATSFontDeactivate(containerRef, NULL, kATSOptionFlagsDefault);
|
||||
|
@ -932,10 +951,8 @@ gfxMacPlatformFontList::MakePlatformFont(const gfxFontEntry *aProxyEntry,
|
|||
// if something is funky about this font, delete immediately
|
||||
#if DEBUG
|
||||
char warnBuf[1024];
|
||||
const gfxProxyFontEntry *proxyEntry =
|
||||
static_cast<const gfxProxyFontEntry*> (aProxyEntry);
|
||||
sprintf(warnBuf, "downloaded font not loaded properly, removed face for (%s)",
|
||||
NS_ConvertUTF16toUTF8(proxyEntry->mFamily->Name()).get());
|
||||
NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get());
|
||||
NS_WARNING(warnBuf);
|
||||
#endif
|
||||
delete newFontEntry;
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefBranch2.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
gfxPlatform *gPlatform = nsnull;
|
||||
|
||||
|
@ -186,7 +187,7 @@ gfxPlatform::Init()
|
|||
|
||||
nsresult rv;
|
||||
|
||||
#if defined(XP_MACOSX) // temporary, until this is implemented on others
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN) // temporary, until this is implemented on others
|
||||
rv = gfxPlatformFontList::Init();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Could not initialize gfxPlatformFontList");
|
||||
|
@ -236,7 +237,7 @@ gfxPlatform::Shutdown()
|
|||
gfxTextRunCache::Shutdown();
|
||||
gfxTextRunWordCache::Shutdown();
|
||||
gfxFontCache::Shutdown();
|
||||
#if defined(XP_MACOSX) // temporary, until this is implemented on others
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN) // temporary, until this is implemented on others
|
||||
gfxPlatformFontList::Shutdown();
|
||||
#endif
|
||||
|
||||
|
@ -440,8 +441,27 @@ PRBool gfxPlatform::ForEachPrefFont(eFontPrefLang aLangArray[], PRUint32 aLangAr
|
|||
prefName.Append(genericDotLang);
|
||||
rv = prefs->GetCharPref(prefName.get(), getter_Copies(nameListValue));
|
||||
if (NS_SUCCEEDED(rv) && !nameListValue.Equals(nameValue)) {
|
||||
if (!aCallback(prefLang, NS_ConvertUTF8toUTF16(nameListValue), aClosure))
|
||||
return PR_FALSE;
|
||||
const char kComma = ',';
|
||||
const char *p, *p_end;
|
||||
nsCAutoString list(nameListValue);
|
||||
list.BeginReading(p);
|
||||
list.EndReading(p_end);
|
||||
while (p < p_end) {
|
||||
while (nsCRT::IsAsciiSpace(*p)) {
|
||||
if (++p == p_end)
|
||||
break;
|
||||
}
|
||||
if (p == p_end)
|
||||
break;
|
||||
const char *start = p;
|
||||
while (++p != p_end && *p != kComma)
|
||||
/* nothing */ ;
|
||||
nsCAutoString fontName(Substring(start, p));
|
||||
fontName.CompressWhitespace(PR_FALSE, PR_TRUE);
|
||||
if (!aCallback(prefLang, NS_ConvertUTF8toUTF16(fontName), aClosure))
|
||||
return PR_FALSE;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -247,9 +247,28 @@ gfxPlatformFontList::HashEnumFuncForFamilies(nsStringHashKey::KeyType aKey,
|
|||
{
|
||||
FontListData *data = static_cast<FontListData*>(aUserArg);
|
||||
|
||||
nsAutoString localizedFamilyName;
|
||||
aFamilyEntry->LocalizedName(localizedFamilyName);
|
||||
data->mListOfFonts.AppendElement(localizedFamilyName);
|
||||
// use the first variation for now. This data should be the same
|
||||
// for all the variations and should probably be moved up to
|
||||
// the Family
|
||||
gfxFontStyle style;
|
||||
style.langGroup = data->mLangGroup;
|
||||
PRBool needsBold;
|
||||
nsRefPtr<gfxFontEntry> aFontEntry = aFamilyEntry->FindFontForStyle(style, needsBold);
|
||||
NS_ASSERTION(aFontEntry, "couldn't find any font entry in family");
|
||||
if (!aFontEntry)
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
/* skip symbol fonts */
|
||||
if (aFontEntry->IsSymbolFont())
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
if (aFontEntry->SupportsLangGroup(data->mLangGroup) &&
|
||||
aFontEntry->MatchesGenericFamily(data->mGenericFamily)) {
|
||||
nsAutoString localizedFamilyName;
|
||||
aFamilyEntry->LocalizedName(localizedFamilyName);
|
||||
data->mListOfFonts.AppendElement(localizedFamilyName);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
|
@ -417,6 +436,14 @@ gfxPlatformFontList::AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString&
|
|||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
gfxPlatformFontList::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
|
||||
{
|
||||
aFamilyName.Truncate();
|
||||
ResolveFontName(aFontName, aFamilyName);
|
||||
return !aFamilyName.IsEmpty();
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::InitLoader()
|
||||
{
|
||||
|
@ -460,4 +487,3 @@ gfxPlatformFontList::FinishLoader()
|
|||
mFontFamiliesToLoad.Clear();
|
||||
mNumFamilies = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,12 +109,13 @@ public:
|
|||
|
||||
// create a new platform font from downloaded data (@font-face)
|
||||
// this method is responsible to ensure aFontData is NS_Free()'d
|
||||
virtual gfxFontEntry* MakePlatformFont(const gfxFontEntry *aProxyEntry,
|
||||
virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const PRUint8 *aFontData,
|
||||
PRUint32 aLength) = 0;
|
||||
|
||||
// get the standard family name on the platform for a given font name
|
||||
virtual PRBool GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName) = 0;
|
||||
// (platforms may override, eg Mac)
|
||||
virtual PRBool GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
|
||||
|
||||
protected:
|
||||
gfxPlatformFontList();
|
||||
|
|
|
@ -189,14 +189,12 @@ gfxFontEntry*
|
|||
gfxPlatformMac::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const PRUint8 *aFontData, PRUint32 aLength)
|
||||
{
|
||||
// Ownership of aFontData is passed in here.
|
||||
// After activating the font via ATS, we can discard the data.
|
||||
gfxFontEntry *fe =
|
||||
gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry,
|
||||
aFontData,
|
||||
aLength);
|
||||
NS_Free((void*)aFontData);
|
||||
return fe;
|
||||
// Ownership of aFontData is received here, and passed on to
|
||||
// gfxPlatformFontList::MakePlatformFont(), which must ensure the data
|
||||
// is released with NS_Free when no longer needed
|
||||
return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry,
|
||||
aFontData,
|
||||
aLength);
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -60,8 +60,10 @@
|
|||
#include "gfxFT2Fonts.h"
|
||||
#include "cairo-ft.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "gfxFT2FontList.h"
|
||||
#else
|
||||
#include "gfxWindowsFonts.h"
|
||||
#include "gfxGDIFontList.h"
|
||||
#endif
|
||||
|
||||
/*XXX to get CAIRO_HAS_DDRAW_SURFACE */
|
||||
|
@ -83,11 +85,6 @@
|
|||
static FT_Library gPlatformFTLibrary = NULL;
|
||||
#endif
|
||||
|
||||
// font info loader constants
|
||||
static const PRUint32 kDelayBeforeLoadingCmaps = 8 * 1000; // 8secs
|
||||
static const PRUint32 kIntervalBetweenLoadingCmaps = 150; // 150ms
|
||||
static const PRUint32 kNumFontsPerSlice = 10; // read in info 10 fonts at a time
|
||||
|
||||
static __inline void
|
||||
BuildKeyNameFromFontName(nsAString &aName)
|
||||
{
|
||||
|
@ -96,54 +93,14 @@ BuildKeyNameFromFontName(nsAString &aName)
|
|||
ToLowerCase(aName);
|
||||
}
|
||||
|
||||
class gfxWindowsPlatformPrefObserver : public nsIObserver {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(gfxWindowsPlatformPrefObserver, nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
gfxWindowsPlatformPrefObserver::Observe(nsISupports *aSubject,
|
||||
const char *aTopic,
|
||||
const PRUnichar *aData)
|
||||
{
|
||||
NS_ASSERTION(!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID), "invalid topic");
|
||||
// XXX this could be made to only clear out the cache for the prefs that were changed
|
||||
// but it probably isn't that big a deal.
|
||||
gfxWindowsPlatform::GetPlatform()->ClearPrefFonts();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
gfxWindowsPlatform::gfxWindowsPlatform()
|
||||
: mStartIndex(0), mIncrement(kNumFontsPerSlice), mNumFamilies(0)
|
||||
{
|
||||
mFonts.Init(200);
|
||||
mFontAliases.Init(20);
|
||||
mFontSubstitutes.Init(50);
|
||||
mPrefFonts.Init(10);
|
||||
mPrefFonts.Init(50);
|
||||
|
||||
#ifdef MOZ_FT2_FONTS
|
||||
FT_Init_FreeType(&gPlatformFTLibrary);
|
||||
#else
|
||||
FontEntry::InitializeFontEmbeddingProcs();
|
||||
#endif
|
||||
|
||||
UpdateFontList();
|
||||
|
||||
nsCOMPtr<nsIPrefBranch2> pref = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
|
||||
if (pref) {
|
||||
gfxWindowsPlatformPrefObserver *observer = new gfxWindowsPlatformPrefObserver();
|
||||
if (observer) {
|
||||
pref->AddObserver("font.", observer, PR_FALSE);
|
||||
pref->AddObserver("font.name-list.", observer, PR_FALSE);
|
||||
pref->AddObserver("intl.accept_languages", observer, PR_FALSE);
|
||||
// don't bother unregistering. We'll get shutdown after the pref service
|
||||
}
|
||||
}
|
||||
|
||||
/* Pick the default render mode differently between
|
||||
* desktop, Windows Mobile, and Windows CE.
|
||||
*/
|
||||
|
@ -155,6 +112,8 @@ gfxWindowsPlatform::gfxWindowsPlatform()
|
|||
mRenderMode = RENDER_GDI;
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIPrefBranch2> pref = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
|
||||
PRInt32 rmode;
|
||||
if (NS_SUCCEEDED(pref->GetIntPref("mozilla.widget.render-mode", &rmode))) {
|
||||
if (rmode >= 0 || rmode < RENDER_MODE_MAX) {
|
||||
|
@ -173,6 +132,16 @@ gfxWindowsPlatform::~gfxWindowsPlatform()
|
|||
// these FT_Faces. See bug 458169.
|
||||
}
|
||||
|
||||
gfxPlatformFontList*
|
||||
gfxWindowsPlatform::CreatePlatformFontList()
|
||||
{
|
||||
#ifdef MOZ_FT2_FONTS
|
||||
return new gfxFT2FontList();
|
||||
#else
|
||||
return new gfxGDIFontList();
|
||||
#endif
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
gfxWindowsPlatform::CreateOffscreenSurface(const gfxIntSize& size,
|
||||
gfxASurface::gfxImageFormat imageFormat)
|
||||
|
@ -197,85 +166,12 @@ gfxWindowsPlatform::CreateOffscreenSurface(const gfxIntSize& size,
|
|||
return surf;
|
||||
}
|
||||
|
||||
int CALLBACK
|
||||
gfxWindowsPlatform::FontEnumProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
const NEWTEXTMETRICEXW *nmetrics,
|
||||
DWORD fontType, LPARAM data)
|
||||
{
|
||||
FontTable *ht = reinterpret_cast<FontTable*>(data);
|
||||
|
||||
const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
|
||||
const LOGFONTW& logFont = lpelfe->elfLogFont;
|
||||
|
||||
// Ignore vertical fonts
|
||||
if (logFont.lfFaceName[0] == L'@')
|
||||
return 1;
|
||||
|
||||
nsAutoString name(logFont.lfFaceName);
|
||||
BuildKeyNameFromFontName(name);
|
||||
|
||||
nsRefPtr<FontFamily> ff;
|
||||
if (!ht->Get(name, &ff)) {
|
||||
ff = new FontFamily(nsDependentString(logFont.lfFaceName));
|
||||
ht->Put(name, ff);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// general cmap reading routines moved to gfxFontUtils.cpp
|
||||
|
||||
struct FontListData {
|
||||
FontListData(const nsACString& aLangGroup, const nsACString& aGenericFamily, nsTArray<nsString>& aListOfFonts) :
|
||||
mLangGroup(aLangGroup), mGenericFamily(aGenericFamily), mStringArray(aListOfFonts) {}
|
||||
const nsACString& mLangGroup;
|
||||
const nsACString& mGenericFamily;
|
||||
nsTArray<nsString>& mStringArray;
|
||||
};
|
||||
|
||||
PLDHashOperator
|
||||
gfxWindowsPlatform::HashEnumFunc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontFamily>& aFontFamily,
|
||||
void* userArg)
|
||||
{
|
||||
FontListData *data = (FontListData*)userArg;
|
||||
|
||||
// use the first variation for now. This data should be the same
|
||||
// for all the variations and should probably be moved up to
|
||||
// the Family
|
||||
gfxFontStyle style;
|
||||
style.langGroup = data->mLangGroup;
|
||||
nsRefPtr<FontEntry> aFontEntry = aFontFamily->FindFontEntry(style);
|
||||
NS_ASSERTION(aFontEntry, "couldn't find any font entry in family");
|
||||
if (!aFontEntry)
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
|
||||
#ifndef MOZ_FT2_FONTS
|
||||
/* skip symbol fonts */
|
||||
if (aFontEntry->mSymbolFont)
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
if (aFontEntry->SupportsLangGroup(data->mLangGroup) &&
|
||||
aFontEntry->MatchesGenericFamily(data->mGenericFamily))
|
||||
#endif
|
||||
data->mStringArray.AppendElement(aFontFamily->Name());
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxWindowsPlatform::GetFontList(const nsACString& aLangGroup,
|
||||
const nsACString& aGenericFamily,
|
||||
nsTArray<nsString>& aListOfFonts)
|
||||
{
|
||||
FontListData data(aLangGroup, aGenericFamily, aListOfFonts);
|
||||
|
||||
mFonts.Enumerate(gfxWindowsPlatform::HashEnumFunc, &data);
|
||||
|
||||
aListOfFonts.Sort();
|
||||
aListOfFonts.Compact();
|
||||
gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup, aGenericFamily, aListOfFonts);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -288,225 +184,15 @@ RemoveCharsetFromFontSubstitute(nsAString &aName)
|
|||
aName.Truncate(comma);
|
||||
}
|
||||
|
||||
#ifdef MOZ_FT2_FONTS
|
||||
void gfxWindowsPlatform::AppendFacesFromFontFile(const PRUnichar *aFileName) {
|
||||
char fileName[MAX_PATH];
|
||||
WideCharToMultiByte(CP_ACP, 0, aFileName, -1, fileName, MAX_PATH, NULL, NULL);
|
||||
FT_Face dummy;
|
||||
if (FT_Err_Ok == FT_New_Face(GetFTLibrary(), fileName, -1, &dummy)) {
|
||||
for (FT_Long i = 0; i < dummy->num_faces; i++) {
|
||||
FT_Face face;
|
||||
if (FT_Err_Ok != FT_New_Face(GetFTLibrary(), fileName,
|
||||
i, &face))
|
||||
continue;
|
||||
|
||||
FontEntry* fe = FontEntry::CreateFontEntryFromFace(face);
|
||||
if (fe) {
|
||||
NS_ConvertUTF8toUTF16 name(face->family_name);
|
||||
BuildKeyNameFromFontName(name);
|
||||
nsRefPtr<FontFamily> ff;
|
||||
if (!mFonts.Get(name, &ff)) {
|
||||
ff = new FontFamily(name);
|
||||
mFonts.Put(name, ff);
|
||||
}
|
||||
ff->AddFontEntry(fe);
|
||||
ff->SetHasStyles(PR_TRUE);
|
||||
}
|
||||
}
|
||||
FT_Done_Face(dummy);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::FindFonts()
|
||||
{
|
||||
nsTArray<nsString> searchPaths(3);
|
||||
nsTArray<nsString> fontPatterns(3);
|
||||
fontPatterns.AppendElement(NS_LITERAL_STRING("\\*.ttf"));
|
||||
fontPatterns.AppendElement(NS_LITERAL_STRING("\\*.ttc"));
|
||||
fontPatterns.AppendElement(NS_LITERAL_STRING("\\*.otf"));
|
||||
wchar_t pathBuf[256];
|
||||
SHGetSpecialFolderPathW(0, pathBuf, CSIDL_WINDOWS, 0);
|
||||
searchPaths.AppendElement(pathBuf);
|
||||
SHGetSpecialFolderPathW(0, pathBuf, CSIDL_FONTS, 0);
|
||||
searchPaths.AppendElement(pathBuf);
|
||||
nsCOMPtr<nsIFile> resDir;
|
||||
NS_GetSpecialDirectory(NS_APP_RES_DIR, getter_AddRefs(resDir));
|
||||
if (resDir) {
|
||||
resDir->Append(NS_LITERAL_STRING("fonts"));
|
||||
nsAutoString resPath;
|
||||
resDir->GetPath(resPath);
|
||||
searchPaths.AppendElement(resPath);
|
||||
}
|
||||
WIN32_FIND_DATAW results;
|
||||
for (PRUint32 i = 0; i < searchPaths.Length(); i++) {
|
||||
const nsString& path(searchPaths[i]);
|
||||
for (PRUint32 j = 0; j < fontPatterns.Length(); j++) {
|
||||
nsAutoString pattern(path);
|
||||
pattern.Append(fontPatterns[j]);
|
||||
HANDLE handle = FindFirstFileExW(pattern.get(),
|
||||
FindExInfoStandard,
|
||||
&results,
|
||||
FindExSearchNameMatch,
|
||||
NULL,
|
||||
0);
|
||||
PRBool moreFiles = handle != INVALID_HANDLE_VALUE;
|
||||
while (moreFiles) {
|
||||
nsAutoString filePath(path);
|
||||
filePath.AppendLiteral("\\");
|
||||
filePath.Append(results.cFileName);
|
||||
AppendFacesFromFontFile(static_cast<const PRUnichar*>(filePath.get()));
|
||||
moreFiles = FindNextFile(handle, &results);
|
||||
}
|
||||
if (handle != INVALID_HANDLE_VALUE)
|
||||
FindClose(handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
nsresult
|
||||
gfxWindowsPlatform::UpdateFontList()
|
||||
{
|
||||
gfxFontCache *fc = gfxFontCache::GetCache();
|
||||
if (fc)
|
||||
fc->AgeAllGenerations();
|
||||
mFonts.Clear();
|
||||
mFontAliases.Clear();
|
||||
mNonExistingFonts.Clear();
|
||||
mFontSubstitutes.Clear();
|
||||
mPrefFonts.Clear();
|
||||
mCodepointsWithNoFonts.reset();
|
||||
CancelLoader();
|
||||
#ifdef MOZ_FT2_FONTS
|
||||
FindFonts();
|
||||
#else
|
||||
LOGFONTW logFont;
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
logFont.lfFaceName[0] = 0;
|
||||
logFont.lfPitchAndFamily = 0;
|
||||
|
||||
// Use the screen DC here.. should we use something else for printing?
|
||||
HDC dc = ::GetDC(nsnull);
|
||||
EnumFontFamiliesExW(dc, &logFont, (FONTENUMPROCW)gfxWindowsPlatform::FontEnumProc, (LPARAM)&mFonts, 0);
|
||||
::ReleaseDC(nsnull, dc);
|
||||
#endif
|
||||
// initialize the cmap loading process after font list has been initialized
|
||||
StartLoader(kDelayBeforeLoadingCmaps, kIntervalBetweenLoadingCmaps);
|
||||
|
||||
// Create the list of FontSubstitutes
|
||||
nsCOMPtr<nsIWindowsRegKey> regKey = do_CreateInstance("@mozilla.org/windows-registry-key;1");
|
||||
if (!regKey)
|
||||
return NS_ERROR_FAILURE;
|
||||
NS_NAMED_LITERAL_STRING(kFontSubstitutesKey, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes");
|
||||
|
||||
nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
|
||||
kFontSubstitutesKey, nsIWindowsRegKey::ACCESS_READ);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
PRUint32 count;
|
||||
rv = regKey->GetValueCount(&count);
|
||||
if (NS_FAILED(rv) || count == 0)
|
||||
return rv;
|
||||
for (PRUint32 i = 0; i < count; i++) {
|
||||
nsAutoString substituteName;
|
||||
rv = regKey->GetValueName(i, substituteName);
|
||||
if (NS_FAILED(rv) || substituteName.IsEmpty() ||
|
||||
substituteName.CharAt(1) == PRUnichar('@'))
|
||||
continue;
|
||||
PRUint32 valueType;
|
||||
rv = regKey->GetValueType(substituteName, &valueType);
|
||||
if (NS_FAILED(rv) || valueType != nsIWindowsRegKey::TYPE_STRING)
|
||||
continue;
|
||||
nsAutoString actualFontName;
|
||||
rv = regKey->ReadStringValue(substituteName, actualFontName);
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
RemoveCharsetFromFontSubstitute(substituteName);
|
||||
BuildKeyNameFromFontName(substituteName);
|
||||
RemoveCharsetFromFontSubstitute(actualFontName);
|
||||
BuildKeyNameFromFontName(actualFontName);
|
||||
nsRefPtr<FontFamily> ff;
|
||||
if (!actualFontName.IsEmpty() && mFonts.Get(actualFontName, &ff))
|
||||
mFontSubstitutes.Put(substituteName, ff);
|
||||
else
|
||||
mNonExistingFonts.AppendElement(substituteName);
|
||||
}
|
||||
|
||||
// initialize ranges of characters for which system-wide font search should be skipped
|
||||
mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls
|
||||
mCodepointsWithNoFonts.SetRange(0x7f,0x9f); // C1 controls
|
||||
|
||||
InitBadUnderlineList();
|
||||
gfxPlatformFontList::PlatformFontList()->UpdateFontList();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
struct FontFamilyListData {
|
||||
FontFamilyListData(nsTArray<nsRefPtr<FontFamily> >& aFamilyArray)
|
||||
: mFamilyArray(aFamilyArray)
|
||||
{}
|
||||
|
||||
static PLDHashOperator AppendFamily(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontFamily>& aFamilyEntry,
|
||||
void *aUserArg)
|
||||
{
|
||||
FontFamilyListData *data = (FontFamilyListData*)aUserArg;
|
||||
data->mFamilyArray.AppendElement(aFamilyEntry);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsTArray<nsRefPtr<FontFamily> >& mFamilyArray;
|
||||
};
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::GetFontFamilyList(nsTArray<nsRefPtr<FontFamily> >& aFamilyArray)
|
||||
{
|
||||
FontFamilyListData data(aFamilyArray);
|
||||
mFonts.Enumerate(FontFamilyListData::AppendFamily, &data);
|
||||
}
|
||||
|
||||
static PRBool SimpleResolverCallback(const nsAString& aName, void* aClosure)
|
||||
{
|
||||
nsString *result = static_cast<nsString*>(aClosure);
|
||||
result->Assign(aName);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::InitBadUnderlineList()
|
||||
{
|
||||
// Only windows fonts have mIsBadUnderlineFontFamily flag
|
||||
#ifndef MOZ_FT2_FONTS
|
||||
nsAutoTArray<nsString, 10> blacklist;
|
||||
gfxFontUtils::GetPrefsFontList("font.blacklist.underline_offset", blacklist);
|
||||
PRUint32 numFonts = blacklist.Length();
|
||||
for (PRUint32 i = 0; i < numFonts; i++) {
|
||||
PRBool aborted;
|
||||
nsAutoString resolved;
|
||||
ResolveFontName(blacklist[i], SimpleResolverCallback, &resolved, aborted);
|
||||
if (resolved.IsEmpty())
|
||||
continue;
|
||||
FontFamily *ff = FindFontFamily(resolved);
|
||||
if (!ff)
|
||||
continue;
|
||||
ff->mIsBadUnderlineFontFamily = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxWindowsPlatform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
|
||||
{
|
||||
aFamilyName.Truncate();
|
||||
PRBool aborted;
|
||||
return ResolveFontName(aFontName, SimpleResolverCallback, &aFamilyName, aborted);
|
||||
}
|
||||
|
||||
struct ResolveData {
|
||||
ResolveData(gfxPlatform::FontResolverCallback aCallback,
|
||||
gfxWindowsPlatform *aCaller, const nsAString *aFontName,
|
||||
|
@ -523,186 +209,23 @@ struct ResolveData {
|
|||
nsresult
|
||||
gfxWindowsPlatform::ResolveFontName(const nsAString& aFontName,
|
||||
FontResolverCallback aCallback,
|
||||
void *aClosure,
|
||||
PRBool& aAborted)
|
||||
void *aClosure, PRBool& aAborted)
|
||||
{
|
||||
if (aFontName.IsEmpty())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsAutoString keyName(aFontName);
|
||||
BuildKeyNameFromFontName(keyName);
|
||||
|
||||
nsRefPtr<FontFamily> ff;
|
||||
if (mFonts.Get(keyName, &ff) ||
|
||||
mFontSubstitutes.Get(keyName, &ff) ||
|
||||
mFontAliases.Get(keyName, &ff)) {
|
||||
aAborted = !(*aCallback)(ff->Name(), aClosure);
|
||||
// XXX If the font has font link, we should add the linked font.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mNonExistingFonts.Contains(keyName)) {
|
||||
nsAutoString resolvedName;
|
||||
if (!gfxPlatformFontList::PlatformFontList()->
|
||||
ResolveFontName(aFontName, resolvedName)) {
|
||||
aAborted = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
LOGFONTW logFont;
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
logFont.lfPitchAndFamily = 0;
|
||||
PRInt32 len = aFontName.Length();
|
||||
if (len >= LF_FACESIZE)
|
||||
len = LF_FACESIZE - 1;
|
||||
memcpy(logFont.lfFaceName,
|
||||
nsPromiseFlatString(aFontName).get(), len * sizeof(PRUnichar));
|
||||
logFont.lfFaceName[len] = 0;
|
||||
|
||||
HDC dc = ::GetDC(nsnull);
|
||||
ResolveData data(aCallback, this, &keyName, aClosure);
|
||||
aAborted = !EnumFontFamiliesExW(dc, &logFont,
|
||||
(FONTENUMPROCW)gfxWindowsPlatform::FontResolveProc,
|
||||
(LPARAM)&data, 0);
|
||||
if (data.mFoundCount == 0)
|
||||
mNonExistingFonts.AppendElement(keyName);
|
||||
::ReleaseDC(nsnull, dc);
|
||||
|
||||
aAborted = !(*aCallback)(resolvedName, aClosure);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int CALLBACK
|
||||
gfxWindowsPlatform::FontResolveProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
const NEWTEXTMETRICEXW *nmetrics,
|
||||
DWORD fontType, LPARAM data)
|
||||
nsresult
|
||||
gfxWindowsPlatform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
|
||||
{
|
||||
const LOGFONTW& logFont = lpelfe->elfLogFont;
|
||||
// Ignore vertical fonts
|
||||
if (logFont.lfFaceName[0] == L'@' || logFont.lfFaceName[0] == 0)
|
||||
return 1;
|
||||
|
||||
ResolveData *rData = reinterpret_cast<ResolveData*>(data);
|
||||
|
||||
nsAutoString name(logFont.lfFaceName);
|
||||
|
||||
// Save the alias name to cache
|
||||
nsRefPtr<FontFamily> ff;
|
||||
nsAutoString keyName(name);
|
||||
BuildKeyNameFromFontName(keyName);
|
||||
if (!rData->mCaller->mFonts.Get(keyName, &ff)) {
|
||||
// This case only occurs on failing to build
|
||||
// the list of font substitue. In this case, the user should
|
||||
// reboot the Windows. Probably, we don't have the good way for
|
||||
// resolving in this time.
|
||||
NS_WARNING("Cannot find actual font");
|
||||
return 1;
|
||||
}
|
||||
|
||||
rData->mFoundCount++;
|
||||
rData->mCaller->mFontAliases.Put(*(rData->mFontName), ff);
|
||||
|
||||
return (rData->mCallback)(name, rData->mClosure);
|
||||
|
||||
// XXX If the font has font link, we should add the linked font.
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
gfxWindowsPlatform::FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontFamily>& aFontFamily,
|
||||
void* userArg)
|
||||
{
|
||||
FontSearch *data = (FontSearch*)userArg;
|
||||
|
||||
#ifdef MOZ_FT2_FONTS
|
||||
aFontFamily->FindFontForChar(data);
|
||||
#else
|
||||
const PRUint32 ch = data->mCh;
|
||||
|
||||
nsRefPtr<FontEntry> fe = aFontFamily->FindFontEntry(*data->mFontToMatch->GetStyle());
|
||||
NS_ASSERTION(fe, "couldn't find any font entry in family");
|
||||
if (!fe)
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
// initialize rank to 1 so that any match is better than the initial
|
||||
// value of data->mMatchRank (zero); therefore the first font that
|
||||
// passes the mCharacterMap.test() will become the mBestMatch until
|
||||
// a better entry is found
|
||||
PRInt32 rank = 1;
|
||||
|
||||
// skip over non-unicode and bitmap fonts and fonts that don't have
|
||||
// the code point we're looking for
|
||||
if (fe->IsCrappyFont() || !fe->mCharacterMap.test(ch))
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
// fonts that claim to support the range are more
|
||||
// likely to be "better fonts" than ones that don't... (in theory)
|
||||
if (fe->SupportsRange(gfxFontUtils::CharRangeBit(ch)))
|
||||
rank += 1;
|
||||
|
||||
if (fe->SupportsLangGroup(data->mFontToMatch->GetStyle()->langGroup))
|
||||
rank += 2;
|
||||
|
||||
FontEntry* mfe = static_cast<FontEntry*>(data->mFontToMatch->GetFontEntry());
|
||||
|
||||
if (fe->mWindowsFamily == mfe->mWindowsFamily)
|
||||
rank += 3;
|
||||
if (fe->mWindowsPitch == mfe->mWindowsPitch)
|
||||
rank += 3;
|
||||
|
||||
/* italic */
|
||||
const PRBool italic = (data->mFontToMatch->GetStyle()->style != FONT_STYLE_NORMAL);
|
||||
if (fe->mItalic != italic)
|
||||
rank += 3;
|
||||
|
||||
/* weight */
|
||||
PRInt8 baseWeight, weightDistance;
|
||||
data->mFontToMatch->GetStyle()->ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
||||
if (fe->mWeight == (baseWeight * 100) + (weightDistance * 100))
|
||||
rank += 2;
|
||||
else if (fe->mWeight == data->mFontToMatch->GetFontEntry()->mWeight)
|
||||
rank += 1;
|
||||
|
||||
if (rank > data->mMatchRank ||
|
||||
(rank == data->mMatchRank && Compare(fe->Name(), data->mBestMatch->Name()) > 0)) {
|
||||
data->mBestMatch = fe;
|
||||
data->mMatchRank = rank;
|
||||
}
|
||||
#endif
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
already_AddRefed<gfxFont>
|
||||
gfxWindowsPlatform::FindFontForChar(PRUint32 aCh, gfxFont *aFont)
|
||||
{
|
||||
// is codepoint with no matching font? return null immediately
|
||||
if (mCodepointsWithNoFonts.test(aCh)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
FontSearch data(aCh, aFont);
|
||||
|
||||
// find fonts that support the character
|
||||
mFonts.Enumerate(gfxWindowsPlatform::FindFontForCharProc, &data);
|
||||
|
||||
if (data.mBestMatch) {
|
||||
#ifdef MOZ_FT2_FONTS
|
||||
nsRefPtr<gfxFT2Font> font =
|
||||
gfxFT2Font::GetOrMakeFont(static_cast<FontEntry*>(data.mBestMatch.get()),
|
||||
aFont->GetStyle());
|
||||
gfxFont* ret = font.forget().get();
|
||||
return already_AddRefed<gfxFont>(ret);
|
||||
#else
|
||||
nsRefPtr<gfxWindowsFont> font =
|
||||
gfxWindowsFont::GetOrMakeFont(static_cast<FontEntry*>(data.mBestMatch.get()),
|
||||
aFont->GetStyle());
|
||||
if (font->IsValid()) {
|
||||
gfxFont* ret = font.forget().get();
|
||||
return already_AddRefed<gfxFont>(ret);
|
||||
}
|
||||
#endif
|
||||
return nsnull;
|
||||
}
|
||||
// no match? add to set of non-matching codepoints
|
||||
mCodepointsWithNoFonts.set(aCh);
|
||||
return nsnull;
|
||||
gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName, aFamilyName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
gfxFontGroup *
|
||||
|
@ -717,143 +240,21 @@ gfxWindowsPlatform::CreateFontGroup(const nsAString &aFamilies,
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
struct FullFontNameSearch {
|
||||
FullFontNameSearch(const nsAString& aFullName)
|
||||
: mFound(PR_FALSE), mFullName(aFullName), mDC(nsnull), mFontEntry(nsnull)
|
||||
{ }
|
||||
|
||||
PRPackedBool mFound;
|
||||
nsString mFullName;
|
||||
nsString mFamilyName;
|
||||
HDC mDC;
|
||||
gfxFontEntry *mFontEntry;
|
||||
};
|
||||
|
||||
#ifndef MOZ_FT2_FONTS
|
||||
// callback called for each face within a single family
|
||||
// match against elfFullName
|
||||
|
||||
static int CALLBACK
|
||||
FindFullNameForFace(const ENUMLOGFONTEXW *lpelfe,
|
||||
const NEWTEXTMETRICEXW *nmetrics,
|
||||
DWORD fontType, LPARAM userArg)
|
||||
{
|
||||
FullFontNameSearch *data = reinterpret_cast<FullFontNameSearch*>(userArg);
|
||||
|
||||
// does the full name match?
|
||||
if (!data->mFullName.Equals(nsDependentString(lpelfe->elfFullName)))
|
||||
return 1; // continue
|
||||
|
||||
// found match, create a new font entry
|
||||
data->mFound = PR_TRUE;
|
||||
|
||||
const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
|
||||
LOGFONTW logFont = lpelfe->elfLogFont;
|
||||
|
||||
// Some fonts claim to support things > 900, but we don't so clamp the sizes
|
||||
logFont.lfWeight = PR_MAX(PR_MIN(logFont.lfWeight, 900), 100);
|
||||
|
||||
gfxWindowsFontType feType = FontEntry::DetermineFontType(metrics, fontType);
|
||||
|
||||
data->mFontEntry = FontEntry::CreateFontEntry(data->mFamilyName, feType, (logFont.lfItalic == 0xFF), (PRUint16) (logFont.lfWeight), nsnull, data->mDC, &logFont);
|
||||
|
||||
return 0; // stop iteration
|
||||
}
|
||||
#endif
|
||||
|
||||
// callback called for each family name, based on the assumption that the
|
||||
// first part of the full name is the family name
|
||||
|
||||
static PLDHashOperator
|
||||
FindFullName(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontFamily>& aFontFamily,
|
||||
void* userArg)
|
||||
{
|
||||
FullFontNameSearch *data = reinterpret_cast<FullFontNameSearch*>(userArg);
|
||||
|
||||
// does the family name match up to the length of the family name?
|
||||
const nsString& family = aFontFamily->Name();
|
||||
|
||||
nsString fullNameFamily;
|
||||
data->mFullName.Left(fullNameFamily, family.Length());
|
||||
|
||||
// if so, iterate over faces in this family to see if there is a match
|
||||
if (family.Equals(fullNameFamily)) {
|
||||
#ifdef MOZ_FT2_FONTS
|
||||
int len = aFontFamily->GetFontList().Length();
|
||||
int index = 0;
|
||||
for (; index < len &&
|
||||
!aFontFamily->GetFontList()[index]->Name().Equals(data->mFullName); index++);
|
||||
if (index < len) {
|
||||
data->mFound = PR_TRUE;
|
||||
data->mFontEntry = aFontFamily->GetFontList()[index];
|
||||
}
|
||||
#else
|
||||
HDC hdc;
|
||||
|
||||
if (!data->mDC) {
|
||||
data->mDC= GetDC(nsnull);
|
||||
SetGraphicsMode(data->mDC, GM_ADVANCED);
|
||||
}
|
||||
hdc = data->mDC;
|
||||
|
||||
LOGFONTW logFont;
|
||||
memset(&logFont, 0, sizeof(LOGFONTW));
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
logFont.lfPitchAndFamily = 0;
|
||||
PRUint32 l = PR_MIN(family.Length(), LF_FACESIZE - 1);
|
||||
memcpy(logFont.lfFaceName,
|
||||
nsPromiseFlatString(family).get(),
|
||||
l * sizeof(PRUnichar));
|
||||
logFont.lfFaceName[l] = 0;
|
||||
data->mFamilyName.Assign(family);
|
||||
|
||||
EnumFontFamiliesExW(hdc, &logFont, (FONTENUMPROCW)FindFullNameForFace, (LPARAM)data, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (data->mFound)
|
||||
return PL_DHASH_STOP;
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxWindowsPlatform::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFontName)
|
||||
{
|
||||
#ifdef MOZ_FT2_FONTS
|
||||
// walk over list of names
|
||||
FullFontNameSearch data(aFontName);
|
||||
|
||||
// find fonts that support the character
|
||||
mFonts.Enumerate(FindFullName, &data);
|
||||
|
||||
if (data.mDC)
|
||||
ReleaseDC(nsnull, data.mDC);
|
||||
|
||||
return data.mFontEntry;
|
||||
#else
|
||||
return FontEntry::LoadLocalFont(*aProxyEntry, aFontName);
|
||||
#endif
|
||||
return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aProxyEntry,
|
||||
aFontName);
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxWindowsPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const PRUint8 *aFontData, PRUint32 aLength)
|
||||
{
|
||||
#ifdef MOZ_FT2_FONTS
|
||||
// The FT2 font needs the font data to persist, so we do NOT free it here
|
||||
// but instead pass ownership to the font entry.
|
||||
// Deallocation will happen later, when the font face is destroyed.
|
||||
return FontEntry::CreateFontEntry(*aProxyEntry, aFontData, aLength);
|
||||
#else
|
||||
// With GDI, we can free the downloaded data after activating the font
|
||||
gfxFontEntry *fe = FontEntry::LoadFont(*aProxyEntry, aFontData, aLength);
|
||||
NS_Free((void*)aFontData);
|
||||
return fe;
|
||||
#endif
|
||||
return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry,
|
||||
aFontData,
|
||||
aLength);
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -879,29 +280,21 @@ gfxWindowsPlatform::IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlag
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
FontFamily *
|
||||
gfxFontFamily *
|
||||
gfxWindowsPlatform::FindFontFamily(const nsAString& aName)
|
||||
{
|
||||
nsAutoString name(aName);
|
||||
BuildKeyNameFromFontName(name);
|
||||
|
||||
nsRefPtr<FontFamily> ff;
|
||||
if (!mFonts.Get(name, &ff) &&
|
||||
!mFontSubstitutes.Get(name, &ff) &&
|
||||
!mFontAliases.Get(name, &ff)) {
|
||||
return nsnull;
|
||||
}
|
||||
return ff.get();
|
||||
return gfxPlatformFontList::PlatformFontList()->FindFamily(aName);
|
||||
}
|
||||
|
||||
FontEntry *
|
||||
gfxFontEntry *
|
||||
gfxWindowsPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle)
|
||||
{
|
||||
nsRefPtr<FontFamily> ff = FindFontFamily(aName);
|
||||
nsRefPtr<gfxFontFamily> ff = FindFontFamily(aName);
|
||||
if (!ff)
|
||||
return nsnull;
|
||||
|
||||
return ff->FindFontEntry(aFontStyle);
|
||||
PRBool aNeedsBold;
|
||||
return ff->FindFontForStyle(aFontStyle, aNeedsBold);
|
||||
}
|
||||
|
||||
qcms_profile*
|
||||
|
@ -938,50 +331,17 @@ gfxWindowsPlatform::GetPlatformCMSOutputProfile()
|
|||
}
|
||||
|
||||
PRBool
|
||||
gfxWindowsPlatform::GetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<FontEntry> > *array)
|
||||
gfxWindowsPlatform::GetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<gfxFontEntry> > *array)
|
||||
{
|
||||
return mPrefFonts.Get(aKey, array);
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::SetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<FontEntry> >& array)
|
||||
gfxWindowsPlatform::SetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<gfxFontEntry> >& array)
|
||||
{
|
||||
mPrefFonts.Put(aKey, array);
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::InitLoader()
|
||||
{
|
||||
GetFontFamilyList(mFontFamilies);
|
||||
mStartIndex = 0;
|
||||
mNumFamilies = mFontFamilies.Length();
|
||||
}
|
||||
|
||||
PRBool
|
||||
gfxWindowsPlatform::RunLoader()
|
||||
{
|
||||
PRUint32 i, endIndex = ( mStartIndex + mIncrement < mNumFamilies ? mStartIndex + mIncrement : mNumFamilies );
|
||||
|
||||
#ifndef MOZ_FT2_FONTS
|
||||
// for each font family, load in various font info
|
||||
for (i = mStartIndex; i < endIndex; i++) {
|
||||
// load the cmaps for all variations
|
||||
mFontFamilies[i]->FindStyleVariations();
|
||||
}
|
||||
#endif
|
||||
mStartIndex += mIncrement;
|
||||
if (mStartIndex < mNumFamilies)
|
||||
return PR_FALSE;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::FinishLoader()
|
||||
{
|
||||
mFontFamilies.Clear();
|
||||
mNumFamilies = 0;
|
||||
}
|
||||
|
||||
#ifdef MOZ_FT2_FONTS
|
||||
FT_Library
|
||||
gfxWindowsPlatform::GetFTLibrary()
|
||||
|
|
Загрузка…
Ссылка в новой задаче