Bug 1207734 - Part 7. Pass a combined transform list to the nsDisplayTransform. draft
authorcku <cku@mozilla.com>
Wed, 06 Dec 2017 22:42:33 +0800
changeset 708806 ade1ec586d4ce896418c56a36d5b624f0f1e1c54
parent 708805 c1868d20a81c6fc3e981a86e1821230a9b13f83b
child 708807 8be70e9aa9d667bc899ecd53e79c42acb85e3ce1
push id92454
push userbmo:cku@mozilla.com
push dateThu, 07 Dec 2017 06:47:50 +0000
bugs1207734
milestone59.0a1
Bug 1207734 - Part 7. Pass a combined transform list to the nsDisplayTransform. MozReview-Commit-ID: 9kM3U9zp0My
layout/painting/nsDisplayList.cpp
layout/style/nsCSSValue.cpp
layout/style/nsCSSValue.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -8166,17 +8166,17 @@ nsDisplayTransform::ComputePerspectiveMa
   aOutMatrix.ChangeBasis(Point3D(perspectiveOrigin.x, perspectiveOrigin.y, 0));
   return true;
 }
 
 nsDisplayTransform::FrameTransformProperties::FrameTransformProperties(const nsIFrame* aFrame,
                                                                        float aAppUnitsPerPixel,
                                                                        const nsRect* aBoundsOverride)
   : mFrame(aFrame)
-  , mTransformList(aFrame->StyleDisplay()->mSpecifiedTransform)
+  , mTransformList(aFrame->StyleDisplay()->GetCombinedTransform())
   , mToTransformOrigin(GetDeltaToTransformOrigin(aFrame, aAppUnitsPerPixel, aBoundsOverride))
 {
 }
 
 /* Wraps up the transform matrix in a change-of-basis matrix pair that
  * translates from local coordinate space to transform coordinate space, then
  * hands it back.
  */
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -2499,16 +2499,36 @@ nsCSSValueSharedList::SizeOfIncludingThi
   size_t n = 0;
   if (mRefCnt <= 1) {
     n += aMallocSizeOf(this);
     n += mHead->SizeOfIncludingThis(aMallocSizeOf);
   }
   return n;
 }
 
+already_AddRefed<nsCSSValueSharedList>
+nsCSSValueSharedList::Clone() const
+{
+  if (!mHead) {
+    return do_AddRef(new nsCSSValueSharedList());
+  }
+
+  RefPtr<nsCSSValueSharedList> result = new nsCSSValueSharedList(mHead->Clone());
+
+  nsCSSValueList* head = result->mHead;
+  for (const nsCSSValueList* list = mHead->mNext; list != nullptr; list = list->mNext) {
+    nsCSSValueList* cloned = list->Clone();
+    head->mNext = cloned;
+    head = head->mNext;
+  }
+  head->mNext = nullptr;
+
+  return result.forget();
+}
+
 // --- nsCSSRect -----------------
 
 nsCSSRect::nsCSSRect(void)
 {
   MOZ_COUNT_CTOR(nsCSSRect);
 }
 
 nsCSSRect::nsCSSRect(const nsCSSRect& aCopy)
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -1177,16 +1177,18 @@ struct nsCSSValueSharedList final {
   }
 
   // Takes ownership of aList.
   explicit nsCSSValueSharedList(nsCSSValueList* aList)
     : mHead(aList)
   {
   }
 
+  already_AddRefed<nsCSSValueSharedList> Clone() const;
+
 private:
   // Private destructor, to discourage deletion outside of Release():
   ~nsCSSValueSharedList();
 
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsCSSValueSharedList)
 
   void AppendToString(nsCSSPropertyID aProperty, nsAString& aResult) const;
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -3997,16 +3997,62 @@ nsStyleDisplay::CalcDifference(const nsS
        mAnimationIterationCountCount != aNewData.mAnimationIterationCountCount ||
        mScrollSnapCoordinate != aNewData.mScrollSnapCoordinate)) {
     hint |= nsChangeHint_NeutralChange;
   }
 
   return hint;
 }
 
+already_AddRefed<nsCSSValueSharedList>
+nsStyleDisplay::GetCombinedTransform() const
+{
+    if (!mSpecifiedTransform && !mSpecifiedScale && !mSpecifiedTranslate &&
+        !mSpecifiedRotate) {
+    return nullptr;
+  }
+
+  // https://drafts.csswg.org/css-transforms-2/#ctm
+  // translate > rotate > scale > transform
+  nsTArray<nsCSSValueList*> lists;
+  if (mSpecifiedTranslate) {
+    RefPtr<nsCSSValueSharedList> scale = mSpecifiedTranslate->Clone();
+    lists.AppendElement(scale->mHead);
+    scale->mHead = nullptr;
+  }
+
+  if (mSpecifiedRotate) {
+    RefPtr<nsCSSValueSharedList> scale = mSpecifiedRotate->Clone();
+    lists.AppendElement(scale->mHead);
+    scale->mHead = nullptr;
+  }
+
+  if (mSpecifiedScale) {
+    RefPtr<nsCSSValueSharedList> scale = mSpecifiedScale->Clone();
+    lists.AppendElement(scale->mHead);
+    scale->mHead = nullptr;
+  }
+
+  if (mSpecifiedTransform) {
+    RefPtr<nsCSSValueSharedList> transform = mSpecifiedTransform->Clone();
+    lists.AppendElement(transform->mHead);
+    transform->mHead = nullptr;
+  }
+
+  // Concat all lists.
+  MOZ_ASSERT(lists.Length());
+  RefPtr<nsCSSValueSharedList> result = new nsCSSValueSharedList();
+  for (uint32_t i = 0; i < lists.Length() - 1; i++) {
+    lists[i]->mNext = lists[i + 1];
+  }
+
+  // TODO: should we cache this combined list?
+  result->mHead = lists[0];
+  return result.forget();
+}
 // --------------------
 // 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
@@ -2740,16 +2740,18 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
     return mSpecifiedTransform != nullptr ||
            mSpecifiedRotate != nullptr ||
            mSpecifiedTranslate != nullptr ||
            mSpecifiedScale != nullptr ||
            mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
            (mWillChangeBitField & NS_STYLE_WILL_CHANGE_TRANSFORM);
   }
 
+  already_AddRefed<nsCSSValueSharedList> GetCombinedTransform() const;
+
   bool HasPerspectiveStyle() const {
     return mChildPerspective.GetUnit() == eStyleUnit_Coord;
   }
 
   bool BackfaceIsHidden() const {
     return mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN;
   }