bug 577380 - use Core Text shaping for fonts requiring AAT layout on Mac OS X. r=jdaggett

This commit is contained in:
Jonathan Kew 2010-07-22 10:25:21 +01:00
Родитель cb8fa3b5ba
Коммит ed2ddf2315
7 изменённых файлов: 133 добавлений и 42 удалений

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

@ -43,6 +43,7 @@
#include "gfxHarfBuzzShaper.h"
#include "gfxPlatformMac.h"
#include "gfxContext.h"
#include "gfxUnicodeProperties.h"
#include "cairo-quartz.h"
@ -149,6 +150,64 @@ gfxMacFont::~gfxMacFont()
::CGFontRelease(mCGFont);
}
PRBool
gfxMacFont::InitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength,
PRInt32 aRunScript)
{
if (!mIsValid) {
NS_WARNING("invalid font! expect incorrect text rendering");
return PR_FALSE;
}
PRBool ok = PR_FALSE;
if (mHarfBuzzShaper &&
!static_cast<MacOSFontEntry*>(GetFontEntry())->RequiresAATLayout())
{
if (gfxPlatform::GetPlatform()->UseHarfBuzzLevel() >=
gfxUnicodeProperties::ScriptShapingLevel(aRunScript)) {
ok = mHarfBuzzShaper->InitTextRun(aContext, aTextRun, aString,
aRunStart, aRunLength,
aRunScript);
#if DEBUG
if (!ok) {
NS_ConvertUTF16toUTF8 name(GetName());
char msg[256];
sprintf(msg, "HarfBuzz shaping failed for font: %s",
name.get());
NS_WARNING(msg);
}
#endif
}
}
if (!ok) {
// fallback to Core Text shaping
if (!mPlatformShaper) {
CreatePlatformShaper();
}
ok = mPlatformShaper->InitTextRun(aContext, aTextRun, aString,
aRunStart, aRunLength,
aRunScript);
#if DEBUG
if (!ok) {
NS_ConvertUTF16toUTF8 name(GetName());
char msg[256];
sprintf(msg, "Core Text shaping failed for font: %s",
name.get());
NS_WARNING(msg);
}
#endif
}
return ok;
}
void
gfxMacFont::CreatePlatformShaper()
{

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

@ -57,6 +57,13 @@ public:
ATSFontRef GetATSFontRef() const { return mATSFont; }
CGFontRef GetCGFontRef() const { return mCGFont; }
virtual PRBool InitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength,
PRInt32 aRunScript);
/* overrides for the pure virtual methods in gfxFont */
virtual const gfxFont::Metrics& GetMetrics() {
return mMetrics;

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

@ -66,6 +66,8 @@ public:
ATSFontRef GetFontRef();
nsresult ReadCMAP();
PRBool RequiresAATLayout() const { return mRequiresAAT; }
virtual nsresult GetFontTable(PRUint32 aTableTag, nsTArray<PRUint8>& aBuffer);
protected:
@ -78,6 +80,7 @@ protected:
ATSFontRef mATSFontRef;
PRPackedBool mATSFontRefInitialized;
PRPackedBool mRequiresAAT;
};
class gfxMacPlatformFontList : public gfxPlatformFontList {

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

@ -136,7 +136,8 @@ MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
PRBool aIsStandardFace)
: gfxFontEntry(aPostscriptName, aFamily, aIsStandardFace),
mATSFontRef(0),
mATSFontRefInitialized(PR_FALSE)
mATSFontRefInitialized(PR_FALSE),
mRequiresAAT(PR_FALSE)
{
mWeight = aWeight;
}
@ -146,7 +147,8 @@ MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName, ATSFontRef aFon
gfxUserFontData *aUserFontData)
: gfxFontEntry(aPostscriptName),
mATSFontRef(aFontRef),
mATSFontRefInitialized(PR_TRUE)
mATSFontRefInitialized(PR_TRUE),
mRequiresAAT(PR_FALSE)
{
// xxx - stretch is basically ignored for now
@ -198,7 +200,6 @@ const ScriptRange gScriptsThatRequireShaping[] = {
nsresult
MacOSFontEntry::ReadCMAP()
{
OSStatus status;
ByteCount size;
// attempt this once, if errors occur leave a blank cmap
@ -214,20 +215,37 @@ MacOSFontEntry::ReadCMAP()
PRPackedBool unicodeFont, symbolFont; // currently ignored
nsresult rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
mCharacterMap, mUVSOffset, unicodeFont, symbolFont);
mCharacterMap, mUVSOffset,
unicodeFont, symbolFont);
if (NS_FAILED(rv)) {
mCharacterMap.reset();
return rv;
}
mHasCmapTable = PR_TRUE;
// for complex scripts, check for the presence of mort/morx
PRBool checkedForMorphTable = PR_FALSE, hasMorphTable = PR_FALSE;
ATSFontRef fontRef = GetFontRef();
PRUint32 s, numScripts = sizeof(gScriptsThatRequireShaping) / sizeof(ScriptRange);
for (s = 0; s < numScripts; s++) {
// for layout support, check for the presence of mort/morx and GSUB/GPOS
PRBool hasAATLayout =
(::ATSFontGetTable(fontRef, TRUETYPE_TAG('m','o','r','x'),
0, 0, 0, &size) == noErr) ||
(::ATSFontGetTable(fontRef, TRUETYPE_TAG('m','o','r','t'),
0, 0, 0, &size) == noErr);
PRBool hasOTLayout =
(::ATSFontGetTable(fontRef, TRUETYPE_TAG('G','S','U','B'),
0, 0, 0, &size) == noErr) ||
(::ATSFontGetTable(fontRef, TRUETYPE_TAG('G','P','O','S'),
0, 0, 0, &size) == noErr);
if (hasAATLayout && !hasOTLayout) {
mRequiresAAT = PR_TRUE;
}
PRUint32 numScripts =
sizeof(gScriptsThatRequireShaping) / sizeof(ScriptRange);
for (PRUint32 s = 0; s < numScripts; s++) {
eComplexScript whichScript = gScriptsThatRequireShaping[s].script;
// check to see if the cmap includes complex script codepoints
@ -235,42 +253,17 @@ MacOSFontEntry::ReadCMAP()
gScriptsThatRequireShaping[s].rangeEnd)) {
PRBool omitRange = PR_TRUE;
// check for mort/morx table, if haven't already
if (!checkedForMorphTable) {
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, TRUETYPE_TAG('m','o','r','t'), 0, 0, 0, &size);
checkedForMorphTable = PR_TRUE;
if (status == noErr) {
hasMorphTable = PR_TRUE;
}
}
}
if (hasMorphTable) {
if (hasAATLayout) {
omitRange = PR_FALSE;
}
// special-cases for Arabic:
if (whichScript == eComplexScriptArabic) {
} else if (whichScript == eComplexScriptArabic) {
// special-case for Arabic:
// even if there's no morph table, CoreText can shape Arabic
// if there's GSUB support
status = ::ATSFontGetTable(fontRef, TRUETYPE_TAG('G','S','U','B'), 0, 0, 0, &size);
if (status == noErr) {
// TODO: to be really thorough, we could check that the GSUB table
// actually supports the 'arab' script tag.
// using OpenType layout
if (hasOTLayout) {
// TODO: to be really thorough, we could check that the
// GSUB table actually supports the 'arab' script tag.
omitRange = PR_FALSE;
}
// rude hack - the Chinese STxxx fonts on 10.4 contain morx tables and Arabic glyphs but
// lack the proper info for shaping Arabic, so exclude explicitly, ick
if (mName.CharAt(0) == 'S' && mName.CharAt(1) == 'T') {
omitRange = PR_TRUE;
}
}
if (omitRange) {
@ -281,7 +274,8 @@ MacOSFontEntry::ReadCMAP()
}
PR_LOG(gFontInfoLog, PR_LOG_DEBUG, ("(fontinit-cmap) psname: %s, size: %d\n",
NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize()));
NS_ConvertUTF16toUTF8(mName).get(),
mCharacterMap.GetSize()));
return rv;
}

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

@ -0,0 +1,13 @@
<html>
<head>
<style type="text/css">
body {
font-family: Times; /* this test is only for OS X, we know Times will be there */
font-size: 40px;
}
</style>
</head>
<body>
&#xfb01;
</body>
</html>

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

@ -0,0 +1,13 @@
<html>
<head>
<style type="text/css">
body {
font-family: Times; /* this test is only for OS X, we know Times will be there */
font-size: 40px;
}
</style>
</head>
<body>
fi
</body>
</html>

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

@ -57,3 +57,5 @@ random HTTP(..) == 475092-pos.html 475092-sub.html # bug 482596
== 476378-soft-hyphen-fallback.html 476378-soft-hyphen-fallback-ref.html
# Test for bug 484954
== rgba-text.html rgba-text-ref.html
# Test for bug 577380, support for AAT layout (on OS X only)
random-if(MOZ_WIDGET_TOOLKIT!="cocoa") == 577380.html 577380-ref.html