bug 580863 part 2 - scale glyph metrics correctly when initializing CFF fonts on OS X 10.6. r=jdaggett a=blocking-betaN

This commit is contained in:
Jonathan Kew 2010-10-07 08:59:16 +01:00
Родитель caa84d02a4
Коммит e72058c4cc
4 изменённых файлов: 56 добавлений и 12 удалений

Просмотреть файл

@ -268,6 +268,16 @@ gfxMacFont::InitMetrics()
mAdjustedSize = PR_MAX(mStyle.size, 1.0f); mAdjustedSize = PR_MAX(mStyle.size, 1.0f);
mFUnitsConvFactor = mAdjustedSize / upem; mFUnitsConvFactor = mAdjustedSize / upem;
// For CFF fonts, when scaling values read from CGFont* APIs, we need to
// use CG's idea of unitsPerEm, which may differ from the "true" value in
// the head table of the font (see bug 580863)
gfxFloat cgConvFactor;
if (static_cast<MacOSFontEntry*>(mFontEntry.get())->IsCFF()) {
cgConvFactor = mAdjustedSize / ::CGFontGetUnitsPerEm(mCGFont);
} else {
cgConvFactor = mFUnitsConvFactor;
}
// Try to read 'sfnt' metrics; for local, non-sfnt fonts ONLY, fall back to // Try to read 'sfnt' metrics; for local, non-sfnt fonts ONLY, fall back to
// platform APIs. The InitMetrics...() functions will set mIsValid on success. // platform APIs. The InitMetrics...() functions will set mIsValid on success.
if (!InitMetricsFromSfntTables(mMetrics) && if (!InitMetricsFromSfntTables(mMetrics) &&
@ -279,7 +289,7 @@ gfxMacFont::InitMetrics()
} }
if (mMetrics.xHeight == 0.0) { if (mMetrics.xHeight == 0.0) {
mMetrics.xHeight = ::CGFontGetXHeight(mCGFont) * mFUnitsConvFactor; mMetrics.xHeight = ::CGFontGetXHeight(mCGFont) * cgConvFactor;
} }
if (mStyle.sizeAdjust != 0.0 && mStyle.size > 0.0 && if (mStyle.sizeAdjust != 0.0 && mStyle.size > 0.0 &&
@ -288,6 +298,11 @@ gfxMacFont::InitMetrics()
gfxFloat aspect = mMetrics.xHeight / mStyle.size; gfxFloat aspect = mMetrics.xHeight / mStyle.size;
mAdjustedSize = mStyle.GetAdjustedSize(aspect); mAdjustedSize = mStyle.GetAdjustedSize(aspect);
mFUnitsConvFactor = mAdjustedSize / upem; mFUnitsConvFactor = mAdjustedSize / upem;
if (static_cast<MacOSFontEntry*>(mFontEntry.get())->IsCFF()) {
cgConvFactor = mAdjustedSize / ::CGFontGetUnitsPerEm(mCGFont);
} else {
cgConvFactor = mFUnitsConvFactor;
}
mMetrics.xHeight = 0.0; mMetrics.xHeight = 0.0;
if (!InitMetricsFromSfntTables(mMetrics) && if (!InitMetricsFromSfntTables(mMetrics) &&
(!mFontEntry->IsUserFont() || mFontEntry->IsLocalUserFont())) { (!mFontEntry->IsUserFont() || mFontEntry->IsLocalUserFont())) {
@ -299,7 +314,7 @@ gfxMacFont::InitMetrics()
return; return;
} }
if (mMetrics.xHeight == 0.0) { if (mMetrics.xHeight == 0.0) {
mMetrics.xHeight = ::CGFontGetXHeight(mCGFont) * mFUnitsConvFactor; mMetrics.xHeight = ::CGFontGetXHeight(mCGFont) * cgConvFactor;
} }
} }
@ -317,7 +332,8 @@ gfxMacFont::InitMetrics()
PRUint32 glyphID; PRUint32 glyphID;
if (mMetrics.aveCharWidth <= 0) { if (mMetrics.aveCharWidth <= 0) {
mMetrics.aveCharWidth = GetCharWidth(cmap, 'x', &glyphID); mMetrics.aveCharWidth = GetCharWidth(cmap, 'x', &glyphID,
cgConvFactor);
if (glyphID == 0) { if (glyphID == 0) {
// we didn't find 'x', so use maxAdvance rather than zero // we didn't find 'x', so use maxAdvance rather than zero
mMetrics.aveCharWidth = mMetrics.maxAdvance; mMetrics.aveCharWidth = mMetrics.maxAdvance;
@ -326,14 +342,15 @@ gfxMacFont::InitMetrics()
mMetrics.aveCharWidth += mSyntheticBoldOffset; mMetrics.aveCharWidth += mSyntheticBoldOffset;
mMetrics.maxAdvance += mSyntheticBoldOffset; mMetrics.maxAdvance += mSyntheticBoldOffset;
mMetrics.spaceWidth = GetCharWidth(cmap, ' ', &glyphID); mMetrics.spaceWidth = GetCharWidth(cmap, ' ', &glyphID, cgConvFactor);
if (glyphID == 0) { if (glyphID == 0) {
// no space glyph?! // no space glyph?!
mMetrics.spaceWidth = mMetrics.aveCharWidth; mMetrics.spaceWidth = mMetrics.aveCharWidth;
} }
mSpaceGlyph = glyphID; mSpaceGlyph = glyphID;
mMetrics.zeroOrAveCharWidth = GetCharWidth(cmap, '0', &glyphID); mMetrics.zeroOrAveCharWidth = GetCharWidth(cmap, '0', &glyphID,
cgConvFactor);
if (glyphID == 0) { if (glyphID == 0) {
mMetrics.zeroOrAveCharWidth = mMetrics.aveCharWidth; mMetrics.zeroOrAveCharWidth = mMetrics.aveCharWidth;
} }
@ -360,7 +377,7 @@ gfxMacFont::InitMetrics()
gfxFloat gfxFloat
gfxMacFont::GetCharWidth(CFDataRef aCmap, PRUnichar aUniChar, gfxMacFont::GetCharWidth(CFDataRef aCmap, PRUnichar aUniChar,
PRUint32 *aGlyphID) PRUint32 *aGlyphID, gfxFloat aConvFactor)
{ {
CGGlyph glyph = 0; CGGlyph glyph = 0;
@ -377,7 +394,7 @@ gfxMacFont::GetCharWidth(CFDataRef aCmap, PRUnichar aUniChar,
if (glyph) { if (glyph) {
int advance; int advance;
if (::CGFontGetGlyphAdvances(mCGFont, &glyph, 1, &advance)) { if (::CGFontGetGlyphAdvances(mCGFont, &glyph, 1, &advance)) {
return advance * mFUnitsConvFactor; return advance * aConvFactor;
} }
} }

Просмотреть файл

@ -85,10 +85,10 @@ protected:
void InitMetrics(); void InitMetrics();
void InitMetricsFromATSMetrics(); void InitMetricsFromATSMetrics();
// Get width and glyph ID for a character; requires that // Get width and glyph ID for a character; uses aConvFactor
// mFUnitsConvFactor has been set before this is called // to convert font units as returned by CG to actual dimensions
gfxFloat GetCharWidth(CFDataRef aCmap, PRUnichar aUniChar, gfxFloat GetCharWidth(CFDataRef aCmap, PRUnichar aUniChar,
PRUint32 *aGlyphID); PRUint32 *aGlyphID, gfxFloat aConvFactor);
static void DestroyBlobFunc(void* aUserData); static void DestroyBlobFunc(void* aUserData);

Просмотреть файл

@ -70,6 +70,8 @@ public:
virtual nsresult GetFontTable(PRUint32 aTableTag, nsTArray<PRUint8>& aBuffer); virtual nsresult GetFontTable(PRUint32 aTableTag, nsTArray<PRUint8>& aBuffer);
PRBool IsCFF();
protected: protected:
// for use with data fonts // for use with data fonts
MacOSFontEntry(const nsAString& aPostscriptName, ATSFontRef aFontRef, MacOSFontEntry(const nsAString& aPostscriptName, ATSFontRef aFontRef,
@ -81,6 +83,8 @@ protected:
ATSFontRef mATSFontRef; ATSFontRef mATSFontRef;
PRPackedBool mATSFontRefInitialized; PRPackedBool mATSFontRefInitialized;
PRPackedBool mRequiresAAT; PRPackedBool mRequiresAAT;
PRPackedBool mIsCFF;
PRPackedBool mIsCFFInitialized;
}; };
class gfxMacPlatformFontList : public gfxPlatformFontList { class gfxMacPlatformFontList : public gfxPlatformFontList {

Просмотреть файл

@ -137,7 +137,9 @@ MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
: gfxFontEntry(aPostscriptName, aFamily, aIsStandardFace), : gfxFontEntry(aPostscriptName, aFamily, aIsStandardFace),
mATSFontRef(0), mATSFontRef(0),
mATSFontRefInitialized(PR_FALSE), mATSFontRefInitialized(PR_FALSE),
mRequiresAAT(PR_FALSE) mRequiresAAT(PR_FALSE),
mIsCFF(PR_FALSE),
mIsCFFInitialized(PR_FALSE)
{ {
mWeight = aWeight; mWeight = aWeight;
} }
@ -148,7 +150,8 @@ MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName, ATSFontRef aFon
: gfxFontEntry(aPostscriptName), : gfxFontEntry(aPostscriptName),
mATSFontRef(aFontRef), mATSFontRef(aFontRef),
mATSFontRefInitialized(PR_TRUE), mATSFontRefInitialized(PR_TRUE),
mRequiresAAT(PR_FALSE) mRequiresAAT(PR_FALSE),
mIsCFFInitialized(PR_FALSE)
{ {
// xxx - stretch is basically ignored for now // xxx - stretch is basically ignored for now
@ -313,6 +316,26 @@ MacOSFontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeeds
return new gfxMacFont(this, aFontStyle, aNeedsBold); return new gfxMacFont(this, aFontStyle, aNeedsBold);
} }
PRBool
MacOSFontEntry::IsCFF()
{
if (!mIsCFFInitialized) {
mIsCFFInitialized = PR_TRUE;
ATSFontRef fontRef = GetFontRef();
if (fontRef != (ATSFontRef)kATSUInvalidFontID) {
ByteCount dataLength;
OSStatus status = ::ATSFontGetTable(fontRef,
TRUETYPE_TAG('C','F','F',' '),
0, 0, 0, &dataLength);
if (status == noErr && dataLength > 0) {
mIsCFF = PR_TRUE;
}
}
}
return mIsCFF;
}
/* gfxMacFontFamily */ /* gfxMacFontFamily */
#pragma mark- #pragma mark-