Bug 1207734 - Part 4.a. Store the final combined transform in nsStyleDisplay::mCombinedTransform. draft
authorcku <cku@mozilla.com>
Wed, 13 Dec 2017 01:17:05 +0800
changeset 720492 b46369422bbb20a8986aa321c0d5b7755d36cbc1
parent 720250 d5e9a0ff410ba6f4a66aa0cf077333038f1ffc4a
child 720493 fd603c0591ad758e216be11a033734bc36566d88
push id95566
push userbmo:cku@mozilla.com
push dateMon, 15 Jan 2018 18:18:47 +0000
bugs1207734
milestone59.0a1
Bug 1207734 - Part 4.a. Store the final combined transform in nsStyleDisplay::mCombinedTransform. 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,16 +3726,18 @@ 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());
@@ -4010,16 +4013,74 @@ nsStyleDisplay::CalcDifference(const nsS
        mAnimationIterationCountCount != aNewData.mAnimationIterationCountCount ||
        mScrollSnapCoordinate != aNewData.mScrollSnapCoordinate)) {
     hint |= nsChangeHint_NeutralChange;
   }
 
   return hint;
 }
 
+already_AddRefed<nsCSSValueSharedList>
+nsStyleDisplay::GetCombinedTransform() const
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (mCombinedTransform) {
+    return do_AddRef(mCombinedTransform);
+  }
+
+  // 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 nullptr;
+  }
+  if (shareLists.Length() == 1) {
+    return do_AddRef(shareLists[0]);
+  }
+
+  // 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];
+  }
+
+  RefPtr<nsCSSValueSharedList>& combinedTransform =
+    const_cast<RefPtr<nsCSSValueSharedList>&>(this->mCombinedTransform);
+
+  combinedTransform = new nsCSSValueSharedList(valueLists[0]);
+  return do_AddRef(combinedTransform);
+}
+
 // --------------------
 // 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,30 @@ 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;
+
 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;
-
 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;
 };