backout changeset 48b74ab18f92 (bug 1018034) due to MS Sans Serif regression with Thai system locale (see bug 1020826).
authorJonathan Kew <jkew@mozilla.com>
Fri, 06 Jun 2014 22:41:07 +0100
changeset 207647 6be2448e325c1ffbcb9c87dfd1cbf6730ed9c551
parent 207646 0e387a55464687d5a8224c90bb046af46294bceb
child 207648 5cf33b3e3d5e456df098d213056aff4754653579
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1018034, 1020826
milestone32.0a1
backs out48b74ab18f9278ae3202803af5e6c8a0757a83cb
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
backout changeset 48b74ab18f92 (bug 1018034) due to MS Sans Serif regression with Thai system locale (see bug 1020826).
gfx/thebes/gfxFT2Fonts.cpp
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
intl/unicharutil/util/nsUnicodeProperties.cpp
intl/unicharutil/util/nsUnicodeProperties.h
layout/reftests/indic-shaping/reftest.list
modules/libpref/src/init/all.js
--- a/gfx/thebes/gfxFT2Fonts.cpp
+++ b/gfx/thebes/gfxFT2Fonts.cpp
@@ -60,17 +60,17 @@ gfxFT2Font::ShapeText(gfxContext      *a
                 mGraphiteShaper = new gfxGraphiteShaper(this);
             }
             ok = mGraphiteShaper->ShapeText(aContext, aText,
                                             aOffset, aLength,
                                             aScript, aShapedText);
         }
     }
 
-    if (!ok) {
+    if (!ok && gfxPlatform::GetPlatform()->UseHarfBuzzForScript(aScript)) {
         if (!mHarfBuzzShaper) {
             mHarfBuzzShaper = new gfxHarfBuzzShaper(this);
         }
         ok = mHarfBuzzShaper->ShapeText(aContext, aText,
                                         aOffset, aLength,
                                         aScript, aShapedText);
     }
 
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -3969,18 +3969,20 @@ gfxFont::ShapeText(gfxContext      *aCon
     bool ok = false;
 
     if (mGraphiteShaper && gfxPlatform::GetPlatform()->UseGraphiteShaping()) {
         ok = mGraphiteShaper->ShapeText(aContext, aText, aOffset, aLength,
                                         aScript, aShapedText);
     }
 
     if (!ok && mHarfBuzzShaper && !aPreferPlatformShaping) {
-        ok = mHarfBuzzShaper->ShapeText(aContext, aText, aOffset, aLength,
-                                        aScript, aShapedText);
+        if (gfxPlatform::GetPlatform()->UseHarfBuzzForScript(aScript)) {
+            ok = mHarfBuzzShaper->ShapeText(aContext, aText, aOffset, aLength,
+                                            aScript, aShapedText);
+        }
     }
 
     if (!ok) {
         if (!mPlatformShaper) {
             CreatePlatformShaper();
         }
         if (mPlatformShaper) {
             ok = mPlatformShaper->ShapeText(aContext, aText, aOffset, aLength,
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -138,16 +138,18 @@ public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIOBSERVER
 };
 
 NS_IMPL_ISUPPORTS(SRGBOverrideObserver, nsIObserver, nsISupportsWeakReference)
 
 #define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
 
+#define GFX_PREF_HARFBUZZ_SCRIPTS "gfx.font_rendering.harfbuzz.scripts"
+#define HARFBUZZ_SCRIPTS_DEFAULT  mozilla::unicode::SHAPING_DEFAULT
 #define GFX_PREF_FALLBACK_USE_CMAPS  "gfx.font_rendering.fallback.always_use_cmaps"
 
 #define GFX_PREF_OPENTYPE_SVG "gfx.font_rendering.opentype_svg.enabled"
 
 #define GFX_PREF_WORD_CACHE_CHARLIMIT "gfx.font_rendering.wordcache.charlimit"
 #define GFX_PREF_WORD_CACHE_MAXENTRIES "gfx.font_rendering.wordcache.maxentries"
 
 #define GFX_PREF_GRAPHITE_SHAPING "gfx.font_rendering.graphite.enabled"
@@ -255,16 +257,17 @@ static const char *gPrefLangNames[] = {
     "x-tibt",
     "x-unicode",
 };
 
 gfxPlatform::gfxPlatform()
   : mAzureCanvasBackendCollector(MOZ_THIS_IN_INITIALIZER_LIST(),
                                  &gfxPlatform::GetAzureBackendInfo)
 {
+    mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
     mAllowDownloadableFonts = UNINITIALIZED_VALUE;
     mFallbackUsesCmaps = UNINITIALIZED_VALUE;
 
     mWordCacheCharLimit = UNINITIALIZED_VALUE;
     mWordCacheMaxEntries = UNINITIALIZED_VALUE;
     mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
     mOpenTypeSVGEnabled = UNINITIALIZED_VALUE;
     mBidiNumeralOption = UNINITIALIZED_VALUE;
@@ -1105,16 +1108,28 @@ gfxPlatform::UseGraphiteShaping()
     if (mGraphiteShapingEnabled == UNINITIALIZED_VALUE) {
         mGraphiteShapingEnabled =
             Preferences::GetBool(GFX_PREF_GRAPHITE_SHAPING, false);
     }
 
     return mGraphiteShapingEnabled;
 }
 
+bool
+gfxPlatform::UseHarfBuzzForScript(int32_t aScriptCode)
+{
+    if (mUseHarfBuzzScripts == UNINITIALIZED_VALUE) {
+        mUseHarfBuzzScripts = Preferences::GetInt(GFX_PREF_HARFBUZZ_SCRIPTS, HARFBUZZ_SCRIPTS_DEFAULT);
+    }
+
+    int32_t shapingType = mozilla::unicode::ScriptShapingType(aScriptCode);
+
+    return (mUseHarfBuzzScripts & shapingType) != 0;
+}
+
 gfxFontEntry*
 gfxPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
                               const uint8_t *aFontData,
                               uint32_t aLength)
 {
     // Default implementation does not handle activating downloaded fonts;
     // just free the data and return.
     // Platforms that support @font-face must override this,
@@ -1841,16 +1856,19 @@ gfxPlatform::FontsPrefsChanged(const cha
         mWordCacheCharLimit = UNINITIALIZED_VALUE;
         FlushFontAndWordCaches();
     } else if (!strcmp(GFX_PREF_WORD_CACHE_MAXENTRIES, aPref)) {
         mWordCacheMaxEntries = UNINITIALIZED_VALUE;
         FlushFontAndWordCaches();
     } else if (!strcmp(GFX_PREF_GRAPHITE_SHAPING, aPref)) {
         mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
         FlushFontAndWordCaches();
+    } else if (!strcmp(GFX_PREF_HARFBUZZ_SCRIPTS, aPref)) {
+        mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
+        FlushFontAndWordCaches();
     } else if (!strcmp(BIDI_NUMERAL_PREF, aPref)) {
         mBidiNumeralOption = UNINITIALIZED_VALUE;
     } else if (!strcmp(GFX_PREF_OPENTYPE_SVG, aPref)) {
         mOpenTypeSVGEnabled = UNINITIALIZED_VALUE;
         gfxFontCache::GetCache()->AgeAllGenerations();
     }
 }
 
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -380,16 +380,23 @@ public:
     uint32_t WordCacheMaxEntries();
 
     /**
      * Whether to use the SIL Graphite rendering engine
      * (for fonts that include Graphite tables)
      */
     bool UseGraphiteShaping();
 
+    /**
+     * Whether to use the harfbuzz shaper (depending on script complexity).
+     *
+     * This allows harfbuzz to be enabled selectively via the preferences.
+     */
+    bool UseHarfBuzzForScript(int32_t aScriptCode);
+
     // check whether format is supported on a platform or not (if unclear, returns true)
     virtual bool IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags) { return false; }
 
     void GetPrefFonts(nsIAtom *aLanguage, nsString& array, bool aAppendUnicode = true);
 
     // in some situations, need to make decisions about ambiguous characters, may need to look at multiple pref langs
     void GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang);
     
@@ -607,16 +614,19 @@ protected:
     int8_t  mOpenTypeSVGEnabled;
 
     int8_t  mBidiNumeralOption;
 
     // whether to always search font cmaps globally 
     // when doing system font fallback
     int8_t  mFallbackUsesCmaps;
 
+    // which scripts should be shaped with harfbuzz
+    int32_t mUseHarfBuzzScripts;
+
     // max character limit for words in word cache
     int32_t mWordCacheCharLimit;
 
     // max number of entries in word cache
     int32_t mWordCacheMaxEntries;
 
 private:
     /**
--- a/intl/unicharutil/util/nsUnicodeProperties.cpp
+++ b/intl/unicharutil/util/nsUnicodeProperties.cpp
@@ -244,16 +244,74 @@ bool
 IsClusterExtender(uint32_t aCh, uint8_t aCategory)
 {
     return ((aCategory >= HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK &&
              aCategory <= HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) ||
             (aCh >= 0x200c && aCh <= 0x200d) || // ZWJ, ZWNJ
             (aCh >= 0xff9e && aCh <= 0xff9f));  // katakana sound marks
 }
 
+// TODO: replace this with a properties file or similar;
+// expect this to evolve as harfbuzz shaping support matures.
+//
+// The "shaping type" of each script run, as returned by this
+// function, is compared to the bits set in the
+// gfx.font_rendering.harfbuzz.scripts
+// preference to decide whether to use the harfbuzz shaper.
+//
+int32_t
+ScriptShapingType(int32_t aScriptCode)
+{
+    switch (aScriptCode) {
+    default:
+        return SHAPING_DEFAULT; // scripts not explicitly listed here are
+                                // assumed to just use default shaping
+
+    case MOZ_SCRIPT_ARABIC:
+    case MOZ_SCRIPT_SYRIAC:
+    case MOZ_SCRIPT_NKO:
+    case MOZ_SCRIPT_MANDAIC:
+        return SHAPING_ARABIC; // bidi scripts with Arabic-style shaping
+
+    case MOZ_SCRIPT_HEBREW:
+        return SHAPING_HEBREW;
+
+    case MOZ_SCRIPT_HANGUL:
+        return SHAPING_HANGUL;
+
+    case MOZ_SCRIPT_MONGOLIAN: // to be supported by the Arabic shaper?
+        return SHAPING_MONGOLIAN;
+
+    case MOZ_SCRIPT_THAI: // no complex OT features, but MS engines like to do
+                          // sequence checking
+        return SHAPING_THAI;
+
+    case MOZ_SCRIPT_BENGALI:
+    case MOZ_SCRIPT_DEVANAGARI:
+    case MOZ_SCRIPT_GUJARATI:
+    case MOZ_SCRIPT_GURMUKHI:
+    case MOZ_SCRIPT_KANNADA:
+    case MOZ_SCRIPT_MALAYALAM:
+    case MOZ_SCRIPT_ORIYA:
+    case MOZ_SCRIPT_SINHALA:
+    case MOZ_SCRIPT_TAMIL:
+    case MOZ_SCRIPT_TELUGU:
+    case MOZ_SCRIPT_KHMER:
+    case MOZ_SCRIPT_LAO:
+    case MOZ_SCRIPT_TIBETAN:
+    case MOZ_SCRIPT_NEW_TAI_LUE:
+    case MOZ_SCRIPT_TAI_LE:
+    case MOZ_SCRIPT_MYANMAR:
+    case MOZ_SCRIPT_PHAGS_PA:
+    case MOZ_SCRIPT_BATAK:
+    case MOZ_SCRIPT_BRAHMI:
+        return SHAPING_INDIC; // scripts that require Indic or other "special" shaping
+    }
+}
+
 void
 ClusterIterator::Next()
 {
     if (AtEnd()) {
         NS_WARNING("ClusterIterator has already reached the end");
         return;
     }
 
--- a/intl/unicharutil/util/nsUnicodeProperties.h
+++ b/intl/unicharutil/util/nsUnicodeProperties.h
@@ -114,16 +114,28 @@ inline HSType GetHangulSyllableType(uint
 // Case mappings for the full Unicode range;
 // note that it may be worth testing for ASCII chars and taking
 // a separate fast-path before calling these, in perf-critical places
 uint32_t GetUppercase(uint32_t aCh);
 uint32_t GetLowercase(uint32_t aCh);
 uint32_t GetTitlecaseForLower(uint32_t aCh); // maps LC to titlecase, UC unchanged
 uint32_t GetTitlecaseForAll(uint32_t aCh); // maps both UC and LC to titlecase
 
+enum ShapingType {
+  SHAPING_DEFAULT   = 0x0001,
+  SHAPING_ARABIC    = 0x0002,
+  SHAPING_HEBREW    = 0x0004,
+  SHAPING_HANGUL    = 0x0008,
+  SHAPING_MONGOLIAN = 0x0010,
+  SHAPING_INDIC     = 0x0020,
+  SHAPING_THAI      = 0x0040
+};
+
+int32_t ScriptShapingType(int32_t aScriptCode);
+
 // A simple iterator for a string of char16_t codepoints that advances
 // by Unicode grapheme clusters
 class ClusterIterator
 {
 public:
     ClusterIterator(const char16_t* aText, uint32_t aLength)
         : mPos(aText), mLimit(aText + aLength)
 #ifdef DEBUG
--- a/layout/reftests/indic-shaping/reftest.list
+++ b/layout/reftests/indic-shaping/reftest.list
@@ -1,22 +1,22 @@
-skip-if(B2G) HTTP(..) == devanagari-1a.html devanagari-1-ref.html
-HTTP(..) != devanagari-1b.html devanagari-1-ref.html
-HTTP(..) == devanagari-2.html devanagari-2-ref.html
-HTTP(..) != devanagari-3a.html devanagari-3-ref.html
-HTTP(..) == devanagari-3b.html devanagari-3-ref.html
-HTTP(..) != devanagari-4.html devanagari-4-notref.html
+skip-if(B2G) pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) == devanagari-1a.html devanagari-1-ref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) != devanagari-1b.html devanagari-1-ref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) == devanagari-2.html devanagari-2-ref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) != devanagari-3a.html devanagari-3-ref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) == devanagari-3b.html devanagari-3-ref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) != devanagari-4.html devanagari-4-notref.html
 
-HTTP(..) == gujarati-1a.html gujarati-1-ref.html
-HTTP(..) != gujarati-1b.html gujarati-1-ref.html
-HTTP(..) == gujarati-2.html gujarati-2-ref.html
-HTTP(..) != gujarati-3a.html gujarati-3-ref.html
-skip-if(B2G) HTTP(..) == gujarati-3b.html gujarati-3-ref.html
-HTTP(..) != gujarati-4.html gujarati-4-notref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) == gujarati-1a.html gujarati-1-ref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) != gujarati-1b.html gujarati-1-ref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) == gujarati-2.html gujarati-2-ref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) != gujarati-3a.html gujarati-3-ref.html
+skip-if(B2G) pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) == gujarati-3b.html gujarati-3-ref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) != gujarati-4.html gujarati-4-notref.html
 
-skip-if(B2G) HTTP(..) == bengali-1a.html bengali-1-ref.html
-HTTP(..) != bengali-1b.html bengali-1-ref.html
-HTTP(..) != bengali-2a.html bengali-2-ref.html
-HTTP(..) != bengali-2b.html bengali-2-ref.html
-skip-if(B2G) HTTP(..) == bengali-3a.html bengali-3-ref.html
-HTTP(..) != bengali-3b.html bengali-3-ref.html
-HTTP(..) != bengali-3c.html bengali-3-ref.html
-HTTP(..) != bengali-3c.html bengali-3b.html
+skip-if(B2G) pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) == bengali-1a.html bengali-1-ref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) != bengali-1b.html bengali-1-ref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) != bengali-2a.html bengali-2-ref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) != bengali-2b.html bengali-2-ref.html
+skip-if(B2G) pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) == bengali-3a.html bengali-3-ref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) != bengali-3b.html bengali-3-ref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) != bengali-3c.html bengali-3-ref.html
+pref(gfx.font_rendering.harfbuzz.scripts,-1) HTTP(..) != bengali-3c.html bengali-3b.html
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -430,16 +430,33 @@ pref("gfx.font_rendering.fallback.always
 // cache shaped word results
 pref("gfx.font_rendering.wordcache.charlimit", 32);
 
 // cache shaped word results
 pref("gfx.font_rendering.wordcache.maxentries", 10000);
 
 pref("gfx.font_rendering.graphite.enabled", true);
 
+// Check intl/unicharutil/util/nsUnicodeProperties.h for definitions of script bits
+// in the ShapingType enumeration
+// Currently-defined bits:
+//  SHAPING_DEFAULT   = 0x0001,
+//  SHAPING_ARABIC    = 0x0002,
+//  SHAPING_HEBREW    = 0x0004,
+//  SHAPING_HANGUL    = 0x0008,
+//  SHAPING_MONGOLIAN = 0x0010,
+//  SHAPING_INDIC     = 0x0020,
+//  SHAPING_THAI      = 0x0040
+// (see http://mxr.mozilla.org/mozilla-central/ident?i=ShapingType)
+// Scripts not listed are grouped in the default category.
+// Set the pref to 255 to have all text shaped via the harfbuzz backend.
+// Default setting:
+// We use harfbuzz for all scripts (except when using AAT fonts on OS X).
+pref("gfx.font_rendering.harfbuzz.scripts", 255);
+
 #ifdef XP_WIN
 pref("gfx.font_rendering.directwrite.enabled", false);
 pref("gfx.font_rendering.directwrite.use_gdi_table_loading", true);
 #endif
 
 pref("gfx.font_rendering.opentype_svg.enabled", true);
 
 #ifdef XP_WIN