Bug 1362167 - Split gfxShapedText.mFlags into two 16-bit flags fields, and arrange storage more compactly to reduce size of gfxShapedWord and gfxTextRun objects. r=jrmuizel
authorJonathan Kew <jkew@mozilla.com>
Thu, 04 May 2017 22:25:16 +0100
changeset 404824 0cbf75382a9abb55be44e22cbc351e9214f4431f
parent 404823 af1ace67caaa08555f37799bf0b837b0a7a497a9
child 404825 ed010b85ea12896dd62015ae399e22d700f998e9
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1362167
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 1362167 - Split gfxShapedText.mFlags into two 16-bit flags fields, and arrange storage more compactly to reduce size of gfxShapedWord and gfxTextRun objects. r=jrmuizel
dom/canvas/CanvasRenderingContext2D.cpp
gfx/src/nsFontMetrics.cpp
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFont.h
gfx/thebes/gfxTextRun.cpp
gfx/thebes/gfxTextRun.h
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/generic/MathMLTextRunFactory.cpp
layout/generic/moz.build
layout/generic/nsTextFrame.cpp
layout/generic/nsTextFrameUtils.cpp
layout/generic/nsTextFrameUtils.h
layout/generic/nsTextRunTransformations.cpp
layout/generic/nsTextRunTransformations.h
layout/mathml/nsMathMLChar.cpp
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -4261,27 +4261,27 @@ struct MOZ_STACK_CLASS CanvasBidiProcess
   }
 
   typedef CanvasRenderingContext2D::ContextState ContextState;
 
   virtual void SetText(const char16_t* aText, int32_t aLength, nsBidiDirection aDirection)
   {
     mFontgrp->UpdateUserFonts(); // ensure user font generation is current
     // adjust flags for current direction run
-    uint32_t flags = mTextRunFlags;
+    uint16_t flags = mTextRunFlags;
     if (aDirection == NSBIDI_RTL) {
       flags |= gfxTextRunFactory::TEXT_IS_RTL;
     } else {
       flags &= ~gfxTextRunFactory::TEXT_IS_RTL;
     }
     mTextRun = mFontgrp->MakeTextRun(aText,
                                      aLength,
                                      mDrawTarget,
                                      mAppUnitsPerDevPixel,
-                                     flags,
+                                     flags, 0,
                                      mMissingFonts);
   }
 
   virtual nscoord GetWidth()
   {
     gfxTextRun::Metrics textRunMetrics = mTextRun->MeasureText(
         mDoMeasureBoundingBox ? gfxFont::TIGHT_INK_EXTENTS
                               : gfxFont::LOOSE_INK_EXTENTS, mDrawTarget);
@@ -4484,17 +4484,17 @@ struct MOZ_STACK_CLASS CanvasBidiProcess
 
   // operation (fill or stroke)
   CanvasRenderingContext2D::TextDrawOperation mOp;
 
   // union of bounding boxes of all runs, needed for shadows
   gfxRect mBoundingBox;
 
   // flags to use when creating textrun, based on CSS style
-  uint32_t mTextRunFlags;
+  uint16_t mTextRunFlags;
 
   // true iff the bounding box should be measured
   bool mDoMeasureBoundingBox;
 };
 
 nsresult
 CanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
                                             float aX,
--- a/gfx/src/nsFontMetrics.cpp
+++ b/gfx/src/nsFontMetrics.cpp
@@ -33,37 +33,37 @@ public:
 
     AutoTextRun(nsFontMetrics* aMetrics, DrawTarget* aDrawTarget,
                 const char* aString, int32_t aLength)
     {
         mTextRun = aMetrics->GetThebesFontGroup()->MakeTextRun(
             reinterpret_cast<const uint8_t*>(aString), aLength,
             aDrawTarget,
             aMetrics->AppUnitsPerDevPixel(),
-            ComputeFlags(aMetrics),
+            ComputeFlags(aMetrics), 0,
             nullptr);
     }
 
     AutoTextRun(nsFontMetrics* aMetrics, DrawTarget* aDrawTarget,
                 const char16_t* aString, int32_t aLength)
     {
         mTextRun = aMetrics->GetThebesFontGroup()->MakeTextRun(
             aString, aLength,
             aDrawTarget,
             aMetrics->AppUnitsPerDevPixel(),
-            ComputeFlags(aMetrics),
+            ComputeFlags(aMetrics), 0,
             nullptr);
     }
 
     gfxTextRun *get() { return mTextRun.get(); }
     gfxTextRun *operator->() { return mTextRun.get(); }
 
 private:
-    static uint32_t ComputeFlags(nsFontMetrics* aMetrics) {
-        uint32_t flags = 0;
+    static uint16_t ComputeFlags(nsFontMetrics* aMetrics) {
+        uint16_t flags = 0;
         if (aMetrics->GetTextRunRTL()) {
             flags |= gfxTextRunFactory::TEXT_IS_RTL;
         }
         if (aMetrics->GetVertical()) {
             switch (aMetrics->GetTextOrientation()) {
             case NS_STYLE_TEXT_ORIENTATION_MIXED:
                 flags |= gfxTextRunFactory::TEXT_ORIENT_VERTICAL_MIXED;
                 break;
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -2566,17 +2566,17 @@ template<typename T>
 gfxShapedWord*
 gfxFont::GetShapedWord(DrawTarget *aDrawTarget,
                        const T    *aText,
                        uint32_t    aLength,
                        uint32_t    aHash,
                        Script      aRunScript,
                        bool        aVertical,
                        int32_t     aAppUnitsPerDevUnit,
-                       uint32_t    aFlags,
+                       uint16_t    aFlags,
                        RoundingFlags aRounding,
                        gfxTextPerfMetrics *aTextPerf GFX_MAYBE_UNUSED)
 {
     // if the cache is getting too big, flush it and start over
     uint32_t wordCacheMaxEntries =
         gfxPlatform::GetPlatform()->WordCacheMaxEntries();
     if (mWordCache->Count() > wordCacheMaxEntries) {
         NS_WARNING("flushing shaped-word cache");
@@ -2961,17 +2961,17 @@ gfxFont::SplitAndInitTextRun(DrawTarget 
                                              aRunScript, aVertical,
                                              rounding, aTextRun);
         }
     }
 
     InitWordCache();
 
     // the only flags we care about for ShapedWord construction/caching
-    uint32_t flags = aTextRun->GetFlags();
+    uint16_t flags = aTextRun->GetFlags();
     flags &= (gfxTextRunFactory::TEXT_IS_RTL |
               gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES |
               gfxTextRunFactory::TEXT_USE_MATH_SCRIPT |
               gfxTextRunFactory::TEXT_ORIENT_MASK);
     if (sizeof(T) == sizeof(uint8_t)) {
         flags |= gfxTextRunFactory::TEXT_IS_8BIT;
     }
 
@@ -3013,17 +3013,17 @@ gfxFont::SplitAndInitTextRun(DrawTarget 
                                                     aRunScript,
                                                     aVertical,
                                                     rounding,
                                                     aTextRun);
             if (!ok) {
                 return false;
             }
         } else if (length > 0) {
-            uint32_t wordFlags = flags;
+            uint16_t wordFlags = flags;
             // in the 8-bit version of this method, TEXT_IS_8BIT was
             // already set as part of |flags|, so no need for a per-word
             // adjustment here
             if (sizeof(T) == sizeof(char16_t)) {
                 if (wordIs8Bit) {
                     wordFlags |= gfxTextRunFactory::TEXT_IS_8BIT;
                 }
             }
@@ -3252,27 +3252,27 @@ gfxFont::InitFakeSmallCapsRun(DrawTarget
                     // into the destination textrun but have to handle the
                     // mismatch of character positions.
                     gfxTextRunFactory::Parameters params = {
                         aDrawTarget, nullptr, nullptr, nullptr, 0,
                         aTextRun->GetAppUnitsPerDevUnit()
                     };
                     RefPtr<gfxTextRun> tempRun(
                         gfxTextRun::Create(&params, convertedString.Length(),
-                                           aTextRun->GetFontGroup(), 0));
+                                           aTextRun->GetFontGroup(), 0, 0));
                     tempRun->AddGlyphRun(f, aMatchType, 0, true, aOrientation);
                     if (!f->SplitAndInitTextRun(aDrawTarget, tempRun.get(),
                                                 convertedString.BeginReading(),
                                                 0, convertedString.Length(),
                                                 aScript, vertical)) {
                         ok = false;
                     } else {
                         RefPtr<gfxTextRun> mergedRun(
                             gfxTextRun::Create(&params, runLength,
-                                               aTextRun->GetFontGroup(), 0));
+                                               aTextRun->GetFontGroup(), 0, 0));
                         MergeCharactersInTextRun(mergedRun.get(), tempRun.get(),
                                                  charsToMergeArray.Elements(),
                                                  deletedCharsArray.Elements());
                         gfxTextRun::Range runRange(0, runLength);
                         aTextRun->CopyGlyphDataFrom(mergedRun.get(), runRange,
                                                     aOffset + runStart);
                     }
                 } else {
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -456,85 +456,86 @@ public:
 
 class gfxTextRunFactory {
     // Used by stylo
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxTextRunFactory)
 
 public:
     typedef mozilla::gfx::DrawTarget DrawTarget;
 
-    // Flags in the mask 0xFFFF0000 are reserved for textrun clients
-    // Flags in the mask 0x0000F000 are reserved for per-platform fonts
-    // Flags in the mask 0x00000FFF are set by the textrun creator.
+    // Flags that live in the gfxShapedText::mFlags field.
+    // (Note that gfxTextRun has an additional mFlags2 field for use
+    // by textrun clients like nsTextFrame.)
     enum {
-        CACHE_TEXT_FLAGS    = 0xF0000000,
-        USER_TEXT_FLAGS     = 0x0FFF0000,
-        TEXTRUN_TEXT_FLAGS  = 0x0000FFFF,
-        SETTABLE_FLAGS      = CACHE_TEXT_FLAGS | USER_TEXT_FLAGS,
-
         /**
          * When set, the text string pointer used to create the text run
          * is guaranteed to be available during the lifetime of the text run.
          */
         TEXT_IS_PERSISTENT           = 0x0001,
         /**
-         * When set, the text is known to be all-ASCII (< 128).
-         */
-        TEXT_IS_ASCII                = 0x0002,
-        /**
          * When set, the text is RTL.
          */
-        TEXT_IS_RTL                  = 0x0004,
+        TEXT_IS_RTL                  = 0x0002,
         /**
          * When set, spacing is enabled and the textrun needs to call GetSpacing
          * on the spacing provider.
          */
-        TEXT_ENABLE_SPACING          = 0x0008,
+        TEXT_ENABLE_SPACING          = 0x0004,
+        /**
+         * When set, the text has no characters above 255 and it is stored
+         * in the textrun in 8-bit format.
+         */
+        TEXT_IS_8BIT                 = 0x0008,
         /**
          * When set, GetHyphenationBreaks may return true for some character
          * positions, otherwise it will always return false for all characters.
          */
         TEXT_ENABLE_HYPHEN_BREAKS    = 0x0010,
         /**
-         * When set, the text has no characters above 255 and it is stored
-         * in the textrun in 8-bit format.
-         */
-        TEXT_IS_8BIT                 = 0x0020,
-        /**
          * When set, the RunMetrics::mBoundingBox field will be initialized
          * properly based on glyph extents, in particular, glyph extents that
          * overflow the standard font-box (the box defined by the ascent, descent
          * and advance width of the glyph). When not set, it may just be the
          * standard font-box even if glyphs overflow.
          */
-        TEXT_NEED_BOUNDING_BOX       = 0x0040,
+        TEXT_NEED_BOUNDING_BOX       = 0x0020,
         /**
          * When set, optional ligatures are disabled. Ligatures that are
          * required for legible text should still be enabled.
          */
-        TEXT_DISABLE_OPTIONAL_LIGATURES = 0x0080,
+        TEXT_DISABLE_OPTIONAL_LIGATURES = 0x0040,
         /**
          * When set, the textrun should favour speed of construction over
          * quality. This may involve disabling ligatures and/or kerning or
          * other effects.
          */
-        TEXT_OPTIMIZE_SPEED          = 0x0100,
-        /**
-         * For internal use by the memory reporter when accounting for
-         * storage used by textruns.
-         * Because the reporter may visit each textrun multiple times while
-         * walking the frame trees and textrun cache, it needs to mark
-         * textruns that have been seen so as to avoid multiple-accounting.
-         */
-        TEXT_RUN_SIZE_ACCOUNTED      = 0x0200,
+        TEXT_OPTIMIZE_SPEED          = 0x0080,
         /**
          * When set, the textrun should discard control characters instead of
          * turning them into hexboxes.
          */
-        TEXT_HIDE_CONTROL_CHARACTERS = 0x0400,
+        TEXT_HIDE_CONTROL_CHARACTERS = 0x0100,
+
+        /**
+         * nsTextFrameThebes sets these, but they're defined here rather than
+         * in nsTextFrameUtils.h because ShapedWord creation/caching also needs
+         * to check the _INCOMING flag
+         */
+        TEXT_TRAILING_ARABICCHAR     = 0x0200,
+        /**
+         * When set, the previous character for this textrun was an Arabic
+         * character.  This is used for the context detection necessary for
+         * bidi.numeral implementation.
+         */
+        TEXT_INCOMING_ARABICCHAR     = 0x0400,
+
+        /**
+         * Set if the textrun should use the OpenType 'math' script.
+         */
+        TEXT_USE_MATH_SCRIPT         = 0x0800,
 
         /**
          * Field for orientation of the textrun and glyphs within it.
          * Possible values of the TEXT_ORIENT_MASK field:
          *   TEXT_ORIENT_HORIZONTAL
          *   TEXT_ORIENT_VERTICAL_UPRIGHT
          *   TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT
          *   TEXT_ORIENT_VERTICAL_SIDEWAYS_LEFT
@@ -544,38 +545,22 @@ public:
          *
          * The MIXED value indicates vertical textRuns for which the CSS
          * text-orientation property is 'mixed', but is never used for
          * individual glyphRuns; it will be resolved to either UPRIGHT
          * or SIDEWAYS_RIGHT according to the UTR50 properties of the
          * characters, and separate glyphRuns created for the resulting
          * glyph orientations.
          */
-        TEXT_ORIENT_MASK                    = 0xF000,
+        TEXT_ORIENT_MASK                    = 0x7000,
         TEXT_ORIENT_HORIZONTAL              = 0x0000,
         TEXT_ORIENT_VERTICAL_UPRIGHT        = 0x1000,
         TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT = 0x2000,
+        TEXT_ORIENT_VERTICAL_MIXED          = 0x3000,
         TEXT_ORIENT_VERTICAL_SIDEWAYS_LEFT  = 0x4000,
-        TEXT_ORIENT_VERTICAL_MIXED          = 0x8000,
-
-        /**
-         * nsTextFrameThebes sets these, but they're defined here rather than
-         * in nsTextFrameUtils.h because ShapedWord creation/caching also needs
-         * to check the _INCOMING flag
-         */
-        TEXT_TRAILING_ARABICCHAR = 0x20000000,
-        /**
-         * When set, the previous character for this textrun was an Arabic
-         * character.  This is used for the context detection necessary for
-         * bidi.numeral implementation.
-         */
-        TEXT_INCOMING_ARABICCHAR = 0x40000000,
-
-        // Set if the textrun should use the OpenType 'math' script.
-        TEXT_USE_MATH_SCRIPT = 0x80000000,
     };
 
     /**
      * This record contains all the parameters needed to initialize a textrun.
      */
     struct Parameters {
         // Shape text params suggesting where the textrun will be rendered
         DrawTarget   *mDrawTarget;
@@ -686,17 +671,17 @@ MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gf
  * their entirety rather than using cached words, because there may be layout
  * features that depend on the inter-word spaces).
  */
 class gfxShapedText
 {
 public:
     typedef mozilla::unicode::Script Script;
 
-    gfxShapedText(uint32_t aLength, uint32_t aFlags,
+    gfxShapedText(uint32_t aLength, uint16_t aFlags,
                   int32_t aAppUnitsPerDevUnit)
         : mLength(aLength)
         , mFlags(aFlags)
         , mAppUnitsPerDevUnit(aAppUnitsPerDevUnit)
     { }
 
     virtual ~gfxShapedText() { }
 
@@ -963,17 +948,17 @@ public:
                                 const char16_t *aString,
                                 uint32_t         aLength);
     // In 8-bit text, there won't actually be any clusters, but we still need
     // the space-marking functionality.
     void SetupClusterBoundaries(uint32_t       aOffset,
                                 const uint8_t *aString,
                                 uint32_t       aLength);
 
-    uint32_t GetFlags() const {
+    uint16_t GetFlags() const {
         return mFlags;
     }
 
     bool IsVertical() const {
         return (GetFlags() & gfxTextRunFactory::TEXT_ORIENT_MASK) !=
                 gfxTextRunFactory::TEXT_ORIENT_HORIZONTAL;
     }
 
@@ -1156,19 +1141,19 @@ protected:
     };
 
     mozilla::UniquePtr<DetailedGlyphStore>   mDetailedGlyphs;
 
     // Number of char16_t characters and CompressedGlyph glyph records
     uint32_t                        mLength;
 
     // Shaping flags (direction, ligature-suppression)
-    uint32_t                        mFlags;
+    uint16_t                        mFlags;
 
-    int32_t                         mAppUnitsPerDevUnit;
+    uint16_t                        mAppUnitsPerDevUnit;
 };
 
 /*
  * gfxShapedWord: an individual (space-delimited) run of text shaped with a
  * particular font, without regard to external context.
  *
  * The glyph data is copied into gfxTextRuns as needed from the cache of
  * ShapedWords associated with each gfxFont instance.
@@ -1185,17 +1170,17 @@ 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,
+                                 uint16_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) +
@@ -1209,17 +1194,17 @@ public:
         return new (storage) gfxShapedWord(aText, aLength, aRunScript,
                                            aAppUnitsPerDevUnit, aFlags,
                                            aRounding);
     }
 
     static gfxShapedWord* Create(const char16_t *aText, uint32_t aLength,
                                  Script aRunScript,
                                  int32_t aAppUnitsPerDevUnit,
-                                 uint32_t aFlags,
+                                 uint16_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) {
@@ -1296,32 +1281,32 @@ 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, uint16_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, uint16_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]);
@@ -1782,17 +1767,17 @@ public:
     template<typename T>
     gfxShapedWord* GetShapedWord(DrawTarget *aDrawTarget,
                                  const T *aText,
                                  uint32_t aLength,
                                  uint32_t aHash,
                                  Script aRunScript,
                                  bool aVertical,
                                  int32_t aAppUnitsPerDevUnit,
-                                 uint32_t aFlags,
+                                 uint16_t aFlags,
                                  RoundingFlags aRounding,
                                  gfxTextPerfMetrics *aTextPerf);
 
     // Ensure the ShapedWord cache is initialized. This MUST be called before
     // any attempt to use GetShapedWord().
     void InitWordCache() {
         if (!mWordCache) {
             mWordCache = mozilla::MakeUnique<nsTHashtable<CacheHashEntry>>();
@@ -2037,27 +2022,27 @@ protected:
     RefPtr<gfxFontEntry> mFontEntry;
 
     struct CacheHashKey {
         union {
             const uint8_t   *mSingle;
             const char16_t *mDouble;
         }                mText;
         uint32_t         mLength;
-        uint32_t         mFlags;
+        uint16_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, RoundingFlags aRounding)
+                     uint16_t aFlags, RoundingFlags aRounding)
             : mLength(aLength),
               mFlags(aFlags),
               mScript(aScriptCode),
               mAppUnitsPerDevUnit(aAppUnitsPerDevUnit),
               mHashKey(aStringHash
                            + static_cast<int32_t>(aScriptCode)
                            + aAppUnitsPerDevUnit * 0x100
                            + aFlags * 0x10000
@@ -2068,17 +2053,17 @@ protected:
             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, RoundingFlags aRounding)
+                     uint16_t aFlags, RoundingFlags aRounding)
             : mLength(aLength),
               mFlags(aFlags),
               mScript(aScriptCode),
               mAppUnitsPerDevUnit(aAppUnitsPerDevUnit),
               mHashKey(aStringHash
                            + static_cast<int32_t>(aScriptCode)
                            + aAppUnitsPerDevUnit * 0x100
                            + aFlags * 0x10000
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -140,34 +140,38 @@ gfxTextRun::AllocateStorageForTextRun(si
     memset(reinterpret_cast<char*>(storage) + aSize, 0,
            aLength * sizeof(CompressedGlyph));
 
     return storage;
 }
 
 already_AddRefed<gfxTextRun>
 gfxTextRun::Create(const gfxTextRunFactory::Parameters *aParams,
-                   uint32_t aLength, gfxFontGroup *aFontGroup, uint32_t aFlags)
+                   uint32_t aLength, gfxFontGroup *aFontGroup,
+                   uint16_t aFlags, uint16_t aFlags2)
 {
     void *storage = AllocateStorageForTextRun(sizeof(gfxTextRun), aLength);
     if (!storage) {
         return nullptr;
     }
 
     RefPtr<gfxTextRun> result = new (storage) gfxTextRun(aParams, aLength,
-                                                         aFontGroup, aFlags);
+                                                         aFontGroup,
+                                                         aFlags, aFlags2);
     return result.forget();
 }
 
 gfxTextRun::gfxTextRun(const gfxTextRunFactory::Parameters *aParams,
-                       uint32_t aLength, gfxFontGroup *aFontGroup, uint32_t aFlags)
+                       uint32_t aLength, gfxFontGroup *aFontGroup,
+                       uint16_t aFlags, uint16_t aFlags2)
     : gfxShapedText(aLength, aFlags, aParams->mAppUnitsPerDevUnit)
     , mSingleGlyphRun()
     , mUserData(aParams->mUserData)
     , mFontGroup(aFontGroup)
+    , mFlags2(aFlags2)
     , mReleasedFontGroup(false)
     , mHasGlyphRunArray(false)
     , mShapingState(eShapingState_Normal)
 {
     NS_ASSERTION(mAppUnitsPerDevUnit > 0, "Invalid app unit scale");
     NS_ADDREF(mFontGroup);
 
 #ifndef RELEASE_OR_BETA
@@ -192,17 +196,18 @@ gfxTextRun::gfxTextRun(const gfxTextRunF
 
 gfxTextRun::~gfxTextRun()
 {
 #ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
     AccountStorageForTextRun(this, -1);
 #endif
 #ifdef DEBUG
     // Make it easy to detect a dead text run
-    mFlags = 0xFFFFFFFF;
+    mFlags = 0xFFFF;
+    mFlags2 = 0xFFFF;
 #endif
 
     if (mHasGlyphRunArray) {
         mGlyphRunArray.~nsTArray<GlyphRun>();
     } else {
         mSingleGlyphRun.mFont = nullptr;
     }
 
@@ -1596,18 +1601,17 @@ gfxTextRun::SetSpaceGlyph(gfxFont* aFont
                           uint32_t aCharIndex, uint16_t aOrientation)
 {
     if (SetSpaceGlyphIfSimple(aFont, aCharIndex, ' ', aOrientation)) {
         return;
     }
 
     aFont->InitWordCache();
     static const uint8_t space = ' ';
-    uint32_t flags = gfxTextRunFactory::TEXT_IS_8BIT |
-                     gfxTextRunFactory::TEXT_IS_ASCII |
+    uint16_t flags = gfxTextRunFactory::TEXT_IS_8BIT |
                      gfxTextRunFactory::TEXT_IS_PERSISTENT |
                      aOrientation;
     bool vertical =
         (GetFlags() & gfxTextRunFactory::TEXT_ORIENT_VERTICAL_UPRIGHT) != 0;
     gfxFontShaper::RoundingFlags roundingFlags =
         aFont->GetRoundOffsetsToPixels(aDrawTarget);
     gfxShapedWord* sw = aFont->GetShapedWord(aDrawTarget,
                                              &space, 1,
@@ -2163,29 +2167,31 @@ gfxFontGroup::IsInvalidChar(char16_t ch)
         return true;
     }
     return (((ch & 0xFF00) == 0x2000 /* Unicode control character */ &&
              (ch == 0x200B/*ZWSP*/ || ch == 0x2028/*LSEP*/ || ch == 0x2029/*PSEP*/)) ||
             IsBidiControl(ch));
 }
 
 already_AddRefed<gfxTextRun>
-gfxFontGroup::MakeEmptyTextRun(const Parameters *aParams, uint32_t aFlags)
+gfxFontGroup::MakeEmptyTextRun(const Parameters *aParams,
+                               uint16_t aFlags, uint16_t aFlags2)
 {
-    aFlags |= TEXT_IS_8BIT | TEXT_IS_ASCII | TEXT_IS_PERSISTENT;
-    return gfxTextRun::Create(aParams, 0, this, aFlags);
+    aFlags |= TEXT_IS_8BIT | TEXT_IS_PERSISTENT;
+    return gfxTextRun::Create(aParams, 0, this, aFlags, aFlags2);
 }
 
 already_AddRefed<gfxTextRun>
-gfxFontGroup::MakeSpaceTextRun(const Parameters *aParams, uint32_t aFlags)
+gfxFontGroup::MakeSpaceTextRun(const Parameters *aParams,
+                               uint16_t aFlags, uint16_t aFlags2)
 {
-    aFlags |= TEXT_IS_8BIT | TEXT_IS_ASCII | TEXT_IS_PERSISTENT;
+    aFlags |= TEXT_IS_8BIT | TEXT_IS_PERSISTENT;
 
     RefPtr<gfxTextRun> textRun =
-        gfxTextRun::Create(aParams, 1, this, aFlags);
+        gfxTextRun::Create(aParams, 1, this, aFlags, aFlags2);
     if (!textRun) {
         return nullptr;
     }
 
     uint16_t orientation = aFlags & TEXT_ORIENT_MASK;
     if (orientation == TEXT_ORIENT_VERTICAL_MIXED) {
         orientation = TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT;
     }
@@ -2221,20 +2227,21 @@ gfxFontGroup::MakeSpaceTextRun(const Par
     // Note that the gfxGlyphExtents glyph bounds storage for the font will
     // always contain an entry for the font's space glyph, so we don't have
     // to call FetchGlyphExtents here.
     return textRun.forget();
 }
 
 already_AddRefed<gfxTextRun>
 gfxFontGroup::MakeBlankTextRun(uint32_t aLength,
-                               const Parameters *aParams, uint32_t aFlags)
+                               const Parameters *aParams,
+                               uint16_t aFlags, uint16_t aFlags2)
 {
     RefPtr<gfxTextRun> textRun =
-        gfxTextRun::Create(aParams, aLength, this, aFlags);
+        gfxTextRun::Create(aParams, aLength, this, aFlags, aFlags2);
     if (!textRun) {
         return nullptr;
     }
 
     uint16_t orientation = aFlags & TEXT_ORIENT_MASK;
     if (orientation == TEXT_ORIENT_VERTICAL_MIXED) {
         orientation = TEXT_ORIENT_VERTICAL_UPRIGHT;
     }
@@ -2249,22 +2256,22 @@ gfxFontGroup::MakeHyphenTextRun(DrawTarg
 {
     // only use U+2010 if it is supported by the first font in the group;
     // it's better to use ASCII '-' from the primary font than to fall back to
     // U+2010 from some other, possibly poorly-matching face
     static const char16_t hyphen = 0x2010;
     gfxFont *font = GetFirstValidFont(uint32_t(hyphen));
     if (font->HasCharacter(hyphen)) {
         return MakeTextRun(&hyphen, 1, aDrawTarget, aAppUnitsPerDevUnit,
-                           gfxFontGroup::TEXT_IS_PERSISTENT, nullptr);
+                           gfxFontGroup::TEXT_IS_PERSISTENT, 0, nullptr);
     }
 
     static const uint8_t dash = '-';
     return MakeTextRun(&dash, 1, aDrawTarget, aAppUnitsPerDevUnit,
-                       gfxFontGroup::TEXT_IS_PERSISTENT, nullptr);
+                       gfxFontGroup::TEXT_IS_PERSISTENT, 0, nullptr);
 }
 
 gfxFloat
 gfxFontGroup::GetHyphenWidth(const gfxTextRun::PropertyProvider* aProvider)
 {
     if (mHyphenWidth < 0) {
         RefPtr<DrawTarget> dt(aProvider->GetDrawTarget());
         if (dt) {
@@ -2274,67 +2281,69 @@ gfxFontGroup::GetHyphenWidth(const gfxTe
             mHyphenWidth = hyphRun.get() ? hyphRun->GetAdvanceWidth() : 0;
         }
     }
     return mHyphenWidth;
 }
 
 already_AddRefed<gfxTextRun>
 gfxFontGroup::MakeTextRun(const uint8_t *aString, uint32_t aLength,
-                          const Parameters *aParams, uint32_t aFlags,
+                          const Parameters *aParams,
+                          uint16_t aFlags, uint16_t aFlags2,
                           gfxMissingFontRecorder *aMFR)
 {
     if (aLength == 0) {
-        return MakeEmptyTextRun(aParams, aFlags);
+        return MakeEmptyTextRun(aParams, aFlags, aFlags2);
     }
     if (aLength == 1 && aString[0] == ' ') {
-        return MakeSpaceTextRun(aParams, aFlags);
+        return MakeSpaceTextRun(aParams, aFlags, aFlags2);
     }
 
     aFlags |= TEXT_IS_8BIT;
 
     if (MOZ_UNLIKELY(GetStyle()->size == 0) ||
         MOZ_UNLIKELY(GetStyle()->sizeAdjust == 0.0f)) {
         // Short-circuit for size-0 fonts, as Windows and ATSUI can't handle
         // them, and always create at least size 1 fonts, i.e. they still
         // render something for size 0 fonts.
-        return MakeBlankTextRun(aLength, aParams, aFlags);
+        return MakeBlankTextRun(aLength, aParams, aFlags, aFlags2);
     }
 
     RefPtr<gfxTextRun> textRun = gfxTextRun::Create(aParams, aLength, this,
-                                                    aFlags);
+                                                    aFlags, aFlags2);
     if (!textRun) {
         return nullptr;
     }
 
     InitTextRun(aParams->mDrawTarget, textRun.get(), aString, aLength, aMFR);
 
     textRun->FetchGlyphExtents(aParams->mDrawTarget);
 
     return textRun.forget();
 }
 
 already_AddRefed<gfxTextRun>
 gfxFontGroup::MakeTextRun(const char16_t *aString, uint32_t aLength,
-                          const Parameters *aParams, uint32_t aFlags,
+                          const Parameters *aParams,
+                          uint16_t aFlags, uint16_t aFlags2,
                           gfxMissingFontRecorder *aMFR)
 {
     if (aLength == 0) {
-        return MakeEmptyTextRun(aParams, aFlags);
+        return MakeEmptyTextRun(aParams, aFlags, aFlags2);
     }
     if (aLength == 1 && aString[0] == ' ') {
-        return MakeSpaceTextRun(aParams, aFlags);
+        return MakeSpaceTextRun(aParams, aFlags, aFlags2);
     }
     if (MOZ_UNLIKELY(GetStyle()->size == 0) ||
         MOZ_UNLIKELY(GetStyle()->sizeAdjust == 0.0f)) {
-        return MakeBlankTextRun(aLength, aParams, aFlags);
+        return MakeBlankTextRun(aLength, aParams, aFlags, aFlags2);
     }
 
     RefPtr<gfxTextRun> textRun = gfxTextRun::Create(aParams, aLength, this,
-                                                    aFlags);
+                                                    aFlags, aFlags2);
     if (!textRun) {
         return nullptr;
     }
 
     InitTextRun(aParams->mDrawTarget, textRun.get(), aString, aLength, aMFR);
 
     textRun->FetchGlyphExtents(aParams->mDrawTarget);
 
@@ -2742,17 +2751,18 @@ gfxFontGroup::InitScriptRun(DrawTarget* 
     }
 
     if (aMFR && missingChars) {
         aMFR->RecordScript(aRunScript);
     }
 }
 
 gfxTextRun *
-gfxFontGroup::GetEllipsisTextRun(int32_t aAppUnitsPerDevPixel, uint32_t aFlags,
+gfxFontGroup::GetEllipsisTextRun(int32_t aAppUnitsPerDevPixel,
+                                 uint16_t aFlags,
                                  LazyReferenceDrawTargetGetter& aRefDrawTargetGetter)
 {
     MOZ_ASSERT(!(aFlags & ~TEXT_ORIENT_MASK),
                "flags here should only be used to specify orientation");
     if (mCachedEllipsisTextRun &&
         (mCachedEllipsisTextRun->GetFlags() & TEXT_ORIENT_MASK) == aFlags &&
         mCachedEllipsisTextRun->GetAppUnitsPerDevUnit() == aAppUnitsPerDevPixel) {
         return mCachedEllipsisTextRun.get();
@@ -2768,17 +2778,17 @@ gfxFontGroup::GetEllipsisTextRun(int32_t
                             ArrayLength(kASCIIPeriodsChar) - 1);
 
     RefPtr<DrawTarget> refDT = aRefDrawTargetGetter.GetRefDrawTarget();
     Parameters params = {
         refDT, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevPixel
     };
     mCachedEllipsisTextRun =
         MakeTextRun(ellipsis.get(), ellipsis.Length(), &params,
-                    aFlags | TEXT_IS_PERSISTENT, nullptr);
+                    aFlags | TEXT_IS_PERSISTENT, 0, nullptr);
     if (!mCachedEllipsisTextRun) {
         return nullptr;
     }
     // don't let the presence of a cached ellipsis textrun prolong the
     // fontgroup's life
     mCachedEllipsisTextRun->ReleaseFontGroup();
     return mCachedEllipsisTextRun.get();
 }
--- a/gfx/thebes/gfxTextRun.h
+++ b/gfx/thebes/gfxTextRun.h
@@ -15,16 +15,17 @@
 #include "nsTArray.h"
 #include "gfxSkipChars.h"
 #include "gfxPlatform.h"
 #include "mozilla/MemoryReporting.h"
 #include "DrawMode.h"
 #include "harfbuzz/hb.h"
 #include "nsUnicodeScriptCodes.h"
 #include "nsColor.h"
+#include "nsTextFrameUtils.h"
 
 #ifdef DEBUG
 #include <stdio.h>
 #endif
 
 class gfxContext;
 class gfxFontGroup;
 class gfxUserFontEntry;
@@ -426,36 +427,32 @@ public:
                                  bool aCanWordWrap,
                                  gfxBreakPriority *aBreakPriority);
 
     // Utility getters
 
     void *GetUserData() const { return mUserData; }
     void SetUserData(void *aUserData) { mUserData = aUserData; }
 
-    void SetFlagBits(uint32_t aFlags) {
-      NS_ASSERTION(!(aFlags & ~gfxTextRunFactory::SETTABLE_FLAGS),
-                   "Only user flags should be mutable");
-      mFlags |= aFlags;
+    void SetFlagBits(uint16_t aFlags) {
+      mFlags2 |= aFlags;
     }
-    void ClearFlagBits(uint32_t aFlags) {
-      NS_ASSERTION(!(aFlags & ~gfxTextRunFactory::SETTABLE_FLAGS),
-                   "Only user flags should be mutable");
-      mFlags &= ~aFlags;
+    void ClearFlagBits(uint16_t aFlags) {
+      mFlags2 &= ~aFlags;
     }
     const gfxSkipChars& GetSkipChars() const { return mSkipChars; }
     gfxFontGroup *GetFontGroup() const { return mFontGroup; }
 
 
     // Call this, don't call "new gfxTextRun" directly. This does custom
     // allocation and initialization
     static already_AddRefed<gfxTextRun>
     Create(const gfxTextRunFactory::Parameters *aParams,
            uint32_t aLength, gfxFontGroup *aFontGroup,
-           uint32_t aFlags);
+           uint16_t aFlags, uint16_t aFlags2);
 
     // The text is divided into GlyphRuns as necessary. (In the vast majority
     // of cases, a gfxTextRun contains just a single GlyphRun.)
     struct GlyphRun {
         RefPtr<gfxFont> mFont; // never null in a valid GlyphRun
         uint32_t        mCharacterOffset; // into original UTF16 string
         uint16_t        mOrientation; // gfxTextRunFactory::TEXT_ORIENT_* value
         uint8_t         mMatchType;
@@ -637,33 +634,37 @@ public:
 
     // return storage used by this run, for memory reporter;
     // nsTransformedTextRun needs to override this as it holds additional data
     virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
       MOZ_MUST_OVERRIDE;
     virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
       MOZ_MUST_OVERRIDE;
 
+    uint16_t GetFlags2() const {
+        return mFlags2;
+    }
+
     // Get the size, if it hasn't already been gotten, marking as it goes.
     size_t MaybeSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)  {
-        if (mFlags & gfxTextRunFactory::TEXT_RUN_SIZE_ACCOUNTED) {
+        if (mFlags2 & nsTextFrameUtils::TEXT_RUN_SIZE_ACCOUNTED) {
             return 0;
         }
-        mFlags |= gfxTextRunFactory::TEXT_RUN_SIZE_ACCOUNTED;
+        mFlags2 |= nsTextFrameUtils::TEXT_RUN_SIZE_ACCOUNTED;
         return SizeOfIncludingThis(aMallocSizeOf);
     }
     void ResetSizeOfAccountingFlags() {
-        mFlags &= ~gfxTextRunFactory::TEXT_RUN_SIZE_ACCOUNTED;
+        mFlags2 &= ~nsTextFrameUtils::TEXT_RUN_SIZE_ACCOUNTED;
     }
 
     // shaping state - for some font features, fallback is required that
     // affects the entire run. for example, fallback for one script/font
     // portion of a textrun requires fallback to be applied to the entire run
 
-    enum ShapingState {
+    enum ShapingState : uint8_t {
         eShapingState_Normal,                 // default state
         eShapingState_ShapingWithFeature,     // have shaped with feature
         eShapingState_ShapingWithFallback,    // have shaped with fallback
         eShapingState_Aborted,                // abort initial iteration
         eShapingState_ForceFallbackFeature    // redo with fallback forced on
     };
 
     ShapingState GetShapingState() const { return mShapingState; }
@@ -696,17 +697,18 @@ public:
 protected:
     /**
      * Create a textrun, and set its mCharacterGlyphs to point immediately
      * after the base object; this is ONLY used in conjunction with placement
      * new, after allocating a block large enough for the glyph records to
      * follow the base textrun object.
      */
     gfxTextRun(const gfxTextRunFactory::Parameters *aParams,
-               uint32_t aLength, gfxFontGroup *aFontGroup, uint32_t aFlags);
+               uint32_t aLength, gfxFontGroup *aFontGroup,
+               uint16_t aFlags, uint16_t aFlags2);
 
     /**
      * Helper for the Create() factory method to allocate the required
      * glyph storage for a textrun object with the basic size aSize,
      * plus room for aLength glyph records.
      */
     static void* AllocateStorageForTextRun(size_t aSize, uint32_t aLength);
 
@@ -800,16 +802,18 @@ private:
         mHasGlyphRunArray = false;
     }
 
     void             *mUserData;
     gfxFontGroup     *mFontGroup; // addrefed on creation, but our reference
                                   // may be released by ReleaseFontGroup()
     gfxSkipChars      mSkipChars;
 
+    uint16_t          mFlags2; // additional flags (see also gfxShapedText::mFlags)
+
     bool              mSkipDrawing; // true if the font group we used had a user font
                                     // download that's in progress, so we should hide text
                                     // until the download completes (or timeout fires)
     bool              mReleasedFontGroup; // we already called NS_RELEASE on
                                           // mFontGroup, so don't do it again
     bool              mHasGlyphRunArray; // whether we're using an array or
                                          // just storing a single glyphrun
 
@@ -855,45 +859,47 @@ public:
     /**
      * Make a textrun for a given string.
      * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
      * textrun will copy it.
      * This calls FetchGlyphExtents on the textrun.
      */
     virtual already_AddRefed<gfxTextRun>
     MakeTextRun(const char16_t *aString, uint32_t aLength,
-                const Parameters *aParams, uint32_t aFlags,
+                const Parameters *aParams,
+                uint16_t aFlags, uint16_t aFlags2,
                 gfxMissingFontRecorder *aMFR);
     /**
      * Make a textrun for a given string.
      * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
      * textrun will copy it.
      * This calls FetchGlyphExtents on the textrun.
      */
     virtual already_AddRefed<gfxTextRun>
     MakeTextRun(const uint8_t *aString, uint32_t aLength,
-                const Parameters *aParams, uint32_t aFlags,
+                const Parameters *aParams,
+                uint16_t aFlags, uint16_t aFlags2,
                 gfxMissingFontRecorder *aMFR);
 
     /**
      * Textrun creation helper for clients that don't want to pass
      * a full Parameters record.
      */
     template<typename T>
     already_AddRefed<gfxTextRun>
     MakeTextRun(const T* aString, uint32_t aLength,
                 DrawTarget* aRefDrawTarget,
                 int32_t aAppUnitsPerDevUnit,
-                uint32_t aFlags,
+                uint16_t aFlags, uint16_t aFlags2,
                 gfxMissingFontRecorder *aMFR)
     {
         gfxTextRunFactory::Parameters params = {
             aRefDrawTarget, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevUnit
         };
-        return MakeTextRun(aString, aLength, &params, aFlags, aMFR);
+        return MakeTextRun(aString, aLength, &params, aFlags, aFlags2, aMFR);
     }
 
     // Get the (possibly-cached) width of the hyphen character.
     gfxFloat GetHyphenWidth(const gfxTextRun::PropertyProvider* aProvider);
 
     /**
      * Make a text run representing a single hyphen character.
      * This will use U+2010 HYPHEN if available in the first font,
@@ -964,17 +970,18 @@ public:
     public:
       virtual already_AddRefed<DrawTarget> GetRefDrawTarget() = 0;
     };
     // The gfxFontGroup keeps ownership of this textrun.
     // It is only guaranteed to exist until the next call to GetEllipsisTextRun
     // (which might use a different appUnitsPerDev value or flags) for the font
     // group, or until UpdateUserFonts is called, or the fontgroup is destroyed.
     // Get it/use it/forget it :) - don't keep a reference that might go stale.
-    gfxTextRun* GetEllipsisTextRun(int32_t aAppUnitsPerDevPixel, uint32_t aFlags,
+    gfxTextRun* GetEllipsisTextRun(int32_t aAppUnitsPerDevPixel,
+                                   uint16_t aFlags,
                                    LazyReferenceDrawTargetGetter& aRefDrawTargetGetter);
 
 protected:
     // search through pref fonts for a character, return nullptr if no matching pref font
     already_AddRefed<gfxFont> WhichPrefFontSupportsChar(uint32_t aCh);
 
     already_AddRefed<gfxFont>
         WhichSystemFontSupportsChar(uint32_t aCh, uint32_t aNextCh,
@@ -1156,24 +1163,26 @@ protected:
                                           // download to complete (or fallback
                                           // timer to fire)
 
     /**
      * Textrun creation short-cuts for special cases where we don't need to
      * call a font shaper to generate glyphs.
      */
     already_AddRefed<gfxTextRun>
-    MakeEmptyTextRun(const Parameters *aParams, uint32_t aFlags);
+    MakeEmptyTextRun(const Parameters *aParams,
+                     uint16_t aFlags, uint16_t aFlags2);
 
     already_AddRefed<gfxTextRun>
-    MakeSpaceTextRun(const Parameters *aParams, uint32_t aFlags);
+    MakeSpaceTextRun(const Parameters *aParams,
+                     uint16_t aFlags, uint16_t aFlags2);
 
     already_AddRefed<gfxTextRun>
     MakeBlankTextRun(uint32_t aLength, const Parameters *aParams,
-                     uint32_t aFlags);
+                     uint16_t aFlags, uint16_t aFlags2);
 
     // Initialize the list of fonts
     void BuildFontList();
 
     // Get the font at index i within the fontlist.
     // Will initiate userfont load if not already loaded.
     // May return null if userfont not loaded or if font invalid
     virtual gfxFont* GetFontAt(int32_t i, uint32_t aCh = 0x20);
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -6992,23 +6992,23 @@ nsLayoutUtils::GetReferenceFrame(nsIFram
     nsIFrame* parent = GetCrossDocParentFrame(f);
     if (!parent) {
       return f;
     }
     f = parent;
   }
 }
 
-/* static */ uint32_t
+/* static */ uint16_t
 nsLayoutUtils::GetTextRunFlagsForStyle(nsStyleContext* aStyleContext,
                                        const nsStyleFont* aStyleFont,
                                        const nsStyleText* aStyleText,
                                        nscoord aLetterSpacing)
 {
-  uint32_t result = 0;
+  uint16_t result = 0;
   if (aLetterSpacing != 0 ||
       aStyleText->mTextJustify == StyleTextJustify::InterCharacter) {
     result |= gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES;
   }
   if (aStyleText->mControlCharacterVisibility == NS_STYLE_CONTROL_CHARACTER_VISIBILITY_HIDDEN) {
     result |= gfxTextRunFactory::TEXT_HIDE_CONTROL_CHARACTERS;
   }
   switch (aStyleContext->StyleText()->mTextRendering) {
@@ -7022,17 +7022,17 @@ nsLayoutUtils::GetTextRunFlagsForStyle(n
     }
     break;
   default:
     break;
   }
   return result | GetTextRunOrientFlagsForStyle(aStyleContext);
 }
 
-/* static */ uint32_t
+/* static */ uint16_t
 nsLayoutUtils::GetTextRunOrientFlagsForStyle(nsStyleContext* aStyleContext)
 {
   uint8_t writingMode = aStyleContext->StyleVisibility()->mWritingMode;
   switch (writingMode) {
   case NS_STYLE_WRITING_MODE_HORIZONTAL_TB:
     return gfxTextRunFactory::TEXT_ORIENT_HORIZONTAL;
 
   case NS_STYLE_WRITING_MODE_VERTICAL_LR:
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -1992,25 +1992,25 @@ public:
 
   /**
    * Get textrun construction flags determined by a given style; in particular
    * some combination of:
    * -- TEXT_DISABLE_OPTIONAL_LIGATURES if letter-spacing is in use
    * -- TEXT_OPTIMIZE_SPEED if the text-rendering CSS property and font size
    * and prefs indicate we should be optimizing for speed over quality
    */
-  static uint32_t GetTextRunFlagsForStyle(nsStyleContext* aStyleContext,
+  static uint16_t GetTextRunFlagsForStyle(nsStyleContext* aStyleContext,
                                           const nsStyleFont* aStyleFont,
                                           const nsStyleText* aStyleText,
                                           nscoord aLetterSpacing);
 
   /**
    * Get orientation flags for textrun construction.
    */
-  static uint32_t GetTextRunOrientFlagsForStyle(nsStyleContext* aStyleContext);
+  static uint16_t GetTextRunOrientFlagsForStyle(nsStyleContext* aStyleContext);
 
   /**
    * Takes two rectangles whose origins must be the same, and computes
    * the difference between their union and their intersection as two
    * rectangles. (This difference is a superset of the difference
    * between the two rectangles.)
    */
   static void GetRectDifferenceStrips(const nsRect& aR1, const nsRect& aR2,
--- a/layout/generic/MathMLTextRunFactory.cpp
+++ b/layout/generic/MathMLTextRunFactory.cpp
@@ -537,17 +537,17 @@ MathMLTextRunFactory::RebuildTextRun(nsT
   nsAutoString convertedString;
   AutoTArray<bool,50> charsToMergeArray;
   AutoTArray<bool,50> deletedCharsArray;
   AutoTArray<RefPtr<nsTransformedCharStyle>,50> styleArray;
   AutoTArray<uint8_t,50> canBreakBeforeArray;
   bool mergeNeeded = false;
 
   bool singleCharMI =
-    aTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SINGLE_CHAR_MI;
+    aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_SINGLE_CHAR_MI;
 
   uint32_t length = aTextRun->GetLength();
   const char16_t* str = aTextRun->mString.BeginReading();
   const nsTArray<RefPtr<nsTransformedCharStyle>>& styles = aTextRun->mStyles;
   nsFont font;
   if (length) {
     font = styles[0]->mFont;
 
@@ -705,17 +705,17 @@ MathMLTextRunFactory::RebuildTextRun(nsT
     while (extraChars-- > 0) {
       mergeNeeded = true;
       charsToMergeArray.AppendElement(true);
       styleArray.AppendElement(styles[i]);
       canBreakBeforeArray.AppendElement(false);
     }
   }
 
-  uint32_t flags;
+  uint16_t flags;
   gfxTextRunFactory::Parameters innerParams =
       GetParametersForInner(aTextRun, &flags, aRefDrawTarget);
 
   RefPtr<nsTransformedTextRun> transformedChild;
   RefPtr<gfxTextRun> cachedChild;
   gfxTextRun* child;
 
   if (mathVar == NS_MATHML_MATHVARIANT_BOLD && doMathvariantStyling) {
@@ -755,22 +755,22 @@ MathMLTextRunFactory::RebuildTextRun(nsT
     // If we can't get a new font group, fall back to the old one.  Rendering
     // will be incorrect, but not significantly so.
     newFontGroup = fontGroup;
   }
 
   if (mInnerTransformingTextRunFactory) {
     transformedChild = mInnerTransformingTextRunFactory->MakeTextRun(
         convertedString.BeginReading(), convertedString.Length(),
-        &innerParams, newFontGroup, flags, Move(styleArray), false);
+        &innerParams, newFontGroup, flags, 0, Move(styleArray), false);
     child = transformedChild.get();
   } else {
     cachedChild = newFontGroup->MakeTextRun(
         convertedString.BeginReading(), convertedString.Length(),
-        &innerParams, flags, aMFR);
+        &innerParams, flags, 0, aMFR);
     child = cachedChild.get();
   }
   if (!child)
     return;
 
   typedef gfxTextRun::Range Range;
 
   // Copy potential linebreaks into child so they're preserved
--- a/layout/generic/moz.build
+++ b/layout/generic/moz.build
@@ -96,16 +96,17 @@ EXPORTS += [
     'nsQueryFrame.h',
     'nsRubyBaseContainerFrame.h',
     'nsRubyBaseFrame.h',
     'nsRubyFrame.h',
     'nsRubyTextContainerFrame.h',
     'nsRubyTextFrame.h',
     'nsSplittableFrame.h',
     'nsSubDocumentFrame.h',
+    'nsTextFrameUtils.h',
     'nsTextRunTransformations.h',
     'RubyUtils.h',
     'ScrollbarActivity.h',
     'ScrollSnap.h',
     'Visibility.h',
 ]
 
 EXPORTS.mozilla += [
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -254,17 +254,17 @@ static const nsFrameState TEXT_WHITESPAC
  * the DOM string.
  *
  * XXX currently we don't handle hyphenated breaks between text frames where the
  * hyphen occurs at the end of the first text frame, e.g.
  *   <b>Kit&shy;</b>ty
  */
 
 /**
- * This is our user data for the textrun, when textRun->GetFlags() has
+ * This is our user data for the textrun, when textRun->GetFlags2() has
  * TEXT_IS_SIMPLE_FLOW set, and also TEXT_MIGHT_HAVE_GLYPH_CHANGES.
  *
  * This allows having an array of observers if there are fonts whose glyphs
  * might change, but also avoid allocation in the simple case that there aren't.
  */
 struct SimpleTextRunUserData {
   nsTArray<UniquePtr<GlyphObserver>> mGlyphObservers;
   nsTextFrame* mFrame;
@@ -305,17 +305,17 @@ struct TextRunUserData {
 #ifdef DEBUG
   TextRunMappedFlow* mMappedFlows;
 #endif
   uint32_t           mMappedFlowCount;
   uint32_t           mLastFlowIndex;
 };
 
 /**
- * This is our user data for the textrun, when textRun->GetFlags() does not
+ * This is our user data for the textrun, when textRun->GetFlags2() does not
  * have TEXT_IS_SIMPLE_FLOW set and has the TEXT_MIGHT HAVE_GLYPH_CHANGES flag.
  */
 struct ComplexTextRunUserData : public TextRunUserData {
   nsTArray<UniquePtr<GlyphObserver>> mGlyphObservers;
 };
 
 /**
  * This helper object computes colors used for painting, and also IME
@@ -505,41 +505,41 @@ DestroyComplexUserData(ComplexTextRunUse
     free(aUserData);
   }
 }
 
 static void
 DestroyTextRunUserData(gfxTextRun* aTextRun)
 {
   MOZ_ASSERT(aTextRun->GetUserData());
-  if (aTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
-    if (aTextRun->GetFlags() & nsTextFrameUtils::TEXT_MIGHT_HAVE_GLYPH_CHANGES) {
+  if (aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
+    if (aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_MIGHT_HAVE_GLYPH_CHANGES) {
       delete static_cast<SimpleTextRunUserData*>(aTextRun->GetUserData());
     }
   } else {
-    if (aTextRun->GetFlags() & nsTextFrameUtils::TEXT_MIGHT_HAVE_GLYPH_CHANGES) {
+    if (aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_MIGHT_HAVE_GLYPH_CHANGES) {
       DestroyComplexUserData(
         static_cast<ComplexTextRunUserData*>(aTextRun->GetUserData()));
     } else {
       DestroyUserData(
         static_cast<TextRunUserData*>(aTextRun->GetUserData()));
     }
   }
   aTextRun->ClearFlagBits(nsTextFrameUtils::TEXT_MIGHT_HAVE_GLYPH_CHANGES);
   aTextRun->SetUserData(nullptr);
 }
 
 static TextRunMappedFlow*
 GetMappedFlows(const gfxTextRun* aTextRun)
 {
   MOZ_ASSERT(aTextRun->GetUserData(), "UserData must exist.");
-  MOZ_ASSERT(!(aTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW),
+  MOZ_ASSERT(!(aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW),
             "The method should not be called for simple flows.");
   TextRunMappedFlow* flows;
-  if (aTextRun->GetFlags() & nsTextFrameUtils::TEXT_MIGHT_HAVE_GLYPH_CHANGES) {
+  if (aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_MIGHT_HAVE_GLYPH_CHANGES) {
     flows = reinterpret_cast<TextRunMappedFlow*>(
       static_cast<ComplexTextRunUserData*>(aTextRun->GetUserData()) + 1);
   } else {
     flows = reinterpret_cast<TextRunMappedFlow*>(
       static_cast<TextRunUserData*>(aTextRun->GetUserData()) + 1);
   }
   MOZ_ASSERT(static_cast<TextRunUserData*>(aTextRun->GetUserData())->
              mMappedFlows == flows,
@@ -549,19 +549,19 @@ GetMappedFlows(const gfxTextRun* aTextRu
 
 /**
  * These are utility functions just for helping with the complexity related with
  * the text runs user data.
  */
 static nsTextFrame*
 GetFrameForSimpleFlow(const gfxTextRun* aTextRun)
 {
-  MOZ_ASSERT(aTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW,
+  MOZ_ASSERT(aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW,
              "Not so simple flow?");
-  if (aTextRun->GetFlags() & nsTextFrameUtils::TEXT_MIGHT_HAVE_GLYPH_CHANGES) {
+  if (aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_MIGHT_HAVE_GLYPH_CHANGES) {
     return static_cast<SimpleTextRunUserData*>(aTextRun->GetUserData())->mFrame;
   }
 
   return static_cast<nsTextFrame*>(aTextRun->GetUserData());
 }
 
 /**
  * Remove |aTextRun| from the frame continuation chain starting at
@@ -615,17 +615,17 @@ ClearAllTextRunReferences(nsTextFrame* a
  */
 static void
 UnhookTextRunFromFrames(gfxTextRun* aTextRun, nsTextFrame* aStartContinuation)
 {
   if (!aTextRun->GetUserData()) {
     return;
   }
 
-  if (aTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
+  if (aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
     nsTextFrame* userDataFrame = GetFrameForSimpleFlow(aTextRun);
     nsFrameState whichTextRunState =
       userDataFrame->GetTextRun(nsTextFrame::eInflated) == aTextRun
         ? TEXT_IN_TEXTRUN_USER_DATA
         : TEXT_IN_UNINFLATED_TEXTRUN_USER_DATA;
     DebugOnly<bool> found =
       ClearAllTextRunReferences(userDataFrame, aTextRun,
                                 aStartContinuation, whichTextRunState);
@@ -697,17 +697,17 @@ InvalidateFrameDueToGlyphsChanged(nsIFra
       shell->FrameNeedsReflow(f, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
     }
   }
 }
 
 void
 GlyphObserver::NotifyGlyphsChanged()
 {
-  if (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
+  if (mTextRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
     InvalidateFrameDueToGlyphsChanged(GetFrameForSimpleFlow(mTextRun));
     return;
   }
 
   auto data = static_cast<TextRunUserData*>(mTextRun->GetUserData());
   TextRunMappedFlow* userMappedFlows = GetMappedFlows(mTextRun);
   for (uint32_t i = 0; i < data->mMappedFlowCount; ++i) {
     InvalidateFrameDueToGlyphsChanged(userMappedFlows[i].mStartFrame);
@@ -892,21 +892,21 @@ IsAllWhitespace(const nsTextFragment* aF
     return false;
   }
   return true;
 }
 
 static void
 ClearObserversFromTextRun(gfxTextRun* aTextRun)
 {
-  if (!(aTextRun->GetFlags() & nsTextFrameUtils::TEXT_MIGHT_HAVE_GLYPH_CHANGES)) {
+  if (!(aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_MIGHT_HAVE_GLYPH_CHANGES)) {
     return;
   }
 
-  if (aTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
+  if (aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
     static_cast<SimpleTextRunUserData*>(aTextRun->GetUserData())
       ->mGlyphObservers.Clear();
   } else {
     static_cast<ComplexTextRunUserData*>(aTextRun->GetUserData())
       ->mGlyphObservers.Clear();
   }
 }
 
@@ -935,29 +935,29 @@ CreateObserversForAnimatedGlyphs(gfxText
     // present too, and resetting the pointer to the frame. In practice, I
     // don't think worth doing that work here, given the flag's only purpose is
     // to distinguish what kind of user data is there.
     return;
   }
 
   nsTArray<UniquePtr<GlyphObserver>>* observers;
 
-  if (aTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
+  if (aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
     // Swap the frame pointer for a just-allocated SimpleTextRunUserData if
     // appropriate.
-    if (!(aTextRun->GetFlags() & nsTextFrameUtils::TEXT_MIGHT_HAVE_GLYPH_CHANGES)) {
+    if (!(aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_MIGHT_HAVE_GLYPH_CHANGES)) {
       auto frame = static_cast<nsTextFrame*>(aTextRun->GetUserData());
       aTextRun->SetUserData(new SimpleTextRunUserData(frame));
     }
 
     auto data =
       static_cast<SimpleTextRunUserData*>(aTextRun->GetUserData());
     observers = &data->mGlyphObservers;
   } else {
-    if (!(aTextRun->GetFlags() & nsTextFrameUtils::TEXT_MIGHT_HAVE_GLYPH_CHANGES)) {
+    if (!(aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_MIGHT_HAVE_GLYPH_CHANGES)) {
       auto oldData = static_cast<TextRunUserData*>(aTextRun->GetUserData());
       TextRunMappedFlow* oldMappedFlows = GetMappedFlows(aTextRun);
       ComplexTextRunUserData* data =
         CreateComplexUserData(oldData->mMappedFlowCount);
       TextRunMappedFlow* dataMappedFlows =
         reinterpret_cast<TextRunMappedFlow*>(data + 1);
       data->mLastFlowIndex = oldData->mLastFlowIndex;
       for (uint32_t i = 0; i < oldData->mMappedFlowCount; ++i) {
@@ -1104,30 +1104,30 @@ public:
       if (mTextRun->SetPotentialLineBreaks(range, aBreakBefore)) {
         // Be conservative and assume that some breaks have been set
         mTextRun->ClearFlagBits(nsTextFrameUtils::TEXT_NO_BREAKS);
       }
     }
 
     virtual void SetCapitalization(uint32_t aOffset, uint32_t aLength,
                                    bool* aCapitalize) override {
-      MOZ_ASSERT(mTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_TRANSFORMED,
+      MOZ_ASSERT(mTextRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_TRANSFORMED,
                  "Text run should be transformed!");
-      if (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_TRANSFORMED) {
+      if (mTextRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_TRANSFORMED) {
         nsTransformedTextRun* transformedTextRun =
           static_cast<nsTransformedTextRun*>(mTextRun.get());
         transformedTextRun->SetCapitalization(aOffset + mOffsetIntoTextRun, aLength,
                                               aCapitalize);
       }
     }
 
     void Finish(gfxMissingFontRecorder* aMFR) {
-      MOZ_ASSERT(!(mTextRun->GetFlags() & nsTextFrameUtils::TEXT_UNUSED_FLAG),
+      MOZ_ASSERT(!(mTextRun->GetFlags2() & nsTextFrameUtils::TEXT_UNUSED_FLAG),
                    "Flag set that should never be set! (memory safety error?)");
-      if (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_TRANSFORMED) {
+      if (mTextRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_TRANSFORMED) {
         nsTransformedTextRun* transformedTextRun =
           static_cast<nsTransformedTextRun*>(mTextRun.get());
         transformedTextRun->FinishSettingProperties(mDrawTarget, aMFR);
       }
       // The way nsTransformedTextRun is implemented, its glyph runs aren't
       // available until after nsTransformedTextRun::FinishSettingProperties()
       // is called. So that's why we defer checking for animated glyphs to here.
       CreateObserversForAnimatedGlyphs(mTextRun);
@@ -1567,17 +1567,17 @@ ExpandBuffer(char16_t* aDest, uint8_t* a
     --aCount;
   }
   return aDest;
 }
 
 bool
 BuildTextRunsScanner::IsTextRunValidForMappedFlows(const gfxTextRun* aTextRun)
 {
-  if (aTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
+  if (aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
     return mMappedFlows.Length() == 1 &&
       mMappedFlows[0].mStartFrame == GetFrameForSimpleFlow(aTextRun) &&
       mMappedFlows[0].mEndFrame == nullptr;
   }
 
   auto userData = static_cast<TextRunUserData*>(aTextRun->GetUserData());
   TextRunMappedFlow* userMappedFlows = GetMappedFlows(aTextRun);
   if (userData->mMappedFlowCount != mMappedFlows.Length())
@@ -1595,32 +1595,32 @@ BuildTextRunsScanner::IsTextRunValidForM
  * This gets called when we need to make a text run for the current list of
  * frames.
  */
 void BuildTextRunsScanner::FlushFrames(bool aFlushLineBreaks, bool aSuppressTrailingBreak)
 {
   RefPtr<gfxTextRun> textRun;
   if (!mMappedFlows.IsEmpty()) {
     if (!mSkipIncompleteTextRuns && mCurrentFramesAllSameTextRun &&
-        ((mCurrentFramesAllSameTextRun->GetFlags() & nsTextFrameUtils::TEXT_INCOMING_WHITESPACE) != 0) ==
+        ((mCurrentFramesAllSameTextRun->GetFlags2() & nsTextFrameUtils::TEXT_INCOMING_WHITESPACE) != 0) ==
         ((mCurrentRunContextInfo & nsTextFrameUtils::INCOMING_WHITESPACE) != 0) &&
         ((mCurrentFramesAllSameTextRun->GetFlags() & gfxTextRunFactory::TEXT_INCOMING_ARABICCHAR) != 0) ==
         ((mCurrentRunContextInfo & nsTextFrameUtils::INCOMING_ARABICCHAR) != 0) &&
         IsTextRunValidForMappedFlows(mCurrentFramesAllSameTextRun)) {
       // Optimization: We do not need to (re)build the textrun.
       textRun = mCurrentFramesAllSameTextRun;
 
       // Feed this run's text into the linebreaker to provide context.
       if (!SetupLineBreakerContext(textRun)) {
         return;
       }
 
       // Update mNextRunContextInfo appropriately
       mNextRunContextInfo = nsTextFrameUtils::INCOMING_NONE;
-      if (textRun->GetFlags() & nsTextFrameUtils::TEXT_TRAILING_WHITESPACE) {
+      if (textRun->GetFlags2() & nsTextFrameUtils::TEXT_TRAILING_WHITESPACE) {
         mNextRunContextInfo |= nsTextFrameUtils::INCOMING_WHITESPACE;
       }
       if (textRun->GetFlags() & gfxTextRunFactory::TEXT_TRAILING_ARABICCHAR) {
         mNextRunContextInfo |= nsTextFrameUtils::INCOMING_ARABICCHAR;
       }
     } else {
       AutoTArray<uint8_t,BIG_TEXT_NODE_SIZE> buffer;
       uint32_t bufferSize = mMaxTextLength*(mDoubleByteText ? 2 : 1);
@@ -1754,17 +1754,17 @@ WordSpacing(nsIFrame* aFrame, const gfxT
     nscoord pctBasis = coord.HasPercent() ? GetSpaceWidthAppUnits(aTextRun) : 0;
     return nsRuleNode::ComputeCoordPercentCalc(coord, pctBasis);
   }
   return 0;
 }
 
 // Returns gfxTextRunFactory::TEXT_ENABLE_SPACING if non-standard
 // letter-spacing or word-spacing is present.
-static uint32_t
+static uint16_t
 GetSpacingFlags(nsIFrame* aFrame, const nsStyleText* aStyleText = nullptr)
 {
   if (nsSVGUtils::IsInSVGTextSubtree(aFrame)) {
     return 0;
   }
 
   const nsStyleText* styleText = aFrame->StyleText();
   const nsStyleCoord& ls = styleText->mLetterSpacing;
@@ -2018,23 +2018,24 @@ BuildTextRunsScanner::BuildTextRunForFra
   gfxSkipChars skipChars;
 
   const void* textPtr = aTextBuffer;
   bool anyTextTransformStyle = false;
   bool anyMathMLStyling = false;
   bool anyTextEmphasis = false;
   uint8_t sstyScriptLevel = 0;
   uint32_t mathFlags = 0;
-  uint32_t textFlags = nsTextFrameUtils::TEXT_NO_BREAKS;
+  uint16_t flags = 0;
+  uint16_t flags2 = nsTextFrameUtils::TEXT_NO_BREAKS;
 
   if (mCurrentRunContextInfo & nsTextFrameUtils::INCOMING_WHITESPACE) {
-    textFlags |= nsTextFrameUtils::TEXT_INCOMING_WHITESPACE;
+    flags2 |= nsTextFrameUtils::TEXT_INCOMING_WHITESPACE;
   }
   if (mCurrentRunContextInfo & nsTextFrameUtils::INCOMING_ARABICCHAR) {
-    textFlags |= gfxTextRunFactory::TEXT_INCOMING_ARABICCHAR;
+    flags |= gfxTextRunFactory::TEXT_INCOMING_ARABICCHAR;
   }
 
   AutoTArray<int32_t,50> textBreakPoints;
   TextRunUserData dummyData;
   TextRunMappedFlow dummyMappedFlow;
   TextRunMappedFlow* userMappedFlows;
   TextRunUserData* userData;
   TextRunUserData* userDataToDestroy;
@@ -2076,31 +2077,31 @@ BuildTextRunsScanner::BuildTextRunForFra
         // text-combine-upright requires converting from full-width
         // characters to non-full-width correspendent in some cases.
         lastStyleContext->IsTextCombined()) {
       anyTextTransformStyle = true;
     }
     if (textStyle->HasTextEmphasis()) {
       anyTextEmphasis = true;
     }
-    textFlags |= GetSpacingFlags(f);
+    flags |= GetSpacingFlags(f);
     nsTextFrameUtils::CompressionMode compression =
       GetCSSWhitespaceToCompressionMode(f, textStyle);
     if ((enabledJustification || f->ShouldSuppressLineBreak()) &&
         !textStyle->WhiteSpaceIsSignificant() && !isSVG) {
-      textFlags |= gfxTextRunFactory::TEXT_ENABLE_SPACING;
+      flags |= gfxTextRunFactory::TEXT_ENABLE_SPACING;
     }
     fontStyle = f->StyleFont();
     nsIFrame* parent = mLineContainer->GetParent();
     if (NS_MATHML_MATHVARIANT_NONE != fontStyle->mMathVariant) {
       if (NS_MATHML_MATHVARIANT_NORMAL != fontStyle->mMathVariant) {
         anyMathMLStyling = true;
       }
     } else if (mLineContainer->GetStateBits() & NS_FRAME_IS_IN_SINGLE_CHAR_MI) {
-      textFlags |= nsTextFrameUtils::TEXT_IS_SINGLE_CHAR_MI;
+      flags2 |= nsTextFrameUtils::TEXT_IS_SINGLE_CHAR_MI;
       anyMathMLStyling = true;
       // Test for fontstyle attribute as StyleFont() may not be accurate
       // To be consistent in terms of ignoring CSS style changes, fontweight
       // gets checked too.
       if (parent) {
         nsIContent* content = parent->GetContent();
         if (content) {
           if (content->AttrValueIs(kNameSpaceID_None,
@@ -2117,17 +2118,17 @@ BuildTextRunsScanner::BuildTextRunForFra
           }
         }
       }
     }
     if (mLineContainer->HasAnyStateBits(TEXT_IS_IN_TOKEN_MATHML)) {
       // All MathML tokens except <mtext> use 'math' script.
       if (!(parent && parent->GetContent() &&
           parent->GetContent()->IsMathMLElement(nsGkAtoms::mtext_))) {
-        textFlags |= gfxTextRunFactory::TEXT_USE_MATH_SCRIPT;
+        flags |= gfxTextRunFactory::TEXT_USE_MATH_SCRIPT;
       }
       nsIMathMLFrame* mathFrame = do_QueryFrame(parent);
       if (mathFrame) {
         nsPresentationData presData;
         mathFrame->GetPresentationData(presData);
         if (NS_MATHML_IS_DTLS_SET(presData.flags)) {
           mathFlags |= MathMLTextRunFactory::MATH_FONT_FEATURE_DTLS;
           anyMathMLStyling = true;
@@ -2173,17 +2174,17 @@ BuildTextRunsScanner::BuildTextRunForFra
     newFlow->mContentLength = contentLength;
 
     while (nextBreakBeforeFrame && nextBreakBeforeFrame->GetContent() == content) {
       textBreakPoints.AppendElement(
           nextBreakBeforeFrame->GetContentOffset() + newFlow->mDOMOffsetToBeforeTransformOffset);
       nextBreakBeforeFrame = GetNextBreakBeforeFrame(&nextBreakIndex);
     }
 
-    uint32_t analysisFlags;
+    uint16_t analysisFlags;
     if (frag->Is2b()) {
       NS_ASSERTION(mDoubleByteText, "Wrong buffer char size!");
       char16_t* bufStart = static_cast<char16_t*>(aTextBuffer);
       char16_t* bufEnd = nsTextFrameUtils::TransformText(
           frag->Get2b() + contentStart, contentLength, bufStart,
           compression, &mNextRunContextInfo, &skipChars, &analysisFlags);
       aTextBuffer = bufEnd;
       currentTransformedTextOffset = bufEnd - static_cast<const char16_t*>(textPtr);
@@ -2208,22 +2209,22 @@ BuildTextRunsScanner::BuildTextRunForFra
         uint8_t* bufStart = static_cast<uint8_t*>(aTextBuffer);
         uint8_t* end = nsTextFrameUtils::TransformText(
             reinterpret_cast<const uint8_t*>(frag->Get1b()) + contentStart, contentLength,
             bufStart, compression, &mNextRunContextInfo, &skipChars, &analysisFlags);
         aTextBuffer = end;
         currentTransformedTextOffset = end - static_cast<const uint8_t*>(textPtr);
       }
     }
-    textFlags |= analysisFlags;
+    flags2 |= analysisFlags;
   }
 
   void* finalUserData;
   if (userData == &dummyData) {
-    textFlags |= nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW;
+    flags2 |= nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW;
     userData = nullptr;
     finalUserData = mMappedFlows[0].mStartFrame;
   } else {
     finalUserData = userData;
   }
 
   uint32_t transformedLength = currentTransformedTextOffset;
 
@@ -2237,40 +2238,40 @@ BuildTextRunsScanner::BuildTextRunForFra
   }
 
   gfxFontGroup* fontGroup = GetFontGroupForFrame(firstFrame, fontInflation);
   if (!fontGroup) {
     DestroyUserData(userDataToDestroy);
     return nullptr;
   }
 
-  if (textFlags & nsTextFrameUtils::TEXT_HAS_TAB) {
-    textFlags |= gfxTextRunFactory::TEXT_ENABLE_SPACING;
-  }
-  if (textFlags & nsTextFrameUtils::TEXT_HAS_SHY) {
-    textFlags |= gfxTextRunFactory::TEXT_ENABLE_HYPHEN_BREAKS;
+  if (flags2 & nsTextFrameUtils::TEXT_HAS_TAB) {
+    flags |= gfxTextRunFactory::TEXT_ENABLE_SPACING;
+  }
+  if (flags2 & nsTextFrameUtils::TEXT_HAS_SHY) {
+    flags |= gfxTextRunFactory::TEXT_ENABLE_HYPHEN_BREAKS;
   }
   if (mBidiEnabled && (IS_LEVEL_RTL(firstFrame->GetEmbeddingLevel()))) {
-    textFlags |= gfxTextRunFactory::TEXT_IS_RTL;
+    flags |= gfxTextRunFactory::TEXT_IS_RTL;
   }
   if (mNextRunContextInfo & nsTextFrameUtils::INCOMING_WHITESPACE) {
-    textFlags |= nsTextFrameUtils::TEXT_TRAILING_WHITESPACE;
+    flags2 |= nsTextFrameUtils::TEXT_TRAILING_WHITESPACE;
   }
   if (mNextRunContextInfo & nsTextFrameUtils::INCOMING_ARABICCHAR) {
-    textFlags |= gfxTextRunFactory::TEXT_TRAILING_ARABICCHAR;
+    flags |= gfxTextRunFactory::TEXT_TRAILING_ARABICCHAR;
   }
   // ContinueTextRunAcrossFrames guarantees that it doesn't matter which
   // frame's style is used, so we use a mixture of the first frame and
   // last frame's style
-  textFlags |= nsLayoutUtils::GetTextRunFlagsForStyle(lastStyleContext,
+  flags |= nsLayoutUtils::GetTextRunFlagsForStyle(lastStyleContext,
       fontStyle, textStyle, LetterSpacing(firstFrame, textStyle));
   // XXX this is a bit of a hack. For performance reasons, if we're favouring
   // performance over quality, don't try to get accurate glyph extents.
-  if (!(textFlags & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED)) {
-    textFlags |= gfxTextRunFactory::TEXT_NEED_BOUNDING_BOX;
+  if (!(flags & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED)) {
+    flags |= gfxTextRunFactory::TEXT_NEED_BOUNDING_BOX;
   }
 
   // Convert linebreak coordinates to transformed string offsets
   NS_ASSERTION(nextBreakIndex == mLineBreakBeforeFrames.Length(),
                "Didn't find all the frames to break-before...");
   gfxSkipCharsIterator iter(skipChars);
   AutoTArray<uint32_t,50> textBreakPointsAfterTransform;
   for (uint32_t i = 0; i < textBreakPoints.Length(); ++i) {
@@ -2316,60 +2317,60 @@ BuildTextRunsScanner::BuildTextRunForFra
           }
         }
         uint32_t j;
         for (j = offset; j < end; ++j) {
           styles.AppendElement(charStyle);
         }
       }
     }
-    textFlags |= nsTextFrameUtils::TEXT_IS_TRANSFORMED;
+    flags2 |= nsTextFrameUtils::TEXT_IS_TRANSFORMED;
     NS_ASSERTION(iter.GetSkippedOffset() == transformedLength,
                  "We didn't cover all the characters in the text run!");
   }
 
   RefPtr<gfxTextRun> textRun;
   gfxTextRunFactory::Parameters params =
       { mDrawTarget, finalUserData, &skipChars,
         textBreakPointsAfterTransform.Elements(),
         uint32_t(textBreakPointsAfterTransform.Length()),
         int32_t(firstFrame->PresContext()->AppUnitsPerDevPixel())};
 
   if (mDoubleByteText) {
     const char16_t* text = static_cast<const char16_t*>(textPtr);
     if (transformingFactory) {
       textRun = transformingFactory->MakeTextRun(text, transformedLength,
-                                                 &params, fontGroup, textFlags,
+                                                 &params, fontGroup, flags, flags2,
                                                  Move(styles), true);
       if (textRun) {
         // ownership of the factory has passed to the textrun
         // TODO: bug 1285316: clean up ownership transfer from the factory to
         // the textrun
         Unused << transformingFactory.release();
       }
     } else {
       textRun = fontGroup->MakeTextRun(text, transformedLength, &params,
-                                       textFlags, mMissingFonts);
+                                       flags, flags2, mMissingFonts);
     }
   } else {
     const uint8_t* text = static_cast<const uint8_t*>(textPtr);
-    textFlags |= gfxFontGroup::TEXT_IS_8BIT;
+    flags |= gfxFontGroup::TEXT_IS_8BIT;
     if (transformingFactory) {
       textRun = transformingFactory->MakeTextRun(text, transformedLength,
-                                                 &params, fontGroup, textFlags,
+                                                 &params, fontGroup, flags, flags2,
                                                  Move(styles), true);
       if (textRun) {
         // ownership of the factory has passed to the textrun
         // TODO: bug 1285316: clean up ownership transfer from the factory to
         // the textrun
         Unused << transformingFactory.release();
       }
     } else {
       textRun = fontGroup->MakeTextRun(text, transformedLength, &params,
-                                       textFlags, mMissingFonts);
+                                       flags, flags2, mMissingFonts);
     }
   }
   if (!textRun) {
     DestroyUserData(userDataToDestroy);
     return nullptr;
   }
 
   // We have to set these up after we've created the textrun, because
@@ -2467,17 +2468,17 @@ BuildTextRunsScanner::SetupLineBreakerCo
     newFlow->mContentLength = contentLength;
 
     while (nextBreakBeforeFrame && nextBreakBeforeFrame->GetContent() == content) {
       textBreakPoints.AppendElement(
           nextBreakBeforeFrame->GetContentOffset() + newFlow->mDOMOffsetToBeforeTransformOffset);
       nextBreakBeforeFrame = GetNextBreakBeforeFrame(&nextBreakIndex);
     }
 
-    uint32_t analysisFlags;
+    uint16_t analysisFlags;
     if (frag->Is2b()) {
       NS_ASSERTION(mDoubleByteText, "Wrong buffer char size!");
       char16_t* bufStart = static_cast<char16_t*>(textPtr);
       char16_t* bufEnd = nsTextFrameUtils::TransformText(
           frag->Get2b() + contentStart, contentLength, bufStart,
           compression, &mNextRunContextInfo, &skipChars, &analysisFlags);
       textPtr = bufEnd;
     } else {
@@ -2586,17 +2587,17 @@ BuildTextRunsScanner::SetupBreakSinksFor
                                  WhiteSpaceCanWrap(initialBreakController)) {
       flags |= nsLineBreaker::BREAK_SUPPRESS_INITIAL;
     }
     nsTextFrame* startFrame = mappedFlow->mStartFrame;
     const nsStyleText* textStyle = startFrame->StyleText();
     if (!textStyle->WhiteSpaceCanWrap(startFrame)) {
       flags |= nsLineBreaker::BREAK_SUPPRESS_INSIDE;
     }
-    if (aTextRun->GetFlags() & nsTextFrameUtils::TEXT_NO_BREAKS) {
+    if (aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_NO_BREAKS) {
       flags |= nsLineBreaker::BREAK_SKIP_SETTING_NO_BREAKS;
     }
     if (textStyle->mTextTransform == NS_STYLE_TEXT_TRANSFORM_CAPITALIZE) {
       flags |= nsLineBreaker::BREAK_NEED_CAPITALIZATION;
     }
     if (textStyle->mHyphens == StyleHyphens::Auto) {
       flags |= nsLineBreaker::BREAK_USE_AUTO_HYPHENATION;
     }
@@ -2735,17 +2736,17 @@ BuildTextRunsScanner::AssignTextRun(gfxT
     MappedFlow* mappedFlow = &mMappedFlows[i];
     nsTextFrame* startFrame = mappedFlow->mStartFrame;
     nsTextFrame* endFrame = mappedFlow->mEndFrame;
     nsTextFrame* f;
     for (f = startFrame; f != endFrame; f = f->GetNextContinuation()) {
 #ifdef DEBUG_roc
       if (f->GetTextRun(mWhichTextRun)) {
         gfxTextRun* textRun = f->GetTextRun(mWhichTextRun);
-        if (textRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
+        if (textRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
           if (mMappedFlows[0].mStartFrame != GetFrameForSimpleFlow(textRun)) {
             NS_WARNING("REASSIGNING SIMPLE FLOW TEXT RUN!");
           }
         } else {
           auto userData = static_cast<TextRunUserData*>(aTextRun->GetUserData());
           TextRunMappedFlow* userMappedFlows = GetMappedFlows(aTextRun);
           if (userData->mMappedFlowCount >= mMappedFlows.Length() ||
               userMappedFlows[userData->mMappedFlowCount - 1].mStartFrame !=
@@ -2755,17 +2756,17 @@ BuildTextRunsScanner::AssignTextRun(gfxT
         }
       }
 #endif
 
       gfxTextRun* oldTextRun = f->GetTextRun(mWhichTextRun);
       if (oldTextRun) {
         nsTextFrame* firstFrame = nullptr;
         uint32_t startOffset = 0;
-        if (oldTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
+        if (oldTextRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
           firstFrame = GetFrameForSimpleFlow(oldTextRun);
         } else {
           auto userData = static_cast<TextRunUserData*>(oldTextRun->GetUserData());
           TextRunMappedFlow* userMappedFlows = GetMappedFlows(oldTextRun);
           firstFrame = userMappedFlows[0].mStartFrame;
           if (MOZ_UNLIKELY(f != firstFrame)) {
             TextRunMappedFlow* flow =
               FindFlowForContent(userData, f->GetContent(), userMappedFlows);
@@ -2839,17 +2840,17 @@ nsTextFrame::EnsureTextRun(TextRunType a
                                   GetPlatform()->EmptySkipChars(), 0);
     }
     TabWidthStore* tabWidths = Properties().Get(TabWidthProperty());
     if (tabWidths && tabWidths->mValidForContentOffset != GetContentOffset()) {
       Properties().Delete(TabWidthProperty());
     }
   }
 
-  if (textRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
+  if (textRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
     if (aFlowEndInTextRun) {
       *aFlowEndInTextRun = textRun->GetLength();
     }
     return gfxSkipCharsIterator(textRun->GetSkipChars(), 0, mContentOffset);
   }
 
   auto userData = static_cast<TextRunUserData*>(textRun->GetUserData());
   TextRunMappedFlow* userMappedFlows = GetMappedFlows(textRun);
@@ -3349,17 +3350,17 @@ PropertyProvider::ComputeJustification(
   return info;
 }
 
 // aStart, aLength in transformed string offsets
 void
 PropertyProvider::GetSpacing(Range aRange, Spacing* aSpacing) const
 {
   GetSpacingInternal(aRange, aSpacing,
-                     (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TAB) == 0);
+                     (mTextRun->GetFlags2() & nsTextFrameUtils::TEXT_HAS_TAB) == 0);
 }
 
 static bool
 CanAddSpacingAfter(const gfxTextRun* aTextRun, uint32_t aOffset)
 {
   if (aOffset + 1 >= aTextRun->GetLength())
     return true;
   return aTextRun->IsClusterStart(aOffset + 1) &&
@@ -5482,24 +5483,24 @@ already_AddRefed<gfxTextRun>
 GenerateTextRunForEmphasisMarks(nsTextFrame* aFrame,
                                 nsFontMetrics* aFontMetrics,
                                 nsStyleContext* aStyleContext,
                                 const nsStyleText* aStyleText)
 {
   const nsString& emphasisString = aStyleText->mTextEmphasisStyleString;
   RefPtr<DrawTarget> dt = CreateReferenceDrawTarget(aFrame);
   auto appUnitsPerDevUnit = aFrame->PresContext()->AppUnitsPerDevPixel();
-  uint32_t flags = nsLayoutUtils::GetTextRunOrientFlagsForStyle(aStyleContext);
+  uint16_t flags = nsLayoutUtils::GetTextRunOrientFlagsForStyle(aStyleContext);
   if (flags == gfxTextRunFactory::TEXT_ORIENT_VERTICAL_MIXED) {
     // The emphasis marks should always be rendered upright per spec.
     flags = gfxTextRunFactory::TEXT_ORIENT_VERTICAL_UPRIGHT;
   }
   return aFontMetrics->GetThebesFontGroup()->
     MakeTextRun<char16_t>(emphasisString.get(), emphasisString.Length(),
-                          dt, appUnitsPerDevUnit, flags, nullptr);
+                          dt, appUnitsPerDevUnit, flags, 0, nullptr);
 }
 
 static nsRubyFrame*
 FindFurthestInlineRubyAncestor(nsTextFrame* aFrame)
 {
   nsRubyFrame* rubyFrame = nullptr;
   for (nsIFrame* frame = aFrame->GetParent();
        frame && frame->IsFrameOfType(nsIFrame::eLineParticipant);
@@ -8358,17 +8359,17 @@ nsTextFrame::AddInlineMinISizeForFlow(ns
   const nsTextFragment* frag = mContent->GetText();
 
   // If we're hyphenating, the PropertyProvider needs the actual length;
   // otherwise we can just pass INT32_MAX to mean "all the text"
   int32_t len = INT32_MAX;
   bool hyphenating = frag->GetLength() > 0 &&
     (textStyle->mHyphens == StyleHyphens::Auto ||
      (textStyle->mHyphens == StyleHyphens::Manual &&
-      (textRun->GetFlags() & gfxTextRunFactory::TEXT_ENABLE_HYPHEN_BREAKS) != 0));
+      (textRun->GetFlags2() & gfxTextRunFactory::TEXT_ENABLE_HYPHEN_BREAKS) != 0));
   if (hyphenating) {
     gfxSkipCharsIterator tmp(iter);
     len = std::min<int32_t>(GetContentOffset() + GetInFlowContentLength(),
                  tmp.ConvertSkippedToOriginal(flowEndInTextRun)) - iter.GetOriginalOffset();
   }
   PropertyProvider provider(textRun, textStyle, frag, this,
                             iter, len, nullptr, 0, aTextRunType);
 
@@ -8451,17 +8452,17 @@ nsTextFrame::AddInlineMinISizeForFlow(ns
         tabWidth = ComputeTabWidthAppUnits(this, textRun);
       }
       gfxFloat afterTab =
         AdvanceToNextTab(aData->mCurrentLine, tabWidth);
       aData->mCurrentLine = nscoord(afterTab + spacing.mAfter);
       wordStart = i + 1;
     } else if (i < flowEndInTextRun ||
         (i == textRun->GetLength() &&
-         (textRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TRAILING_BREAK))) {
+         (textRun->GetFlags2() & nsTextFrameUtils::TEXT_HAS_TRAILING_BREAK))) {
       if (preformattedNewline) {
         aData->ForceBreak();
       } else if (i < flowEndInTextRun && hyphenating &&
                  hyphBuffer[i - start] != gfxTextRun::HyphenType::None) {
         aData->OptionallyBreak(NSToCoordRound(provider.GetHyphenWidth()));
       } else {
         aData->OptionallyBreak();
       }
@@ -8765,17 +8766,17 @@ nsTextFrame::GetPrefWidthTightBounds(nsR
 static bool
 HasSoftHyphenBefore(const nsTextFragment* aFrag, const gfxTextRun* aTextRun,
                     int32_t aStartOffset, const gfxSkipCharsIterator& aIter)
 {
   if (aIter.GetSkippedOffset() < aTextRun->GetLength() &&
       aTextRun->CanHyphenateBefore(aIter.GetSkippedOffset())) {
     return true;
   }
-  if (!(aTextRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_SHY))
+  if (!(aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_HAS_SHY))
     return false;
   gfxSkipCharsIterator iter = aIter;
   while (iter.GetOriginalOffset() > aStartOffset) {
     iter.AdvanceOriginal(-1);
     if (!iter.IsOriginalCharSkipped())
       break;
     if (aFrag->CharAt(iter.GetOriginalOffset()) == CH_SHY)
       return true;
@@ -9243,17 +9244,17 @@ nsTextFrame::ReflowText(nsLineLayout& aL
                     <= mTextRun->GetLength(),
                "Text run does not map enough text for our reflow");
 
   /////////////////////////////////////////////////////////////////////
   // See how much text should belong to this text frame, and measure it
   /////////////////////////////////////////////////////////////////////
 
   iter.SetOriginalOffset(offset);
-  nscoord xOffsetForTabs = (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TAB) ?
+  nscoord xOffsetForTabs = (mTextRun->GetFlags2() & nsTextFrameUtils::TEXT_HAS_TAB) ?
     (aLineLayout.GetCurrentFrameInlineDistanceFromBlock() -
        lineContainer->GetUsedBorderAndPadding().left)
     : -1;
   PropertyProvider provider(mTextRun, textStyle, frag, this, iter, length,
       lineContainer, xOffsetForTabs, nsTextFrame::eInflated);
 
   uint32_t transformedOffset = provider.GetStart().GetSkippedOffset();
 
@@ -9538,17 +9539,17 @@ nsTextFrame::ReflowText(nsLineLayout& aL
       // Record a potential break after final soft hyphen
       aLineLayout.NotifyOptionalBreakPosition(this, length, fits,
                                               gfxBreakPriority::eNormalBreak);
     }
     // length == 0 means either the text is empty or it's all collapsed away
     bool emptyTextAtStartOfLine = atStartOfLine && length == 0;
     if (!breakAfter && charsFit == length && !emptyTextAtStartOfLine &&
         transformedOffset + transformedLength == mTextRun->GetLength() &&
-        (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TRAILING_BREAK)) {
+        (mTextRun->GetFlags2() & nsTextFrameUtils::TEXT_HAS_TRAILING_BREAK)) {
       // We placed all the text in the textrun and we have a break opportunity
       // at the end of the textrun. We need to record it because the following
       // content may not care about nsLineBreaker.
 
       // Note that because we didn't break, we can be sure that (thanks to the
       // code up above) textMetrics.mAdvanceWidth includes the width of any
       // trailing whitespace. So we need to subtract trimmableWidth here
       // because if we did break at this point, that much width would be
@@ -9768,18 +9769,18 @@ static void TransformChars(nsTextFrame* 
     if ((ch == '\n' && !aStyle->NewlineIsSignificant(aFrame)) ||
         (ch == '\t' && !aStyle->TabIsSignificant())) {
       ch = ' ';
     }
     out[i] = ch;
   }
 
   if (aStyle->mTextTransform != NS_STYLE_TEXT_TRANSFORM_NONE) {
-    MOZ_ASSERT(aTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_TRANSFORMED);
-    if (aTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_TRANSFORMED) {
+    MOZ_ASSERT(aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_TRANSFORMED);
+    if (aTextRun->GetFlags2() & nsTextFrameUtils::TEXT_IS_TRANSFORMED) {
       // Apply text-transform according to style in the transformed run.
       auto transformedTextRun =
         static_cast<const nsTransformedTextRun*>(aTextRun);
       nsAutoString convertedString;
       AutoTArray<bool,50> charsToMergeArray;
       AutoTArray<bool,50> deletedCharsArray;
       nsCaseTransformTextRunFactory::TransformString(fragString,
                                                      convertedString,
--- a/layout/generic/nsTextFrameUtils.cpp
+++ b/layout/generic/nsTextFrameUtils.cpp
@@ -11,30 +11,30 @@
 #include "nsStyleStruct.h"
 #include "nsTextFragment.h"
 #include "nsUnicharUtils.h"
 #include <algorithm>
 
 using namespace mozilla;
 
 static bool
-IsDiscardable(char16_t ch, uint32_t* aFlags)
+IsDiscardable(char16_t ch, uint16_t* aFlags)
 {
   // Unlike IS_DISCARDABLE, we don't discard \r. \r will be ignored by gfxTextRun
   // and discarding it would force us to copy text in many cases of preformatted
   // text containing \r\n.
   if (ch == CH_SHY) {
     *aFlags |= nsTextFrameUtils::TEXT_HAS_SHY;
     return true;
   }
   return IsBidiControl(ch);
 }
 
 static bool
-IsDiscardable(uint8_t ch, uint32_t* aFlags)
+IsDiscardable(uint8_t ch, uint16_t* aFlags)
 {
   if (ch == CH_SHY) {
     *aFlags |= nsTextFrameUtils::TEXT_HAS_SHY;
     return true;
   }
   return false;
 }
 
@@ -88,17 +88,17 @@ static void AssertSkippedExpectedChars(c
 
 template<class CharT>
 static CharT*
 TransformWhiteSpaces(const CharT* aText, uint32_t aLength,
                      uint32_t aBegin, uint32_t aEnd,
                      bool aHasSegmentBreak,
                      bool& aInWhitespace,
                      CharT* aOutput,
-                     uint32_t& aFlags,
+                     uint16_t& aFlags,
                      nsTextFrameUtils::CompressionMode aCompression,
                      gfxSkipChars* aSkipChars)
 {
   MOZ_ASSERT(aCompression == nsTextFrameUtils::COMPRESS_WHITESPACE ||
              aCompression == nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE,
              "whitespaces should be skippable!!");
   // Get the context preceding/following this white space range.
   // For 8-bit text (sizeof CharT == 1), the checks here should get optimized
@@ -204,19 +204,19 @@ TransformWhiteSpaces(const CharT* aText,
 
 template<class CharT>
 CharT*
 nsTextFrameUtils::TransformText(const CharT* aText, uint32_t aLength,
                                 CharT* aOutput,
                                 CompressionMode aCompression,
                                 uint8_t* aIncomingFlags,
                                 gfxSkipChars* aSkipChars,
-                                uint32_t* aAnalysisFlags)
+                                uint16_t* aAnalysisFlags)
 {
-  uint32_t flags = 0;
+  uint16_t flags = 0;
   CharT* outputStart = aOutput;
 #ifdef DEBUG
   int32_t skipCharsOffset = aSkipChars->GetOriginalCharCount();
 #endif
 
   bool lastCharArabic = false;
   if (aCompression == COMPRESS_NONE ||
       aCompression == COMPRESS_NONE_TRANSFORM_TO_SPACE) {
@@ -353,24 +353,24 @@ nsTextFrameUtils::TransformText(const Ch
  * could prevent us from the potential risk.
  */
 template uint8_t*
 nsTextFrameUtils::TransformText(const uint8_t* aText, uint32_t aLength,
                                 uint8_t* aOutput,
                                 CompressionMode aCompression,
                                 uint8_t* aIncomingFlags,
                                 gfxSkipChars* aSkipChars,
-                                uint32_t* aAnalysisFlags);
+                                uint16_t* aAnalysisFlags);
 template char16_t*
 nsTextFrameUtils::TransformText(const char16_t* aText, uint32_t aLength,
                                 char16_t* aOutput,
                                 CompressionMode aCompression,
                                 uint8_t* aIncomingFlags,
                                 gfxSkipChars* aSkipChars,
-                                uint32_t* aAnalysisFlags);
+                                uint16_t* aAnalysisFlags);
 template bool
 nsTextFrameUtils::IsSkippableCharacterForTransformText(uint8_t aChar);
 template bool
 nsTextFrameUtils::IsSkippableCharacterForTransformText(char16_t aChar);
 
 uint32_t
 nsTextFrameUtils::ComputeApproximateLengthWithWhitespaceCompression(
                     nsIContent *aContent, const nsStyleText *aStyleText)
--- a/layout/generic/nsTextFrameUtils.h
+++ b/layout/generic/nsTextFrameUtils.h
@@ -21,51 +21,59 @@ struct nsStyleText;
 
 class nsTextFrameUtils {
 public:
   // These constants are used as textrun flags for textframe textruns.
   enum {
     // The following flags are set by TransformText
 
     // the text has at least one untransformed tab character
-    TEXT_HAS_TAB             = 0x010000,
+    TEXT_HAS_TAB             = 0x01,
     // the original text has at least one soft hyphen character
-    TEXT_HAS_SHY             = 0x020000,
-    TEXT_WAS_TRANSFORMED     = 0x040000,
-    TEXT_UNUSED_FLAG         = 0x080000,
+    TEXT_HAS_SHY             = 0x02,
+    TEXT_WAS_TRANSFORMED     = 0x04,
+    TEXT_UNUSED_FLAG         = 0x08,
 
     // The following flags are set by nsTextFrame
 
-    TEXT_IS_SIMPLE_FLOW      = 0x100000,
-    TEXT_INCOMING_WHITESPACE = 0x200000,
-    TEXT_TRAILING_WHITESPACE = 0x400000,
-    TEXT_COMPRESSED_LEADING_WHITESPACE = 0x800000,
-    TEXT_NO_BREAKS           = 0x1000000,
-    TEXT_IS_TRANSFORMED      = 0x2000000,
+    TEXT_IS_SIMPLE_FLOW      = 0x10,
+    TEXT_INCOMING_WHITESPACE = 0x20,
+    TEXT_TRAILING_WHITESPACE = 0x40,
+    TEXT_COMPRESSED_LEADING_WHITESPACE = 0x80,
+    TEXT_NO_BREAKS           = 0x100,
+    TEXT_IS_TRANSFORMED      = 0x200,
     // This gets set if there's a break opportunity at the end of the textrun.
     // We normally don't use this break opportunity because the following text
     // will have a break opportunity at the start, but it's useful for line
     // layout to know about it in case the following content is not text
-    TEXT_HAS_TRAILING_BREAK  = 0x4000000,
+    TEXT_HAS_TRAILING_BREAK  = 0x400,
 
     // This is set if the textrun was created for a textframe whose
     // NS_FRAME_IS_IN_SINGLE_CHAR_MI flag is set.  This occurs if the textframe
     // belongs to a MathML <mi> element whose embedded text consists of a
     // single character.
-    TEXT_IS_SINGLE_CHAR_MI   = 0x8000000,
+    TEXT_IS_SINGLE_CHAR_MI   = 0x800,
 
     // This is set if the text run might be observing for glyph changes.
-    TEXT_MIGHT_HAVE_GLYPH_CHANGES = 0x10000000,
+    TEXT_MIGHT_HAVE_GLYPH_CHANGES = 0x1000,
 
-    // The following are defined by gfxTextRunWordCache rather than here,
-    // so that it also has access to the _INCOMING flag
+    // For internal use by the memory reporter when accounting for
+    // storage used by textruns.
+    // Because the reporter may visit each textrun multiple times while
+    // walking the frame trees and textrun cache, it needs to mark
+    // textruns that have been seen so as to avoid multiple-accounting.
+    TEXT_RUN_SIZE_ACCOUNTED      = 0x2000,
+
+    // The following are defined by gfxTextRunFactory rather than here,
+    // so that it also has access to the _INCOMING and MATH_SCRIPT flags
+    // for shaping purposes.
+    // They live in the gfxShapedText::mFlags field rather than the
+    // gfxTextRun::mFlags2 field.
     // TEXT_TRAILING_ARABICCHAR
     // TEXT_INCOMING_ARABICCHAR
-
-    // This is defined in gfxTextRunFactory to allow access in gfxFont.
     // TEXT_USE_MATH_SCRIPT
   };
 
   // These constants are used in TransformText to represent context information
   // from previous textruns.
   enum {
     INCOMING_NONE       = 0,
     INCOMING_WHITESPACE = 1,
@@ -114,17 +122,17 @@ public:
    * there's an Arabic character or whitespace preceding the end of this text.
    */
   template<class CharT>
   static CharT* TransformText(const CharT* aText, uint32_t aLength,
                               CharT* aOutput,
                               CompressionMode aCompression,
                               uint8_t* aIncomingFlags,
                               gfxSkipChars* aSkipChars,
-                              uint32_t* aAnalysisFlags);
+                              uint16_t* aAnalysisFlags);
 
   /**
    * Returns whether aChar is a character that nsTextFrameUtils::TransformText
    * might mark as skipped.  This is used by
    * SVGTextContentElement::GetNumberOfChars to know whether reflowing frames,
    * so that we have the results of TransformText, is required, or whether we
    * can use a fast path instead.
    */
--- a/layout/generic/nsTextRunTransformations.cpp
+++ b/layout/generic/nsTextRunTransformations.cpp
@@ -33,31 +33,32 @@ using namespace mozilla::gfx;
 #define GREEK_SMALL_LETTER_FINAL_SIGMA         0x03C2
 #define GREEK_SMALL_LETTER_SIGMA               0x03C3
 
 already_AddRefed<nsTransformedTextRun>
 nsTransformedTextRun::Create(const gfxTextRunFactory::Parameters* aParams,
                              nsTransformingTextRunFactory* aFactory,
                              gfxFontGroup* aFontGroup,
                              const char16_t* aString, uint32_t aLength,
-                             const uint32_t aFlags,
+                             const uint16_t aFlags,
+                             const uint16_t aFlags2,
                              nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
                              bool aOwnsFactory)
 {
   NS_ASSERTION(!(aFlags & gfxTextRunFactory::TEXT_IS_8BIT),
                "didn't expect text to be marked as 8-bit here");
 
   void *storage = AllocateStorageForTextRun(sizeof(nsTransformedTextRun), aLength);
   if (!storage) {
     return nullptr;
   }
 
   RefPtr<nsTransformedTextRun> result =
     new (storage) nsTransformedTextRun(aParams, aFactory, aFontGroup,
-                                       aString, aLength, aFlags,
+                                       aString, aLength, aFlags, aFlags2,
                                        Move(aStyles), aOwnsFactory);
   return result.forget();
 }
 
 void
 nsTransformedTextRun::SetCapitalization(uint32_t aStart, uint32_t aLength,
                                         bool* aCapitalization)
 {
@@ -97,37 +98,40 @@ size_t
 nsTransformedTextRun::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
 {
   return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
 }
 
 already_AddRefed<nsTransformedTextRun>
 nsTransformingTextRunFactory::MakeTextRun(const char16_t* aString, uint32_t aLength,
                                           const gfxTextRunFactory::Parameters* aParams,
-                                          gfxFontGroup* aFontGroup, uint32_t aFlags,
+                                          gfxFontGroup* aFontGroup,
+                                          uint16_t aFlags, uint16_t aFlags2,
                                           nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
                                           bool aOwnsFactory)
 {
   return nsTransformedTextRun::Create(aParams, this, aFontGroup,
-                                      aString, aLength, aFlags, Move(aStyles),
+                                      aString, aLength, aFlags, aFlags2, Move(aStyles),
                                       aOwnsFactory);
 }
 
 already_AddRefed<nsTransformedTextRun>
 nsTransformingTextRunFactory::MakeTextRun(const uint8_t* aString, uint32_t aLength,
                                           const gfxTextRunFactory::Parameters* aParams,
-                                          gfxFontGroup* aFontGroup, uint32_t aFlags,
+                                          gfxFontGroup* aFontGroup,
+                                          uint16_t aFlags, uint16_t aFlags2,
                                           nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
                                           bool aOwnsFactory)
 {
   // We'll only have a Unicode code path to minimize the amount of code needed
   // for these rarely used features
   NS_ConvertASCIItoUTF16 unicodeString(reinterpret_cast<const char*>(aString), aLength);
   return MakeTextRun(unicodeString.get(), aLength, aParams, aFontGroup,
                      aFlags & ~(gfxFontGroup::TEXT_IS_PERSISTENT | gfxFontGroup::TEXT_IS_8BIT),
+                     aFlags2,
                      Move(aStyles), aOwnsFactory);
 }
 
 void
 MergeCharactersInTextRun(gfxTextRun* aDest, gfxTextRun* aSrc,
                          const bool* aCharsToMerge, const bool* aDeletedChars)
 {
   aDest->ResetGlyphRuns();
@@ -208,17 +212,18 @@ MergeCharactersInTextRun(gfxTextRun* aDe
     }
     NS_ASSERTION(glyphs.Length() == 0,
                  "Leftover glyphs, don't request merging of the last character with its next!");  
   }
   NS_ASSERTION(offset == aDest->GetLength(), "Bad offset calculations");
 }
 
 gfxTextRunFactory::Parameters
-GetParametersForInner(nsTransformedTextRun* aTextRun, uint32_t* aFlags,
+GetParametersForInner(nsTransformedTextRun* aTextRun,
+                      uint16_t* aFlags,
                       DrawTarget* aRefDrawTarget)
 {
   gfxTextRunFactory::Parameters params =
     { aRefDrawTarget, nullptr, nullptr,
       nullptr, 0, aTextRun->GetAppUnitsPerDevUnit()
     };
   *aFlags = aTextRun->GetFlags() & ~gfxFontGroup::TEXT_IS_PERSISTENT;
   return params;
@@ -655,34 +660,34 @@ nsCaseTransformTextRunFactory::RebuildTe
                                      mAllUppercase,
                                      nullptr,
                                      charsToMergeArray,
                                      deletedCharsArray,
                                      aTextRun, 0,
                                      &canBreakBeforeArray,
                                      &styleArray);
 
-  uint32_t flags;
+  uint16_t flags;
   gfxTextRunFactory::Parameters innerParams =
     GetParametersForInner(aTextRun, &flags, aRefDrawTarget);
   gfxFontGroup* fontGroup = aTextRun->GetFontGroup();
 
   RefPtr<nsTransformedTextRun> transformedChild;
   RefPtr<gfxTextRun> cachedChild;
   gfxTextRun* child;
 
   if (mInnerTransformingTextRunFactory) {
     transformedChild = mInnerTransformingTextRunFactory->MakeTextRun(
         convertedString.BeginReading(), convertedString.Length(),
-        &innerParams, fontGroup, flags, Move(styleArray), false);
+        &innerParams, fontGroup, flags, 0, Move(styleArray), false);
     child = transformedChild.get();
   } else {
     cachedChild = fontGroup->MakeTextRun(
         convertedString.BeginReading(), convertedString.Length(),
-        &innerParams, flags, aMFR);
+        &innerParams, flags, 0, aMFR);
     child = cachedChild.get();
   }
   if (!child)
     return;
   // Copy potential linebreaks into child so they're preserved
   // (and also child will be shaped appropriately)
   NS_ASSERTION(convertedString.Length() == canBreakBeforeArray.Length(),
                "Dropped characters or break-before values somewhere!");
--- a/layout/generic/nsTextRunTransformations.h
+++ b/layout/generic/nsTextRunTransformations.h
@@ -44,24 +44,24 @@ private:
 class nsTransformingTextRunFactory {
 public:
   virtual ~nsTransformingTextRunFactory() {}
 
   // Default 8-bit path just transforms to Unicode and takes that path
   already_AddRefed<nsTransformedTextRun>
   MakeTextRun(const uint8_t* aString, uint32_t aLength,
               const gfxFontGroup::Parameters* aParams,
-              gfxFontGroup* aFontGroup, uint32_t aFlags,
+              gfxFontGroup* aFontGroup, uint16_t aFlags, uint16_t aFlags2,
               nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
               bool aOwnsFactory);
 
   already_AddRefed<nsTransformedTextRun>
   MakeTextRun(const char16_t* aString, uint32_t aLength,
               const gfxFontGroup::Parameters* aParams,
-              gfxFontGroup* aFontGroup, uint32_t aFlags,
+              gfxFontGroup* aFontGroup, uint16_t aFlags, uint16_t aFlags2,
               nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
               bool aOwnsFactory);
 
   virtual void RebuildTextRun(nsTransformedTextRun* aTextRun,
                               mozilla::gfx::DrawTarget* aRefDrawTarget,
                               gfxMissingFontRecorder* aMFR) = 0;
 };
 
@@ -120,17 +120,17 @@ protected:
 class nsTransformedTextRun final : public gfxTextRun {
 public:
 
   static already_AddRefed<nsTransformedTextRun>
   Create(const gfxTextRunFactory::Parameters* aParams,
          nsTransformingTextRunFactory* aFactory,
          gfxFontGroup* aFontGroup,
          const char16_t* aString, uint32_t aLength,
-         const uint32_t aFlags,
+         const uint16_t aFlags, const uint16_t aFlags2,
          nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
          bool aOwnsFactory);
 
   ~nsTransformedTextRun() {
     if (mOwnsFactory) {
       delete mFactory;
     }
   }
@@ -164,20 +164,20 @@ public:
   bool                                mOwnsFactory;
   bool                                mNeedsRebuild;
 
 private:
   nsTransformedTextRun(const gfxTextRunFactory::Parameters* aParams,
                        nsTransformingTextRunFactory* aFactory,
                        gfxFontGroup* aFontGroup,
                        const char16_t* aString, uint32_t aLength,
-                       const uint32_t aFlags,
+                       const uint16_t aFlags, const uint16_t aFlags2,
                        nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
                        bool aOwnsFactory)
-    : gfxTextRun(aParams, aLength, aFontGroup, aFlags),
+    : gfxTextRun(aParams, aLength, aFontGroup, aFlags, aFlags2),
       mFactory(aFactory), mStyles(aStyles), mString(aString, aLength),
       mOwnsFactory(aOwnsFactory), mNeedsRebuild(true)
   {
     mCharacterGlyphs = reinterpret_cast<CompressedGlyph*>(this + 1);
   }
 };
 
 /**
@@ -210,13 +210,14 @@ private:
  * @param aDeletedChars when aDeletedChars[i] is true, the character at this
  * position in aDest was deleted (has no corresponding char in aSrc)
  */
 void
 MergeCharactersInTextRun(gfxTextRun* aDest, gfxTextRun* aSrc,
                          const bool* aCharsToMerge, const bool* aDeletedChars);
 
 gfxTextRunFactory::Parameters
-GetParametersForInner(nsTransformedTextRun* aTextRun, uint32_t* aFlags,
+GetParametersForInner(nsTransformedTextRun* aTextRun,
+                      uint16_t* aFlags,
                       mozilla::gfx::DrawTarget* aRefDrawTarget);
 
 
 #endif /*NSTEXTRUNTRANSFORMATIONS_H_*/
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -388,17 +388,17 @@ nsPropertiesTable::MakeTextRun(DrawTarge
                                int32_t            aAppUnitsPerDevPixel,
                                gfxFontGroup*      aFontGroup,
                                const nsGlyphCode& aGlyph)
 {
   NS_ASSERTION(!aGlyph.IsGlyphID(),
                "nsPropertiesTable can only access glyphs by code point");
   return aFontGroup->
     MakeTextRun(aGlyph.code, aGlyph.Length(), aDrawTarget,
-                aAppUnitsPerDevPixel, 0, nullptr);
+                aAppUnitsPerDevPixel, 0, 0, nullptr);
 }
 
 // An instance of nsOpenTypeTable is associated with one gfxFontEntry that
 // corresponds to an Open Type font with a MATH table. All the glyphs come from
 // the same font and the calls to access size variants and parts are directly
 // forwarded to the gfx code.
 class nsOpenTypeTable final : public nsGlyphTable {
 public:
@@ -469,17 +469,17 @@ private:
 void
 nsOpenTypeTable::UpdateCache(DrawTarget*   aDrawTarget,
                              int32_t       aAppUnitsPerDevPixel,
                              gfxFontGroup* aFontGroup,
                              char16_t      aChar)
 {
   if (mCharCache != aChar) {
     RefPtr<gfxTextRun> textRun = aFontGroup->
-      MakeTextRun(&aChar, 1, aDrawTarget, aAppUnitsPerDevPixel, 0, nullptr);
+      MakeTextRun(&aChar, 1, aDrawTarget, aAppUnitsPerDevPixel, 0, 0, nullptr);
     const gfxTextRun::CompressedGlyph& data = textRun->GetCharacterGlyphs()[0];
     if (data.IsSimpleGlyph()) {
       mGlyphID = data.GetSimpleGlyph();
     } else if (data.GetGlyphCount() == 1) {
       mGlyphID = textRun->GetDetailedGlyphs(0)->mGlyphID;
     } else {
       mGlyphID = 0;
     }
@@ -563,17 +563,17 @@ nsOpenTypeTable::MakeTextRun(DrawTarget*
 {
   NS_ASSERTION(aGlyph.IsGlyphID(),
                "nsOpenTypeTable can only access glyphs by id");
 
   gfxTextRunFactory::Parameters params = {
     aDrawTarget, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevPixel
   };
   RefPtr<gfxTextRun> textRun =
-    gfxTextRun::Create(&params, 1, aFontGroup, 0);
+    gfxTextRun::Create(&params, 1, aFontGroup, 0, 0);
   textRun->AddGlyphRun(aFontGroup->GetFirstValidFont(),
                        gfxTextRange::kFontGroup, 0,
                        false, gfxTextRunFactory::TEXT_ORIENT_HORIZONTAL);
                               // We don't care about CSS writing mode here;
                               // math runs are assumed to be horizontal.
   gfxTextRun::DetailedGlyph detailedGlyph;
   detailedGlyph.mGlyphID = aGlyph.glyphID;
   detailedGlyph.mAdvance =
@@ -1530,17 +1530,17 @@ nsMathMLChar::StretchInternal(nsPresCont
   params.explicitLanguage = styleFont->mExplicitLanguage;
   params.userFontSet = aPresContext->GetUserFontSet();
   params.textPerf = aPresContext->GetTextPerfMetrics();
   RefPtr<nsFontMetrics> fm =
     aPresContext->DeviceContext()->GetMetricsFor(font, params);
   uint32_t len = uint32_t(mData.Length());
   mGlyphs[0] = fm->GetThebesFontGroup()->
     MakeTextRun(static_cast<const char16_t*>(mData.get()), len, aDrawTarget,
-                aPresContext->AppUnitsPerDevPixel(), 0,
+                aPresContext->AppUnitsPerDevPixel(), 0, 0,
                 aPresContext->MissingFontRecorder());
   aDesiredStretchSize = MeasureTextRun(aDrawTarget, mGlyphs[0].get());
 
   bool maxWidth = (NS_STRETCH_MAXWIDTH & aStretchHint) != 0;
   if (!maxWidth) {
     mUnscaledAscent = aDesiredStretchSize.ascent;
   }