Bug 1207734 - Part 4.a. Store the final combined transform in nsStyleDisplay::mCombinedTransform. r=birtles draft
authorcku <cku@mozilla.com>
Wed, 24 Jan 2018 16:22:46 +0900
changeset 749187 793e73f61ee1d0035b3d9d881df4eb784da3c4e9
parent 749186 7f89dd1fa3aa276bfa49b12cdc0df950f9963406
child 749188 6f39ac3e180cdb1706e12f7a662cac3ac1c369d3
push id97349
push userbbirtles@mozilla.com
push dateWed, 31 Jan 2018 02:59:16 +0000
reviewersbirtles
bugs1207734
milestone60.0a1
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
@@ -3647,16 +3647,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)
@@ -3710,32 +3711,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)) {
@@ -3995,16 +4000,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
@@ -2554,16 +2554,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]
 
@@ -2821,26 +2828,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;
 };