зеркало из https://github.com/mozilla/pjs.git
bug 424018. make character map loading lazy to fix ts regression. r=vlad a=beltzner
This commit is contained in:
Родитель
fec8ae0b9e
Коммит
c1e34c0aff
|
@ -307,14 +307,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
ReadCMAPTableFormat12(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap, std::bitset<128>& aUnicodeRanges);
|
ReadCMAPTableFormat12(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap);
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
ReadCMAPTableFormat4(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap, std::bitset<128>& aUnicodeRanges);
|
ReadCMAPTableFormat4(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap);
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCharacterMap, std::bitset<128>& aUnicodeRanges, PRPackedBool& aUnicodeFont,
|
ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCharacterMap,
|
||||||
PRPackedBool& aSymbolFont);
|
PRPackedBool& aUnicodeFont, PRPackedBool& aSymbolFont);
|
||||||
|
|
||||||
static inline bool IsJoiner(PRUint32 ch) {
|
static inline bool IsJoiner(PRUint32 ch) {
|
||||||
return (ch == 0x200C ||
|
return (ch == 0x200C ||
|
||||||
|
|
|
@ -64,12 +64,22 @@ public:
|
||||||
THEBES_INLINE_DECL_REFCOUNTING(FontFamily)
|
THEBES_INLINE_DECL_REFCOUNTING(FontFamily)
|
||||||
|
|
||||||
FontFamily(const nsAString& aName) :
|
FontFamily(const nsAString& aName) :
|
||||||
mName(aName)
|
mName(aName), mHasStyles(PR_FALSE) { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
FontEntry *FindFontEntry(const gfxFontStyle& aFontStyle);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int CALLBACK FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
|
||||||
|
const NEWTEXTMETRICEXW *nmetrics,
|
||||||
|
DWORD fontType, LPARAM data);
|
||||||
|
void FindStyleVariations();
|
||||||
|
|
||||||
|
public:
|
||||||
nsTArray<nsRefPtr<FontEntry> > mVariations;
|
nsTArray<nsRefPtr<FontEntry> > mVariations;
|
||||||
nsString mName;
|
nsString mName;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PRBool mHasStyles;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FontEntry
|
class FontEntry
|
||||||
|
|
|
@ -85,8 +85,7 @@ public:
|
||||||
|
|
||||||
/* Find a FontFamily/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 */
|
||||||
FontFamily *FindFontFamily(const nsAString& aName);
|
FontFamily *FindFontFamily(const nsAString& aName);
|
||||||
FontEntry *FindFontEntry(FontFamily *aFontFamily, const gfxFontStyle *aFontStyle);
|
FontEntry *FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle);
|
||||||
FontEntry *FindFontEntry(const nsAString& aName, const gfxFontStyle *aFontStyle);
|
|
||||||
|
|
||||||
PRBool GetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> > *array);
|
PRBool GetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> > *array);
|
||||||
void SetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> >& array);
|
void SetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> >& array);
|
||||||
|
@ -101,6 +100,9 @@ private:
|
||||||
static int CALLBACK FontEnumProc(const ENUMLOGFONTEXW *lpelfe,
|
static int CALLBACK FontEnumProc(const ENUMLOGFONTEXW *lpelfe,
|
||||||
const NEWTEXTMETRICEXW *metrics,
|
const NEWTEXTMETRICEXW *metrics,
|
||||||
DWORD fontType, LPARAM data);
|
DWORD fontType, LPARAM data);
|
||||||
|
static int CALLBACK FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
|
||||||
|
const NEWTEXTMETRICEXW *nmetrics,
|
||||||
|
DWORD fontType, LPARAM data);
|
||||||
|
|
||||||
static PLDHashOperator PR_CALLBACK FontGetStylesProc(nsStringHashKey::KeyType aKey,
|
static PLDHashOperator PR_CALLBACK FontGetStylesProc(nsStringHashKey::KeyType aKey,
|
||||||
nsRefPtr<FontFamily>& aFontFamily,
|
nsRefPtr<FontFamily>& aFontFamily,
|
||||||
|
|
|
@ -220,7 +220,7 @@ static const struct UnicodeRangeTableEntry gUnicodeRanges[] = {
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
gfxFontUtils::ReadCMAPTableFormat12(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap, std::bitset<128>& aUnicodeRanges)
|
gfxFontUtils::ReadCMAPTableFormat12(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap)
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
OffsetFormat = 0,
|
OffsetFormat = 0,
|
||||||
|
@ -260,7 +260,7 @@ gfxFontUtils::ReadCMAPTableFormat12(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBit
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
gfxFontUtils::ReadCMAPTableFormat4(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap, std::bitset<128>& aUnicodeRanges)
|
gfxFontUtils::ReadCMAPTableFormat4(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap)
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
OffsetFormat = 0,
|
OffsetFormat = 0,
|
||||||
|
@ -340,8 +340,8 @@ gfxFontUtils::ReadCMAPTableFormat4(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitS
|
||||||
(platformID == PlatformIDUnicode && encodingID == EncodingIDUCS4ForUnicodePlatform))
|
(platformID == PlatformIDUnicode && encodingID == EncodingIDUCS4ForUnicodePlatform))
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
gfxFontUtils::ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCharacterMap, std::bitset<128>& aUnicodeRanges,
|
gfxFontUtils::ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCharacterMap,
|
||||||
PRPackedBool& aUnicodeFont, PRPackedBool& aSymbolFont)
|
PRPackedBool& aUnicodeFont, PRPackedBool& aSymbolFont)
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
OffsetVersion = 0,
|
OffsetVersion = 0,
|
||||||
|
@ -395,9 +395,13 @@ gfxFontUtils::ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCha
|
||||||
keepOffset = offset;
|
keepOffset = offset;
|
||||||
break;
|
break;
|
||||||
} else if (format == 4 && acceptableFormat4(platformID, encodingID, keepFormat)) {
|
} else if (format == 4 && acceptableFormat4(platformID, encodingID, keepFormat)) {
|
||||||
|
aUnicodeFont = PR_TRUE;
|
||||||
|
aSymbolFont = PR_FALSE;
|
||||||
keepFormat = format;
|
keepFormat = format;
|
||||||
keepOffset = offset;
|
keepOffset = offset;
|
||||||
} else if (format == 12 && acceptableUCS4Encoding(platformID, encodingID)) {
|
} else if (format == 12 && acceptableUCS4Encoding(platformID, encodingID)) {
|
||||||
|
aUnicodeFont = PR_TRUE;
|
||||||
|
aSymbolFont = PR_FALSE;
|
||||||
keepFormat = format;
|
keepFormat = format;
|
||||||
keepOffset = offset;
|
keepOffset = offset;
|
||||||
break; // we don't want to try anything else when this format is available.
|
break; // we don't want to try anything else when this format is available.
|
||||||
|
@ -407,9 +411,9 @@ gfxFontUtils::ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCha
|
||||||
nsresult rv = NS_ERROR_FAILURE;
|
nsresult rv = NS_ERROR_FAILURE;
|
||||||
|
|
||||||
if (keepFormat == 12)
|
if (keepFormat == 12)
|
||||||
rv = ReadCMAPTableFormat12(aBuf + keepOffset, aBufLength - keepOffset, aCharacterMap, aUnicodeRanges);
|
rv = ReadCMAPTableFormat12(aBuf + keepOffset, aBufLength - keepOffset, aCharacterMap);
|
||||||
else if (keepFormat == 4)
|
else if (keepFormat == 4)
|
||||||
rv = ReadCMAPTableFormat4(aBuf + keepOffset, aBufLength - keepOffset, aCharacterMap, aUnicodeRanges);
|
rv = ReadCMAPTableFormat4(aBuf + keepOffset, aBufLength - keepOffset, aCharacterMap);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,6 @@ protected:
|
||||||
MacOSFamilyEntry *mFamily;
|
MacOSFamilyEntry *mFamily;
|
||||||
|
|
||||||
ATSUFontID mATSUFontID;
|
ATSUFontID mATSUFontID;
|
||||||
std::bitset<128> mUnicodeRanges;
|
|
||||||
gfxSparseBitSet mCharacterMap;
|
gfxSparseBitSet mCharacterMap;
|
||||||
|
|
||||||
PRPackedBool mCmapInitialized;
|
PRPackedBool mCmapInitialized;
|
||||||
|
|
|
@ -190,7 +190,7 @@ MacOSFontEntry::ReadCMAP()
|
||||||
|
|
||||||
nsresult rv = NS_ERROR_FAILURE;
|
nsresult rv = NS_ERROR_FAILURE;
|
||||||
PRPackedBool unicodeFont, symbolFont; // currently ignored
|
PRPackedBool unicodeFont, symbolFont; // currently ignored
|
||||||
rv = gfxFontUtils::ReadCMAP(cmap, size, mCharacterMap, mUnicodeRanges, unicodeFont, symbolFont);
|
rv = gfxFontUtils::ReadCMAP(cmap, size, mCharacterMap, unicodeFont, symbolFont);
|
||||||
|
|
||||||
// for complex scripts, check for the presence of mort/morx
|
// for complex scripts, check for the presence of mort/morx
|
||||||
PRBool checkedForMorphTable = PR_FALSE, hasMorphTable = PR_FALSE;
|
PRBool checkedForMorphTable = PR_FALSE, hasMorphTable = PR_FALSE;
|
||||||
|
|
|
@ -109,6 +109,260 @@ struct DCFromContext {
|
||||||
PRBool needsRelease;
|
PRBool needsRelease;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
*
|
||||||
|
* class FontFamily
|
||||||
|
*
|
||||||
|
**********************************************************************/
|
||||||
|
static nsresult
|
||||||
|
ReadCMAP(HDC hdc, FontEntry *aFontEntry)
|
||||||
|
{
|
||||||
|
const PRUint32 kCMAP = (('c') | ('m' << 8) | ('a' << 16) | ('p' << 24));
|
||||||
|
|
||||||
|
DWORD len = GetFontData(hdc, kCMAP, 0, nsnull, 0);
|
||||||
|
if (len == GDI_ERROR || len == 0) // not a truetype font --
|
||||||
|
return NS_ERROR_FAILURE; // we'll treat it as a symbol font
|
||||||
|
|
||||||
|
nsAutoTArray<PRUint8,16384> buffer;
|
||||||
|
if (!buffer.AppendElements(len))
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
PRUint8 *buf = buffer.Elements();
|
||||||
|
|
||||||
|
DWORD newLen = GetFontData(hdc, kCMAP, 0, buf, len);
|
||||||
|
NS_ENSURE_TRUE(newLen == len, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
return gfxFontUtils::ReadCMAP(buf, len, aFontEntry->mCharacterMap,
|
||||||
|
aFontEntry->mUnicodeFont, aFontEntry->mSymbolFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FamilyAddStyleProcData {
|
||||||
|
HDC dc;
|
||||||
|
FontFamily *ff;
|
||||||
|
};
|
||||||
|
|
||||||
|
int CALLBACK
|
||||||
|
FontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
|
||||||
|
const NEWTEXTMETRICEXW *nmetrics,
|
||||||
|
DWORD fontType, LPARAM data)
|
||||||
|
{
|
||||||
|
const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
|
||||||
|
LOGFONTW logFont = lpelfe->elfLogFont;
|
||||||
|
|
||||||
|
FamilyAddStyleProcData *faspd = reinterpret_cast<FamilyAddStyleProcData*>(data);
|
||||||
|
FontFamily *ff = faspd->ff;
|
||||||
|
HDC hdc = faspd->dc;
|
||||||
|
|
||||||
|
// Some fonts claim to support things > 900, but we don't so clamp the sizes
|
||||||
|
logFont.lfWeight = PR_MAX(PR_MIN(logFont.lfWeight, 900), 100);
|
||||||
|
|
||||||
|
FontEntry *fe = nsnull;
|
||||||
|
for (PRUint32 i = 0; i < ff->mVariations.Length(); ++i) {
|
||||||
|
fe = ff->mVariations[i];
|
||||||
|
|
||||||
|
// check if we already know about this face
|
||||||
|
if (fe->mWeight == logFont.lfWeight &&
|
||||||
|
fe->mItalic == (logFont.lfItalic == 0xFF)) {
|
||||||
|
// update the charset bit here since this could be different
|
||||||
|
fe->mCharset[metrics.tmCharSet] = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fe = new FontEntry(ff->mName);
|
||||||
|
ff->mVariations.AppendElement(fe);
|
||||||
|
|
||||||
|
fe->mItalic = (logFont.lfItalic == 0xFF);
|
||||||
|
fe->mWeight = logFont.lfWeight;
|
||||||
|
|
||||||
|
if (metrics.ntmFlags & NTM_TYPE1)
|
||||||
|
fe->mIsType1 = fe->mForceGDI = PR_TRUE;
|
||||||
|
|
||||||
|
// fontType == TRUETYPE_FONTTYPE when (metrics.ntmFlags & NTM_TT_OPENTYPE)
|
||||||
|
if (fontType == TRUETYPE_FONTTYPE || metrics.ntmFlags & (NTM_PS_OPENTYPE))
|
||||||
|
fe->mTrueType = PR_TRUE;
|
||||||
|
|
||||||
|
// mark the charset bit
|
||||||
|
fe->mCharset[metrics.tmCharSet] = 1;
|
||||||
|
|
||||||
|
fe->mWindowsFamily = logFont.lfPitchAndFamily & 0xF0;
|
||||||
|
fe->mWindowsPitch = logFont.lfPitchAndFamily & 0x0F;
|
||||||
|
|
||||||
|
if (nmetrics->ntmFontSig.fsUsb[0] != 0x00000000 &&
|
||||||
|
nmetrics->ntmFontSig.fsUsb[1] != 0x00000000 &&
|
||||||
|
nmetrics->ntmFontSig.fsUsb[2] != 0x00000000 &&
|
||||||
|
nmetrics->ntmFontSig.fsUsb[3] != 0x00000000) {
|
||||||
|
|
||||||
|
// set the unicode ranges
|
||||||
|
PRUint32 x = 0;
|
||||||
|
for (PRUint32 i = 0; i < 4; ++i) {
|
||||||
|
DWORD range = nmetrics->ntmFontSig.fsUsb[i];
|
||||||
|
for (PRUint32 k = 0; k < 32; ++k) {
|
||||||
|
fe->mUnicodeRanges[x++] = (range & (1 << k)) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read in the character map
|
||||||
|
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);
|
||||||
|
|
||||||
|
// ReadCMAP may change the values of mUnicodeFont and mSymbolFont
|
||||||
|
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;
|
||||||
|
|
||||||
|
// For fonts where we failed to read the character map,
|
||||||
|
// we should use GDI to slowly determine their cmap lazily
|
||||||
|
fe->mForceGDI = PR_TRUE;
|
||||||
|
|
||||||
|
//printf("%d, %s failed to get cmap\n", aFontEntry->mIsType1, NS_ConvertUTF16toUTF8(aFontEntry->mName).get());
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectObject(hdc, oldFont);
|
||||||
|
DeleteObject(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// general cmap reading routines moved to gfxFontUtils.cpp
|
||||||
|
void
|
||||||
|
FontFamily::FindStyleVariations()
|
||||||
|
{
|
||||||
|
mHasStyles = PR_TRUE;
|
||||||
|
|
||||||
|
HDC hdc = GetDC(nsnull);
|
||||||
|
|
||||||
|
LOGFONTW logFont;
|
||||||
|
memset(&logFont, 0, sizeof(LOGFONTW));
|
||||||
|
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||||
|
logFont.lfPitchAndFamily = 0;
|
||||||
|
PRUint32 l = PR_MIN(mName.Length(), LF_FACESIZE - 1);
|
||||||
|
memcpy(logFont.lfFaceName,
|
||||||
|
nsPromiseFlatString(mName).get(),
|
||||||
|
l * sizeof(PRUnichar));
|
||||||
|
logFont.lfFaceName[l] = 0;
|
||||||
|
|
||||||
|
FamilyAddStyleProcData faspd;
|
||||||
|
faspd.dc = hdc;
|
||||||
|
faspd.ff = this;
|
||||||
|
|
||||||
|
EnumFontFamiliesExW(hdc, &logFont, (FONTENUMPROCW)FontFamily::FamilyAddStylesProc, (LPARAM)&faspd, 0);
|
||||||
|
|
||||||
|
ReleaseDC(nsnull, hdc);
|
||||||
|
|
||||||
|
// Look for font families without bold variations and add a FontEntry
|
||||||
|
// with synthetic bold (weight 600) for them.
|
||||||
|
FontEntry *darkestItalic = nsnull;
|
||||||
|
FontEntry *darkestNonItalic = nsnull;
|
||||||
|
PRUint8 highestItalic = 0, highestNonItalic = 0;
|
||||||
|
for (PRUint32 i = 0; i < mVariations.Length(); i++) {
|
||||||
|
FontEntry *fe = mVariations[i];
|
||||||
|
if (fe->mItalic) {
|
||||||
|
if (!darkestItalic || fe->mWeight > darkestItalic->mWeight)
|
||||||
|
darkestItalic = fe;
|
||||||
|
} else {
|
||||||
|
if (!darkestNonItalic || fe->mWeight > darkestNonItalic->mWeight)
|
||||||
|
darkestNonItalic = fe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (darkestItalic && darkestItalic->mWeight < 600) {
|
||||||
|
FontEntry *newEntry = new FontEntry(*darkestItalic);
|
||||||
|
newEntry->mWeight = 600;
|
||||||
|
mVariations.AppendElement(newEntry);
|
||||||
|
}
|
||||||
|
if (darkestNonItalic && darkestNonItalic->mWeight < 600) {
|
||||||
|
FontEntry *newEntry = new FontEntry(*darkestNonItalic);
|
||||||
|
newEntry->mWeight = 600;
|
||||||
|
mVariations.AppendElement(newEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FontEntry *
|
||||||
|
FontFamily::FindFontEntry(const gfxFontStyle& aFontStyle)
|
||||||
|
{
|
||||||
|
if (!mHasStyles)
|
||||||
|
FindStyleVariations();
|
||||||
|
|
||||||
|
PRUint8 bestMatch = 0;
|
||||||
|
PRBool italic = (aFontStyle.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0;
|
||||||
|
|
||||||
|
FontEntry *weightList[10] = { 0 };
|
||||||
|
for (PRUint32 j = 0; j < 2; j++) {
|
||||||
|
PRBool matchesSomething = PR_FALSE;
|
||||||
|
// build up an array of weights that match the italicness we're looking for
|
||||||
|
for (PRUint32 i = 0; i < mVariations.Length(); i++) {
|
||||||
|
FontEntry *fe = mVariations[i];
|
||||||
|
const PRUint8 weight = (fe->mWeight / 100);
|
||||||
|
if (fe->mItalic == italic) {
|
||||||
|
weightList[weight] = fe;
|
||||||
|
matchesSomething = PR_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (matchesSomething)
|
||||||
|
break;
|
||||||
|
italic = !italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRInt8 baseWeight, weightDistance;
|
||||||
|
aFontStyle.ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
||||||
|
|
||||||
|
// 500 isn't quite bold so we want to treat it as 400 if we don't
|
||||||
|
// have a 500 weight
|
||||||
|
if (baseWeight == 5 && weightDistance == 0) {
|
||||||
|
// If we have a 500 weight then use it
|
||||||
|
if (weightList[5])
|
||||||
|
return weightList[5];
|
||||||
|
|
||||||
|
// Otherwise treat as 400
|
||||||
|
baseWeight = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRInt8 matchBaseWeight = 0;
|
||||||
|
PRInt8 direction = (baseWeight > 5) ? 1 : -1;
|
||||||
|
for (PRInt8 i = baseWeight; ; i += direction) {
|
||||||
|
if (weightList[i]) {
|
||||||
|
matchBaseWeight = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we've reached one side without finding a font,
|
||||||
|
// go the other direction until we find a match
|
||||||
|
if (i == 1 || i == 9)
|
||||||
|
direction = -direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
FontEntry *matchFE;
|
||||||
|
const PRInt8 absDistance = abs(weightDistance);
|
||||||
|
direction = (weightDistance >= 0) ? 1 : -1;
|
||||||
|
for (PRInt8 i = matchBaseWeight, k = 0; i < 10 && i > 0; i += direction) {
|
||||||
|
if (weightList[i]) {
|
||||||
|
matchFE = weightList[i];
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
if (k > absDistance)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!matchFE)
|
||||||
|
matchFE = weightList[matchBaseWeight];
|
||||||
|
|
||||||
|
NS_ASSERTION(matchFE, "we should always be able to return something here");
|
||||||
|
return matchFE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
*
|
*
|
||||||
* class gfxWindowsFont
|
* class gfxWindowsFont
|
||||||
|
@ -442,7 +696,7 @@ gfxWindowsFontGroup::GroupFamilyListToArrayList(nsTArray<nsRefPtr<FontEntry> > *
|
||||||
|
|
||||||
PRUint32 len = fonts.Length();
|
PRUint32 len = fonts.Length();
|
||||||
for (PRUint32 i = 0; i < len; ++i) {
|
for (PRUint32 i = 0; i < len; ++i) {
|
||||||
nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(fonts[i], &mStyle);
|
nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(fonts[i], mStyle);
|
||||||
list->AppendElement(fe);
|
list->AppendElement(fe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -458,7 +712,7 @@ gfxWindowsFontGroup::FamilyListToArrayList(const nsString& aFamilies,
|
||||||
PRUint32 len = fonts.Length();
|
PRUint32 len = fonts.Length();
|
||||||
for (PRUint32 i = 0; i < len; ++i) {
|
for (PRUint32 i = 0; i < len; ++i) {
|
||||||
const nsAutoString& str = fonts[i];
|
const nsAutoString& str = fonts[i];
|
||||||
nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(str, &mStyle);
|
nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(str, mStyle);
|
||||||
list->AppendElement(fe);
|
list->AppendElement(fe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -477,7 +731,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), aStyle);
|
nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(nsDependentString(logFont.lfFaceName), *aStyle);
|
||||||
mFontEntries.AppendElement(fe);
|
mFontEntries.AppendElement(fe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,7 +991,7 @@ struct ScriptPropertyEntry {
|
||||||
static const struct ScriptPropertyEntry gScriptToText[] =
|
static const struct ScriptPropertyEntry gScriptToText[] =
|
||||||
{
|
{
|
||||||
{ nsnull, nsnull },
|
{ nsnull, nsnull },
|
||||||
{ "LANG_ARABIC", "ara" },
|
{ "LANG_ARABIC", "ar" }, // ara
|
||||||
{ "LANG_BULGARIAN", "bul" },
|
{ "LANG_BULGARIAN", "bul" },
|
||||||
{ "LANG_CATALAN", "cat" },
|
{ "LANG_CATALAN", "cat" },
|
||||||
{ "LANG_CHINESE", "zh-CN" }, //XXX right lang code?
|
{ "LANG_CHINESE", "zh-CN" }, //XXX right lang code?
|
||||||
|
@ -1304,6 +1558,13 @@ public:
|
||||||
(ch >= 0xF0000 && ch <= 0x10FFFD))
|
(ch >= 0xF0000 && ch <= 0x10FFFD))
|
||||||
return selectedFont;
|
return selectedFont;
|
||||||
|
|
||||||
|
// check out the style's language group
|
||||||
|
if (!selectedFont) {
|
||||||
|
nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
|
||||||
|
this->GetPrefFonts(mGroup->GetStyle()->langGroup.get(), fonts);
|
||||||
|
selectedFont = WhichFontSupportsChar(fonts, ch);
|
||||||
|
}
|
||||||
|
|
||||||
// otherwise search prefs
|
// otherwise search prefs
|
||||||
if (!selectedFont) {
|
if (!selectedFont) {
|
||||||
/* first check with the script properties to see what they think */
|
/* first check with the script properties to see what they think */
|
||||||
|
|
|
@ -58,7 +58,13 @@
|
||||||
|
|
||||||
//#define DEBUG_CMAP_SIZE 1
|
//#define DEBUG_CMAP_SIZE 1
|
||||||
|
|
||||||
static nsresult ReadCMAP(HDC hdc, FontEntry *aFontEntry);
|
static __inline void
|
||||||
|
BuildKeyNameFromFontName(nsAString &aName)
|
||||||
|
{
|
||||||
|
if (aName.Length() >= LF_FACESIZE)
|
||||||
|
aName.Truncate(LF_FACESIZE - 1);
|
||||||
|
ToLowerCase(aName);
|
||||||
|
}
|
||||||
|
|
||||||
int PR_CALLBACK
|
int PR_CALLBACK
|
||||||
gfxWindowsPlatform::PrefChangedCallback(const char *aPrefName, void *closure)
|
gfxWindowsPlatform::PrefChangedCallback(const char *aPrefName, void *closure)
|
||||||
|
@ -107,23 +113,14 @@ gfxWindowsPlatform::FontEnumProc(const ENUMLOGFONTEXW *lpelfe,
|
||||||
FontTable *ht = reinterpret_cast<FontTable*>(data);
|
FontTable *ht = reinterpret_cast<FontTable*>(data);
|
||||||
|
|
||||||
const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
|
const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
|
||||||
LOGFONTW logFont = lpelfe->elfLogFont;
|
const LOGFONTW& logFont = lpelfe->elfLogFont;
|
||||||
|
|
||||||
// Ignore vertical fonts
|
// Ignore vertical fonts
|
||||||
if (logFont.lfFaceName[0] == L'@') {
|
if (logFont.lfFaceName[0] == L'@')
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
// Some fonts claim to support things > 900, but we don't so clamp the sizes
|
nsAutoString name(logFont.lfFaceName);
|
||||||
logFont.lfWeight = PR_MAX(PR_MIN(logFont.lfWeight, 900), 100);
|
BuildKeyNameFromFontName(name);
|
||||||
|
|
||||||
#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<FontFamily> ff;
|
nsRefPtr<FontFamily> ff;
|
||||||
if (!ht->Get(name, &ff)) {
|
if (!ht->Get(name, &ff)) {
|
||||||
|
@ -131,176 +128,12 @@ gfxWindowsPlatform::FontEnumProc(const ENUMLOGFONTEXW *lpelfe,
|
||||||
ht->Put(name, ff);
|
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->mName);
|
|
||||||
/* 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 = fe->mForceGDI = PR_TRUE;
|
|
||||||
if (metrics.ntmFlags & (NTM_PS_OPENTYPE | NTM_TT_OPENTYPE))
|
|
||||||
fe->mTrueType = PR_TRUE;
|
|
||||||
|
|
||||||
// mark the charset bit
|
|
||||||
fe->mCharset[metrics.tmCharSet] = 1;
|
|
||||||
|
|
||||||
fe->mWindowsFamily = logFont.lfPitchAndFamily & 0xF0;
|
|
||||||
fe->mWindowsPitch = logFont.lfPitchAndFamily & 0x0F;
|
|
||||||
|
|
||||||
if (nmetrics->ntmFontSig.fsUsb[0] == 0x00000000 &&
|
|
||||||
nmetrics->ntmFontSig.fsUsb[1] == 0x00000000 &&
|
|
||||||
nmetrics->ntmFontSig.fsUsb[2] == 0x00000000 &&
|
|
||||||
nmetrics->ntmFontSig.fsUsb[3] == 0x00000000) {
|
|
||||||
// no unicode ranges
|
|
||||||
fe->mUnicodeFont = PR_FALSE;
|
|
||||||
} else {
|
|
||||||
fe->mUnicodeFont = PR_TRUE;
|
|
||||||
|
|
||||||
// set the unicode ranges
|
|
||||||
PRUint32 x = 0;
|
|
||||||
for (PRUint32 i = 0; i < 4; ++i) {
|
|
||||||
DWORD range = nmetrics->ntmFontSig.fsUsb[i];
|
|
||||||
for (PRUint32 k = 0; k < 32; ++k) {
|
|
||||||
fe->mUnicodeRanges[x++] = (range & (1 << k)) != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// general cmap reading routines moved to gfxFontUtils.cpp
|
// general cmap reading routines moved to gfxFontUtils.cpp
|
||||||
|
|
||||||
static nsresult
|
|
||||||
ReadCMAP(HDC hdc, FontEntry *aFontEntry)
|
|
||||||
{
|
|
||||||
const PRUint32 kCMAP = (('c') | ('m' << 8) | ('a' << 16) | ('p' << 24));
|
|
||||||
|
|
||||||
DWORD len = GetFontData(hdc, kCMAP, 0, nsnull, 0);
|
|
||||||
if (len == GDI_ERROR || len == 0) // not a truetype font --
|
|
||||||
return NS_ERROR_FAILURE; // we'll treat it as a symbol font
|
|
||||||
|
|
||||||
nsAutoTArray<PRUint8,16384> buffer;
|
|
||||||
if (!buffer.AppendElements(len))
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
PRUint8 *buf = buffer.Elements();
|
|
||||||
|
|
||||||
DWORD newLen = GetFontData(hdc, kCMAP, 0, buf, len);
|
|
||||||
NS_ENSURE_TRUE(newLen == len, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
return gfxFontUtils::ReadCMAP(buf, len, aFontEntry->mCharacterMap, aFontEntry->mUnicodeRanges,
|
|
||||||
aFontEntry->mUnicodeFont, aFontEntry->mSymbolFont);
|
|
||||||
}
|
|
||||||
|
|
||||||
PLDHashOperator PR_CALLBACK
|
|
||||||
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->GetName().Length(), LF_FACESIZE - 1);
|
|
||||||
memcpy(logFont.lfFaceName,
|
|
||||||
nsPromiseFlatString(aFontEntry->GetName()).get(),
|
|
||||||
l * sizeof(PRUnichar));
|
|
||||||
logFont.lfFaceName[l] = 0;
|
|
||||||
|
|
||||||
EnumFontFamiliesExW(hdc, &logFont, (FONTENUMPROCW)gfxWindowsPlatform::FontEnumProc, (LPARAM)userArg, 0);
|
|
||||||
|
|
||||||
ReleaseDC(nsnull, hdc);
|
|
||||||
|
|
||||||
// Look for font families without bold variations and add a FontEntry
|
|
||||||
// with synthetic bold (weight 600) for them.
|
|
||||||
nsRefPtr<FontEntry> darkestItalic;
|
|
||||||
nsRefPtr<FontEntry> darkestNonItalic;
|
|
||||||
PRUint8 highestItalic = 0, highestNonItalic = 0;
|
|
||||||
for (PRUint32 i = 0; i < aFontFamily->mVariations.Length(); i++) {
|
|
||||||
nsRefPtr<FontEntry> fe = aFontFamily->mVariations[i];
|
|
||||||
if (fe->mItalic) {
|
|
||||||
if (!darkestItalic || fe->mWeight > darkestItalic->mWeight)
|
|
||||||
darkestItalic = fe;
|
|
||||||
} else {
|
|
||||||
if (!darkestNonItalic || fe->mWeight > darkestNonItalic->mWeight)
|
|
||||||
darkestNonItalic = fe;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (darkestItalic && darkestItalic->mWeight < 600) {
|
|
||||||
nsRefPtr<FontEntry> newEntry = new FontEntry(*darkestItalic.get());
|
|
||||||
newEntry->mWeight = 600;
|
|
||||||
aFontFamily->mVariations.AppendElement(newEntry);
|
|
||||||
}
|
|
||||||
if (darkestNonItalic && darkestNonItalic->mWeight < 600) {
|
|
||||||
nsRefPtr<FontEntry> newEntry = new FontEntry(*darkestNonItalic.get());
|
|
||||||
newEntry->mWeight = 600;
|
|
||||||
aFontFamily->mVariations.AppendElement(newEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {}
|
||||||
|
@ -355,14 +188,6 @@ RemoveCharsetFromFontSubstitute(nsAString &aName)
|
||||||
aName.Truncate(comma);
|
aName.Truncate(comma);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
BuildKeyNameFromFontName(nsAString &aName)
|
|
||||||
{
|
|
||||||
if (aName.Length() >= LF_FACESIZE)
|
|
||||||
aName.Truncate(LF_FACESIZE - 1);
|
|
||||||
ToLowerCase(aName);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
gfxWindowsPlatform::UpdateFontList()
|
gfxWindowsPlatform::UpdateFontList()
|
||||||
{
|
{
|
||||||
|
@ -386,9 +211,6 @@ gfxWindowsPlatform::UpdateFontList()
|
||||||
EnumFontFamiliesExW(dc, &logFont, (FONTENUMPROCW)gfxWindowsPlatform::FontEnumProc, (LPARAM)&mFonts, 0);
|
EnumFontFamiliesExW(dc, &logFont, (FONTENUMPROCW)gfxWindowsPlatform::FontEnumProc, (LPARAM)&mFonts, 0);
|
||||||
::ReleaseDC(nsnull, dc);
|
::ReleaseDC(nsnull, dc);
|
||||||
|
|
||||||
// Look for additional styles
|
|
||||||
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");
|
||||||
if (!regKey)
|
if (!regKey)
|
||||||
|
@ -441,7 +263,7 @@ gfxWindowsPlatform::UpdateFontList()
|
||||||
|
|
||||||
static PRBool SimpleResolverCallback(const nsAString& aName, void* aClosure)
|
static PRBool SimpleResolverCallback(const nsAString& aName, void* aClosure)
|
||||||
{
|
{
|
||||||
nsString* result = static_cast<nsString*>(aClosure);
|
nsString *result = static_cast<nsString*>(aClosure);
|
||||||
result->Assign(aName);
|
result->Assign(aName);
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -591,7 +413,7 @@ gfxWindowsPlatform::FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
||||||
|
|
||||||
const PRUint32 ch = data->ch;
|
const PRUint32 ch = data->ch;
|
||||||
|
|
||||||
nsRefPtr<FontEntry> fe = GetPlatform()->FindFontEntry(aFontFamily, data->fontToMatch->GetStyle());
|
nsRefPtr<FontEntry> fe = aFontFamily->FindFontEntry(*data->fontToMatch->GetStyle());
|
||||||
|
|
||||||
// skip over non-unicode and bitmap fonts and fonts that don't have
|
// skip over non-unicode and bitmap fonts and fonts that don't have
|
||||||
// the code point we're looking for
|
// the code point we're looking for
|
||||||
|
@ -613,7 +435,7 @@ gfxWindowsPlatform::FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
||||||
rank += 3;
|
rank += 3;
|
||||||
|
|
||||||
/* italic */
|
/* italic */
|
||||||
const PRBool italic = (data->fontToMatch->GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) ? PR_TRUE : PR_FALSE;
|
const PRBool italic = (data->fontToMatch->GetStyle()->style != FONT_STYLE_NORMAL);
|
||||||
if (fe->mItalic != italic)
|
if (fe->mItalic != italic)
|
||||||
rank += 3;
|
rank += 3;
|
||||||
|
|
||||||
|
@ -652,7 +474,7 @@ gfxWindowsPlatform::FindFontForChar(PRUint32 aCh, gfxWindowsFont *aFont)
|
||||||
if (!data.bestMatch) {
|
if (!data.bestMatch) {
|
||||||
mCodepointsWithNoFonts.set(aCh);
|
mCodepointsWithNoFonts.set(aCh);
|
||||||
}
|
}
|
||||||
|
|
||||||
return data.bestMatch;
|
return data.bestMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -666,8 +488,8 @@ gfxWindowsPlatform::CreateFontGroup(const nsAString &aFamilies,
|
||||||
FontFamily *
|
FontFamily *
|
||||||
gfxWindowsPlatform::FindFontFamily(const nsAString& aName)
|
gfxWindowsPlatform::FindFontFamily(const nsAString& aName)
|
||||||
{
|
{
|
||||||
nsString name(aName);
|
nsAutoString name(aName);
|
||||||
ToLowerCase(name);
|
BuildKeyNameFromFontName(name);
|
||||||
|
|
||||||
nsRefPtr<FontFamily> ff;
|
nsRefPtr<FontFamily> ff;
|
||||||
if (!mFonts.Get(name, &ff) &&
|
if (!mFonts.Get(name, &ff) &&
|
||||||
|
@ -679,93 +501,13 @@ gfxWindowsPlatform::FindFontFamily(const nsAString& aName)
|
||||||
}
|
}
|
||||||
|
|
||||||
FontEntry *
|
FontEntry *
|
||||||
gfxWindowsPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle *aFontStyle)
|
gfxWindowsPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle)
|
||||||
{
|
{
|
||||||
nsRefPtr<FontFamily> ff = FindFontFamily(aName);
|
nsRefPtr<FontFamily> ff = FindFontFamily(aName);
|
||||||
if (!ff)
|
if (!ff)
|
||||||
return nsnull;
|
return nsnull;
|
||||||
|
|
||||||
return FindFontEntry(ff, aFontStyle);
|
return ff->FindFontEntry(aFontStyle);
|
||||||
}
|
|
||||||
|
|
||||||
FontEntry *
|
|
||||||
gfxWindowsPlatform::FindFontEntry(FontFamily *aFontFamily, const gfxFontStyle *aFontStyle)
|
|
||||||
{
|
|
||||||
PRUint8 bestMatch = 0;
|
|
||||||
PRBool italic = (aFontStyle->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0;
|
|
||||||
|
|
||||||
nsAutoTArray<nsRefPtr<FontEntry>, 10> weightList;
|
|
||||||
weightList.AppendElements(10);
|
|
||||||
for (PRUint32 j = 0; j < 2; j++) {
|
|
||||||
PRBool matchesSomething = PR_FALSE;
|
|
||||||
// build up an array of weights that match the italicness we're looking for
|
|
||||||
for (PRUint32 i = 0; i < aFontFamily->mVariations.Length(); i++) {
|
|
||||||
nsRefPtr<FontEntry> fe = aFontFamily->mVariations[i];
|
|
||||||
const PRUint8 weight = (fe->mWeight / 100);
|
|
||||||
if (fe->mItalic == italic) {
|
|
||||||
weightList[weight] = fe;
|
|
||||||
matchesSomething = PR_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (matchesSomething)
|
|
||||||
break;
|
|
||||||
italic = !italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRInt8 baseWeight, weightDistance;
|
|
||||||
aFontStyle->ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
|
||||||
|
|
||||||
// 500 isn't quite bold so we want to treat it as 400 if we don't
|
|
||||||
// have a 500 weight
|
|
||||||
if (baseWeight == 5 && weightDistance == 0) {
|
|
||||||
// If we have a 500 weight then use it
|
|
||||||
if (weightList[5])
|
|
||||||
return weightList[5];
|
|
||||||
|
|
||||||
// Otherwise treat as 400
|
|
||||||
baseWeight = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PRInt8 matchBaseWeight = 0;
|
|
||||||
PRInt8 direction = (baseWeight > 5) ? 1 : -1;
|
|
||||||
for (PRInt8 i = baseWeight; ; i += direction) {
|
|
||||||
if (weightList[i]) {
|
|
||||||
matchBaseWeight = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we've reached one side without finding a font,
|
|
||||||
// go the other direction until we find a match
|
|
||||||
if (i == 1 || i == 9)
|
|
||||||
direction = -direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsRefPtr<FontEntry> matchFE;
|
|
||||||
const PRInt8 absDistance = abs(weightDistance);
|
|
||||||
direction = (weightDistance >= 0) ? 1 : -1;
|
|
||||||
for (PRInt8 i = matchBaseWeight, k = 0; i < 10 && i > 0; i += direction) {
|
|
||||||
if (weightList[i]) {
|
|
||||||
matchFE = weightList[i];
|
|
||||||
k++;
|
|
||||||
}
|
|
||||||
if (k > absDistance)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!matchFE) {
|
|
||||||
/* if we still don't have a match, grab the closest thing in the other direction */
|
|
||||||
direction = -direction;
|
|
||||||
for (PRInt8 i = matchBaseWeight; i < 10 && i > 0; i += direction) {
|
|
||||||
if (weightList[i]) {
|
|
||||||
matchFE = weightList[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NS_ASSERTION(matchFE, "we should always be able to return something here");
|
|
||||||
return matchFE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmsHPROFILE
|
cmsHPROFILE
|
||||||
|
|
Загрузка…
Ссылка в новой задаче