diff --git a/gfx/thebes/gfxMacFont.cpp b/gfx/thebes/gfxMacFont.cpp index 593d3af6d2f..eb651b26a6e 100644 --- a/gfx/thebes/gfxMacFont.cpp +++ b/gfx/thebes/gfxMacFont.cpp @@ -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(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() { diff --git a/gfx/thebes/gfxMacFont.h b/gfx/thebes/gfxMacFont.h index c4f5836bfdd..cf9703650d5 100644 --- a/gfx/thebes/gfxMacFont.h +++ b/gfx/thebes/gfxMacFont.h @@ -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; diff --git a/gfx/thebes/gfxMacPlatformFontList.h b/gfx/thebes/gfxMacPlatformFontList.h index 5d104a39baa..b16148847fa 100644 --- a/gfx/thebes/gfxMacPlatformFontList.h +++ b/gfx/thebes/gfxMacPlatformFontList.h @@ -66,6 +66,8 @@ public: ATSFontRef GetFontRef(); nsresult ReadCMAP(); + PRBool RequiresAATLayout() const { return mRequiresAAT; } + virtual nsresult GetFontTable(PRUint32 aTableTag, nsTArray& aBuffer); protected: @@ -78,6 +80,7 @@ protected: ATSFontRef mATSFontRef; PRPackedBool mATSFontRefInitialized; + PRPackedBool mRequiresAAT; }; class gfxMacPlatformFontList : public gfxPlatformFontList { diff --git a/gfx/thebes/gfxMacPlatformFontList.mm b/gfx/thebes/gfxMacPlatformFontList.mm index c803a7958ac..0d6609ee792 100644 --- a/gfx/thebes/gfxMacPlatformFontList.mm +++ b/gfx/thebes/gfxMacPlatformFontList.mm @@ -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; } diff --git a/layout/reftests/text/577380-ref.html b/layout/reftests/text/577380-ref.html new file mode 100644 index 00000000000..ebc48f1461c --- /dev/null +++ b/layout/reftests/text/577380-ref.html @@ -0,0 +1,13 @@ + + + + + +fi + + diff --git a/layout/reftests/text/577380.html b/layout/reftests/text/577380.html new file mode 100644 index 00000000000..b4368c8651f --- /dev/null +++ b/layout/reftests/text/577380.html @@ -0,0 +1,13 @@ + + + + + +fi + + diff --git a/layout/reftests/text/reftest.list b/layout/reftests/text/reftest.list index a7310eeee02..b7100e956bc 100644 --- a/layout/reftests/text/reftest.list +++ b/layout/reftests/text/reftest.list @@ -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