зеркало из https://github.com/mozilla/pjs.git
bug 382542. Deal with different style variations of fonts containing different character maps. r=vlad
This commit is contained in:
Родитель
42c381d824
Коммит
605d1a5e15
|
@ -51,24 +51,45 @@
|
||||||
#include <usp10.h>
|
#include <usp10.h>
|
||||||
#include <cairo-win32.h>
|
#include <cairo-win32.h>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FontEntry is a class that describes one of the fonts on the users system
|
* FontFamily is a class that describes one of the fonts on the users system. It holds
|
||||||
* It contains information such as the name, font type, charset table and unicode ranges.
|
* each FontEntry (maps more directly to a font face) which holds font type, charset info
|
||||||
* It may be extended to also keep basic metrics of the fonts so that we can better
|
* and character map info.
|
||||||
* compare one FontEntry to another.
|
|
||||||
*/
|
*/
|
||||||
|
class FontEntry;
|
||||||
|
class FontFamily
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
THEBES_INLINE_DECL_REFCOUNTING(FontFamily)
|
||||||
|
|
||||||
|
FontFamily(const nsAString& aName) :
|
||||||
|
mName(aName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTArray<nsRefPtr<FontEntry> > mVariations;
|
||||||
|
nsString mName;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class FontEntry
|
class FontEntry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
THEBES_INLINE_DECL_REFCOUNTING(FontEntry)
|
THEBES_INLINE_DECL_REFCOUNTING(FontEntry)
|
||||||
|
|
||||||
FontEntry(const nsAString& aName) :
|
FontEntry(FontFamily *aFontFamily) :
|
||||||
mName(aName), mDefaultWeight(0),
|
mFamily(aFontFamily), mUnicodeFont(PR_FALSE), mSymbolFont(PR_FALSE),
|
||||||
mUnicodeFont(PR_FALSE), mSymbolFont(PR_FALSE), mIsType1(PR_FALSE),
|
mTrueType(PR_FALSE), mIsType1(PR_FALSE),
|
||||||
mIsBadUnderlineFont(PR_FALSE), mCharset(0), mUnicodeRanges(0)
|
mIsBadUnderlineFont(PR_FALSE), mCharset(0), mUnicodeRanges(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nsString& GetName() const {
|
||||||
|
return mFamily->mName;
|
||||||
|
}
|
||||||
|
|
||||||
PRBool IsCrappyFont() const {
|
PRBool IsCrappyFont() const {
|
||||||
/* return if it is a bitmap not a unicode font */
|
/* return if it is a bitmap not a unicode font */
|
||||||
return (!mUnicodeFont || mSymbolFont || mIsType1);
|
return (!mUnicodeFont || mSymbolFont || mIsType1);
|
||||||
|
@ -80,18 +101,18 @@ public:
|
||||||
|
|
||||||
// Japanese 'Mincho' fonts do not belong to FF_MODERN even if
|
// Japanese 'Mincho' fonts do not belong to FF_MODERN even if
|
||||||
// they are fixed pitch because they have variable stroke width.
|
// they are fixed pitch because they have variable stroke width.
|
||||||
if (mFamily == FF_ROMAN && mPitch & FIXED_PITCH) {
|
if (mWindowsFamily == FF_ROMAN && mWindowsPitch & FIXED_PITCH) {
|
||||||
return aGeneric.EqualsLiteral("monospace");
|
return aGeneric.EqualsLiteral("monospace");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Japanese 'Gothic' fonts do not belong to FF_SWISS even if
|
// Japanese 'Gothic' fonts do not belong to FF_SWISS even if
|
||||||
// they are variable pitch because they have constant stroke width.
|
// they are variable pitch because they have constant stroke width.
|
||||||
if (mFamily == FF_MODERN && mPitch & VARIABLE_PITCH) {
|
if (mWindowsFamily == FF_MODERN && mWindowsPitch & VARIABLE_PITCH) {
|
||||||
return aGeneric.EqualsLiteral("sans-serif");
|
return aGeneric.EqualsLiteral("sans-serif");
|
||||||
}
|
}
|
||||||
|
|
||||||
// All other fonts will be grouped correctly using family...
|
// All other fonts will be grouped correctly using family...
|
||||||
switch (mFamily) {
|
switch (mWindowsFamily) {
|
||||||
case FF_DONTCARE:
|
case FF_DONTCARE:
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
case FF_ROMAN:
|
case FF_ROMAN:
|
||||||
|
@ -158,52 +179,29 @@ public:
|
||||||
return mUnicodeRanges[range];
|
return mUnicodeRanges[range];
|
||||||
}
|
}
|
||||||
|
|
||||||
class WeightTable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
THEBES_INLINE_DECL_REFCOUNTING(WeightTable)
|
|
||||||
|
|
||||||
WeightTable() : mWeights(0) {}
|
|
||||||
~WeightTable() {}
|
|
||||||
PRBool TriedWeight(PRUint8 aWeight) {
|
|
||||||
return mWeights[aWeight - 1 + 10];
|
|
||||||
}
|
|
||||||
PRBool HasWeight(PRUint8 aWeight) {
|
|
||||||
return mWeights[aWeight - 1];
|
|
||||||
}
|
|
||||||
void SetWeight(PRUint8 aWeight, PRBool aValue) {
|
|
||||||
mWeights[aWeight - 1] = aValue;
|
|
||||||
mWeights[aWeight - 1 + 10] = PR_TRUE;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
std::bitset<20> mWeights;
|
|
||||||
};
|
|
||||||
|
|
||||||
// whether this font family is in "bad" underline offset blacklist.
|
// whether this font family is in "bad" underline offset blacklist.
|
||||||
PRBool IsBadUnderlineFont() { return mIsBadUnderlineFont != 0; }
|
PRBool IsBadUnderlineFont() { return mIsBadUnderlineFont != 0; }
|
||||||
|
|
||||||
// The family name of the font
|
/* needs to be a weak pointer to avoid a cycle */
|
||||||
nsString mName;
|
FontFamily *mFamily;
|
||||||
|
|
||||||
PRUint16 mDefaultWeight;
|
PRUint8 mWindowsFamily;
|
||||||
|
PRUint8 mWindowsPitch;
|
||||||
PRUint8 mFamily;
|
|
||||||
PRUint8 mPitch;
|
|
||||||
|
|
||||||
PRPackedBool mUnicodeFont;
|
PRPackedBool mUnicodeFont;
|
||||||
PRPackedBool mSymbolFont;
|
PRPackedBool mSymbolFont;
|
||||||
|
PRPackedBool mTrueType;
|
||||||
PRPackedBool mIsType1;
|
PRPackedBool mIsType1;
|
||||||
PRPackedBool mIsBadUnderlineFont;
|
PRPackedBool mIsBadUnderlineFont;
|
||||||
|
PRPackedBool mItalic;
|
||||||
|
PRUint16 mWeight;
|
||||||
|
|
||||||
std::bitset<256> mCharset;
|
std::bitset<256> mCharset;
|
||||||
std::bitset<128> mUnicodeRanges;
|
std::bitset<128> mUnicodeRanges;
|
||||||
|
|
||||||
WeightTable mWeightTable;
|
|
||||||
|
|
||||||
gfxSparseBitSet mCharacterMap;
|
gfxSparseBitSet mCharacterMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
*
|
*
|
||||||
* class gfxWindowsFont
|
* class gfxWindowsFont
|
||||||
|
@ -238,7 +236,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HFONT MakeHFONT();
|
HFONT MakeHFONT();
|
||||||
void FillLogFont(gfxFloat aSize, PRInt16 aWeight);
|
void FillLogFont(gfxFloat aSize);
|
||||||
|
|
||||||
HFONT mFont;
|
HFONT mFont;
|
||||||
gfxFloat mAdjustedSize;
|
gfxFloat mAdjustedSize;
|
||||||
|
@ -297,6 +295,11 @@ public:
|
||||||
|
|
||||||
virtual gfxWindowsFont *GetFontAt(PRInt32 i);
|
virtual gfxWindowsFont *GetFontAt(PRInt32 i);
|
||||||
|
|
||||||
|
void GroupFamilyListToArrayList(nsTArray<nsRefPtr<FontEntry> > *list);
|
||||||
|
void FamilyListToArrayList(const nsString& aFamilies,
|
||||||
|
const nsCString& aLangGroup,
|
||||||
|
nsTArray<nsRefPtr<FontEntry> > *list);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void InitTextRunGDI(gfxContext *aContext, gfxTextRun *aRun, const char *aString, PRUint32 aLength);
|
void InitTextRunGDI(gfxContext *aContext, gfxTextRun *aRun, const char *aString, PRUint32 aLength);
|
||||||
void InitTextRunGDI(gfxContext *aContext, gfxTextRun *aRun, const PRUnichar *aString, PRUint32 aLength);
|
void InitTextRunGDI(gfxContext *aContext, gfxTextRun *aRun, const PRUnichar *aString, PRUint32 aLength);
|
||||||
|
@ -304,6 +307,7 @@ protected:
|
||||||
void InitTextRunUniscribe(gfxContext *aContext, gfxTextRun *aRun, const PRUnichar *aString, PRUint32 aLength);
|
void InitTextRunUniscribe(gfxContext *aContext, gfxTextRun *aRun, const PRUnichar *aString, PRUint32 aLength);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
nsCString mGenericFamily;
|
nsCString mGenericFamily;
|
||||||
nsTArray<nsRefPtr<FontEntry> > mFontEntries;
|
nsTArray<nsRefPtr<FontEntry> > mFontEntries;
|
||||||
};
|
};
|
||||||
|
|
|
@ -83,11 +83,14 @@ public:
|
||||||
*/
|
*/
|
||||||
FontEntry *FindFontForChar(PRUint32 aCh, gfxWindowsFont *aFont);
|
FontEntry *FindFontForChar(PRUint32 aCh, gfxWindowsFont *aFont);
|
||||||
|
|
||||||
/* Find a FontEntry object that represents a font on your system given a name */
|
/* Find a FontFamily/FontEntry object that represents a font on your system given a name */
|
||||||
FontEntry *FindFontEntry(const nsAString& aName);
|
FontFamily *FindFontFamily(const nsAString& aName);
|
||||||
|
FontEntry *FindFontEntry(const nsAString& aName, const gfxFontStyle *aFontStyle);
|
||||||
|
|
||||||
PRBool GetPrefFontEntries(const char *aLangGroup, nsTArray<nsRefPtr<FontEntry> > *array);
|
PRBool GetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> > *array);
|
||||||
void SetPrefFontEntries(const char *aLangGroup, nsTArray<nsRefPtr<FontEntry> >& array);
|
void SetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> >& array);
|
||||||
|
|
||||||
|
typedef nsDataHashtable<nsStringHashKey, nsRefPtr<FontFamily> > FontTable;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Init();
|
void Init();
|
||||||
|
@ -98,8 +101,12 @@ private:
|
||||||
const NEWTEXTMETRICEXW *metrics,
|
const NEWTEXTMETRICEXW *metrics,
|
||||||
DWORD fontType, LPARAM data);
|
DWORD fontType, LPARAM data);
|
||||||
|
|
||||||
|
static PLDHashOperator PR_CALLBACK FontGetStylesProc(nsStringHashKey::KeyType aKey,
|
||||||
|
nsRefPtr<FontFamily>& aFontFamily,
|
||||||
|
void* userArg);
|
||||||
|
|
||||||
static PLDHashOperator PR_CALLBACK FontGetCMapDataProc(nsStringHashKey::KeyType aKey,
|
static PLDHashOperator PR_CALLBACK FontGetCMapDataProc(nsStringHashKey::KeyType aKey,
|
||||||
nsRefPtr<FontEntry>& aFontEntry,
|
nsRefPtr<FontFamily>& aFontFamily,
|
||||||
void* userArg);
|
void* userArg);
|
||||||
|
|
||||||
static int CALLBACK FontResolveProc(const ENUMLOGFONTEXW *lpelfe,
|
static int CALLBACK FontResolveProc(const ENUMLOGFONTEXW *lpelfe,
|
||||||
|
@ -107,20 +114,20 @@ private:
|
||||||
DWORD fontType, LPARAM data);
|
DWORD fontType, LPARAM data);
|
||||||
|
|
||||||
static PLDHashOperator PR_CALLBACK HashEnumFunc(nsStringHashKey::KeyType aKey,
|
static PLDHashOperator PR_CALLBACK HashEnumFunc(nsStringHashKey::KeyType aKey,
|
||||||
nsRefPtr<FontEntry>& aData,
|
nsRefPtr<FontFamily>& aData,
|
||||||
void* userArg);
|
void* userArg);
|
||||||
|
|
||||||
static PLDHashOperator PR_CALLBACK FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
static PLDHashOperator PR_CALLBACK FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
||||||
nsRefPtr<FontEntry>& aFontEntry,
|
nsRefPtr<FontFamily>& aFontFamily,
|
||||||
void* userArg);
|
void* userArg);
|
||||||
|
|
||||||
virtual cmsHPROFILE GetPlatformCMSOutputProfile();
|
virtual cmsHPROFILE GetPlatformCMSOutputProfile();
|
||||||
|
|
||||||
static int PR_CALLBACK PrefChangedCallback(const char*, void*);
|
static int PR_CALLBACK PrefChangedCallback(const char*, void*);
|
||||||
|
|
||||||
nsDataHashtable<nsStringHashKey, nsRefPtr<FontEntry> > mFonts;
|
FontTable mFonts;
|
||||||
nsDataHashtable<nsStringHashKey, nsRefPtr<FontEntry> > mFontAliases;
|
FontTable mFontAliases;
|
||||||
nsDataHashtable<nsStringHashKey, nsRefPtr<FontEntry> > mFontSubstitutes;
|
FontTable mFontSubstitutes;
|
||||||
nsStringArray mNonExistingFonts;
|
nsStringArray mNonExistingFonts;
|
||||||
|
|
||||||
// when system-wide font lookup fails for a character, cache it to skip future searches
|
// when system-wide font lookup fails for a character, cache it to skip future searches
|
||||||
|
|
|
@ -122,7 +122,7 @@ gfxWindowsFont::gfxWindowsFont(const nsAString& aName, const gfxFontStyle *aFont
|
||||||
mMetrics(nsnull)
|
mMetrics(nsnull)
|
||||||
{
|
{
|
||||||
// XXX we should work to get this passed in rather than having to find it again.
|
// XXX we should work to get this passed in rather than having to find it again.
|
||||||
mFontEntry = gfxWindowsPlatform::GetPlatform()->FindFontEntry(aName);
|
mFontEntry = gfxWindowsPlatform::GetPlatform()->FindFontEntry(aName, aFontStyle);
|
||||||
NS_ASSERTION(mFontEntry, "Unable to find font entry for font. Something is whack.");
|
NS_ASSERTION(mFontEntry, "Unable to find font entry for font. Something is whack.");
|
||||||
|
|
||||||
mFont = MakeHFONT(); // create the HFONT, compute metrics, etc
|
mFont = MakeHFONT(); // create the HFONT, compute metrics, etc
|
||||||
|
@ -194,87 +194,10 @@ gfxWindowsFont::MakeHFONT()
|
||||||
if (mFont)
|
if (mFont)
|
||||||
return mFont;
|
return mFont;
|
||||||
|
|
||||||
PRInt8 baseWeight, weightDistance;
|
|
||||||
GetStyle()->ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
|
||||||
|
|
||||||
HDC dc = nsnull;
|
|
||||||
|
|
||||||
PRUint32 chosenWeight = 0;
|
|
||||||
|
|
||||||
PRUint8 direction = (weightDistance >= 0) ? 1 : -1;
|
|
||||||
|
|
||||||
/* Special case 500 and adjust it to 400 if we don't have it so that
|
|
||||||
we don't pick a bolder font */
|
|
||||||
if (baseWeight == 5 && weightDistance == 0) {
|
|
||||||
if (!mFontEntry->mWeightTable.TriedWeight(5)) {
|
|
||||||
if (!dc)
|
|
||||||
dc = GetDC((HWND)nsnull);
|
|
||||||
|
|
||||||
FillLogFont(GetStyle()->size, 500);
|
|
||||||
mFont = CreateFontIndirectW(&mLogFont);
|
|
||||||
HGDIOBJ oldFont = SelectObject(dc, mFont);
|
|
||||||
TEXTMETRIC metrics;
|
|
||||||
GetTextMetrics(dc, &metrics);
|
|
||||||
|
|
||||||
PRBool hasWeight = (metrics.tmWeight == 500);
|
|
||||||
mFontEntry->mWeightTable.SetWeight(5, hasWeight);
|
|
||||||
if (hasWeight)
|
|
||||||
chosenWeight = 500;
|
|
||||||
|
|
||||||
SelectObject(dc, oldFont);
|
|
||||||
}
|
|
||||||
if (!mFontEntry->mWeightTable.HasWeight(5)) {
|
|
||||||
baseWeight--; /* move the base weight to 400 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chosenWeight == 0) {
|
|
||||||
for (PRUint8 i = baseWeight, k = 0; i < 10 && i >= 1; i+=direction) {
|
|
||||||
if (mFontEntry->mWeightTable.HasWeight(i)) {
|
|
||||||
k++;
|
|
||||||
chosenWeight = i * 100;
|
|
||||||
} else if (mFontEntry->mWeightTable.TriedWeight(i)) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
const PRUint32 tryWeight = i * 100;
|
|
||||||
|
|
||||||
if (!dc)
|
|
||||||
dc = GetDC((HWND)nsnull);
|
|
||||||
|
|
||||||
FillLogFont(GetStyle()->size, tryWeight);
|
|
||||||
mFont = CreateFontIndirectW(&mLogFont);
|
|
||||||
HGDIOBJ oldFont = SelectObject(dc, mFont);
|
|
||||||
TEXTMETRIC metrics;
|
|
||||||
GetTextMetrics(dc, &metrics);
|
|
||||||
|
|
||||||
PRBool hasWeight = (metrics.tmWeight == tryWeight);
|
|
||||||
mFontEntry->mWeightTable.SetWeight(i, hasWeight);
|
|
||||||
if (hasWeight) {
|
|
||||||
chosenWeight = i * 100;
|
|
||||||
k++;
|
|
||||||
}
|
|
||||||
|
|
||||||
SelectObject(dc, oldFont);
|
|
||||||
if (k <= abs(weightDistance)) {
|
|
||||||
DeleteObject(mFont);
|
|
||||||
mFont = nsnull;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (k > abs(weightDistance)) {
|
|
||||||
chosenWeight = i * 100;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chosenWeight == 0)
|
|
||||||
chosenWeight = baseWeight * 100;
|
|
||||||
|
|
||||||
mAdjustedSize = GetStyle()->size;
|
mAdjustedSize = GetStyle()->size;
|
||||||
if (GetStyle()->sizeAdjust > 0.0) {
|
if (GetStyle()->sizeAdjust > 0.0) {
|
||||||
if (!mFont) {
|
if (!mFont) {
|
||||||
FillLogFont(mAdjustedSize, chosenWeight);
|
FillLogFont(mAdjustedSize);
|
||||||
mFont = CreateFontIndirectW(&mLogFont);
|
mFont = CreateFontIndirectW(&mLogFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,13 +215,10 @@ gfxWindowsFont::MakeHFONT()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mFont) {
|
if (!mFont) {
|
||||||
FillLogFont(mAdjustedSize, chosenWeight);
|
FillLogFont(mAdjustedSize);
|
||||||
mFont = CreateFontIndirectW(&mLogFont);
|
mFont = CreateFontIndirectW(&mLogFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dc)
|
|
||||||
ReleaseDC((HWND)nsnull, dc);
|
|
||||||
|
|
||||||
return mFont;
|
return mFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +308,7 @@ gfxWindowsFont::ComputeMetrics()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gfxWindowsFont::FillLogFont(gfxFloat aSize, PRInt16 aWeight)
|
gfxWindowsFont::FillLogFont(gfxFloat aSize)
|
||||||
{
|
{
|
||||||
#define CLIP_TURNOFF_FONTASSOCIATION 0x40
|
#define CLIP_TURNOFF_FONTASSOCIATION 0x40
|
||||||
|
|
||||||
|
@ -412,8 +332,20 @@ gfxWindowsFont::FillLogFont(gfxFloat aSize, PRInt16 aWeight)
|
||||||
mLogFont.lfClipPrecision = CLIP_TURNOFF_FONTASSOCIATION;
|
mLogFont.lfClipPrecision = CLIP_TURNOFF_FONTASSOCIATION;
|
||||||
mLogFont.lfQuality = DEFAULT_QUALITY;
|
mLogFont.lfQuality = DEFAULT_QUALITY;
|
||||||
mLogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
|
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 = (GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) ? TRUE : FALSE;
|
mLogFont.lfItalic = (GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) ? TRUE : FALSE;
|
||||||
mLogFont.lfWeight = aWeight;
|
// for truetype fonts we want to use the entry's weight.
|
||||||
|
// for bitmap fonts we want to force our boldness.
|
||||||
|
if (mFontEntry->mTrueType) {
|
||||||
|
mLogFont.lfWeight = mFontEntry->mWeight;
|
||||||
|
} else {
|
||||||
|
PRInt8 baseWeight, weightDistance;
|
||||||
|
GetStyle()->ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
||||||
|
mLogFont.lfWeight = (baseWeight * 100) + (weightDistance * 100);
|
||||||
|
}
|
||||||
|
|
||||||
int len = PR_MIN(mName.Length(), LF_FACESIZE - 1);
|
int len = PR_MIN(mName.Length(), LF_FACESIZE - 1);
|
||||||
memcpy(mLogFont.lfFaceName, nsPromiseFlatString(mName).get(), len * 2);
|
memcpy(mLogFont.lfFaceName, nsPromiseFlatString(mName).get(), len * 2);
|
||||||
|
@ -485,9 +417,9 @@ gfxWindowsFont::SetupCairoFont(gfxContext *aContext)
|
||||||
static already_AddRefed<gfxWindowsFont>
|
static already_AddRefed<gfxWindowsFont>
|
||||||
GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle)
|
GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle)
|
||||||
{
|
{
|
||||||
nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(aFontEntry->mName, aStyle);
|
nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(aFontEntry->GetName(), aStyle);
|
||||||
if (!font) {
|
if (!font) {
|
||||||
font = new gfxWindowsFont(aFontEntry->mName, aStyle);
|
font = new gfxWindowsFont(aFontEntry->GetName(), aStyle);
|
||||||
if (!font)
|
if (!font)
|
||||||
return nsnull;
|
return nsnull;
|
||||||
gfxFontCache::GetCache()->AddNew(font);
|
gfxFontCache::GetCache()->AddNew(font);
|
||||||
|
@ -498,25 +430,53 @@ GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PRBool
|
static PRBool
|
||||||
AddFontEntryToArray(const nsAString& aName,
|
AddFontNameToArray(const nsAString& aName,
|
||||||
const nsACString& aGenericName,
|
const nsACString& aGenericName,
|
||||||
void *closure)
|
void *closure)
|
||||||
{
|
{
|
||||||
if (!aName.IsEmpty()) {
|
if (!aName.IsEmpty()) {
|
||||||
nsTArray<nsRefPtr<FontEntry> > *list = static_cast<nsTArray<nsRefPtr<FontEntry> >*>(closure);
|
nsTArray<nsAutoString> *list = static_cast<nsTArray<nsAutoString> *>(closure);
|
||||||
|
|
||||||
nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(aName);
|
if (list->IndexOf(aName) == list->NoIndex)
|
||||||
if (list->IndexOf(fe) == list->NoIndex)
|
list->AppendElement(aName);
|
||||||
list->AppendElement(fe);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gfxWindowsFontGroup::GroupFamilyListToArrayList(nsTArray<nsRefPtr<FontEntry> > *list)
|
||||||
|
{
|
||||||
|
nsAutoTArray<nsAutoString, 15> fonts;
|
||||||
|
ForEachFont(AddFontNameToArray, &fonts);
|
||||||
|
|
||||||
|
PRUint32 len = fonts.Length();
|
||||||
|
for (PRUint32 i = 0; i < len; ++i) {
|
||||||
|
nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(fonts[i], &mStyle);
|
||||||
|
list->AppendElement(fe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gfxWindowsFontGroup::FamilyListToArrayList(const nsString& aFamilies,
|
||||||
|
const nsCString& aLangGroup,
|
||||||
|
nsTArray<nsRefPtr<FontEntry> > *list)
|
||||||
|
{
|
||||||
|
nsAutoTArray<nsAutoString, 15> fonts;
|
||||||
|
ForEachFont(aFamilies, aLangGroup, AddFontNameToArray, &fonts);
|
||||||
|
|
||||||
|
PRUint32 len = fonts.Length();
|
||||||
|
for (PRUint32 i = 0; i < len; ++i) {
|
||||||
|
const nsAutoString& str = fonts[i];
|
||||||
|
nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(str, &mStyle);
|
||||||
|
list->AppendElement(fe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gfxWindowsFontGroup::gfxWindowsFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle)
|
gfxWindowsFontGroup::gfxWindowsFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle)
|
||||||
: gfxFontGroup(aFamilies, aStyle)
|
: gfxFontGroup(aFamilies, aStyle)
|
||||||
{
|
{
|
||||||
ForEachFont(AddFontEntryToArray, &mFontEntries);
|
GroupFamilyListToArrayList(&mFontEntries);
|
||||||
|
|
||||||
if (mFontEntries.Length() == 0) {
|
if (mFontEntries.Length() == 0) {
|
||||||
// Should append default GUI font if there are no available fonts.
|
// Should append default GUI font if there are no available fonts.
|
||||||
|
@ -527,7 +487,7 @@ gfxWindowsFontGroup::gfxWindowsFontGroup(const nsAString& aFamilies, const gfxFo
|
||||||
NS_ERROR("Failed to create font group");
|
NS_ERROR("Failed to create font group");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(nsDependentString(logFont.lfFaceName));
|
nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(nsDependentString(logFont.lfFaceName), aStyle);
|
||||||
mFontEntries.AppendElement(fe);
|
mFontEntries.AppendElement(fe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1463,7 +1423,7 @@ public:
|
||||||
}
|
}
|
||||||
if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG)) {
|
if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG)) {
|
||||||
if (fe)
|
if (fe)
|
||||||
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Using %s", NS_LossyConvertUTF16toASCII(fe->mName).get()));
|
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Using %s", NS_LossyConvertUTF16toASCII(fe->GetName()).get()));
|
||||||
else
|
else
|
||||||
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Unable to find font"));
|
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Unable to find font"));
|
||||||
}
|
}
|
||||||
|
@ -1490,15 +1450,22 @@ private:
|
||||||
NS_ASSERTION(aLangGroup, "aLangGroup is null");
|
NS_ASSERTION(aLangGroup, "aLangGroup is null");
|
||||||
gfxWindowsPlatform *platform = gfxWindowsPlatform::GetPlatform();
|
gfxWindowsPlatform *platform = gfxWindowsPlatform::GetPlatform();
|
||||||
nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
|
nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
|
||||||
if (!platform->GetPrefFontEntries(aLangGroup, &fonts)) {
|
/* this lookup has to depend on weight and style */
|
||||||
|
nsCAutoString key(aLangGroup);
|
||||||
|
key.Append("-");
|
||||||
|
key.AppendInt(mGroup->GetStyle()->style);
|
||||||
|
key.Append("-");
|
||||||
|
key.AppendInt(mGroup->GetStyle()->weight);
|
||||||
|
if (!platform->GetPrefFontEntries(key, &fonts)) {
|
||||||
nsString fontString;
|
nsString fontString;
|
||||||
platform->GetPrefFonts(aLangGroup, fontString);
|
platform->GetPrefFonts(aLangGroup, fontString);
|
||||||
if (fontString.IsEmpty())
|
if (fontString.IsEmpty())
|
||||||
return;
|
return;
|
||||||
gfxFontGroup::ForEachFont(fontString, nsDependentCString(aLangGroup),
|
|
||||||
AddFontEntryToArray, &fonts);
|
|
||||||
|
|
||||||
platform->SetPrefFontEntries(aLangGroup, fonts);
|
mGroup->FamilyListToArrayList(fontString, nsDependentCString(aLangGroup),
|
||||||
|
&fonts);
|
||||||
|
|
||||||
|
platform->SetPrefFontEntries(key, fonts);
|
||||||
}
|
}
|
||||||
array.AppendElements(fonts);
|
array.AppendElements(fonts);
|
||||||
}
|
}
|
||||||
|
@ -1506,7 +1473,13 @@ private:
|
||||||
// this function assigns to the array passed in.
|
// this function assigns to the array passed in.
|
||||||
void GetCJKPrefFonts(nsTArray<nsRefPtr<FontEntry> >& array) {
|
void GetCJKPrefFonts(nsTArray<nsRefPtr<FontEntry> >& array) {
|
||||||
gfxWindowsPlatform *platform = gfxWindowsPlatform::GetPlatform();
|
gfxWindowsPlatform *platform = gfxWindowsPlatform::GetPlatform();
|
||||||
if (!platform->GetPrefFontEntries("x-internal-cjk", &array)) {
|
|
||||||
|
nsCAutoString key("x-internal-cjk-");
|
||||||
|
key.AppendInt(mGroup->GetStyle()->style);
|
||||||
|
key.Append("-");
|
||||||
|
key.AppendInt(mGroup->GetStyle()->weight);
|
||||||
|
|
||||||
|
if (!platform->GetPrefFontEntries(key, &array)) {
|
||||||
nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||||
if (!prefs)
|
if (!prefs)
|
||||||
return;
|
return;
|
||||||
|
@ -1566,7 +1539,7 @@ private:
|
||||||
GetPrefFonts(CJK_LANG_ZH_HK, array);
|
GetPrefFonts(CJK_LANG_ZH_HK, array);
|
||||||
GetPrefFonts(CJK_LANG_ZH_TW, array);
|
GetPrefFonts(CJK_LANG_ZH_TW, array);
|
||||||
|
|
||||||
platform->SetPrefFontEntries("x-internal-cjk", array);
|
platform->SetPrefFontEntries(key, array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,8 @@
|
||||||
|
|
||||||
//#define DEBUG_CMAP_SIZE 1
|
//#define DEBUG_CMAP_SIZE 1
|
||||||
|
|
||||||
|
static nsresult ReadCMAP(HDC hdc, FontEntry *aFontEntry);
|
||||||
|
|
||||||
int PR_CALLBACK
|
int PR_CALLBACK
|
||||||
gfxWindowsPlatform::PrefChangedCallback(const char *aPrefName, void *closure)
|
gfxWindowsPlatform::PrefChangedCallback(const char *aPrefName, void *closure)
|
||||||
{
|
{
|
||||||
|
@ -102,44 +104,53 @@ gfxWindowsPlatform::FontEnumProc(const ENUMLOGFONTEXW *lpelfe,
|
||||||
const NEWTEXTMETRICEXW *nmetrics,
|
const NEWTEXTMETRICEXW *nmetrics,
|
||||||
DWORD fontType, LPARAM data)
|
DWORD fontType, LPARAM data)
|
||||||
{
|
{
|
||||||
gfxWindowsPlatform *thisp = reinterpret_cast<gfxWindowsPlatform*>(data);
|
FontTable *ht = reinterpret_cast<FontTable*>(data);
|
||||||
|
|
||||||
const LOGFONTW& logFont = lpelfe->elfLogFont;
|
|
||||||
const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
|
const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
|
||||||
|
LOGFONTW logFont = lpelfe->elfLogFont;
|
||||||
#ifdef DEBUG_pavlov
|
|
||||||
printf("%s %d %d %d\n", NS_ConvertUTF16toUTF8(nsDependentString(logFont.lfFaceName)).get(),
|
|
||||||
logFont.lfCharSet, logFont.lfItalic, logFont.lfWeight);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Ignore vertical fonts
|
// Ignore vertical fonts
|
||||||
if (logFont.lfFaceName[0] == L'@') {
|
if (logFont.lfFaceName[0] == L'@') {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_pavlov
|
||||||
|
printf("%s %d %d %d\n", NS_ConvertUTF16toUTF8(nsDependentString(logFont.lfFaceName)).get(),
|
||||||
|
logFont.lfCharSet, logFont.lfItalic, logFont.lfWeight);
|
||||||
|
#endif
|
||||||
|
|
||||||
nsString name(logFont.lfFaceName);
|
nsString name(logFont.lfFaceName);
|
||||||
ToLowerCase(name);
|
ToLowerCase(name);
|
||||||
|
|
||||||
nsRefPtr<FontEntry> fe;
|
nsRefPtr<FontFamily> ff;
|
||||||
if (!thisp->mFonts.Get(name, &fe)) {
|
if (!ht->Get(name, &ff)) {
|
||||||
fe = new FontEntry(nsDependentString(logFont.lfFaceName));
|
ff = new FontFamily(nsDependentString(logFont.lfFaceName));
|
||||||
thisp->mFonts.Put(name, fe);
|
ht->Put(name, ff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsRefPtr<FontEntry> fe;
|
||||||
|
for (PRUint32 i = 0; i < ff->mVariations.Length(); ++i) {
|
||||||
|
fe = ff->mVariations[i];
|
||||||
|
if (fe->mWeight == logFont.lfWeight &&
|
||||||
|
fe->mItalic == (logFont.lfItalic == 0xFF)) {
|
||||||
|
return 1; /* we already know about this font */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fe = new FontEntry(ff);
|
||||||
|
/* don't append it until the end in case of error */
|
||||||
|
|
||||||
|
fe->mItalic = (logFont.lfItalic == 0xFF);
|
||||||
|
fe->mWeight = logFont.lfWeight;
|
||||||
|
|
||||||
if (metrics.ntmFlags & NTM_TYPE1)
|
if (metrics.ntmFlags & NTM_TYPE1)
|
||||||
fe->mIsType1 = PR_TRUE;
|
fe->mIsType1 = PR_TRUE;
|
||||||
|
|
||||||
// mark the charset bit
|
// mark the charset bit
|
||||||
fe->mCharset[metrics.tmCharSet] = 1;
|
fe->mCharset[metrics.tmCharSet] = 1;
|
||||||
|
|
||||||
// put the default weight in the weight table
|
fe->mWindowsFamily = logFont.lfPitchAndFamily & 0xF0;
|
||||||
fe->mWeightTable.SetWeight(PR_MAX(1, PR_MIN(9, metrics.tmWeight / 100)), PR_TRUE);
|
fe->mWindowsPitch = logFont.lfPitchAndFamily & 0x0F;
|
||||||
|
|
||||||
// store the default font weight
|
|
||||||
fe->mDefaultWeight = metrics.tmWeight;
|
|
||||||
|
|
||||||
fe->mFamily = logFont.lfPitchAndFamily & 0xF0;
|
|
||||||
fe->mPitch = logFont.lfPitchAndFamily & 0x0F;
|
|
||||||
|
|
||||||
if (nmetrics->ntmFontSig.fsUsb[0] == 0x00000000 &&
|
if (nmetrics->ntmFontSig.fsUsb[0] == 0x00000000 &&
|
||||||
nmetrics->ntmFontSig.fsUsb[1] == 0x00000000 &&
|
nmetrics->ntmFontSig.fsUsb[1] == 0x00000000 &&
|
||||||
|
@ -160,6 +171,51 @@ gfxWindowsPlatform::FontEnumProc(const ENUMLOGFONTEXW *lpelfe,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* read in the character map */
|
||||||
|
HDC hdc = GetDC(nsnull);
|
||||||
|
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||||
|
HFONT font = CreateFontIndirectW(&logFont);
|
||||||
|
|
||||||
|
NS_ASSERTION(font, "This font creation should never ever ever fail");
|
||||||
|
if (font) {
|
||||||
|
HFONT oldFont = (HFONT)SelectObject(hdc, font);
|
||||||
|
|
||||||
|
TEXTMETRIC metrics;
|
||||||
|
GetTextMetrics(hdc, &metrics);
|
||||||
|
if (metrics.tmPitchAndFamily & TMPF_TRUETYPE)
|
||||||
|
fe->mTrueType = PR_TRUE;
|
||||||
|
|
||||||
|
if (NS_FAILED(ReadCMAP(hdc, fe))) {
|
||||||
|
// Type1 fonts aren't necessarily Unicode but
|
||||||
|
// this is the best guess we can make here
|
||||||
|
if (fe->mIsType1)
|
||||||
|
fe->mUnicodeFont = PR_TRUE;
|
||||||
|
else
|
||||||
|
fe->mUnicodeFont = PR_FALSE;
|
||||||
|
|
||||||
|
//printf("%d, %s failed to get cmap\n", aFontEntry->mIsType1, NS_ConvertUTF16toUTF8(aFontEntry->mName).get());
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectObject(hdc, oldFont);
|
||||||
|
DeleteObject(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseDC(nsnull, hdc);
|
||||||
|
|
||||||
|
if (!fe->mUnicodeFont) {
|
||||||
|
/* non-unicode fonts.. boy lets just set all code points
|
||||||
|
between 0x20 and 0xFF. All the ones on my system do...
|
||||||
|
If we really wanted to test which characters in this
|
||||||
|
range were supported we could just generate a string with
|
||||||
|
each codepoint and do GetGlyphIndicies or similar to determine
|
||||||
|
what is there.
|
||||||
|
*/
|
||||||
|
fe->mCharacterMap.SetRange(0x20, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* append the variation to the font family */
|
||||||
|
ff->mVariations.AppendElement(fe);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,62 +243,32 @@ ReadCMAP(HDC hdc, FontEntry *aFontEntry)
|
||||||
}
|
}
|
||||||
|
|
||||||
PLDHashOperator PR_CALLBACK
|
PLDHashOperator PR_CALLBACK
|
||||||
gfxWindowsPlatform::FontGetCMapDataProc(nsStringHashKey::KeyType aKey,
|
gfxWindowsPlatform::FontGetStylesProc(nsStringHashKey::KeyType aKey,
|
||||||
nsRefPtr<FontEntry>& aFontEntry,
|
nsRefPtr<FontFamily>& aFontFamily,
|
||||||
void* userArg)
|
void* userArg)
|
||||||
{
|
{
|
||||||
|
NS_ASSERTION(aFontFamily->mVariations.Length() == 1, "We should only have 1 variation here");
|
||||||
|
nsRefPtr<FontEntry> aFontEntry = aFontFamily->mVariations[0];
|
||||||
|
|
||||||
HDC hdc = GetDC(nsnull);
|
HDC hdc = GetDC(nsnull);
|
||||||
|
|
||||||
LOGFONTW logFont;
|
LOGFONTW logFont;
|
||||||
memset(&logFont, 0, sizeof(LOGFONTW));
|
memset(&logFont, 0, sizeof(LOGFONTW));
|
||||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||||
logFont.lfPitchAndFamily = 0;
|
logFont.lfPitchAndFamily = 0;
|
||||||
PRUint32 l = PR_MIN(aFontEntry->mName.Length(), LF_FACESIZE - 1);
|
PRUint32 l = PR_MIN(aFontEntry->GetName().Length(), LF_FACESIZE - 1);
|
||||||
memcpy(logFont.lfFaceName,
|
memcpy(logFont.lfFaceName,
|
||||||
nsPromiseFlatString(aFontEntry->mName).get(),
|
nsPromiseFlatString(aFontEntry->GetName()).get(),
|
||||||
l * sizeof(PRUnichar));
|
l * sizeof(PRUnichar));
|
||||||
logFont.lfFaceName[l] = 0;
|
logFont.lfFaceName[l] = 0;
|
||||||
|
|
||||||
HFONT font = CreateFontIndirectW(&logFont);
|
EnumFontFamiliesExW(hdc, &logFont, (FONTENUMPROCW)gfxWindowsPlatform::FontEnumProc, (LPARAM)userArg, 0);
|
||||||
|
|
||||||
if (font) {
|
|
||||||
HFONT oldFont = (HFONT)SelectObject(hdc, font);
|
|
||||||
|
|
||||||
nsresult rv = ReadCMAP(hdc, aFontEntry);
|
|
||||||
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
// Type1 fonts aren't necessarily Unicode but
|
|
||||||
// this is the best guess we can make here
|
|
||||||
if (aFontEntry->mIsType1)
|
|
||||||
aFontEntry->mUnicodeFont = PR_TRUE;
|
|
||||||
else
|
|
||||||
aFontEntry->mUnicodeFont = PR_FALSE;
|
|
||||||
|
|
||||||
//printf("%d, %s failed to get cmap\n", aFontEntry->mIsType1, NS_ConvertUTF16toUTF8(aFontEntry->mName).get());
|
|
||||||
}
|
|
||||||
|
|
||||||
SelectObject(hdc, oldFont);
|
|
||||||
DeleteObject(font);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReleaseDC(nsnull, hdc);
|
ReleaseDC(nsnull, hdc);
|
||||||
|
|
||||||
if (!aFontEntry->mUnicodeFont) {
|
|
||||||
/* non-unicode fonts.. boy lets just set all code points
|
|
||||||
between 0x20 and 0xFF. All the ones on my system do...
|
|
||||||
If we really wanted to test which characters in this
|
|
||||||
range were supported we could just generate a string with
|
|
||||||
each codepoint and do GetGlyphIndicies or similar to determine
|
|
||||||
what is there.
|
|
||||||
*/
|
|
||||||
aFontEntry->mCharacterMap.SetRange(0x20, 0xFF);
|
|
||||||
return PL_DHASH_NEXT;
|
return PL_DHASH_NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return PL_DHASH_NEXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct FontListData {
|
struct FontListData {
|
||||||
FontListData(const nsACString& aLangGroup, const nsACString& aGenericFamily, nsStringArray& aListOfFonts) :
|
FontListData(const nsACString& aLangGroup, const nsACString& aGenericFamily, nsStringArray& aListOfFonts) :
|
||||||
mLangGroup(aLangGroup), mGenericFamily(aGenericFamily), mStringArray(aListOfFonts) {}
|
mLangGroup(aLangGroup), mGenericFamily(aGenericFamily), mStringArray(aListOfFonts) {}
|
||||||
|
@ -253,18 +279,23 @@ struct FontListData {
|
||||||
|
|
||||||
PLDHashOperator PR_CALLBACK
|
PLDHashOperator PR_CALLBACK
|
||||||
gfxWindowsPlatform::HashEnumFunc(nsStringHashKey::KeyType aKey,
|
gfxWindowsPlatform::HashEnumFunc(nsStringHashKey::KeyType aKey,
|
||||||
nsRefPtr<FontEntry>& aFontEntry,
|
nsRefPtr<FontFamily>& aFontFamily,
|
||||||
void* userArg)
|
void* userArg)
|
||||||
{
|
{
|
||||||
FontListData *data = (FontListData*)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
|
||||||
|
nsRefPtr<FontEntry> aFontEntry = aFontFamily->mVariations[0];
|
||||||
|
|
||||||
/* skip symbol fonts */
|
/* skip symbol fonts */
|
||||||
if (aFontEntry->mSymbolFont)
|
if (aFontEntry->mSymbolFont)
|
||||||
return PL_DHASH_NEXT;
|
return PL_DHASH_NEXT;
|
||||||
|
|
||||||
if (aFontEntry->SupportsLangGroup(data->mLangGroup) &&
|
if (aFontEntry->SupportsLangGroup(data->mLangGroup) &&
|
||||||
aFontEntry->MatchesGenericFamily(data->mGenericFamily))
|
aFontEntry->MatchesGenericFamily(data->mGenericFamily))
|
||||||
data->mStringArray.AppendString(aFontEntry->mName);
|
data->mStringArray.AppendString(aFontFamily->mName);
|
||||||
|
|
||||||
return PL_DHASH_NEXT;
|
return PL_DHASH_NEXT;
|
||||||
}
|
}
|
||||||
|
@ -317,11 +348,11 @@ gfxWindowsPlatform::UpdateFontList()
|
||||||
|
|
||||||
// Use the screen DC here.. should we use something else for printing?
|
// Use the screen DC here.. should we use something else for printing?
|
||||||
HDC dc = ::GetDC(nsnull);
|
HDC dc = ::GetDC(nsnull);
|
||||||
EnumFontFamiliesExW(dc, &logFont, (FONTENUMPROCW)gfxWindowsPlatform::FontEnumProc, (LPARAM)this, 0);
|
EnumFontFamiliesExW(dc, &logFont, (FONTENUMPROCW)gfxWindowsPlatform::FontEnumProc, (LPARAM)&mFonts, 0);
|
||||||
::ReleaseDC(nsnull, dc);
|
::ReleaseDC(nsnull, dc);
|
||||||
|
|
||||||
// Update all the fonts cmaps
|
// Look for additional styles
|
||||||
mFonts.Enumerate(gfxWindowsPlatform::FontGetCMapDataProc, nsnull);
|
mFonts.Enumerate(gfxWindowsPlatform::FontGetStylesProc, &mFonts);
|
||||||
|
|
||||||
// Create the list of FontSubstitutes
|
// Create the list of FontSubstitutes
|
||||||
nsCOMPtr<nsIWindowsRegKey> regKey = do_CreateInstance("@mozilla.org/windows-registry-key;1");
|
nsCOMPtr<nsIWindowsRegKey> regKey = do_CreateInstance("@mozilla.org/windows-registry-key;1");
|
||||||
|
@ -357,9 +388,9 @@ gfxWindowsPlatform::UpdateFontList()
|
||||||
BuildKeyNameFromFontName(substituteName);
|
BuildKeyNameFromFontName(substituteName);
|
||||||
RemoveCharsetFromFontSubstitute(actualFontName);
|
RemoveCharsetFromFontSubstitute(actualFontName);
|
||||||
BuildKeyNameFromFontName(actualFontName);
|
BuildKeyNameFromFontName(actualFontName);
|
||||||
nsRefPtr<FontEntry> fe;
|
nsRefPtr<FontFamily> ff;
|
||||||
if (!actualFontName.IsEmpty() && mFonts.Get(actualFontName, &fe))
|
if (!actualFontName.IsEmpty() && mFonts.Get(actualFontName, &ff))
|
||||||
mFontSubstitutes.Put(substituteName, fe);
|
mFontSubstitutes.Put(substituteName, ff);
|
||||||
else
|
else
|
||||||
mNonExistingFonts.AppendString(substituteName);
|
mNonExistingFonts.AppendString(substituteName);
|
||||||
}
|
}
|
||||||
|
@ -392,12 +423,15 @@ gfxWindowsPlatform::InitBadUnderlineList()
|
||||||
ResolveFontName(blacklist[i], SimpleResolverCallback, &resolved, aborted);
|
ResolveFontName(blacklist[i], SimpleResolverCallback, &resolved, aborted);
|
||||||
if (resolved.IsEmpty())
|
if (resolved.IsEmpty())
|
||||||
continue;
|
continue;
|
||||||
FontEntry* fe = FindFontEntry(resolved);
|
FontFamily *ff = FindFontFamily(resolved);
|
||||||
if (!fe)
|
if (!ff)
|
||||||
continue;
|
continue;
|
||||||
|
for (PRUint32 j = 0; j < ff->mVariations.Length(); ++j) {
|
||||||
|
nsRefPtr<FontEntry> fe = ff->mVariations[j];
|
||||||
fe->mIsBadUnderlineFont = 1;
|
fe->mIsBadUnderlineFont = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
gfxWindowsPlatform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
|
gfxWindowsPlatform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
|
||||||
|
@ -432,11 +466,11 @@ gfxWindowsPlatform::ResolveFontName(const nsAString& aFontName,
|
||||||
nsAutoString keyName(aFontName);
|
nsAutoString keyName(aFontName);
|
||||||
BuildKeyNameFromFontName(keyName);
|
BuildKeyNameFromFontName(keyName);
|
||||||
|
|
||||||
nsRefPtr<FontEntry> fe;
|
nsRefPtr<FontFamily> ff;
|
||||||
if (mFonts.Get(keyName, &fe) ||
|
if (mFonts.Get(keyName, &ff) ||
|
||||||
mFontSubstitutes.Get(keyName, &fe) ||
|
mFontSubstitutes.Get(keyName, &ff) ||
|
||||||
mFontAliases.Get(keyName, &fe)) {
|
mFontAliases.Get(keyName, &ff)) {
|
||||||
aAborted = !(*aCallback)(fe->mName, aClosure);
|
aAborted = !(*aCallback)(ff->mName, aClosure);
|
||||||
// XXX If the font has font link, we should add the linked font.
|
// XXX If the font has font link, we should add the linked font.
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -458,8 +492,7 @@ gfxWindowsPlatform::ResolveFontName(const nsAString& aFontName,
|
||||||
|
|
||||||
HDC dc = ::GetDC(nsnull);
|
HDC dc = ::GetDC(nsnull);
|
||||||
ResolveData data(aCallback, this, &keyName, aClosure);
|
ResolveData data(aCallback, this, &keyName, aClosure);
|
||||||
aAborted =
|
aAborted = !EnumFontFamiliesExW(dc, &logFont,
|
||||||
!EnumFontFamiliesExW(dc, &logFont,
|
|
||||||
(FONTENUMPROCW)gfxWindowsPlatform::FontResolveProc,
|
(FONTENUMPROCW)gfxWindowsPlatform::FontResolveProc,
|
||||||
(LPARAM)&data, 0);
|
(LPARAM)&data, 0);
|
||||||
if (data.mFoundCount == 0)
|
if (data.mFoundCount == 0)
|
||||||
|
@ -484,10 +517,10 @@ gfxWindowsPlatform::FontResolveProc(const ENUMLOGFONTEXW *lpelfe,
|
||||||
nsAutoString name(logFont.lfFaceName);
|
nsAutoString name(logFont.lfFaceName);
|
||||||
|
|
||||||
// Save the alias name to cache
|
// Save the alias name to cache
|
||||||
nsRefPtr<FontEntry> fe;
|
nsRefPtr<FontFamily> ff;
|
||||||
nsAutoString keyName(name);
|
nsAutoString keyName(name);
|
||||||
BuildKeyNameFromFontName(keyName);
|
BuildKeyNameFromFontName(keyName);
|
||||||
if (!rData->mCaller->mFonts.Get(keyName, &fe)) {
|
if (!rData->mCaller->mFonts.Get(keyName, &ff)) {
|
||||||
// This case only occurs on failing to build
|
// This case only occurs on failing to build
|
||||||
// the list of font substitue. In this case, the user should
|
// the list of font substitue. In this case, the user should
|
||||||
// reboot the Windows. Probably, we don't have the good way for
|
// reboot the Windows. Probably, we don't have the good way for
|
||||||
|
@ -497,7 +530,7 @@ gfxWindowsPlatform::FontResolveProc(const ENUMLOGFONTEXW *lpelfe,
|
||||||
}
|
}
|
||||||
|
|
||||||
rData->mFoundCount++;
|
rData->mFoundCount++;
|
||||||
rData->mCaller->mFontAliases.Put(*(rData->mFontName), fe);
|
rData->mCaller->mFontAliases.Put(*(rData->mFontName), ff);
|
||||||
|
|
||||||
return (rData->mCallback)(name, rData->mClosure);
|
return (rData->mCallback)(name, rData->mClosure);
|
||||||
|
|
||||||
|
@ -516,53 +549,61 @@ struct FontSearch {
|
||||||
|
|
||||||
PLDHashOperator PR_CALLBACK
|
PLDHashOperator PR_CALLBACK
|
||||||
gfxWindowsPlatform::FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
gfxWindowsPlatform::FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
||||||
nsRefPtr<FontEntry>& aFontEntry,
|
nsRefPtr<FontFamily>& aFontFamily,
|
||||||
void* userArg)
|
void* userArg)
|
||||||
{
|
{
|
||||||
|
// XXX Improve this to look at the variations to find a better font
|
||||||
|
nsRefPtr<FontEntry> aFontEntry = aFontFamily->mVariations[0];
|
||||||
|
|
||||||
// bitmap fonts suck
|
// bitmap fonts suck
|
||||||
if (aFontEntry->IsCrappyFont())
|
if (aFontEntry->IsCrappyFont())
|
||||||
return PL_DHASH_NEXT;
|
return PL_DHASH_NEXT;
|
||||||
|
|
||||||
FontSearch *data = (FontSearch*)userArg;
|
FontSearch *data = (FontSearch*)userArg;
|
||||||
|
|
||||||
PRInt32 rank = 0;
|
|
||||||
|
|
||||||
PRUint32 ch = data->ch;
|
PRUint32 ch = data->ch;
|
||||||
|
|
||||||
if (aFontEntry->mCharacterMap.test(ch)) {
|
for (PRUint32 i = 0; i < aFontFamily->mVariations.Length(); ++i) {
|
||||||
rank += 20;
|
PRInt32 rank = 0;
|
||||||
|
|
||||||
|
nsRefPtr<FontEntry> fe = aFontFamily->mVariations[i];
|
||||||
|
|
||||||
|
if (fe->mCharacterMap.test(ch)) {
|
||||||
// fonts that claim to support the range are more
|
// fonts that claim to support the range are more
|
||||||
// likely to be "better fonts" than ones that don't... (in theory)
|
// likely to be "better fonts" than ones that don't... (in theory)
|
||||||
if (aFontEntry->SupportsRange(gfxFontUtils::CharRangeBit(ch)))
|
if (fe->SupportsRange(gfxFontUtils::CharRangeBit(ch)))
|
||||||
rank += 1;
|
rank += 1;
|
||||||
|
} else {
|
||||||
|
// if we didn't match any characters don't bother wasting more time.
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we didn't match any characters don't bother wasting more time.
|
if (fe->SupportsLangGroup(data->fontToMatch->GetStyle()->langGroup))
|
||||||
if (rank == 0)
|
|
||||||
return PL_DHASH_NEXT;
|
|
||||||
|
|
||||||
|
|
||||||
if (aFontEntry->SupportsLangGroup(data->fontToMatch->GetStyle()->langGroup))
|
|
||||||
rank += 10;
|
rank += 10;
|
||||||
|
|
||||||
if (data->fontToMatch->GetFontEntry()->mFamily == aFontEntry->mFamily)
|
if (fe->mWindowsFamily == data->fontToMatch->GetFontEntry()->mWindowsFamily)
|
||||||
rank += 5;
|
rank += 5;
|
||||||
if (data->fontToMatch->GetFontEntry()->mFamily == aFontEntry->mPitch)
|
if (fe->mWindowsPitch == data->fontToMatch->GetFontEntry()->mWindowsFamily)
|
||||||
rank += 5;
|
rank += 5;
|
||||||
|
|
||||||
|
/* italic */
|
||||||
|
const PRBool italic = (data->fontToMatch->GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) ? PR_TRUE : PR_FALSE;
|
||||||
|
if (fe->mItalic == italic)
|
||||||
|
rank += 55;
|
||||||
|
|
||||||
/* weight */
|
/* weight */
|
||||||
PRInt8 baseWeight, weightDistance;
|
PRInt8 baseWeight, weightDistance;
|
||||||
data->fontToMatch->GetStyle()->ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
data->fontToMatch->GetStyle()->ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
||||||
PRUint16 targetWeight = (baseWeight * 100) + (weightDistance * 100);
|
PRUint16 targetWeight = (baseWeight * 100) + (weightDistance * 100);
|
||||||
if (targetWeight == aFontEntry->mDefaultWeight)
|
if (fe->mWeight == targetWeight)
|
||||||
rank += 5;
|
rank += 50;
|
||||||
|
|
||||||
if (rank > data->matchRank ||
|
if (rank > data->matchRank ||
|
||||||
(rank == data->matchRank && Compare(aFontEntry->mName, data->bestMatch->mName) > 0)) {
|
(rank == data->matchRank && Compare(fe->GetName(), data->bestMatch->GetName()) > 0)) {
|
||||||
data->bestMatch = aFontEntry;
|
data->bestMatch = fe;
|
||||||
data->matchRank = rank;
|
data->matchRank = rank;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return PL_DHASH_NEXT;
|
return PL_DHASH_NEXT;
|
||||||
}
|
}
|
||||||
|
@ -596,19 +637,90 @@ gfxWindowsPlatform::CreateFontGroup(const nsAString &aFamilies,
|
||||||
return new gfxWindowsFontGroup(aFamilies, aStyle);
|
return new gfxWindowsFontGroup(aFamilies, aStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
FontEntry *
|
FontFamily *
|
||||||
gfxWindowsPlatform::FindFontEntry(const nsAString& aName)
|
gfxWindowsPlatform::FindFontFamily(const nsAString& aName)
|
||||||
{
|
{
|
||||||
nsString name(aName);
|
nsString name(aName);
|
||||||
ToLowerCase(name);
|
ToLowerCase(name);
|
||||||
|
|
||||||
nsRefPtr<FontEntry> fe;
|
nsRefPtr<FontFamily> ff;
|
||||||
if (!mFonts.Get(name, &fe) &&
|
if (!mFonts.Get(name, &ff) &&
|
||||||
!mFontSubstitutes.Get(name, &fe) &&
|
!mFontSubstitutes.Get(name, &ff) &&
|
||||||
!mFontAliases.Get(name, &fe)) {
|
!mFontAliases.Get(name, &ff)) {
|
||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
return fe.get();
|
return ff.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
FontEntry *
|
||||||
|
gfxWindowsPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle *aFontStyle)
|
||||||
|
{
|
||||||
|
nsRefPtr<FontFamily> ff = FindFontFamily(aName);
|
||||||
|
if (!ff)
|
||||||
|
return nsnull;
|
||||||
|
|
||||||
|
PRUint8 bestMatch = 0;
|
||||||
|
nsRefPtr<FontEntry> matchFE;
|
||||||
|
const PRBool italic = (aFontStyle->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) ? PR_TRUE : PR_FALSE;
|
||||||
|
|
||||||
|
// build up an array of weights that match the italicness we're looking for
|
||||||
|
nsAutoTArray<nsRefPtr<FontEntry>, 10> weightList;
|
||||||
|
weightList.AppendElements(10);
|
||||||
|
for (PRInt32 i = 0; i < ff->mVariations.Length(); i++) {
|
||||||
|
nsRefPtr<FontEntry> fe = ff->mVariations[i];
|
||||||
|
const PRUint8 weight = (fe->mWeight / 100) - 1;
|
||||||
|
if (italic == fe->mItalic)
|
||||||
|
weightList[weight] = fe;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRInt8 baseWeight, weightDistance;
|
||||||
|
aFontStyle->ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
||||||
|
|
||||||
|
PRUint32 chosenWeight = 0;
|
||||||
|
PRUint8 direction = (weightDistance >= 0) ? 1 : -1;
|
||||||
|
|
||||||
|
WEIGHT_SELECTION:
|
||||||
|
for (PRUint8 i = baseWeight, k = 0; i < 10 && i >= 1; i+=direction) {
|
||||||
|
if (weightList[i - 1]) {
|
||||||
|
k++;
|
||||||
|
chosenWeight = i * 100;
|
||||||
|
}
|
||||||
|
if (k > abs(weightDistance)) {
|
||||||
|
chosenWeight = i * 100;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 500 isn't quite bold, so if we don't have a 500 weight
|
||||||
|
// lets pretend to be 400 and look again
|
||||||
|
if (baseWeight == 5 && weightDistance == 0 && chosenWeight > 500) {
|
||||||
|
baseWeight = 4;
|
||||||
|
goto WEIGHT_SELECTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we still don't have a chosen weight, just pick one
|
||||||
|
if (chosenWeight == 0)
|
||||||
|
chosenWeight = baseWeight * 100;
|
||||||
|
|
||||||
|
// If we end up with something like 900 here but only have 600,
|
||||||
|
// search backwards until we find a match
|
||||||
|
const PRUint32 index = (chosenWeight / 100) - 1;
|
||||||
|
for (PRInt32 j = index; j >= 0; --j) {
|
||||||
|
if (matchFE = weightList[j])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!matchFE) {
|
||||||
|
NS_ASSERTION(italic, "Italic isn't set. This is bad");
|
||||||
|
// We should only ever hit this code in the case where we're looking for an
|
||||||
|
// italic font and there is no face for one, so ask for a match for a normal one.
|
||||||
|
// The font rendering code can still specify italic and Windows will
|
||||||
|
// do synthetic italic
|
||||||
|
gfxFontStyle style(*aFontStyle);
|
||||||
|
style.style = FONT_STYLE_NORMAL;
|
||||||
|
matchFE = FindFontEntry(aName, &style);
|
||||||
|
}
|
||||||
|
return matchFE;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmsHPROFILE
|
cmsHPROFILE
|
||||||
|
@ -633,15 +745,13 @@ gfxWindowsPlatform::GetPlatformCMSOutputProfile()
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
gfxWindowsPlatform::GetPrefFontEntries(const char *aLangGroup, nsTArray<nsRefPtr<FontEntry> > *array)
|
gfxWindowsPlatform::GetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<FontEntry> > *array)
|
||||||
{
|
{
|
||||||
nsCAutoString keyName(aLangGroup);
|
return mPrefFonts.Get(aKey, array);
|
||||||
return mPrefFonts.Get(keyName, array);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gfxWindowsPlatform::SetPrefFontEntries(const char *aLangGroup, nsTArray<nsRefPtr<FontEntry> >& array)
|
gfxWindowsPlatform::SetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<FontEntry> >& array)
|
||||||
{
|
{
|
||||||
nsCAutoString keyName(aLangGroup);
|
mPrefFonts.Put(aKey, array);
|
||||||
mPrefFonts.Put(keyName, array);
|
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче