Bug 1353000 - Respect the round-to-pixels flags when caching shaped-word data. r=jrmuizel
authorJonathan Kew <jkew@mozilla.com>
Wed, 12 Apr 2017 14:55:13 +0100
changeset 355612 fb34b24b4cd63f732bcb001dbda047dd62044f04
parent 355611 795219dcd057dccf452e19a9d095268fc7ef8443
child 355613 7fd87238aa41ab662f6fa2c069510da449ffcef0
push id89710
push userjkew@mozilla.com
push dateFri, 28 Apr 2017 19:07:37 +0000
treeherdermozilla-inbound@7fd87238aa41 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1353000
milestone55.0a1
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
Bug 1353000 - Respect the round-to-pixels flags when caching shaped-word data. r=jrmuizel
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFont.h
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -2582,17 +2582,17 @@ gfxFont::GetShapedWord(DrawTarget *aDraw
         NS_WARNING("flushing shaped-word cache");
         ClearCachedWords();
     }
 
     // if there's a cached entry for this word, just return it
     CacheHashKey key(aText, aLength, aHash,
                      aRunScript,
                      aAppUnitsPerDevUnit,
-                     aFlags);
+                     aFlags, aRounding);
 
     CacheHashEntry *entry = mWordCache->PutEntry(key);
     if (!entry) {
         NS_WARNING("failed to create word cache entry - expect missing text");
         return nullptr;
     }
     gfxShapedWord* sw = entry->mShapedWord.get();
 
@@ -2616,17 +2616,17 @@ gfxFont::GetShapedWord(DrawTarget *aDraw
                           aLength);
 #ifndef RELEASE_OR_BETA
     if (aTextPerf) {
         aTextPerf->current.wordCacheMiss++;
     }
 #endif
 
     sw = gfxShapedWord::Create(aText, aLength, aRunScript, aAppUnitsPerDevUnit,
-                               aFlags);
+                               aFlags, aRounding);
     entry->mShapedWord.reset(sw);
     if (!sw) {
         NS_WARNING("failed to create gfxShapedWord - expect missing text");
         return nullptr;
     }
 
     DebugOnly<bool> ok =
         ShapeText(aDrawTarget, aText, 0, aLength, aRunScript, aVertical,
@@ -2641,16 +2641,17 @@ bool
 gfxFont::CacheHashEntry::KeyEquals(const KeyTypePointer aKey) const
 {
     const gfxShapedWord* sw = mShapedWord.get();
     if (!sw) {
         return false;
     }
     if (sw->GetLength() != aKey->mLength ||
         sw->GetFlags() != aKey->mFlags ||
+        sw->GetRounding() != aKey->mRounding ||
         sw->GetAppUnitsPerDevUnit() != aKey->mAppUnitsPerDevUnit ||
         sw->GetScript() != aKey->mScript) {
         return false;
     }
     if (sw->TextIs8Bit()) {
         if (aKey->mTextIs8Bit) {
             return (0 == memcmp(sw->Text8Bit(), aKey->mText.mSingle,
                                 aKey->mLength * sizeof(uint8_t)));
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -1185,63 +1185,68 @@ public:
     // so caller must check for success.
     //
     // This does NOT perform shaping, so the returned word contains no
     // glyph data; the caller must call gfxFont::ShapeText() with appropriate
     // parameters to set up the glyphs.
     static gfxShapedWord* Create(const uint8_t *aText, uint32_t aLength,
                                  Script aRunScript,
                                  int32_t aAppUnitsPerDevUnit,
-                                 uint32_t aFlags) {
+                                 uint32_t aFlags,
+                                 gfxFontShaper::RoundingFlags aRounding) {
         NS_ASSERTION(aLength <= gfxPlatform::GetPlatform()->WordCacheCharLimit(),
                      "excessive length for gfxShapedWord!");
 
         // Compute size needed including the mCharacterGlyphs array
         // and a copy of the original text
         uint32_t size =
             offsetof(gfxShapedWord, mCharGlyphsStorage) +
             aLength * (sizeof(CompressedGlyph) + sizeof(uint8_t));
         void *storage = malloc(size);
         if (!storage) {
             return nullptr;
         }
 
         // Construct in the pre-allocated storage, using placement new
         return new (storage) gfxShapedWord(aText, aLength, aRunScript,
-                                           aAppUnitsPerDevUnit, aFlags);
+                                           aAppUnitsPerDevUnit, aFlags,
+                                           aRounding);
     }
 
     static gfxShapedWord* Create(const char16_t *aText, uint32_t aLength,
                                  Script aRunScript,
                                  int32_t aAppUnitsPerDevUnit,
-                                 uint32_t aFlags) {
+                                 uint32_t aFlags,
+                                 gfxFontShaper::RoundingFlags aRounding) {
         NS_ASSERTION(aLength <= gfxPlatform::GetPlatform()->WordCacheCharLimit(),
                      "excessive length for gfxShapedWord!");
 
         // In the 16-bit version of Create, if the TEXT_IS_8BIT flag is set,
         // then we convert the text to an 8-bit version and call the 8-bit
         // Create function instead.
         if (aFlags & gfxTextRunFactory::TEXT_IS_8BIT) {
             nsAutoCString narrowText;
             LossyAppendUTF16toASCII(nsDependentSubstring(aText, aLength),
                                     narrowText);
             return Create((const uint8_t*)(narrowText.BeginReading()),
-                          aLength, aRunScript, aAppUnitsPerDevUnit, aFlags);
+                          aLength, aRunScript, aAppUnitsPerDevUnit, aFlags,
+                          aRounding);
         }
 
         uint32_t size =
             offsetof(gfxShapedWord, mCharGlyphsStorage) +
             aLength * (sizeof(CompressedGlyph) + sizeof(char16_t));
         void *storage = malloc(size);
         if (!storage) {
             return nullptr;
         }
 
         return new (storage) gfxShapedWord(aText, aLength, aRunScript,
-                                           aAppUnitsPerDevUnit, aFlags);
+                                           aAppUnitsPerDevUnit, aFlags,
+                                           aRounding);
     }
 
     // Override operator delete to properly free the object that was
     // allocated via malloc.
     void operator delete(void* p) {
         free(p);
     }
 
@@ -1267,16 +1272,20 @@ public:
         return TextIs8Bit() ?
             char16_t(Text8Bit()[aOffset]) : TextUnicode()[aOffset];
     }
 
     Script GetScript() const {
         return mScript;
     }
 
+    gfxFontShaper::RoundingFlags GetRounding() const {
+        return mRounding;
+    }
+
     void ResetAge() {
         mAgeCounter = 0;
     }
     uint32_t IncrementAge() {
         return ++mAgeCounter;
     }
 
     // Helper used when hashing a word for the shaped-word caches
@@ -1287,42 +1296,48 @@ public:
 
 private:
     // so that gfxTextRun can share our DetailedGlyphStore class
     friend class gfxTextRun;
 
     // Construct storage for a ShapedWord, ready to receive glyph data
     gfxShapedWord(const uint8_t *aText, uint32_t aLength,
                   Script aRunScript,
-                  int32_t aAppUnitsPerDevUnit, uint32_t aFlags)
+                  int32_t aAppUnitsPerDevUnit, uint32_t aFlags,
+                  gfxFontShaper::RoundingFlags aRounding)
         : gfxShapedText(aLength, aFlags | gfxTextRunFactory::TEXT_IS_8BIT,
                         aAppUnitsPerDevUnit)
         , mScript(aRunScript)
+        , mRounding(aRounding)
         , mAgeCounter(0)
     {
         memset(mCharGlyphsStorage, 0, aLength * sizeof(CompressedGlyph));
         uint8_t *text = reinterpret_cast<uint8_t*>(&mCharGlyphsStorage[aLength]);
         memcpy(text, aText, aLength * sizeof(uint8_t));
     }
 
     gfxShapedWord(const char16_t *aText, uint32_t aLength,
                   Script aRunScript,
-                  int32_t aAppUnitsPerDevUnit, uint32_t aFlags)
+                  int32_t aAppUnitsPerDevUnit, uint32_t aFlags,
+                  gfxFontShaper::RoundingFlags aRounding)
         : gfxShapedText(aLength, aFlags, aAppUnitsPerDevUnit)
         , mScript(aRunScript)
+        , mRounding(aRounding)
         , mAgeCounter(0)
     {
         memset(mCharGlyphsStorage, 0, aLength * sizeof(CompressedGlyph));
         char16_t *text = reinterpret_cast<char16_t*>(&mCharGlyphsStorage[aLength]);
         memcpy(text, aText, aLength * sizeof(char16_t));
         SetupClusterBoundaries(0, aText, aLength);
     }
 
     Script           mScript;
 
+    gfxFontShaper::RoundingFlags mRounding;
+
     uint32_t         mAgeCounter;
 
     // The mCharGlyphsStorage array is actually a variable-size member;
     // when the ShapedWord is created, its size will be increased as necessary
     // to allow the proper number of glyphs to be stored.
     // The original text, in either 8-bit or 16-bit form, will be stored
     // immediately following the CompressedGlyphs.
     CompressedGlyph  mCharGlyphsStorage[1];
@@ -2027,45 +2042,54 @@ protected:
             const char16_t *mDouble;
         }                mText;
         uint32_t         mLength;
         uint32_t         mFlags;
         Script           mScript;
         int32_t          mAppUnitsPerDevUnit;
         PLDHashNumber    mHashKey;
         bool             mTextIs8Bit;
+        RoundingFlags    mRounding;
 
         CacheHashKey(const uint8_t *aText, uint32_t aLength,
                      uint32_t aStringHash,
                      Script aScriptCode, int32_t aAppUnitsPerDevUnit,
-                     uint32_t aFlags)
+                     uint32_t aFlags, RoundingFlags aRounding)
             : mLength(aLength),
               mFlags(aFlags),
               mScript(aScriptCode),
               mAppUnitsPerDevUnit(aAppUnitsPerDevUnit),
-              mHashKey(aStringHash + static_cast<int32_t>(aScriptCode) +
-                  aAppUnitsPerDevUnit * 0x100 + aFlags * 0x10000),
-              mTextIs8Bit(true)
+              mHashKey(aStringHash
+                           + static_cast<int32_t>(aScriptCode)
+                           + aAppUnitsPerDevUnit * 0x100
+                           + aFlags * 0x10000
+                           + int(aRounding)),
+              mTextIs8Bit(true),
+              mRounding(aRounding)
         {
             NS_ASSERTION(aFlags & gfxTextRunFactory::TEXT_IS_8BIT,
                          "8-bit flag should have been set");
             mText.mSingle = aText;
         }
 
         CacheHashKey(const char16_t *aText, uint32_t aLength,
                      uint32_t aStringHash,
                      Script aScriptCode, int32_t aAppUnitsPerDevUnit,
-                     uint32_t aFlags)
+                     uint32_t aFlags, RoundingFlags aRounding)
             : mLength(aLength),
               mFlags(aFlags),
               mScript(aScriptCode),
               mAppUnitsPerDevUnit(aAppUnitsPerDevUnit),
-              mHashKey(aStringHash + static_cast<int32_t>(aScriptCode) +
-                  aAppUnitsPerDevUnit * 0x100 + aFlags * 0x10000),
-              mTextIs8Bit(false)
+              mHashKey(aStringHash
+                           + static_cast<int32_t>(aScriptCode)
+                           + aAppUnitsPerDevUnit * 0x100
+                           + aFlags * 0x10000
+                           + int(aRounding)),
+              mTextIs8Bit(false),
+              mRounding(aRounding)
         {
             // We can NOT assert that TEXT_IS_8BIT is false in aFlags here,
             // because this might be an 8bit-only word from a 16-bit textrun,
             // in which case the text we're passed is still in 16-bit form,
             // and we'll have to use an 8-to-16bit comparison in KeyEquals.
             mText.mDouble = aText;
         }
     };