Bug 468387 - (reland) disable synthetic faces for downloadable fonts on Windows already specified as bold/italic. r=vlad

This commit is contained in:
John Daggett 2009-04-02 17:06:33 +09:00
parent 586c538ed3
commit ba340eb217
8 changed files with 479 additions and 101 deletions

View File

@ -290,6 +290,8 @@ public:
nsTArray< nsAutoPtr<Block> > mBlocks;
};
#define TRUETYPE_TAG(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
class THEBES_API gfxFontUtils {
public:
@ -328,7 +330,7 @@ public:
static nsresult
ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCharacterMap,
PRPackedBool& aUnicodeFont, PRPackedBool& aSymbolFont);
#ifdef XP_WIN
// given a TrueType/OpenType data file, produce a EOT-format header
// for use with Windows T2Embed API AddFontResource type API's
@ -352,6 +354,36 @@ public:
RenameFont(const nsAString& aName, const PRUint8 *aFontData,
PRUint32 aFontDataLength, nsTArray<PRUint8> *aNewFont);
// constansts used with name table read methods
enum {
PLATFORM_ALL = -1,
PLATFORM_UNICODE = 0,
PLATFORM_MACINTOSH = 1,
PLATFORM_MICROSOFT = 3,
NAME_LANG_ALL = -1,
// name record id's
NAME_ID_FAMILY = 1,
NAME_ID_STYLE = 2,
NAME_ID_UNIQUE = 3,
NAME_ID_FULL = 4, // used as key to GDI CreateFontIndirect
NAME_ID_VERSION = 5,
NAME_ID_POSTSCRIPT = 6,
NAME_ID_PREFERRED_FAMILY = 16
};
// read all names matching aNameID, returning in aNames array
static nsresult
ReadNames(nsTArray<PRUint8>& aNameTable, PRUint32 aNameID,
PRInt32 aPlatformID, nsTArray<nsString>& aNames);
// reads English or first name matching aNameID, returning in aName
// platform based on OS
static nsresult
ReadCanonicalName(nsTArray<PRUint8>& aNameTable, PRUint32 aNameID,
nsString& aName);
static inline bool IsJoiner(PRUint32 ch) {
return (ch == 0x200C ||
ch == 0x200D ||
@ -371,6 +403,11 @@ public:
// generate a unique font name
static nsresult MakeUniqueUserFontName(nsAString& aName);
protected:
static nsresult
ReadNames(nsTArray<PRUint8>& aNameTable, PRUint32 aNameID,
PRInt32 aLangID, PRInt32 aPlatformID, nsTArray<nsString>& aNames);
};
// helper class for loading in font info spaced out at regular intervals

View File

@ -110,13 +110,18 @@ private:
class FontEntry : public gfxFontEntry
{
public:
FontEntry(const nsAString& aFaceName) :
gfxFontEntry(aFaceName), mFontType(GFX_FONT_TYPE_UNKNOWN),
FontEntry(const nsAString& aFaceName, gfxWindowsFontType aFontType,
PRBool aItalic, PRUint16 aWeight, gfxUserFontData *aUserFontData) :
gfxFontEntry(aFaceName), mFontType(aFontType),
mForceGDI(PR_FALSE), mUnknownCMAP(PR_FALSE),
mUnicodeFont(PR_FALSE), mSymbolFont(PR_FALSE),
mUnicodeFont(PR_FALSE), mSymbolFont(PR_FALSE), mUserFont(PR_FALSE),
mCharset(0), mUnicodeRanges(0)
{
mUserFontData = aUserFontData;
mItalic = aItalic;
mWeight = aWeight;
if (IsType1())
mForceGDI = PR_TRUE;
}
FontEntry(const FontEntry& aFontEntry) :
@ -128,6 +133,7 @@ public:
mUnknownCMAP(aFontEntry.mUnknownCMAP),
mUnicodeFont(aFontEntry.mUnicodeFont),
mSymbolFont(aFontEntry.mSymbolFont),
mUserFont(aFontEntry.mUserFont),
mCharset(aFontEntry.mCharset),
mUnicodeRanges(aFontEntry.mUnicodeRanges)
{
@ -135,16 +141,29 @@ public:
}
static void InitializeFontEmbeddingProcs();
static FontEntry* CreateFontEntry(const gfxProxyFontEntry &aProxyEntry,
nsISupports *aLoader,
const PRUint8 *aFontData,
PRUint32 aLength);
static FontEntry* CreateFontEntry(const nsAString& aName, gfxWindowsFontType aFontType, PRBool aItalic, PRUint16 aWeight, gfxUserFontData* aUserFontData, HDC hdc = 0, LOGFONTW *aLogFont = nsnull);
// create a font entry from downloaded font data
static FontEntry* LoadFont(const gfxProxyFontEntry &aProxyEntry,
nsISupports *aLoader,
const PRUint8 *aFontData,
PRUint32 aLength);
static void FillLogFont(LOGFONTW *aLogFont, FontEntry *aFontEntry, gfxFloat aSize, PRBool aItalic);
// create a font entry for a font with a given name
static FontEntry* CreateFontEntry(const nsAString& aName,
gfxWindowsFontType aFontType,
PRBool aItalic, PRUint16 aWeight,
gfxUserFontData* aUserFontData,
HDC hdc = 0, LOGFONTW *aLogFont = nsnull);
static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics, DWORD fontType)
// create a font entry for a font referenced by its fullname
static FontEntry* LoadLocalFont(const gfxProxyFontEntry &aProxyEntry,
const nsAString& aFullname);
static void FillLogFont(LOGFONTW *aLogFont, const nsAString& aName,
gfxWindowsFontType aFontType, PRBool aItalic,
PRUint16 aWeight, gfxFloat aSize);
static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics,
DWORD fontType)
{
gfxWindowsFontType feType;
if (metrics.ntmFlags & NTM_TYPE1)
@ -274,6 +293,7 @@ public:
PRPackedBool mUnknownCMAP : 1;
PRPackedBool mUnicodeFont : 1;
PRPackedBool mSymbolFont : 1;
PRPackedBool mUserFont : 1;
std::bitset<256> mCharset;
std::bitset<128> mUnicodeRanges;

View File

@ -491,7 +491,7 @@ gfxAtsuiFont::HasMirroringInfo()
ByteCount size;
// 361695 - if the font has a 'prop' table, assume that ATSUI will handle glyph mirroring
status = ATSFontGetTable(GetATSFontRef(), 'prop', 0, 0, 0, &size);
status = ATSFontGetTable(GetATSFontRef(), TRUETYPE_TAG('p','r','o','p'), 0, 0, 0, &size);
mHasMirroring = (status == noErr);
mHasMirroringLookedUp = PR_TRUE;
}

View File

@ -51,6 +51,9 @@
#include "plbase64.h"
#ifdef XP_MACOSX
#include <CoreFoundation/CoreFoundation.h>
#endif
#define NO_RANGE_FOUND 126 // bit 126 in the font unicode ranges is required to be 0
@ -331,19 +334,19 @@ gfxFontUtils::ReadCMAPTableFormat4(PRUint8 *aBuf, PRUint32 aLength, gfxSparseBit
// For fonts with two format-4 tables, the first one (Unicode platform) is preferred on the Mac.
#if defined(XP_MACOSX)
#define acceptablePlatform(p) ((p) == PlatformIDUnicode || (p) == PlatformIDMicrosoft)
#define acceptableFormat4(p,e,k) ( ((p) == PlatformIDMicrosoft && (e) == EncodingIDMicrosoft && (k) != 4) || \
((p) == PlatformIDUnicode) )
#define isSymbol(p,e) ((p) == PlatformIDMicrosoft && (e) == EncodingIDSymbol)
#define acceptablePlatform(p) ((p) == PLATFORM_UNICODE || (p) == PLATFORM_MICROSOFT)
#define acceptableFormat4(p,e,k) ( ((p) == PLATFORM_MICROSOFT && (e) == EncodingIDMicrosoft && (k) != 4) || \
((p) == PLATFORM_UNICODE) )
#define isSymbol(p,e) ((p) == PLATFORM_MICROSOFT && (e) == EncodingIDSymbol)
#else
#define acceptablePlatform(p) ((p) == PlatformIDMicrosoft)
#define acceptablePlatform(p) ((p) == PLATFORM_MICROSOFT)
#define acceptableFormat4(p,e,k) ((e) == EncodingIDMicrosoft)
#define isSymbol(p,e) ((e) == EncodingIDSymbol)
#endif
#define acceptableUCS4Encoding(p, e) \
((platformID == PlatformIDMicrosoft && encodingID == EncodingIDUCS4ForMicrosoftPlatform) || \
(platformID == PlatformIDUnicode && encodingID == EncodingIDUCS4ForUnicodePlatform))
((platformID == PLATFORM_MICROSOFT && encodingID == EncodingIDUCS4ForMicrosoftPlatform) || \
(platformID == PLATFORM_UNICODE && encodingID == EncodingIDUCS4ForUnicodePlatform))
nsresult
gfxFontUtils::ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCharacterMap,
@ -361,10 +364,6 @@ gfxFontUtils::ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCha
SubtableOffsetFormat = 0
};
enum {
PlatformIDUnicode = 0,
PlatformIDMicrosoft = 3
};
enum {
EncodingIDSymbol = 0,
EncodingIDMicrosoft = 1,
@ -600,16 +599,9 @@ struct NameRecord {
AutoSwap_PRUint16 offset; // String offset from start of storage area (in bytes).
enum {
NAME_ID_FAMILY = 1,
NAME_ID_STYLE = 2,
NAME_ID_UNIQUE = 3,
NAME_ID_FULL = 4,
NAME_ID_VERSION = 5,
NAME_ID_POSTSCRIPT = 6,
PLATFORM_ID_UNICODE = 0, // Mac OS uses this typically
PLATFORM_ID_MICROSOFT = 3,
ENCODING_ID_MICROSOFT_UNICODEBMP = 1, // with Microsoft platformID, BMP-only Unicode encoding
LANG_ID_MICROSOFT_EN_US = 0x0409 // with Microsoft platformID, EN US lang code
LANG_ID_MICROSOFT_EN_US = 0x0409, // with Microsoft platformID, EN US lang code
LANG_ID_MACINTOSH_EN = 0
};
};
@ -667,7 +659,7 @@ IsValidSFNTVersion(PRUint32 version)
{
// normally 0x00010000, CFF-style OT fonts == 'OTTO' and Apple TT fonts = 'true'
// 'typ1' is also possible for old Type 1 fonts in a SFNT container but not supported
return version == 0x10000 || version == 'OTTO' || version == 'true';
return version == 0x10000 || version == TRUETYPE_TAG('O','T','T','O') || version == TRUETYPE_TAG('t','r','u','e');
}
// copy and swap UTF-16 values, assume no surrogate pairs, can be in place
@ -706,7 +698,7 @@ gfxFontUtils::ValidateSFNTHeaders(const PRUint8 *aFontData,
}
if (aIsCFF)
*aIsCFF = (sfntVersion == 'OTTO');
*aIsCFF = (sfntVersion == TRUETYPE_TAG('O','T','T','O'));
// iterate through the table headers to find the head, name and OS/2 tables
PRBool foundHead = PR_FALSE, foundOS2 = PR_FALSE, foundName = PR_FALSE;
@ -747,7 +739,7 @@ gfxFontUtils::ValidateSFNTHeaders(const PRUint8 *aFontData,
switch (dirEntry->tag) {
case 'head':
case TRUETYPE_TAG('h','e','a','d'):
foundHead = PR_TRUE;
headOffset = dirEntry->offset;
headLen = dirEntry->length;
@ -757,21 +749,21 @@ gfxFontUtils::ValidateSFNTHeaders(const PRUint8 *aFontData,
}
break;
case 'name':
case TRUETYPE_TAG('n','a','m','e'):
foundName = PR_TRUE;
nameOffset = dirEntry->offset;
nameLen = dirEntry->length;
break;
case 'OS/2':
case TRUETYPE_TAG('O','S','/','2'):
foundOS2 = PR_TRUE;
break;
case 'glyf': // TrueType-style quadratic glyph table
case TRUETYPE_TAG('g','l','y','f'): // TrueType-style quadratic glyph table
foundGlyphs = PR_TRUE;
break;
case 'CFF ': // PS-style cubic glyph table
case TRUETYPE_TAG('C','F','F',' '): // PS-style cubic glyph table
foundCFF = PR_TRUE;
break;
@ -811,7 +803,7 @@ gfxFontUtils::ValidateSFNTHeaders(const PRUint8 *aFontData,
}
// need glyf or CFF table based on sfnt version
if (sfntVersion == 'OTTO') {
if (sfntVersion == TRUETYPE_TAG('O','T','T','O')) {
if (!foundCFF) {
NS_WARNING("invalid font (missing CFF table)");
return PR_FALSE;
@ -861,11 +853,11 @@ gfxFontUtils::RenameFont(const nsAString& aName, const PRUint8 *aFontData,
PRUint64 dataLength(aFontDataLength);
// new name table
static const PRUint32 neededNameIDs[] = {NameRecord::NAME_ID_FAMILY,
NameRecord::NAME_ID_STYLE,
NameRecord::NAME_ID_UNIQUE,
NameRecord::NAME_ID_FULL,
NameRecord::NAME_ID_POSTSCRIPT};
static const PRUint32 neededNameIDs[] = {gfxFontUtils::NAME_ID_FAMILY,
gfxFontUtils::NAME_ID_STYLE,
gfxFontUtils::NAME_ID_UNIQUE,
gfxFontUtils::NAME_ID_FULL,
gfxFontUtils::NAME_ID_POSTSCRIPT};
// calculate new name table size
PRUint16 nameCount = NS_ARRAY_LENGTH(neededNameIDs);
@ -909,7 +901,7 @@ gfxFontUtils::RenameFont(const nsAString& aName, const PRUint8 *aFontData,
NameRecord *nameRecord = reinterpret_cast<NameRecord*>(nameHeader + 1);
for (i = 0; i < nameCount; i++, nameRecord++) {
nameRecord->platformID = NameRecord::PLATFORM_ID_MICROSOFT;
nameRecord->platformID = gfxFontUtils::PLATFORM_MICROSOFT;
nameRecord->encodingID = NameRecord::ENCODING_ID_MICROSOFT_UNICODEBMP;
nameRecord->languageID = NameRecord::LANG_ID_MICROSOFT_EN_US;
nameRecord->nameID = neededNameIDs[i];
@ -939,7 +931,7 @@ gfxFontUtils::RenameFont(const nsAString& aName, const PRUint8 *aFontData,
PRBool foundName = PR_FALSE;
for (i = 0; i < numTables; i++, dirEntry++) {
if (dirEntry->tag == 'name') {
if (dirEntry->tag == TRUETYPE_TAG('n','a','m','e')) {
foundName = PR_TRUE;
break;
}
@ -980,7 +972,7 @@ gfxFontUtils::RenameFont(const nsAString& aName, const PRUint8 *aFontData,
dirEntry = reinterpret_cast<TableDirEntry*>(newFontData + sizeof(SFNTHeader));
for (i = 0; i < numTables; i++, dirEntry++) {
if (dirEntry->tag == 'head') {
if (dirEntry->tag == TRUETYPE_TAG('h','e','a','d')) {
headOffset = dirEntry->offset;
}
checksum += dirEntry->checkSum;
@ -995,6 +987,216 @@ gfxFontUtils::RenameFont(const nsAString& aName, const PRUint8 *aFontData,
return NS_OK;
}
enum {
#if defined(XP_MACOSX)
CANONICAL_LANG_ID = NameRecord::LANG_ID_MACINTOSH_EN,
PLATFORM_ID = gfxFontUtils::PLATFORM_MACINTOSH
#else
CANONICAL_LANG_ID = NameRecord::LANG_ID_MICROSOFT_EN_US,
PLATFORM_ID = gfxFontUtils::PLATFORM_MICROSOFT
#endif
};
nsresult
gfxFontUtils::ReadNames(nsTArray<PRUint8>& aNameTable, PRUint32 aNameID,
PRInt32 aPlatformID, nsTArray<nsString>& aNames)
{
return ReadNames(aNameTable, aNameID, NAME_LANG_ALL, aPlatformID, aNames);
}
nsresult
gfxFontUtils::ReadCanonicalName(nsTArray<PRUint8>& aNameTable, PRUint32 aNameID,
nsString& aName)
{
nsresult rv;
nsTArray<nsString> names;
// first, look for the English name (this will succeed 99% of the time)
rv = ReadNames(aNameTable, aNameID, CANONICAL_LANG_ID, PLATFORM_ID, names);
NS_ENSURE_SUCCESS(rv, rv);
// otherwise, grab names for all languages
if (names.Length() == 0) {
rv = ReadNames(aNameTable, aNameID, NAME_LANG_ALL, PLATFORM_ID, names);
NS_ENSURE_SUCCESS(rv, rv);
}
#if defined(XP_MACOSX)
// may be dealing with font that only has Microsoft name entries
if (names.Length() == 0) {
rv = ReadNames(aNameTable, aNameID, NameRecord::LANG_ID_MICROSOFT_EN_US,
gfxFontUtils::PLATFORM_MICROSOFT, names);
NS_ENSURE_SUCCESS(rv, rv);
// getting really desperate now, take anything!
if (names.Length() == 0) {
rv = ReadNames(aNameTable, aNameID, NAME_LANG_ALL,
gfxFontUtils::PLATFORM_MICROSOFT, names);
NS_ENSURE_SUCCESS(rv, rv);
}
}
#endif
// return the first name (99.9% of the time names will
// contain a single English name)
if (names.Length()) {
aName.Assign(names[0]);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
nsresult
DecodeName(PRUint8 *aNameData, PRUint32 aByteLen, PRInt32 aPlatform,
PRUint32 aEncoding, nsAString& aName)
{
NS_ASSERTION(aPlatform != gfxFontUtils::PLATFORM_ALL, "need a defined platform to decode string");
#if defined(XP_MACOSX)
CFStringRef name = NULL;
if (aPlatform == gfxFontUtils::PLATFORM_MACINTOSH) {
name = CFStringCreateWithBytes(kCFAllocatorDefault, aNameData, aByteLen,
(CFStringEncoding) aEncoding, false);
} else if (aPlatform == gfxFontUtils::PLATFORM_UNICODE
|| aPlatform == gfxFontUtils::PLATFORM_MICROSOFT)
{
name = CFStringCreateWithBytes(kCFAllocatorDefault, aNameData, aByteLen,
kCFStringEncodingUTF16BE, false);
}
if (!name)
return NS_ERROR_FAILURE;
CFIndex len = CFStringGetLength(name);
aName.SetLength(len);
CFStringGetCharacters(name, CFRangeMake(0, len), aName.BeginWriting());
CFRelease(name);
#else
// skip non-MS platforms and non-Unicode encodings
if (aPlatform != gfxFontUtils::PLATFORM_MICROSOFT
|| aEncoding != NameRecord::ENCODING_ID_MICROSOFT_UNICODEBMP)
return NS_ERROR_FAILURE;
PRUint32 strLen = aByteLen/2;
PRUnichar *str;
#ifdef IS_LITTLE_ENDIAN
nsAutoTArray<PRUnichar,256> swapBuf;
if (!swapBuf.AppendElements(strLen))
NS_ERROR_FAILURE;
str = (PRUnichar*) (swapBuf.Elements());
PRUnichar *ch, *end = (PRUnichar*)(aNameData + aByteLen);
for (ch = (PRUnichar*) aNameData; ch < end; ch++) {
*str++ = NS_SWAP16(*ch);
}
str = (PRUnichar*) (swapBuf.Elements());
#else
str = (PRUnichar*) aNameData;
#endif
aName.Assign(str, strLen);
#endif
return NS_OK;
}
nsresult
gfxFontUtils::ReadNames(nsTArray<PRUint8>& aNameTable, PRUint32 aNameID,
PRInt32 aLangID, PRInt32 aPlatformID,
nsTArray<nsString>& aNames)
{
PRUint32 nameTableLen = aNameTable.Length();
NS_ASSERTION(nameTableLen != 0, "null name table");
if (nameTableLen == 0)
return NS_ERROR_FAILURE;
PRUint8 *nameTable = aNameTable.Elements();
// -- name table data
const NameHeader *nameHeader = reinterpret_cast<const NameHeader*>(nameTable);
PRUint32 nameCount = nameHeader->count;
// -- sanity check the number of name records
if (PRUint64(nameCount) * sizeof(NameRecord) > nameTableLen) {
NS_WARNING("invalid font (name table data)");
return NS_ERROR_FAILURE;
}
// -- iterate through name records
const NameRecord *nameRecord
= reinterpret_cast<const NameRecord*>(nameTable + sizeof(NameHeader));
PRUint64 nameStringsBase = PRUint64(nameHeader->stringOffset);
PRUint32 i;
for (i = 0; i < nameCount; i++, nameRecord++) {
PRUint32 platformID;
// skip over unwanted nameID's
if (PRUint32(nameRecord->nameID) != aNameID)
continue;
// skip over unwanted platform data
platformID = nameRecord->platformID;
if (aPlatformID != PLATFORM_ALL
&& PRUint32(nameRecord->platformID) != PLATFORM_ID)
continue;
// skip over unwanted languages
if (aLangID != NAME_LANG_ALL
&& PRUint32(nameRecord->languageID) != PRUint32(aLangID))
continue;
// add name to names array
// -- calculate string location
PRUint32 namelen = nameRecord->length;
PRUint32 nameoff = nameRecord->offset; // offset from base of string storage
if (nameStringsBase + PRUint64(nameoff) + PRUint64(namelen)
> nameTableLen) {
NS_WARNING("invalid font (name table strings)");
return NS_ERROR_FAILURE;
}
// -- decode if necessary and make nsString
nsAutoString name;
nsresult rv;
rv = DecodeName(nameTable + nameStringsBase + nameoff, namelen,
platformID, PRUint32(nameRecord->encodingID), name);
if (NS_FAILED(rv))
continue;
PRUint32 k, numNames;
PRBool foundName = PR_FALSE;
numNames = aNames.Length();
for (k = 0; k < numNames; k++) {
if (name.Equals(aNames[k])) {
foundName = PR_TRUE;
break;
}
}
if (!foundName)
aNames.AppendElement(name);
}
return NS_OK;
}
// Embedded OpenType (EOT) handling
// needed for dealing with downloadable fonts on Windows
//
@ -1142,7 +1344,7 @@ gfxFontUtils::MakeEOTHeader(const PRUint8 *aFontData, PRUint32 aFontDataLength,
switch (dirEntry->tag) {
case 'head':
case TRUETYPE_TAG('h','e','a','d'):
foundHead = PR_TRUE;
headOffset = dirEntry->offset;
headLen = dirEntry->length;
@ -1150,23 +1352,23 @@ gfxFontUtils::MakeEOTHeader(const PRUint8 *aFontData, PRUint32 aFontDataLength,
return NS_ERROR_FAILURE;
break;
case 'name':
case TRUETYPE_TAG('n','a','m','e'):
foundName = PR_TRUE;
nameOffset = dirEntry->offset;
nameLen = dirEntry->length;
break;
case 'OS/2':
case TRUETYPE_TAG('O','S','/','2'):
foundOS2 = PR_TRUE;
os2Offset = dirEntry->offset;
os2Len = dirEntry->length;
break;
case 'glyf': // TrueType-style quadratic glyph table
case TRUETYPE_TAG('g','l','y','f'): // TrueType-style quadratic glyph table
foundGlyphs = PR_TRUE;
break;
case 'CFF ': // PS-style cubic glyph table
case TRUETYPE_TAG('C','F','F',' '): // PS-style cubic glyph table
foundGlyphs = PR_TRUE;
break;
@ -1217,32 +1419,32 @@ gfxFontUtils::MakeEOTHeader(const PRUint8 *aFontData, PRUint32 aFontDataLength,
for (i = 0; i < nameCount; i++, nameRecord++) {
// looking for Microsoft English US name strings, skip others
if (PRUint32(nameRecord->platformID) != NameRecord::PLATFORM_ID_MICROSOFT ||
if (PRUint32(nameRecord->platformID) != gfxFontUtils::PLATFORM_MICROSOFT ||
PRUint32(nameRecord->encodingID) != NameRecord::ENCODING_ID_MICROSOFT_UNICODEBMP ||
PRUint32(nameRecord->languageID) != NameRecord::LANG_ID_MICROSOFT_EN_US)
continue;
switch ((PRUint32)nameRecord->nameID) {
case NameRecord::NAME_ID_FAMILY:
case gfxFontUtils::NAME_ID_FAMILY:
names[EOTFixedHeader::EOT_FAMILY_NAME_INDEX].offset = nameRecord->offset;
names[EOTFixedHeader::EOT_FAMILY_NAME_INDEX].length = nameRecord->length;
needNames &= ~(1 << EOTFixedHeader::EOT_FAMILY_NAME_INDEX);
break;
case NameRecord::NAME_ID_STYLE:
case gfxFontUtils::NAME_ID_STYLE:
names[EOTFixedHeader::EOT_STYLE_NAME_INDEX].offset = nameRecord->offset;
names[EOTFixedHeader::EOT_STYLE_NAME_INDEX].length = nameRecord->length;
needNames &= ~(1 << EOTFixedHeader::EOT_STYLE_NAME_INDEX);
break;
case NameRecord::NAME_ID_FULL:
case gfxFontUtils::NAME_ID_FULL:
names[EOTFixedHeader::EOT_FULL_NAME_INDEX].offset = nameRecord->offset;
names[EOTFixedHeader::EOT_FULL_NAME_INDEX].length = nameRecord->length;
needNames &= ~(1 << EOTFixedHeader::EOT_FULL_NAME_INDEX);
break;
case NameRecord::NAME_ID_VERSION:
case gfxFontUtils::NAME_ID_VERSION:
names[EOTFixedHeader::EOT_VERSION_NAME_INDEX].offset = nameRecord->offset;
names[EOTFixedHeader::EOT_VERSION_NAME_INDEX].length = nameRecord->length;
needNames &= ~(1 << EOTFixedHeader::EOT_VERSION_NAME_INDEX);

View File

@ -195,7 +195,9 @@ MacOSFontEntry::ReadCMAP()
// attempt this once, if errors occur leave a blank cmap
mCmapInitialized = PR_TRUE;
status = ATSFontGetTable(fontRef, 'cmap', 0, 0, 0, &size);
PRUint32 kCMAP = TRUETYPE_TAG('c','m','a','p');
status = ATSFontGetTable(fontRef, kCMAP, 0, 0, 0, &size);
cmapSize = size;
//printf( "cmap size: %s %d", NS_ConvertUTF16toUTF8(mName).get(), size );
#if DEBUG
@ -212,7 +214,7 @@ MacOSFontEntry::ReadCMAP()
return NS_ERROR_OUT_OF_MEMORY;
PRUint8 *cmap = buffer.Elements();
status = ATSFontGetTable(fontRef, 'cmap', 0, size, cmap, &size);
status = ATSFontGetTable(fontRef, kCMAP, 0, size, cmap, &size);
NS_ENSURE_TRUE(status == noErr, NS_ERROR_FAILURE);
nsresult rv = NS_ERROR_FAILURE;
@ -232,13 +234,13 @@ MacOSFontEntry::ReadCMAP()
// check for mort/morx table, if haven't already
if (!checkedForMorphTable) {
status = ATSFontGetTable(fontRef, 'morx', 0, 0, 0, &size);
status = ATSFontGetTable(fontRef, TRUETYPE_TAG('m','o','r','x'), 0, 0, 0, &size);
if (status == noErr) {
checkedForMorphTable = PR_TRUE;
hasMorphTable = PR_TRUE;
} else {
// check for a mort table
status = ATSFontGetTable(fontRef, 'mort', 0, 0, 0, &size);
status = ATSFontGetTable(fontRef, TRUETYPE_TAG('m','o','r','t'), 0, 0, 0, &size);
checkedForMorphTable = PR_TRUE;
if (status == noErr) {
hasMorphTable = PR_TRUE;

View File

@ -64,6 +64,7 @@
#include "nsIPrefService.h"
#include "nsIPrefLocalizedString.h"
#include "nsServiceManagerUtils.h"
#include "nsIStreamBufferAccess.h"
#include "nsCRT.h"
@ -147,7 +148,7 @@ struct DCFromContext {
static nsresult
ReadCMAP(HDC hdc, FontEntry *aFontEntry)
{
const PRUint32 kCMAP = (('c') | ('m' << 8) | ('a' << 16) | ('p' << 24));
const PRUint32 kCMAP = NS_SWAP32(TRUETYPE_TAG('c','m','a','p'));
DWORD len = GetFontData(hdc, kCMAP, 0, nsnull, 0);
if (len == GDI_ERROR || len == 0) // not a truetype font --
@ -494,9 +495,9 @@ public:
/* static */
FontEntry*
FontEntry::CreateFontEntry(const gfxProxyFontEntry &aProxyEntry,
nsISupports *aLoader,const PRUint8 *aFontData,
PRUint32 aLength) {
FontEntry::LoadFont(const gfxProxyFontEntry &aProxyEntry,
nsISupports *aLoader,const PRUint8 *aFontData,
PRUint32 aLength) {
// if calls aren't available, bail
if (!TTLoadEmbeddedFontPtr || !TTDeleteEmbeddedFontPtr)
return nsnull;
@ -579,13 +580,45 @@ FontEntry::CreateFontEntry(const gfxProxyFontEntry &aProxyEntry,
PRUint32(aProxyEntry.mItalic ? FONT_STYLE_ITALIC : FONT_STYLE_NORMAL),
w, winUserFontData);
if (fe && isCFF)
if (!fe)
return fe;
fe->mUserFont = PR_TRUE;
if (isCFF)
fe->mForceGDI = PR_TRUE;
return fe;
}
class AutoReleaseDC {
public:
AutoReleaseDC(HDC hdc) : mDC(hdc) {
SetGraphicsMode(hdc, GM_ADVANCED);
}
~AutoReleaseDC() { ReleaseDC(nsnull, mDC); }
HDC mDC;
};
class AutoPushPopFont {
public:
AutoPushPopFont(HDC hdc, HFONT aFont) : mDC(hdc), mFont(aFont) {
mOldFont = (HFONT)SelectObject(mDC, mFont);
}
~AutoPushPopFont() {
SelectObject(mDC, mOldFont);
DeleteObject(mFont);
}
HDC mDC;
HFONT mFont;
HFONT mOldFont;
};
/* static */
FontEntry*
FontEntry::CreateFontEntry(const nsAString& aName, gfxWindowsFontType aFontType, PRBool aItalic, PRUint16 aWeight, gfxUserFontData* aUserFontData, HDC hdc, LOGFONTW *aLogFont)
FontEntry::CreateFontEntry(const nsAString& aName, gfxWindowsFontType aFontType,
PRBool aItalic, PRUint16 aWeight,
gfxUserFontData* aUserFontData,
HDC hdc, LOGFONTW *aLogFont)
{
LOGFONTW logFont;
PRBool needRelease = PR_FALSE;
@ -594,19 +627,11 @@ FontEntry::CreateFontEntry(const nsAString& aName, gfxWindowsFontType aFontType,
FontEntry *fe;
fe = new FontEntry(aName);
fe->mFontType = aFontType;
fe->mUserFontData = aUserFontData;
fe->mItalic = aItalic;
fe->mWeight = aWeight;
if (fe->IsType1())
fe->mForceGDI = PR_TRUE;
fe = new FontEntry(aName, aFontType, aItalic, aWeight, aUserFontData);
if (!aLogFont) {
aLogFont = &logFont;
FontEntry::FillLogFont(aLogFont, fe, 0, aItalic);
FontEntry::FillLogFont(aLogFont, aName, aFontType, aItalic, aWeight, 0);
}
if (!hdc) {
@ -614,11 +639,11 @@ FontEntry::CreateFontEntry(const nsAString& aName, gfxWindowsFontType aFontType,
SetGraphicsMode(hdc, GM_ADVANCED);
needRelease = PR_TRUE;
}
HFONT font = CreateFontIndirectW(aLogFont);
if (font) {
HFONT oldFont = (HFONT)SelectObject(hdc, font);
AutoPushPopFont fontCleanup(hdc, font);
// ReadCMAP may change the values of mUnicodeFont and mSymbolFont
if (NS_FAILED(::ReadCMAP(hdc, fe))) {
@ -634,9 +659,6 @@ FontEntry::CreateFontEntry(const nsAString& aName, gfxWindowsFontType aFontType,
fe->mUnknownCMAP = PR_TRUE;
}
SelectObject(hdc, oldFont);
DeleteObject(font);
}
if (needRelease)
@ -645,9 +667,82 @@ FontEntry::CreateFontEntry(const nsAString& aName, gfxWindowsFontType aFontType,
return fe;
}
/* static */
FontEntry*
FontEntry::LoadLocalFont(const gfxProxyFontEntry &aProxyEntry,
const nsAString& aFullname)
{
// lookup name with CreateFontIndirect
HDC hdc = GetDC(nsnull);
AutoReleaseDC dcCleanup(hdc);
SetGraphicsMode(hdc, GM_ADVANCED);
LOGFONTW logFont;
memset(&logFont, 0, sizeof(LOGFONTW));
logFont.lfCharSet = DEFAULT_CHARSET;
PRUint32 namelen = PR_MIN(aFullname.Length(), LF_FACESIZE - 1);
memcpy(logFont.lfFaceName,
nsPromiseFlatString(aFullname).get(),
namelen * sizeof(PRUnichar));
logFont.lfFaceName[namelen] = 0;
HFONT font = CreateFontIndirectW(&logFont);
if (!font)
return nsnull;
// fetch fullname from name table (Windows takes swapped tag order)
const PRUint32 kNameTag = NS_SWAP32(TRUETYPE_TAG('n','a','m','e'));
nsAutoString fullName;
{
AutoPushPopFont fontCleanup(hdc, font);
DWORD len = GetFontData(hdc, kNameTag, 0, nsnull, 0);
if (len == GDI_ERROR || len == 0) // not a truetype font --
return nsnull; // so just ignore
nsAutoTArray<PRUint8,1024> nameData;
if (!nameData.AppendElements(len))
return nsnull;
PRUint8 *nameTable = nameData.Elements();
DWORD newLen = GetFontData(hdc, kNameTag, 0, nameTable, len);
if (newLen != len)
return nsnull;
nsresult rv;
rv = gfxFontUtils::ReadCanonicalName(nameData,
gfxFontUtils::NAME_ID_FULL,
fullName);
if (NS_FAILED(rv))
return nsnull;
}
// reject if different from canonical fullname
if (!aFullname.Equals(fullName))
return nsnull;
// create a new font entry
PRUint16 w = (aProxyEntry.mWeight == 0 ? 400 : aProxyEntry.mWeight);
PRBool isCFF = PR_FALSE; // jtdfix -- need to determine this
FontEntry *fe = FontEntry::CreateFontEntry(aFullname,
gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/,
PRUint32(aProxyEntry.mItalic ? FONT_STYLE_ITALIC : FONT_STYLE_NORMAL),
w, nsnull);
if (!fe)
return fe;
fe->mUserFont = PR_TRUE;
return fe;
}
void
FontEntry::FillLogFont(LOGFONTW *aLogFont, FontEntry *aFontEntry, gfxFloat aSize, PRBool aItalic)
FontEntry::FillLogFont(LOGFONTW *aLogFont, const nsAString& aName,
gfxWindowsFontType aFontType, PRBool aItalic,
PRUint16 aWeight, gfxFloat aSize)
{
#define CLIP_TURNOFF_FONTASSOCIATION 0x40
@ -663,7 +758,7 @@ FontEntry::FillLogFont(LOGFONTW *aLogFont, FontEntry *aFontEntry, gfxFloat aSize
aLogFont->lfUnderline = FALSE;
aLogFont->lfStrikeOut = FALSE;
aLogFont->lfCharSet = DEFAULT_CHARSET;
aLogFont->lfOutPrecision = FontTypeToOutPrecision(aFontEntry->mFontType);
aLogFont->lfOutPrecision = FontTypeToOutPrecision(aFontType);
aLogFont->lfClipPrecision = CLIP_TURNOFF_FONTASSOCIATION;
aLogFont->lfQuality = DEFAULT_QUALITY;
aLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
@ -672,10 +767,10 @@ FontEntry::FillLogFont(LOGFONTW *aLogFont, FontEntry *aFontEntry, gfxFloat aSize
// it may give us a regular one based on weight. Windows should
// do fake italic for us in that case.
aLogFont->lfItalic = aItalic;
aLogFont->lfWeight = aFontEntry->mWeight;
aLogFont->lfWeight = aWeight;
int len = PR_MIN(aFontEntry->Name().Length(), LF_FACESIZE - 1);
memcpy(aLogFont->lfFaceName, nsPromiseFlatString(aFontEntry->Name()).get(), len * 2);
int len = PR_MIN(aName.Length(), LF_FACESIZE - 1);
memcpy(aLogFont->lfFaceName, nsPromiseFlatString(aName).get(), len * 2);
aLogFont->lfFaceName[len] = '\0';
}
@ -961,7 +1056,23 @@ gfxWindowsFont::ComputeMetrics()
void
gfxWindowsFont::FillLogFont(gfxFloat aSize)
{
FontEntry::FillLogFont(&mLogFont, GetFontEntry(), aSize, (GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)));
FontEntry *fe = GetFontEntry();
PRBool isItalic;
isItalic = (GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE));
PRUint16 weight = fe->Weight();
// if user font, disable italics/bold if defined to be italics/bold face
// this avoids unwanted synthetic italics/bold
if (fe->mUserFont) {
if (fe->IsItalic())
isItalic = PR_FALSE; // avoid synthetic italic
if (fe->IsBold())
weight = 400; // avoid synthetic bold
}
FontEntry::FillLogFont(&mLogFont, fe->Name(), fe->mFontType, isItalic,
weight, aSize);
}

View File

@ -754,6 +754,7 @@ gfxFontEntry*
gfxWindowsPlatform::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
const nsAString& aFontName)
{
#ifdef MOZ_FT2_FONTS
// walk over list of names
FullFontNameSearch data(aFontName);
@ -764,6 +765,9 @@ gfxWindowsPlatform::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
ReleaseDC(nsnull, data.mDC);
return data.mFontEntry;
#else
return FontEntry::LoadLocalFont(*aProxyEntry, aFontName);
#endif
}
gfxFontEntry*
@ -771,8 +775,7 @@ gfxWindowsPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
nsISupports *aLoader,
const PRUint8 *aFontData, PRUint32 aLength)
{
return FontEntry::CreateFontEntry(*aProxyEntry, aLoader,
aFontData, aLength);
return FontEntry::LoadFont(*aProxyEntry, aLoader, aFontData, aLength);
}
PRBool

View File

@ -25,15 +25,18 @@ HTTP(..) == src-list-format-4.html src-list-format-1-ref.html
HTTP(..) == src-list-format-5.html src-list-format-2-ref.html
HTTP(..) == src-list-format-6.html src-list-format-3-ref.html
# assumes AAT fonts are only supported on MacOS
skip-if(MOZ_WIDGET_TOOLKIT=="cocoa") HTTP(..) == src-list-format-7.html src-list-format-2-ref.html
skip-if(MOZ_WIDGET_TOOLKIT!="cocoa") HTTP(..) == src-list-format-7.html src-list-format-3-ref.html
skip-if(MOZ_WIDGET_TOOLKIT=="windows") == src-list-local-full.html src-list-local-full-ref.html # bug 468387 (windows)
skip-if(MOZ_WIDGET_TOOLKIT=="windows") == src-list-local-full-quotes.html src-list-local-full-ref.html # bug 468387 (windows)
random-if(MOZ_WIDGET_TOOLKIT=="cocoa") HTTP(..) == src-list-format-7.html src-list-format-2-ref.html
random-if(MOZ_WIDGET_TOOLKIT!="cocoa") HTTP(..) == src-list-format-7.html src-list-format-3-ref.html
== src-list-local-full.html src-list-local-full-ref.html
== src-list-local-full-quotes.html src-list-local-full-ref.html
HTTP(..) == src-list-local-fallback.html src-list-local-fallback-ref.html
# localized full fontnames should *not* match, only English ones (need locale-invariant key)
random-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == src-list-local-localized.html src-list-local-localized-ref.html
# Postscript name lookup only supported on MacOS currently
skip-if(MOZ_WIDGET_TOOLKIT!="cocoa") == src-list-local-ps.html src-list-local-full-ref.html
skip-if(MOZ_WIDGET_TOOLKIT!="cocoa") == helveticaneue-ultra.html helveticaneue-ultra-ref.html
random-if(MOZ_WIDGET_TOOLKIT!="cocoa") == src-list-local-ps.html src-list-local-full-ref.html
random-if(MOZ_WIDGET_TOOLKIT!="cocoa") == helveticaneue-ultra.html helveticaneue-ultra-ref.html
# Arabic support requires AAT fonts under Mac OS, OpenType otherwise
random-if(MOZ_WIDGET_TOOLKIT!="cocoa") HTTP(..) == src-format-arabic.html src-format-arabic-aat-ref.html
@ -80,5 +83,5 @@ HTTP(..) == ahem-metrics-1.html ahem-metrics-1-ref.html
HTTP(..) == ex-unit-1.html ex-unit-1-ref.html
HTTP(..) == ex-unit-1-dynamic.html ex-unit-1-ref.html
fails-if(MOZ_WIDGET_TOOLKIT=="windows") == local-1.html local-1-ref.html # bug 468387
fails-if(MOZ_WIDGET_TOOLKIT=="windows") HTTP(..) == synthetic-weight-style.html synthetic-weight-style-ref.html # bug 468387
== local-1.html local-1-ref.html
HTTP(..) == synthetic-weight-style.html synthetic-weight-style-ref.html