bug 382542. fix problems with font fallback and font variations. r=vlad/jdaggett

This commit is contained in:
pavlov@pavlov.net 2008-03-19 17:41:19 -07:00
parent 8851b96936
commit 1156635031
4 changed files with 60 additions and 61 deletions

View File

@ -210,7 +210,7 @@ public:
class gfxWindowsFont : public gfxFont {
public:
gfxWindowsFont(const nsAString& aName, const gfxFontStyle *aFontStyle);
gfxWindowsFont(const nsAString& aName, const gfxFontStyle *aFontStyle, FontEntry *aFontEntry);
virtual ~gfxWindowsFont();
virtual const gfxFont::Metrics& GetMetrics();

View File

@ -85,6 +85,7 @@ public:
/* Find a FontFamily/FontEntry object that represents a font on your system given a name */
FontFamily *FindFontFamily(const nsAString& aName);
FontEntry *FindFontEntry(FontFamily *aFontFamily, const gfxFontStyle *aFontStyle);
FontEntry *FindFontEntry(const nsAString& aName, const gfxFontStyle *aFontStyle);
PRBool GetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> > *array);

View File

@ -115,14 +115,12 @@ struct DCFromContext {
*
**********************************************************************/
gfxWindowsFont::gfxWindowsFont(const nsAString& aName, const gfxFontStyle *aFontStyle)
gfxWindowsFont::gfxWindowsFont(const nsAString& aName, const gfxFontStyle *aFontStyle, FontEntry *aFontEntry)
: gfxFont(aName, aFontStyle),
mFont(nsnull), mAdjustedSize(0.0), mScriptCache(nsnull),
mFontFace(nsnull), mScaledFont(nsnull),
mMetrics(nsnull)
mMetrics(nsnull), mFontEntry(aFontEntry)
{
// XXX we should work to get this passed in rather than having to find it again.
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
@ -419,7 +417,7 @@ GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle)
{
nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(aFontEntry->GetName(), aStyle);
if (!font) {
font = new gfxWindowsFont(aFontEntry->GetName(), aStyle);
font = new gfxWindowsFont(aFontEntry->GetName(), aStyle, aFontEntry);
if (!font)
return nsnull;
gfxFontCache::GetCache()->AddNew(font);
@ -621,9 +619,7 @@ SetupDCFont(HDC dc, gfxWindowsFont *aFont)
/* GetGlyphIndices is buggy for bitmap and vector fonts,
so send them to uniscribe */
TEXTMETRIC metrics;
GetTextMetrics(dc, &metrics);
if ((metrics.tmPitchAndFamily & (TMPF_TRUETYPE)) == 0)
if (!aFont->GetFontEntry()->mTrueType)
return PR_FALSE;
return PR_TRUE;

View File

@ -145,6 +145,8 @@ gfxWindowsPlatform::FontEnumProc(const ENUMLOGFONTEXW *lpelfe,
if (metrics.ntmFlags & NTM_TYPE1)
fe->mIsType1 = PR_TRUE;
if (metrics.ntmFlags & (NTM_PS_OPENTYPE | NTM_TT_OPENTYPE))
fe->mTrueType = PR_TRUE;
// mark the charset bit
fe->mCharset[metrics.tmCharSet] = 1;
@ -552,57 +554,48 @@ gfxWindowsPlatform::FindFontForCharProc(nsStringHashKey::KeyType aKey,
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;
PRUint32 ch = data->ch;
const PRUint32 ch = data->ch;
for (PRUint32 i = 0; i < aFontFamily->mVariations.Length(); ++i) {
PRInt32 rank = 0;
nsRefPtr<FontEntry> fe = GetPlatform()->FindFontEntry(aFontFamily, data->fontToMatch->GetStyle());
nsRefPtr<FontEntry> fe = aFontFamily->mVariations[i];
// 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;
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;
}
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 (fe->SupportsRange(gfxFontUtils::CharRangeBit(ch)))
rank += 1;
if (fe->SupportsLangGroup(data->fontToMatch->GetStyle()->langGroup))
rank += 10;
if (fe->SupportsLangGroup(data->fontToMatch->GetStyle()->langGroup))
rank += 2;
if (fe->mWindowsFamily == data->fontToMatch->GetFontEntry()->mWindowsFamily)
rank += 5;
if (fe->mWindowsPitch == data->fontToMatch->GetFontEntry()->mWindowsFamily)
rank += 5;
if (fe->mWindowsFamily == data->fontToMatch->GetFontEntry()->mWindowsFamily)
rank += 3;
if (fe->mWindowsPitch == data->fontToMatch->GetFontEntry()->mWindowsFamily)
rank += 3;
/* italic */
const PRBool italic = (data->fontToMatch->GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) ? PR_TRUE : PR_FALSE;
if (fe->mItalic == italic)
rank += 55;
/* italic */
const PRBool italic = (data->fontToMatch->GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) ? PR_TRUE : PR_FALSE;
if (fe->mItalic != italic)
rank += 3;
/* weight */
PRInt8 baseWeight, weightDistance;
data->fontToMatch->GetStyle()->ComputeWeightAndOffset(&baseWeight, &weightDistance);
PRUint16 targetWeight = (baseWeight * 100) + (weightDistance * 100);
if (fe->mWeight == targetWeight)
rank += 50;
/* weight */
PRInt8 baseWeight, weightDistance;
data->fontToMatch->GetStyle()->ComputeWeightAndOffset(&baseWeight, &weightDistance);
if (fe->mWeight == (baseWeight * 100) + (weightDistance * 100))
rank += 2;
else if (fe->mWeight == data->fontToMatch->GetFontEntry()->mWeight)
rank += 1;
if (rank > data->matchRank ||
(rank == data->matchRank && Compare(fe->GetName(), data->bestMatch->GetName()) > 0)) {
data->bestMatch = fe;
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;
@ -659,6 +652,12 @@ gfxWindowsPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle *aF
if (!ff)
return nsnull;
return FindFontEntry(ff, aFontStyle);
}
FontEntry *
gfxWindowsPlatform::FindFontEntry(FontFamily *aFontFamily, const gfxFontStyle *aFontStyle)
{
PRUint8 bestMatch = 0;
nsRefPtr<FontEntry> matchFE;
const PRBool italic = (aFontStyle->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) ? PR_TRUE : PR_FALSE;
@ -666,10 +665,10 @@ gfxWindowsPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle *aF
// 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];
for (PRInt32 i = 0; i < aFontFamily->mVariations.Length(); i++) {
nsRefPtr<FontEntry> fe = aFontFamily->mVariations[i];
const PRUint8 weight = (fe->mWeight / 100) - 1;
if (italic == fe->mItalic)
if (fe->mItalic == italic)
weightList[weight] = fe;
}
@ -709,16 +708,19 @@ gfxWindowsPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle *aF
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
// Not having a match can occur in 2 ways:
// The font only has an italic face and we're looking for a normal one.
// The font has no italic face and we're looking for italic.
// So search for the opposite of what we're looking for
gfxFontStyle style(*aFontStyle);
style.style = FONT_STYLE_NORMAL;
matchFE = FindFontEntry(aName, &style);
if (aFontStyle->style == FONT_STYLE_NORMAL)
style.style = FONT_STYLE_ITALIC;
else
style.style = FONT_STYLE_NORMAL;
matchFE = FindFontEntry(aFontFamily, &style);
}
return matchFE;
}