Bug 921858 - Check for spaces in textrun before skipping word cache. r=jfkthame, a=1.4+
authorJohn Daggett <jdaggett@mozilla.com>
Thu, 20 Mar 2014 14:43:30 +0800
changeset 193091 c963101ad96e12d58dfb64749ccc8b01793f8bb6
parent 193090 d140b15c4e1e272876238314ae22af42a9c15c69
child 193092 393fe487357421c6ba2c7a97c87a9bc5dafb4ef2
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame, 1
bugs921858
milestone30.0a2
Bug 921858 - Check for spaces in textrun before skipping word cache. r=jfkthame, a=1.4+
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFont.h
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -2355,17 +2355,17 @@ gfxFont::HasSubstitutionRulesWithSpaceLo
     {
         return true;
     }
 
     return false;
 }
 
 bool
-gfxFont::BypassShapedWordCache(int32_t aRunScript)
+gfxFont::SpaceMayParticipateInShaping(int32_t aRunScript)
 {
     // We record the presence of space-dependent features in the font entry
     // so that subsequent instantiations for the same font face won't
     // require us to re-check the tables; however, the actual check is done
     // by gfxFont because not all font entry subclasses know how to create
     // a harfbuzz face for introspection.
     if (!mFontEntry->mHasSpaceFeaturesInitialized) {
         CheckForFeaturesInvolvingSpace();
@@ -3699,16 +3699,31 @@ gfxFont::ShapeTextWithoutWordCache(gfxCo
 #define TEXT_PERF_INCR(tp, m) (tp ? (tp)->current.m++ : 0)
 #else
 #define TEXT_PERF_INCR(tp, m)
 #endif
 
 inline static bool IsChar8Bit(uint8_t /*aCh*/) { return true; }
 inline static bool IsChar8Bit(char16_t aCh) { return aCh < 0x100; }
 
+inline static bool HasSpaces(const uint8_t *aString, uint32_t aLen)
+{
+    return memchr(aString, 0x20, aLen) != nullptr;
+}
+
+inline static bool HasSpaces(const char16_t *aString, uint32_t aLen)
+{
+    for (const char16_t *ch = aString; ch < aString + aLen; ch++) {
+        if (*ch == 0x20) {
+            return true;
+        }
+    }
+    return false;
+}
+
 template<typename T>
 bool
 gfxFont::SplitAndInitTextRun(gfxContext *aContext,
                              gfxTextRun *aTextRun,
                              const T *aString,
                              uint32_t aRunStart,
                              uint32_t aRunLength,
                              int32_t aRunScript)
@@ -3729,26 +3744,34 @@ gfxFont::SplitAndInitTextRun(gfxContext 
         }
         tp->current.numChars += aRunLength;
         if (aRunLength > tp->current.maxTextRunLen) {
             tp->current.maxTextRunLen = aRunLength;
         }
     }
 #endif
 
-    if (BypassShapedWordCache(aRunScript)) {
-        TEXT_PERF_INCR(tp, wordCacheSpaceRules);
-        return ShapeTextWithoutWordCache(aContext, aString + aRunStart,
-                                         aRunStart, aRunLength, aRunScript,
-                                         aTextRun);
+    uint32_t wordCacheCharLimit =
+        gfxPlatform::GetPlatform()->WordCacheCharLimit();
+
+    // If spaces can participate in shaping (e.g. within lookups for automatic
+    // fractions), need to shape without using the word cache which segments
+    // textruns on space boundaries. Word cache can be used if the textrun
+    // is short enough to fit in the word cache and it lacks spaces.
+    if (SpaceMayParticipateInShaping(aRunScript)) {
+        if (aRunLength > wordCacheCharLimit ||
+            HasSpaces(aString + aRunStart, aRunLength)) {
+            TEXT_PERF_INCR(tp, wordCacheSpaceRules);
+            return ShapeTextWithoutWordCache(aContext, aString + aRunStart,
+                                             aRunStart, aRunLength, aRunScript,
+                                             aTextRun);
+        }
     }
 
     InitWordCache();
-    uint32_t wordCacheCharLimit =
-        gfxPlatform::GetPlatform()->WordCacheCharLimit();
 
     // the only flags we care about for ShapedWord construction/caching
     uint32_t flags = aTextRun->GetFlags();
     flags &= (gfxTextRunFactory::TEXT_IS_RTL |
               gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES |
               gfxTextRunFactory::TEXT_USE_MATH_SCRIPT);
     if (sizeof(T) == sizeof(uint8_t)) {
         flags |= gfxTextRunFactory::TEXT_IS_8BIT;
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -1802,18 +1802,18 @@ public:
 
 protected:
     void AddGlyphChangeObserver(GlyphChangeObserver *aObserver);
     void RemoveGlyphChangeObserver(GlyphChangeObserver *aObserver);
 
     // whether font contains substitution lookups containing spaces
     bool HasSubstitutionRulesWithSpaceLookups(int32_t aRunScript);
 
-    // whether to use word cache or not
-    bool BypassShapedWordCache(int32_t aRunScript);
+    // do spaces participate in shaping rules? if so, can't used word cache
+    bool SpaceMayParticipateInShaping(int32_t aRunScript);
 
     // For 8-bit text, expand to 16-bit and then call the following method.
     bool ShapeText(gfxContext    *aContext,
                    const uint8_t *aText,
                    uint32_t       aOffset, // dest offset in gfxShapedText
                    uint32_t       aLength,
                    int32_t        aScript,
                    gfxShapedText *aShapedText, // where to store the result