зеркало из https://github.com/mozilla/pjs.git
bug 195038, finally add support for the quirky <font face=Symbol> on Windows to the delight of proponents of bug 33127, r=jshin, sr=roc
This commit is contained in:
Родитель
e7a046b501
Коммит
24f3a35327
|
@ -670,7 +670,7 @@ enum eGetNameError
|
|||
};
|
||||
|
||||
static eGetNameError
|
||||
GetNAME(HDC aDC, nsString* aName)
|
||||
GetNAME(HDC aDC, nsString* aName, PRBool* aIsSymbolEncoding = nsnull)
|
||||
{
|
||||
DWORD len = GetFontData(aDC, NAME, 0, nsnull, 0);
|
||||
if (len == GDI_ERROR) {
|
||||
|
@ -713,6 +713,9 @@ GetNAME(HDC aDC, nsString* aName)
|
|||
p += 2;
|
||||
// encoding: 1 == Unicode; 0 == symbol
|
||||
if ((platform == 3) && ((encoding == 1) || (!encoding)) && (name == 3)) {
|
||||
if (aIsSymbolEncoding) {
|
||||
*aIsSymbolEncoding = encoding == 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -721,8 +724,14 @@ GetNAME(HDC aDC, nsString* aName)
|
|||
}
|
||||
p = buf + offset + idOffset;
|
||||
idLength /= 2;
|
||||
// Prefix with a little flag to distinguish quirky fonts. Assume
|
||||
// '0' (i.e., non quirks) to begin with. On return, the caller can
|
||||
// decide to treat this font in quirks fashion and override with
|
||||
// aName[0] = '1'. More info in bug 195038.
|
||||
PRUnichar c = '0';
|
||||
aName->Append(c);
|
||||
for (i = 0; i < idLength; ++i) {
|
||||
PRUnichar c = GET_SHORT(p);
|
||||
c = GET_SHORT(p);
|
||||
p += 2;
|
||||
aName->Append(c);
|
||||
}
|
||||
|
@ -1267,7 +1276,7 @@ static PRUint8 gBitToUnicodeRange[] =
|
|||
|
||||
// Helper to determine if a font has a private encoding that we know something about
|
||||
static nsresult
|
||||
GetEncoding(const char* aFontName, nsCString& aValue)
|
||||
GetCustomEncoding(const char* aFontName, nsCString& aValue, PRBool* aIsWide)
|
||||
{
|
||||
// this is "MS P Gothic" in Japanese
|
||||
static const char* mspgothic=
|
||||
|
@ -1306,7 +1315,16 @@ GetEncoding(const char* aFontName, nsCString& aValue)
|
|||
if (gFontEncodingProperties) {
|
||||
nsAutoString prop;
|
||||
nsresult rv = gFontEncodingProperties->GetStringProperty(name, prop);
|
||||
aValue.AssignWithConversion(prop);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
aValue.AssignWithConversion(prop);
|
||||
|
||||
// The encoding name of a wide NonUnicode font in fontEncoding.properties
|
||||
// has '.wide' suffix which has to be removed to get the actual encoding.
|
||||
*aIsWide = StringEndsWith(aValue, NS_LITERAL_CSTRING(".wide"));
|
||||
if (*aIsWide) {
|
||||
aValue.Truncate(aValue.Length()-5);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
@ -1332,24 +1350,29 @@ GetDefaultConverterForTTFSymbolEncoding(nsIUnicodeEncoder** aConverter)
|
|||
}
|
||||
|
||||
static nsresult
|
||||
GetConverter(const char* aFontName, nsIUnicodeEncoder** aConverter, PRBool* aIsWide = nsnull)
|
||||
GetConverter(const char* aFontName, PRBool aNameQuirks,
|
||||
nsIUnicodeEncoder** aConverter, PRBool* aIsWide = nsnull)
|
||||
{
|
||||
*aConverter = nsnull;
|
||||
|
||||
nsCAutoString value;
|
||||
nsresult rv = GetEncoding(aFontName, value);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// The encoding name of a wide NonUnicode font in fontEncoding.properties
|
||||
// has '.wide' suffix which has to be removed to get the converter
|
||||
// for the encoding.
|
||||
if (StringEndsWith(value, NS_LITERAL_CSTRING(".wide"))) {
|
||||
value.Truncate(value.Length()-5);
|
||||
if (aIsWide)
|
||||
*aIsWide = PR_TRUE;
|
||||
if (aNameQuirks) {
|
||||
#ifdef NS_DEBUG
|
||||
// we don't apply the quirky behavior to wide Non-Unicode fonts
|
||||
nsCAutoString value;
|
||||
PRBool isWide = PR_FALSE;
|
||||
NS_ASSERTION(NS_FAILED(GetCustomEncoding(aFontName, value, &isWide)) || !isWide,
|
||||
"internal error -- shouldn't get here");
|
||||
#endif
|
||||
return GetDefaultConverterForTTFSymbolEncoding(aConverter);
|
||||
}
|
||||
|
||||
nsCAutoString value;
|
||||
PRBool isWide = PR_FALSE;
|
||||
nsresult rv = GetCustomEncoding(aFontName, value, &isWide);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (aIsWide) {
|
||||
*aIsWide = isWide;
|
||||
}
|
||||
else
|
||||
if (aIsWide)
|
||||
*aIsWide = PR_FALSE;
|
||||
|
||||
return GetConverterCommon(value.get(), aConverter);
|
||||
}
|
||||
|
@ -1357,14 +1380,11 @@ GetConverter(const char* aFontName, nsIUnicodeEncoder** aConverter, PRBool* aIsW
|
|||
// This function uses the charset converter manager to fill the map for the
|
||||
// font whose name is given
|
||||
static PRUint16*
|
||||
GetCCMapThroughConverter(const char* aFontName)
|
||||
GetCCMapThroughConverter(const char* aFontName, PRBool aNameQuirks)
|
||||
{
|
||||
// see if we know something about the converter of this font
|
||||
nsCOMPtr<nsIUnicodeEncoder> converter;
|
||||
// we don't check "familyNameQuirks" here because we are only generating CCMAP.
|
||||
// the flag will be checked later when the font is about to be loaded.
|
||||
if (NS_SUCCEEDED(GetConverter(aFontName, getter_AddRefs(converter))) ||
|
||||
NS_SUCCEEDED(GetDefaultConverterForTTFSymbolEncoding(getter_AddRefs(converter)))) {
|
||||
if (NS_SUCCEEDED(GetConverter(aFontName, aNameQuirks, getter_AddRefs(converter)))) {
|
||||
nsCOMPtr<nsICharRepresentable> mapper(do_QueryInterface(converter));
|
||||
if (mapper)
|
||||
return MapperToCCMap(mapper);
|
||||
|
@ -1617,7 +1637,8 @@ ReadCMAPTableFormat4(PRUint8* aBuf, PRInt32 aLength, PRUint32* aMap, PRUint8* aI
|
|||
}
|
||||
|
||||
PRUint16*
|
||||
nsFontMetricsWin::GetFontCCMAP(HDC aDC, const char* aShortName, eFontType& aFontType, PRUint8& aCharset)
|
||||
nsFontMetricsWin::GetFontCCMAP(HDC aDC, const char* aShortName,
|
||||
PRBool aNameQuirks, eFontType& aFontType, PRUint8& aCharset)
|
||||
{
|
||||
PRUint16 *ccmap = nsnull;
|
||||
DWORD len = GetFontData(aDC, CMAP, 0, nsnull, 0);
|
||||
|
@ -1658,12 +1679,12 @@ nsFontMetricsWin::GetFontCCMAP(HDC aDC, const char* aShortName, eFontType& aFont
|
|||
// Here, we check if this font is a pseudo-unicode font that
|
||||
// we know something about, and we force it to be treated as
|
||||
// a non-unicode font.
|
||||
nsCAutoString encoding;
|
||||
if (NS_SUCCEEDED(GetEncoding(aShortName, encoding))) {
|
||||
ccmap = GetCCMapThroughConverter(aShortName, aNameQuirks);
|
||||
if (ccmap) {
|
||||
aCharset = DEFAULT_CHARSET;
|
||||
aFontType = eFontType_NonUnicode;
|
||||
return GetCCMapThroughConverter(aShortName);
|
||||
} // if GetEncoding();
|
||||
return ccmap;
|
||||
}
|
||||
PRUint16 format = GET_SHORT(buf+offset);
|
||||
if (format == eTTFormat4SegmentMappingToDeltaValues) {
|
||||
keepFormat = eTTFormat4SegmentMappingToDeltaValues;
|
||||
|
@ -1673,7 +1694,7 @@ nsFontMetricsWin::GetFontCCMAP(HDC aDC, const char* aShortName, eFontType& aFont
|
|||
else if (encodingID == eTTMicrosoftEncodingSymbol) { // symbol
|
||||
aCharset = SYMBOL_CHARSET;
|
||||
aFontType = eFontType_NonUnicode;
|
||||
return GetCCMapThroughConverter(aShortName);
|
||||
return GetCCMapThroughConverter(aShortName, aNameQuirks);
|
||||
} // if (encodingID == eTTMicrosoftEncodingSymbol)
|
||||
else if (encodingID == eTTMicrosoftEncodingUCS4) {
|
||||
PRUint16 format = GET_SHORT(buf+offset);
|
||||
|
@ -1722,7 +1743,8 @@ nsFontMetricsWin::GetFontCCMAP(HDC aDC, const char* aShortName, eFontType& aFont
|
|||
// with it). Otherwise, you will leave a dangling pointer in the gFontMaps
|
||||
// hashtable.
|
||||
PRUint16*
|
||||
nsFontMetricsWin::GetCCMAP(HDC aDC, const char* aShortName, eFontType* aFontType, PRUint8* aCharset)
|
||||
nsFontMetricsWin::GetCCMAP(HDC aDC, const char* aShortName,
|
||||
PRBool* aNameQuirks, eFontType* aFontType, PRUint8* aCharset)
|
||||
{
|
||||
if (!gFontMaps) {
|
||||
gFontMaps = PL_NewHashTable(0, HashKey, CompareKeys, nsnull, &fontmap_HashAllocOps,
|
||||
|
@ -1737,7 +1759,7 @@ nsFontMetricsWin::GetCCMAP(HDC aDC, const char* aShortName, eFontType* aFontType
|
|||
return nsnull;
|
||||
}
|
||||
}
|
||||
eFontType fontType = eFontType_Unicode;
|
||||
eFontType fontType = aFontType ? *aFontType : eFontType_Unicode;
|
||||
PRUint8 charset = DEFAULT_CHARSET;
|
||||
nsString* name = new nsString(); // deleted by fontmap_FreeEntry
|
||||
if (!name) {
|
||||
|
@ -1746,8 +1768,20 @@ nsFontMetricsWin::GetCCMAP(HDC aDC, const char* aShortName, eFontType* aFontType
|
|||
nsFontInfo* info;
|
||||
PLHashEntry *he, **hep = NULL; // shouldn't be NULL, using it as a flag to catch bad changes
|
||||
PLHashNumber hash;
|
||||
eGetNameError ret = GetNAME(aDC, name);
|
||||
PRBool nameQuirks = aNameQuirks ? *aNameQuirks : PR_FALSE;
|
||||
PRBool isSymbolEncoding = PR_FALSE;
|
||||
eGetNameError ret = GetNAME(aDC, name, &isSymbolEncoding);
|
||||
if (ret == eGetName_OK) {
|
||||
// see if we should treat this name as a quirks name
|
||||
if (nameQuirks && (isSymbolEncoding || fontType != eFontType_Unicode)) {
|
||||
name->SetCharAt(PRUnichar('1'), 0); // change the prefix: name[0] = '1'
|
||||
}
|
||||
else {
|
||||
nameQuirks = PR_FALSE;
|
||||
if (aNameQuirks) {
|
||||
*aNameQuirks = PR_FALSE;
|
||||
}
|
||||
}
|
||||
// lookup the hashtable (if we miss, the computed hash and hep are fed back in HT-RawAdd)
|
||||
hash = HashKey(name);
|
||||
hep = PL_HashTableRawLookup(gFontMaps, hash, name);
|
||||
|
@ -1804,7 +1838,7 @@ nsFontMetricsWin::GetCCMAP(HDC aDC, const char* aShortName, eFontType* aFontType
|
|||
fontType = *aFontType;
|
||||
if (aCharset)
|
||||
charset = *aCharset;
|
||||
PRUint16* ccmap = GetFontCCMAP(aDC, aShortName, fontType, charset);
|
||||
PRUint16* ccmap = GetFontCCMAP(aDC, aShortName, nameQuirks, fontType, charset);
|
||||
if (aFontType)
|
||||
*aFontType = fontType;
|
||||
if (aCharset)
|
||||
|
@ -2389,7 +2423,7 @@ nsFontMetricsWin::CreateFontHandle(HDC aDC, nsGlobalFont* aGlobalFont, LOGFONT*
|
|||
}
|
||||
|
||||
nsFontWin*
|
||||
nsFontMetricsWin::LoadFont(HDC aDC, const nsString& aName)
|
||||
nsFontMetricsWin::LoadFont(HDC aDC, const nsString& aName, PRBool aNameQuirks)
|
||||
{
|
||||
LOGFONT logFont;
|
||||
HFONT hfont = CreateFontHandle(aDC, aName, &logFont);
|
||||
|
@ -2398,25 +2432,34 @@ nsFontMetricsWin::LoadFont(HDC aDC, const nsString& aName)
|
|||
char name[sizeof(logFont.lfFaceName)];
|
||||
if (::GetTextFace(aDC, sizeof(name), name) &&
|
||||
!strcmpi(name, logFont.lfFaceName)) {
|
||||
eFontType fontType = eFontType_UNKNOWN;
|
||||
nsFontWin* font = nsnull;
|
||||
if (mIsUserDefined) {
|
||||
font = new nsFontWinNonUnicode(&logFont, hfont, gUserDefinedCCMap,
|
||||
gUserDefinedConverter);
|
||||
} else {
|
||||
PRUint16* ccmap = GetCCMAP(aDC, logFont.lfFaceName, &fontType, nsnull);
|
||||
eFontType fontType = eFontType_Unicode;
|
||||
PRBool nameQuirks = aNameQuirks;
|
||||
// see if we should override the quirks -- not all fonts are treated as quirks
|
||||
if (nameQuirks) {
|
||||
nsCAutoString encoding;
|
||||
PRBool isWide = PR_FALSE;
|
||||
if (NS_SUCCEEDED(GetCustomEncoding(logFont.lfFaceName, encoding, &isWide))) {
|
||||
nameQuirks = !isWide;
|
||||
fontType = eFontType_NonUnicode;
|
||||
}
|
||||
}
|
||||
PRUint16* ccmap = GetCCMAP(aDC, logFont.lfFaceName, &nameQuirks,
|
||||
&fontType, nsnull);
|
||||
if (ccmap) {
|
||||
if (eFontType_Unicode == fontType) {
|
||||
font = new nsFontWinUnicode(&logFont, hfont, ccmap);
|
||||
}
|
||||
else if (eFontType_NonUnicode == fontType) {
|
||||
PRBool isWide = PR_FALSE;
|
||||
nsCOMPtr<nsIUnicodeEncoder> converter;
|
||||
PRBool isWide;
|
||||
if (NS_SUCCEEDED(GetConverter(logFont.lfFaceName, getter_AddRefs(converter), &isWide)))
|
||||
if (NS_SUCCEEDED(GetConverter(logFont.lfFaceName, nameQuirks,
|
||||
getter_AddRefs(converter), &isWide)))
|
||||
font = new nsFontWinNonUnicode(&logFont, hfont, ccmap, converter, isWide);
|
||||
else if (mFont.familyNameQuirks)
|
||||
if (NS_SUCCEEDED(GetDefaultConverterForTTFSymbolEncoding(getter_AddRefs(converter))))
|
||||
font = new nsFontWinNonUnicode(&logFont, hfont, ccmap, converter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2449,7 +2492,8 @@ nsFontMetricsWin::LoadGlobalFont(HDC aDC, nsGlobalFont* aGlobalFont)
|
|||
else if (eFontType_NonUnicode == aGlobalFont->fonttype) {
|
||||
nsCOMPtr<nsIUnicodeEncoder> converter;
|
||||
PRBool isWide;
|
||||
if (NS_SUCCEEDED(GetConverter(logFont.lfFaceName, getter_AddRefs(converter), &isWide))) {
|
||||
if (NS_SUCCEEDED(GetConverter(logFont.lfFaceName, PR_FALSE,
|
||||
getter_AddRefs(converter), &isWide))) {
|
||||
font = new nsFontWinNonUnicode(&logFont, hfont, aGlobalFont->ccmap, converter, isWide);
|
||||
}
|
||||
}
|
||||
|
@ -2631,7 +2675,8 @@ nsFontMetricsWin::FindGlobalFont(HDC aDC, PRUint32 c)
|
|||
continue;
|
||||
}
|
||||
HFONT oldFont = (HFONT)::SelectObject(aDC, hfont);
|
||||
font->ccmap = GetCCMAP(aDC, font->logFont.lfFaceName, &font->fonttype, nsnull);
|
||||
font->ccmap = GetCCMAP(aDC, font->logFont.lfFaceName,
|
||||
nsnull, &font->fonttype, nsnull);
|
||||
::SelectObject(aDC, oldFont);
|
||||
::DeleteObject(hfont);
|
||||
if (!font->ccmap || font->ccmap == gEmptyCCMap) {
|
||||
|
@ -3263,7 +3308,8 @@ nsFontMetricsWin::FindLocalFont(HDC aDC, PRUint32 aChar)
|
|||
if (!winName) {
|
||||
winName = name;
|
||||
}
|
||||
nsFontWin* font = LoadFont(aDC, *winName);
|
||||
// the familyNameQuirks should not affect generic & global fonts
|
||||
nsFontWin* font = LoadFont(aDC, *winName, mFont.familyNameQuirks);
|
||||
if (font && font->HasGlyph(aChar)) {
|
||||
return font;
|
||||
}
|
||||
|
@ -4861,7 +4907,7 @@ nsFontWinA::DumpFontInfo()
|
|||
#endif
|
||||
|
||||
nsFontWin*
|
||||
nsFontMetricsWinA::LoadFont(HDC aDC, const nsString& aName)
|
||||
nsFontMetricsWinA::LoadFont(HDC aDC, const nsString& aName, PRBool aNameQuirks)
|
||||
{
|
||||
LOGFONT logFont;
|
||||
HFONT hfont = CreateFontHandle(aDC, aName, &logFont);
|
||||
|
@ -4873,7 +4919,8 @@ nsFontMetricsWinA::LoadFont(HDC aDC, const nsString& aName)
|
|||
char name[sizeof(logFont.lfFaceName)];
|
||||
if (::GetTextFace(aDC, sizeof(name), name) &&
|
||||
!strcmpi(name, logFont.lfFaceName)) {
|
||||
PRUint16* ccmap = GetCCMAP(aDC, logFont.lfFaceName, nsnull, nsnull);
|
||||
PRUint16* ccmap = GetCCMAP(aDC, logFont.lfFaceName,
|
||||
nsnull, nsnull, nsnull);
|
||||
if (ccmap) {
|
||||
nsFontWinA* font = new nsFontWinA(&logFont, hfont, ccmap);
|
||||
if (font) {
|
||||
|
@ -5069,7 +5116,8 @@ nsFontMetricsWinA::FindGlobalFont(HDC aDC, PRUint32 c)
|
|||
continue;
|
||||
}
|
||||
HFONT oldFont = (HFONT)::SelectObject(aDC, hfont);
|
||||
globalFont->ccmap = GetCCMAP(aDC, globalFont->logFont.lfFaceName, nsnull, nsnull);
|
||||
globalFont->ccmap = GetCCMAP(aDC, globalFont->logFont.lfFaceName,
|
||||
nsnull, nsnull, nsnull);
|
||||
::SelectObject(aDC, oldFont);
|
||||
::DeleteObject(hfont);
|
||||
if (!globalFont->ccmap || globalFont->ccmap == gEmptyCCMap) {
|
||||
|
@ -5286,9 +5334,10 @@ nsFontMetricsWinA::ResolveForwards(HDC aDC,
|
|||
// mLoadedFont[0] == font for invisible ignorable characters
|
||||
PRUint32 firstFont = count > 1 ? 1 : 0;
|
||||
if (currFont == mLoadedFonts[firstFont]) {
|
||||
while (currChar < lastChar &&
|
||||
while (++currChar < lastChar &&
|
||||
currFont->HasGlyph(*currChar) && currSubset->HasGlyph(*currChar) &&
|
||||
!CCMAP_HAS_CHAR_EXT(gIgnorableCCMapExt, *currChar))
|
||||
;
|
||||
|
||||
fontSwitch.mFontWin = currSubset;
|
||||
if (!(*aFunc)(&fontSwitch, firstChar, currChar - firstChar, aData))
|
||||
|
|
|
@ -247,7 +247,7 @@ public:
|
|||
virtual nsFontWin* FindGlobalFont(HDC aDC, PRUint32 aChar);
|
||||
virtual nsFontWin* FindSubstituteFont(HDC aDC, PRUint32 aChar);
|
||||
|
||||
virtual nsFontWin* LoadFont(HDC aDC, const nsString& aName);
|
||||
virtual nsFontWin* LoadFont(HDC aDC, const nsString& aName, PRBool aNameQuirks=PR_FALSE);
|
||||
virtual nsFontWin* LoadGenericFont(HDC aDC, PRUint32 aChar, const nsString& aName);
|
||||
virtual nsFontWin* LoadGlobalFont(HDC aDC, nsGlobalFont* aGlobalFontItem);
|
||||
virtual nsFontWin* LoadSubstituteFont(HDC aDC, const nsString& aName);
|
||||
|
@ -280,8 +280,10 @@ public:
|
|||
static void SetFontWeight(PRInt32 aWeight, PRUint16* aWeightTable);
|
||||
static PRBool IsFontWeightAvailable(PRInt32 aWeight, PRUint16 aWeightTable);
|
||||
|
||||
static PRUint16* GetFontCCMAP(HDC aDC, const char* aShortName, eFontType& aFontType, PRUint8& aCharset);
|
||||
static PRUint16* GetCCMAP(HDC aDC, const char* aShortName, eFontType* aFontType, PRUint8* aCharset);
|
||||
static PRUint16* GetFontCCMAP(HDC aDC, const char* aShortName,
|
||||
PRBool aNameQuirks, eFontType& aFontType, PRUint8& aCharset);
|
||||
static PRUint16* GetCCMAP(HDC aDC, const char* aShortName,
|
||||
PRBool* aNameQuirks, eFontType* aFontType, PRUint8* aCharset);
|
||||
|
||||
static int SameAsPreviousMap(int aIndex);
|
||||
|
||||
|
@ -412,7 +414,7 @@ public:
|
|||
virtual nsFontWin* FindGlobalFont(HDC aDC, PRUint32 aChar);
|
||||
virtual nsFontWin* FindSubstituteFont(HDC aDC, PRUint32 aChar);
|
||||
|
||||
virtual nsFontWin* LoadFont(HDC aDC, const nsString& aName);
|
||||
virtual nsFontWin* LoadFont(HDC aDC, const nsString& aName, PRBool aNameQuirks=PR_FALSE);
|
||||
virtual nsFontWin* LoadGlobalFont(HDC aDC, nsGlobalFont* aGlobalFontItem);
|
||||
virtual nsFontWin* LoadSubstituteFont(HDC aDC, const nsString& aName);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче