зеркало из 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 <cairo-win32.h>
|
||||
|
||||
|
||||
/**
|
||||
* FontEntry is a class that describes one of the fonts on the users system
|
||||
* It contains information such as the name, font type, charset table and unicode ranges.
|
||||
* It may be extended to also keep basic metrics of the fonts so that we can better
|
||||
* compare one FontEntry to another.
|
||||
* 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:
|
||||
THEBES_INLINE_DECL_REFCOUNTING(FontFamily)
|
||||
|
||||
FontFamily(const nsAString& aName) :
|
||||
mName(aName)
|
||||
{
|
||||
}
|
||||
|
||||
nsTArray<nsRefPtr<FontEntry> > mVariations;
|
||||
nsString mName;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class FontEntry
|
||||
{
|
||||
public:
|
||||
THEBES_INLINE_DECL_REFCOUNTING(FontEntry)
|
||||
|
||||
FontEntry(const nsAString& aName) :
|
||||
mName(aName), mDefaultWeight(0),
|
||||
mUnicodeFont(PR_FALSE), mSymbolFont(PR_FALSE), mIsType1(PR_FALSE),
|
||||
FontEntry(FontFamily *aFontFamily) :
|
||||
mFamily(aFontFamily), mUnicodeFont(PR_FALSE), mSymbolFont(PR_FALSE),
|
||||
mTrueType(PR_FALSE), mIsType1(PR_FALSE),
|
||||
mIsBadUnderlineFont(PR_FALSE), mCharset(0), mUnicodeRanges(0)
|
||||
{
|
||||
}
|
||||
|
||||
const nsString& GetName() const {
|
||||
return mFamily->mName;
|
||||
}
|
||||
|
||||
PRBool IsCrappyFont() const {
|
||||
/* return if it is a bitmap not a unicode font */
|
||||
return (!mUnicodeFont || mSymbolFont || mIsType1);
|
||||
|
@ -80,18 +101,18 @@ public:
|
|||
|
||||
// Japanese 'Mincho' fonts do not belong to FF_MODERN even if
|
||||
// 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");
|
||||
}
|
||||
|
||||
// Japanese 'Gothic' fonts do not belong to FF_SWISS even if
|
||||
// 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");
|
||||
}
|
||||
|
||||
// All other fonts will be grouped correctly using family...
|
||||
switch (mFamily) {
|
||||
switch (mWindowsFamily) {
|
||||
case FF_DONTCARE:
|
||||
return PR_TRUE;
|
||||
case FF_ROMAN:
|
||||
|
@ -158,52 +179,29 @@ public:
|
|||
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.
|
||||
PRBool IsBadUnderlineFont() { return mIsBadUnderlineFont != 0; }
|
||||
|
||||
// The family name of the font
|
||||
nsString mName;
|
||||
/* needs to be a weak pointer to avoid a cycle */
|
||||
FontFamily *mFamily;
|
||||
|
||||
PRUint16 mDefaultWeight;
|
||||
|
||||
PRUint8 mFamily;
|
||||
PRUint8 mPitch;
|
||||
PRUint8 mWindowsFamily;
|
||||
PRUint8 mWindowsPitch;
|
||||
|
||||
PRPackedBool mUnicodeFont;
|
||||
PRPackedBool mSymbolFont;
|
||||
PRPackedBool mTrueType;
|
||||
PRPackedBool mIsType1;
|
||||
PRPackedBool mIsBadUnderlineFont;
|
||||
PRPackedBool mItalic;
|
||||
PRUint16 mWeight;
|
||||
|
||||
std::bitset<256> mCharset;
|
||||
std::bitset<128> mUnicodeRanges;
|
||||
|
||||
WeightTable mWeightTable;
|
||||
|
||||
gfxSparseBitSet mCharacterMap;
|
||||
};
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* class gfxWindowsFont
|
||||
|
@ -238,7 +236,7 @@ public:
|
|||
|
||||
protected:
|
||||
HFONT MakeHFONT();
|
||||
void FillLogFont(gfxFloat aSize, PRInt16 aWeight);
|
||||
void FillLogFont(gfxFloat aSize);
|
||||
|
||||
HFONT mFont;
|
||||
gfxFloat mAdjustedSize;
|
||||
|
@ -297,6 +295,11 @@ public:
|
|||
|
||||
virtual gfxWindowsFont *GetFontAt(PRInt32 i);
|
||||
|
||||
void GroupFamilyListToArrayList(nsTArray<nsRefPtr<FontEntry> > *list);
|
||||
void FamilyListToArrayList(const nsString& aFamilies,
|
||||
const nsCString& aLangGroup,
|
||||
nsTArray<nsRefPtr<FontEntry> > *list);
|
||||
|
||||
protected:
|
||||
void InitTextRunGDI(gfxContext *aContext, gfxTextRun *aRun, const char *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);
|
||||
|
||||
private:
|
||||
|
||||
nsCString mGenericFamily;
|
||||
nsTArray<nsRefPtr<FontEntry> > mFontEntries;
|
||||
};
|
||||
|
|
|
@ -83,11 +83,14 @@ public:
|
|||
*/
|
||||
FontEntry *FindFontForChar(PRUint32 aCh, gfxWindowsFont *aFont);
|
||||
|
||||
/* Find a FontEntry object that represents a font on your system given a name */
|
||||
FontEntry *FindFontEntry(const nsAString& aName);
|
||||
/* 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);
|
||||
|
||||
PRBool GetPrefFontEntries(const char *aLangGroup, nsTArray<nsRefPtr<FontEntry> > *array);
|
||||
void SetPrefFontEntries(const char *aLangGroup, nsTArray<nsRefPtr<FontEntry> >& array);
|
||||
PRBool GetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> > *array);
|
||||
void SetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> >& array);
|
||||
|
||||
typedef nsDataHashtable<nsStringHashKey, nsRefPtr<FontFamily> > FontTable;
|
||||
|
||||
private:
|
||||
void Init();
|
||||
|
@ -98,8 +101,12 @@ private:
|
|||
const NEWTEXTMETRICEXW *metrics,
|
||||
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,
|
||||
nsRefPtr<FontEntry>& aFontEntry,
|
||||
nsRefPtr<FontFamily>& aFontFamily,
|
||||
void* userArg);
|
||||
|
||||
static int CALLBACK FontResolveProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
|
@ -107,20 +114,20 @@ private:
|
|||
DWORD fontType, LPARAM data);
|
||||
|
||||
static PLDHashOperator PR_CALLBACK HashEnumFunc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontEntry>& aData,
|
||||
nsRefPtr<FontFamily>& aData,
|
||||
void* userArg);
|
||||
|
||||
static PLDHashOperator PR_CALLBACK FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontEntry>& aFontEntry,
|
||||
nsRefPtr<FontFamily>& aFontFamily,
|
||||
void* userArg);
|
||||
|
||||
virtual cmsHPROFILE GetPlatformCMSOutputProfile();
|
||||
|
||||
static int PR_CALLBACK PrefChangedCallback(const char*, void*);
|
||||
|
||||
nsDataHashtable<nsStringHashKey, nsRefPtr<FontEntry> > mFonts;
|
||||
nsDataHashtable<nsStringHashKey, nsRefPtr<FontEntry> > mFontAliases;
|
||||
nsDataHashtable<nsStringHashKey, nsRefPtr<FontEntry> > mFontSubstitutes;
|
||||
FontTable mFonts;
|
||||
FontTable mFontAliases;
|
||||
FontTable mFontSubstitutes;
|
||||
nsStringArray mNonExistingFonts;
|
||||
|
||||
// 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)
|
||||
{
|
||||
// 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.");
|
||||
|
||||
mFont = MakeHFONT(); // create the HFONT, compute metrics, etc
|
||||
|
@ -194,87 +194,10 @@ gfxWindowsFont::MakeHFONT()
|
|||
if (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;
|
||||
if (GetStyle()->sizeAdjust > 0.0) {
|
||||
if (!mFont) {
|
||||
FillLogFont(mAdjustedSize, chosenWeight);
|
||||
FillLogFont(mAdjustedSize);
|
||||
mFont = CreateFontIndirectW(&mLogFont);
|
||||
}
|
||||
|
||||
|
@ -292,13 +215,10 @@ gfxWindowsFont::MakeHFONT()
|
|||
}
|
||||
|
||||
if (!mFont) {
|
||||
FillLogFont(mAdjustedSize, chosenWeight);
|
||||
FillLogFont(mAdjustedSize);
|
||||
mFont = CreateFontIndirectW(&mLogFont);
|
||||
}
|
||||
|
||||
if (dc)
|
||||
ReleaseDC((HWND)nsnull, dc);
|
||||
|
||||
return mFont;
|
||||
}
|
||||
|
||||
|
@ -388,7 +308,7 @@ gfxWindowsFont::ComputeMetrics()
|
|||
}
|
||||
|
||||
void
|
||||
gfxWindowsFont::FillLogFont(gfxFloat aSize, PRInt16 aWeight)
|
||||
gfxWindowsFont::FillLogFont(gfxFloat aSize)
|
||||
{
|
||||
#define CLIP_TURNOFF_FONTASSOCIATION 0x40
|
||||
|
||||
|
@ -398,7 +318,7 @@ gfxWindowsFont::FillLogFont(gfxFloat aSize, PRInt16 aWeight)
|
|||
mLogFont.lfHeight = -1;
|
||||
|
||||
// Fill in logFont structure
|
||||
mLogFont.lfWidth = 0;
|
||||
mLogFont.lfWidth = 0;
|
||||
mLogFont.lfEscapement = 0;
|
||||
mLogFont.lfOrientation = 0;
|
||||
mLogFont.lfUnderline = FALSE;
|
||||
|
@ -412,8 +332,20 @@ gfxWindowsFont::FillLogFont(gfxFloat aSize, PRInt16 aWeight)
|
|||
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 = (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);
|
||||
memcpy(mLogFont.lfFaceName, nsPromiseFlatString(mName).get(), len * 2);
|
||||
|
@ -485,9 +417,9 @@ gfxWindowsFont::SetupCairoFont(gfxContext *aContext)
|
|||
static already_AddRefed<gfxWindowsFont>
|
||||
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) {
|
||||
font = new gfxWindowsFont(aFontEntry->mName, aStyle);
|
||||
font = new gfxWindowsFont(aFontEntry->GetName(), aStyle);
|
||||
if (!font)
|
||||
return nsnull;
|
||||
gfxFontCache::GetCache()->AddNew(font);
|
||||
|
@ -498,25 +430,53 @@ GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle)
|
|||
}
|
||||
|
||||
static PRBool
|
||||
AddFontEntryToArray(const nsAString& aName,
|
||||
const nsACString& aGenericName,
|
||||
void *closure)
|
||||
AddFontNameToArray(const nsAString& aName,
|
||||
const nsACString& aGenericName,
|
||||
void *closure)
|
||||
{
|
||||
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(fe) == list->NoIndex)
|
||||
list->AppendElement(fe);
|
||||
if (list->IndexOf(aName) == list->NoIndex)
|
||||
list->AppendElement(aName);
|
||||
}
|
||||
|
||||
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)
|
||||
: gfxFontGroup(aFamilies, aStyle)
|
||||
{
|
||||
ForEachFont(AddFontEntryToArray, &mFontEntries);
|
||||
GroupFamilyListToArrayList(&mFontEntries);
|
||||
|
||||
if (mFontEntries.Length() == 0) {
|
||||
// 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");
|
||||
return;
|
||||
}
|
||||
nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(nsDependentString(logFont.lfFaceName));
|
||||
nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(nsDependentString(logFont.lfFaceName), aStyle);
|
||||
mFontEntries.AppendElement(fe);
|
||||
}
|
||||
|
||||
|
@ -1463,9 +1423,9 @@ public:
|
|||
}
|
||||
if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG)) {
|
||||
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
|
||||
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Unable to find font"));
|
||||
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Unable to find font"));
|
||||
}
|
||||
}
|
||||
mRanges[mRanges.Length()-1].end = mItemLength;
|
||||
|
@ -1490,15 +1450,22 @@ private:
|
|||
NS_ASSERTION(aLangGroup, "aLangGroup is null");
|
||||
gfxWindowsPlatform *platform = gfxWindowsPlatform::GetPlatform();
|
||||
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;
|
||||
platform->GetPrefFonts(aLangGroup, fontString);
|
||||
if (fontString.IsEmpty())
|
||||
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);
|
||||
}
|
||||
|
@ -1506,7 +1473,13 @@ private:
|
|||
// this function assigns to the array passed in.
|
||||
void GetCJKPrefFonts(nsTArray<nsRefPtr<FontEntry> >& array) {
|
||||
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);
|
||||
if (!prefs)
|
||||
return;
|
||||
|
@ -1566,7 +1539,7 @@ private:
|
|||
GetPrefFonts(CJK_LANG_ZH_HK, 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
|
||||
|
||||
static nsresult ReadCMAP(HDC hdc, FontEntry *aFontEntry);
|
||||
|
||||
int PR_CALLBACK
|
||||
gfxWindowsPlatform::PrefChangedCallback(const char *aPrefName, void *closure)
|
||||
{
|
||||
|
@ -102,44 +104,53 @@ gfxWindowsPlatform::FontEnumProc(const ENUMLOGFONTEXW *lpelfe,
|
|||
const NEWTEXTMETRICEXW *nmetrics,
|
||||
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;
|
||||
|
||||
#ifdef DEBUG_pavlov
|
||||
printf("%s %d %d %d\n", NS_ConvertUTF16toUTF8(nsDependentString(logFont.lfFaceName)).get(),
|
||||
logFont.lfCharSet, logFont.lfItalic, logFont.lfWeight);
|
||||
#endif
|
||||
LOGFONTW logFont = lpelfe->elfLogFont;
|
||||
|
||||
// Ignore vertical fonts
|
||||
if (logFont.lfFaceName[0] == L'@') {
|
||||
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);
|
||||
ToLowerCase(name);
|
||||
|
||||
nsRefPtr<FontEntry> fe;
|
||||
if (!thisp->mFonts.Get(name, &fe)) {
|
||||
fe = new FontEntry(nsDependentString(logFont.lfFaceName));
|
||||
thisp->mFonts.Put(name, fe);
|
||||
nsRefPtr<FontFamily> ff;
|
||||
if (!ht->Get(name, &ff)) {
|
||||
ff = new FontFamily(nsDependentString(logFont.lfFaceName));
|
||||
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)
|
||||
fe->mIsType1 = PR_TRUE;
|
||||
|
||||
// mark the charset bit
|
||||
fe->mCharset[metrics.tmCharSet] = 1;
|
||||
|
||||
// put the default weight in the weight table
|
||||
fe->mWeightTable.SetWeight(PR_MAX(1, PR_MIN(9, metrics.tmWeight / 100)), PR_TRUE);
|
||||
|
||||
// store the default font weight
|
||||
fe->mDefaultWeight = metrics.tmWeight;
|
||||
|
||||
fe->mFamily = logFont.lfPitchAndFamily & 0xF0;
|
||||
fe->mPitch = logFont.lfPitchAndFamily & 0x0F;
|
||||
fe->mWindowsFamily = logFont.lfPitchAndFamily & 0xF0;
|
||||
fe->mWindowsPitch = logFont.lfPitchAndFamily & 0x0F;
|
||||
|
||||
if (nmetrics->ntmFontSig.fsUsb[0] == 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;
|
||||
}
|
||||
|
||||
|
@ -183,66 +239,36 @@ ReadCMAP(HDC hdc, FontEntry *aFontEntry)
|
|||
NS_ENSURE_TRUE(newLen == len, NS_ERROR_FAILURE);
|
||||
|
||||
return gfxFontUtils::ReadCMAP(buf, len, aFontEntry->mCharacterMap, aFontEntry->mUnicodeRanges,
|
||||
aFontEntry->mUnicodeFont, aFontEntry->mSymbolFont);
|
||||
aFontEntry->mUnicodeFont, aFontEntry->mSymbolFont);
|
||||
}
|
||||
|
||||
PLDHashOperator PR_CALLBACK
|
||||
gfxWindowsPlatform::FontGetCMapDataProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontEntry>& aFontEntry,
|
||||
void* userArg)
|
||||
gfxWindowsPlatform::FontGetStylesProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontFamily>& aFontFamily,
|
||||
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);
|
||||
|
||||
LOGFONTW logFont;
|
||||
memset(&logFont, 0, sizeof(LOGFONTW));
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
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,
|
||||
nsPromiseFlatString(aFontEntry->mName).get(),
|
||||
nsPromiseFlatString(aFontEntry->GetName()).get(),
|
||||
l * sizeof(PRUnichar));
|
||||
logFont.lfFaceName[l] = 0;
|
||||
|
||||
HFONT font = CreateFontIndirectW(&logFont);
|
||||
|
||||
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);
|
||||
}
|
||||
EnumFontFamiliesExW(hdc, &logFont, (FONTENUMPROCW)gfxWindowsPlatform::FontEnumProc, (LPARAM)userArg, 0);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
struct FontListData {
|
||||
FontListData(const nsACString& aLangGroup, const nsACString& aGenericFamily, nsStringArray& aListOfFonts) :
|
||||
mLangGroup(aLangGroup), mGenericFamily(aGenericFamily), mStringArray(aListOfFonts) {}
|
||||
|
@ -253,18 +279,23 @@ struct FontListData {
|
|||
|
||||
PLDHashOperator PR_CALLBACK
|
||||
gfxWindowsPlatform::HashEnumFunc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontEntry>& aFontEntry,
|
||||
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
|
||||
nsRefPtr<FontEntry> aFontEntry = aFontFamily->mVariations[0];
|
||||
|
||||
/* skip symbol fonts */
|
||||
if (aFontEntry->mSymbolFont)
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
if (aFontEntry->SupportsLangGroup(data->mLangGroup) &&
|
||||
aFontEntry->MatchesGenericFamily(data->mGenericFamily))
|
||||
data->mStringArray.AppendString(aFontEntry->mName);
|
||||
data->mStringArray.AppendString(aFontFamily->mName);
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
@ -317,11 +348,11 @@ gfxWindowsPlatform::UpdateFontList()
|
|||
|
||||
// Use the screen DC here.. should we use something else for printing?
|
||||
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);
|
||||
|
||||
// Update all the fonts cmaps
|
||||
mFonts.Enumerate(gfxWindowsPlatform::FontGetCMapDataProc, nsnull);
|
||||
// Look for additional styles
|
||||
mFonts.Enumerate(gfxWindowsPlatform::FontGetStylesProc, &mFonts);
|
||||
|
||||
// Create the list of FontSubstitutes
|
||||
nsCOMPtr<nsIWindowsRegKey> regKey = do_CreateInstance("@mozilla.org/windows-registry-key;1");
|
||||
|
@ -357,9 +388,9 @@ gfxWindowsPlatform::UpdateFontList()
|
|||
BuildKeyNameFromFontName(substituteName);
|
||||
RemoveCharsetFromFontSubstitute(actualFontName);
|
||||
BuildKeyNameFromFontName(actualFontName);
|
||||
nsRefPtr<FontEntry> fe;
|
||||
if (!actualFontName.IsEmpty() && mFonts.Get(actualFontName, &fe))
|
||||
mFontSubstitutes.Put(substituteName, fe);
|
||||
nsRefPtr<FontFamily> ff;
|
||||
if (!actualFontName.IsEmpty() && mFonts.Get(actualFontName, &ff))
|
||||
mFontSubstitutes.Put(substituteName, ff);
|
||||
else
|
||||
mNonExistingFonts.AppendString(substituteName);
|
||||
}
|
||||
|
@ -392,10 +423,13 @@ gfxWindowsPlatform::InitBadUnderlineList()
|
|||
ResolveFontName(blacklist[i], SimpleResolverCallback, &resolved, aborted);
|
||||
if (resolved.IsEmpty())
|
||||
continue;
|
||||
FontEntry* fe = FindFontEntry(resolved);
|
||||
if (!fe)
|
||||
FontFamily *ff = FindFontFamily(resolved);
|
||||
if (!ff)
|
||||
continue;
|
||||
fe->mIsBadUnderlineFont = 1;
|
||||
for (PRUint32 j = 0; j < ff->mVariations.Length(); ++j) {
|
||||
nsRefPtr<FontEntry> fe = ff->mVariations[j];
|
||||
fe->mIsBadUnderlineFont = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -432,11 +466,11 @@ gfxWindowsPlatform::ResolveFontName(const nsAString& aFontName,
|
|||
nsAutoString keyName(aFontName);
|
||||
BuildKeyNameFromFontName(keyName);
|
||||
|
||||
nsRefPtr<FontEntry> fe;
|
||||
if (mFonts.Get(keyName, &fe) ||
|
||||
mFontSubstitutes.Get(keyName, &fe) ||
|
||||
mFontAliases.Get(keyName, &fe)) {
|
||||
aAborted = !(*aCallback)(fe->mName, aClosure);
|
||||
nsRefPtr<FontFamily> ff;
|
||||
if (mFonts.Get(keyName, &ff) ||
|
||||
mFontSubstitutes.Get(keyName, &ff) ||
|
||||
mFontAliases.Get(keyName, &ff)) {
|
||||
aAborted = !(*aCallback)(ff->mName, aClosure);
|
||||
// XXX If the font has font link, we should add the linked font.
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -458,10 +492,9 @@ gfxWindowsPlatform::ResolveFontName(const nsAString& aFontName,
|
|||
|
||||
HDC dc = ::GetDC(nsnull);
|
||||
ResolveData data(aCallback, this, &keyName, aClosure);
|
||||
aAborted =
|
||||
!EnumFontFamiliesExW(dc, &logFont,
|
||||
(FONTENUMPROCW)gfxWindowsPlatform::FontResolveProc,
|
||||
(LPARAM)&data, 0);
|
||||
aAborted = !EnumFontFamiliesExW(dc, &logFont,
|
||||
(FONTENUMPROCW)gfxWindowsPlatform::FontResolveProc,
|
||||
(LPARAM)&data, 0);
|
||||
if (data.mFoundCount == 0)
|
||||
mNonExistingFonts.AppendString(keyName);
|
||||
::ReleaseDC(nsnull, dc);
|
||||
|
@ -484,10 +517,10 @@ gfxWindowsPlatform::FontResolveProc(const ENUMLOGFONTEXW *lpelfe,
|
|||
nsAutoString name(logFont.lfFaceName);
|
||||
|
||||
// Save the alias name to cache
|
||||
nsRefPtr<FontEntry> fe;
|
||||
nsRefPtr<FontFamily> ff;
|
||||
nsAutoString keyName(name);
|
||||
BuildKeyNameFromFontName(keyName);
|
||||
if (!rData->mCaller->mFonts.Get(keyName, &fe)) {
|
||||
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
|
||||
|
@ -497,7 +530,7 @@ gfxWindowsPlatform::FontResolveProc(const ENUMLOGFONTEXW *lpelfe,
|
|||
}
|
||||
|
||||
rData->mFoundCount++;
|
||||
rData->mCaller->mFontAliases.Put(*(rData->mFontName), fe);
|
||||
rData->mCaller->mFontAliases.Put(*(rData->mFontName), ff);
|
||||
|
||||
return (rData->mCallback)(name, rData->mClosure);
|
||||
|
||||
|
@ -516,52 +549,60 @@ struct FontSearch {
|
|||
|
||||
PLDHashOperator PR_CALLBACK
|
||||
gfxWindowsPlatform::FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontEntry>& aFontEntry,
|
||||
void* userArg)
|
||||
nsRefPtr<FontFamily>& aFontFamily,
|
||||
void* userArg)
|
||||
{
|
||||
// XXX Improve this to look at the variations to find a better font
|
||||
nsRefPtr<FontEntry> aFontEntry = aFontFamily->mVariations[0];
|
||||
|
||||
// bitmap fonts suck
|
||||
if (aFontEntry->IsCrappyFont())
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
FontSearch *data = (FontSearch*)userArg;
|
||||
|
||||
PRInt32 rank = 0;
|
||||
|
||||
PRUint32 ch = data->ch;
|
||||
|
||||
if (aFontEntry->mCharacterMap.test(ch)) {
|
||||
rank += 20;
|
||||
for (PRUint32 i = 0; i < aFontFamily->mVariations.Length(); ++i) {
|
||||
PRInt32 rank = 0;
|
||||
|
||||
// fonts that claim to support the range are more
|
||||
// likely to be "better fonts" than ones that don't... (in theory)
|
||||
if (aFontEntry->SupportsRange(gfxFontUtils::CharRangeBit(ch)))
|
||||
rank += 1;
|
||||
}
|
||||
nsRefPtr<FontEntry> fe = aFontFamily->mVariations[i];
|
||||
|
||||
// if we didn't match any characters don't bother wasting more time.
|
||||
if (rank == 0)
|
||||
return PL_DHASH_NEXT;
|
||||
if (fe->mCharacterMap.test(ch)) {
|
||||
// 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;
|
||||
} else {
|
||||
// if we didn't match any characters don't bother wasting more time.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fe->SupportsLangGroup(data->fontToMatch->GetStyle()->langGroup))
|
||||
rank += 10;
|
||||
|
||||
if (aFontEntry->SupportsLangGroup(data->fontToMatch->GetStyle()->langGroup))
|
||||
rank += 10;
|
||||
if (fe->mWindowsFamily == data->fontToMatch->GetFontEntry()->mWindowsFamily)
|
||||
rank += 5;
|
||||
if (fe->mWindowsPitch == data->fontToMatch->GetFontEntry()->mWindowsFamily)
|
||||
rank += 5;
|
||||
|
||||
if (data->fontToMatch->GetFontEntry()->mFamily == aFontEntry->mFamily)
|
||||
rank += 5;
|
||||
if (data->fontToMatch->GetFontEntry()->mFamily == aFontEntry->mPitch)
|
||||
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 */
|
||||
PRInt8 baseWeight, weightDistance;
|
||||
data->fontToMatch->GetStyle()->ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
||||
PRUint16 targetWeight = (baseWeight * 100) + (weightDistance * 100);
|
||||
if (targetWeight == aFontEntry->mDefaultWeight)
|
||||
rank += 5;
|
||||
/* weight */
|
||||
PRInt8 baseWeight, weightDistance;
|
||||
data->fontToMatch->GetStyle()->ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
||||
PRUint16 targetWeight = (baseWeight * 100) + (weightDistance * 100);
|
||||
if (fe->mWeight == targetWeight)
|
||||
rank += 50;
|
||||
|
||||
if (rank > data->matchRank ||
|
||||
(rank == data->matchRank && Compare(aFontEntry->mName, data->bestMatch->mName) > 0)) {
|
||||
data->bestMatch = aFontEntry;
|
||||
data->matchRank = rank;
|
||||
if (rank > data->matchRank ||
|
||||
(rank == data->matchRank && Compare(fe->GetName(), data->bestMatch->GetName()) > 0)) {
|
||||
data->bestMatch = fe;
|
||||
data->matchRank = rank;
|
||||
}
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
|
@ -596,19 +637,90 @@ gfxWindowsPlatform::CreateFontGroup(const nsAString &aFamilies,
|
|||
return new gfxWindowsFontGroup(aFamilies, aStyle);
|
||||
}
|
||||
|
||||
FontEntry *
|
||||
gfxWindowsPlatform::FindFontEntry(const nsAString& aName)
|
||||
FontFamily *
|
||||
gfxWindowsPlatform::FindFontFamily(const nsAString& aName)
|
||||
{
|
||||
nsString name(aName);
|
||||
ToLowerCase(name);
|
||||
|
||||
nsRefPtr<FontEntry> fe;
|
||||
if (!mFonts.Get(name, &fe) &&
|
||||
!mFontSubstitutes.Get(name, &fe) &&
|
||||
!mFontAliases.Get(name, &fe)) {
|
||||
nsRefPtr<FontFamily> ff;
|
||||
if (!mFonts.Get(name, &ff) &&
|
||||
!mFontSubstitutes.Get(name, &ff) &&
|
||||
!mFontAliases.Get(name, &ff)) {
|
||||
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
|
||||
|
@ -633,15 +745,13 @@ gfxWindowsPlatform::GetPlatformCMSOutputProfile()
|
|||
}
|
||||
|
||||
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(keyName, array);
|
||||
return mPrefFonts.Get(aKey, array);
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::SetPrefFontEntries(const char *aLangGroup, nsTArray<nsRefPtr<FontEntry> >& array)
|
||||
gfxWindowsPlatform::SetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<FontEntry> >& array)
|
||||
{
|
||||
nsCAutoString keyName(aLangGroup);
|
||||
mPrefFonts.Put(keyName, array);
|
||||
mPrefFonts.Put(aKey, array);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче