Bug 1207734 - Part 4.a. Store the final combined transform in nsStyleDisplay::mCombinedTransform. r=birtles
☠☠ backed out by 6002f08576ab ☠ ☠
authorcku <cku@mozilla.com>
Wed, 13 Dec 2017 01:17:05 +0800
changeset 453938 8991d046864265d64f7c7804b601741248215ffc
parent 453937 2bc1fdf79e03573395a94cbd8f66d7d0a81439d5
child 453939 a4626910ce097f0ce939113be575debf30ef0cb3
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbirtles
bugs1207734
milestone59.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 1207734 - Part 4.a. Store the final combined transform in nsStyleDisplay::mCombinedTransform. r=birtles MozReview-Commit-ID: FsuaMoclnL8
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -3662,16 +3662,17 @@ nsStyleDisplay::nsStyleDisplay(const nsS
   , mScrollSnapCoordinate(aSource.mScrollSnapCoordinate)
   , mBackfaceVisibility(aSource.mBackfaceVisibility)
   , mTransformStyle(aSource.mTransformStyle)
   , mTransformBox(aSource.mTransformBox)
   , mSpecifiedTransform(aSource.mSpecifiedTransform)
   , mSpecifiedRotate(aSource.mSpecifiedRotate)
   , mSpecifiedTranslate(aSource.mSpecifiedTranslate)
   , mSpecifiedScale(aSource.mSpecifiedScale)
+  , mCombinedTransform(aSource.mCombinedTransform)
   , mTransformOrigin{ aSource.mTransformOrigin[0],
                       aSource.mTransformOrigin[1],
                       aSource.mTransformOrigin[2] }
   , mChildPerspective(aSource.mChildPerspective)
   , mPerspectiveOrigin{ aSource.mPerspectiveOrigin[0],
                         aSource.mPerspectiveOrigin[1] }
   , mVerticalAlign(aSource.mVerticalAlign)
   , mTransitions(aSource.mTransitions)
@@ -3725,32 +3726,36 @@ nsStyleDisplay::~nsStyleDisplay()
   ReleaseSharedListOnMainThread("nsStyleDisplay::mSpecifiedTransform",
                                 mSpecifiedTransform);
   ReleaseSharedListOnMainThread("nsStyleDisplay::mSpecifiedRotate",
                                 mSpecifiedRotate);
   ReleaseSharedListOnMainThread("nsStyleDisplay::mSpecifiedTranslate",
                                 mSpecifiedTranslate);
   ReleaseSharedListOnMainThread("nsStyleDisplay::mSpecifiedScale",
                                 mSpecifiedScale);
+  ReleaseSharedListOnMainThread("nsStyleDisplay::mCombinedTransform",
+                                mCombinedTransform);
 
   MOZ_COUNT_DTOR(nsStyleDisplay);
 }
 
 void
 nsStyleDisplay::FinishStyle(nsPresContext* aPresContext)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
 
   if (mShapeOutside.GetType() == StyleShapeSourceType::Image) {
     const UniquePtr<nsStyleImage>& shapeImage = mShapeOutside.GetShapeImage();
     if (shapeImage) {
       shapeImage->ResolveImage(aPresContext);
     }
   }
+
+  GenerateCombinedTransform();
 }
 
 static inline nsChangeHint
 CompareTransformValues(const RefPtr<nsCSSValueSharedList>& aList,
                        const RefPtr<nsCSSValueSharedList>& aNewList)
 {
   nsChangeHint result = nsChangeHint(0);
   if (!aList != !aNewList || (aList && *aList != *aNewList)) {
@@ -4010,16 +4015,67 @@ nsStyleDisplay::CalcDifference(const nsS
        mAnimationIterationCountCount != aNewData.mAnimationIterationCountCount ||
        mScrollSnapCoordinate != aNewData.mScrollSnapCoordinate)) {
     hint |= nsChangeHint_NeutralChange;
   }
 
   return hint;
 }
 
+void
+nsStyleDisplay::GenerateCombinedTransform()
+{
+  mCombinedTransform = nullptr;
+
+  // Follow the order defined in the spec to append transform functions.
+  // https://drafts.csswg.org/css-transforms-2/#ctm
+  AutoTArray<nsCSSValueSharedList*, 4> shareLists;
+  if (mSpecifiedTranslate) {
+    shareLists.AppendElement(mSpecifiedTranslate.get());
+  }
+  if (mSpecifiedRotate) {
+    shareLists.AppendElement(mSpecifiedRotate.get());
+  }
+  if (mSpecifiedScale) {
+    shareLists.AppendElement(mSpecifiedScale.get());
+  }
+  if (mSpecifiedTransform) {
+    shareLists.AppendElement(mSpecifiedTransform.get());
+  }
+
+  if (shareLists.Length() == 0) {
+    return;
+  }
+
+  if (shareLists.Length() == 1) {
+    mCombinedTransform = shareLists[0];
+    return;
+  }
+
+  // In common, we may have 3 transform functions(for rotate, translate and
+  // scale) in mSpecifiedTransform, one rotate function in mSpecifiedRotate,
+  // one translate function in mSpecifiedTranslate, and one scale function in
+  // mSpecifiedScale. So 6 slots are enough for the most cases.
+  AutoTArray<nsCSSValueList*, 6> valueLists;
+  for (auto list: shareLists) {
+    if (list) {
+      valueLists.AppendElement(list->mHead->Clone());
+    }
+  }
+
+  // Check we have at least one list or else valueLists.Length() - 1 below will
+  // underflow.
+  MOZ_ASSERT(valueLists.Length());
+
+  for (uint32_t i = 0; i < valueLists.Length() - 1; i++) {
+    valueLists[i]->mNext = valueLists[i + 1];
+  }
+
+  mCombinedTransform = new nsCSSValueSharedList(valueLists[0]);
+}
 // --------------------
 // nsStyleVisibility
 //
 
 nsStyleVisibility::nsStyleVisibility(const nsPresContext* aContext)
   : mDirection(aContext->GetBidi() == IBMBIDI_TEXTDIRECTION_RTL
                  ? NS_STYLE_DIRECTION_RTL
                  : NS_STYLE_DIRECTION_LTR)
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -2588,16 +2588,23 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   // null, as appropriate.)
   uint8_t mBackfaceVisibility;
   uint8_t mTransformStyle;
   StyleGeometryBox mTransformBox; // [reset] see nsStyleConsts.h
   RefPtr<nsCSSValueSharedList> mSpecifiedTransform; // [reset]
   RefPtr<nsCSSValueSharedList> mSpecifiedRotate; // [reset]
   RefPtr<nsCSSValueSharedList> mSpecifiedTranslate; // [reset]
   RefPtr<nsCSSValueSharedList> mSpecifiedScale; // [reset]
+
+  // Used to store the final combination of mSpecifiedTranslate,
+  // mSpecifiedRotate, mSpecifiedScale and mSpecifiedTransform.
+  // Use GetCombinedTransform() to get the final transform, instead of
+  // accessing mCombinedTransform directly.
+  RefPtr<nsCSSValueSharedList> mCombinedTransform;
+
   nsStyleCoord mTransformOrigin[3]; // [reset] percent, coord, calc, 3rd param is coord, calc only
   nsStyleCoord mChildPerspective; // [reset] none, coord
   nsStyleCoord mPerspectiveOrigin[2]; // [reset] percent, coord, calc
 
   nsStyleCoord mVerticalAlign;  // [reset] coord, percent, calc, enum (see nsStyleConsts.h)
 
   nsStyleAutoArray<mozilla::StyleTransition> mTransitions; // [reset]
 
@@ -2855,26 +2862,38 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
    * The same as IsFixedPosContainingBlock, except skipping the tests that
    * are based on the frame rather than the style context (thus
    * potentially returning a false positive).
    */
   template<class StyleContextLike>
   inline bool IsFixedPosContainingBlockForAppropriateFrame(
                 StyleContextLike* aStyleContext) const;
 
+  /**
+   * Returns the final combined transform.
+   **/
+  already_AddRefed<nsCSSValueSharedList> GetCombinedTransform() const {
+    if (mCombinedTransform) {
+      return do_AddRef(mCombinedTransform);
+    }
+
+    // backward compatible to gecko-backed style system.
+    return mSpecifiedTransform ? do_AddRef(mSpecifiedTransform) : nullptr;
+  }
+
 private:
   // Helpers for above functions, which do some but not all of the tests
   // for them (since transform must be tested separately for each).
   template<class StyleContextLike>
   inline bool HasAbsPosContainingBlockStyleInternal(
                 StyleContextLike* aStyleContext) const;
   template<class StyleContextLike>
   inline bool HasFixedPosContainingBlockStyleInternal(
                 StyleContextLike* aStyleContext) const;
-
+  void GenerateCombinedTransform();
 public:
   // Return the 'float' and 'clear' properties, with inline-{start,end} values
   // resolved to {left,right} according to the given writing mode. These are
   // defined in WritingModes.h.
   inline mozilla::StyleFloat PhysicalFloats(mozilla::WritingMode aWM) const;
   inline mozilla::StyleClear PhysicalBreakType(mozilla::WritingMode aWM) const;
 };