Bug 1207734 - Part 5. Implement the getComputedStyle API for individual transform. r=birtles draft
authorcku <cku@mozilla.com>
Tue, 19 Dec 2017 14:33:09 +0800
changeset 749190 ee81993c07a30fe5b8788d2ce6707967eb0a832a
parent 749189 dd508458f70d5473256a4bfe5a2f6bc665bbac9d
child 749191 308a4ed50826254e195fa2f4a14334d4114bd1f9
push id97349
push userbbirtles@mozilla.com
push dateWed, 31 Jan 2018 02:59:16 +0000
reviewersbirtles
bugs1207734
milestone60.0a1
Bug 1207734 - Part 5. Implement the getComputedStyle API for individual transform. r=birtles MozReview-Commit-ID: 3w1kA6VCXsg
layout/style/nsComputedDOMStyle.cpp
layout/style/nsComputedDOMStyle.h
layout/style/nsComputedDOMStylePropertyList.h
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1715,16 +1715,223 @@ nsComputedDOMStyle::DoGetTransformBox()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
   val->SetIdent(
       nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mTransformBox,
                                      nsCSSProps::kTransformBoxKTable));
   return val.forget();
 }
 
+static already_AddRefed<CSSValue>
+ReadIndividualTransformValue(nsCSSValueSharedList* aList,
+                             const std::function<void(const nsCSSValue::Array*,
+                                                      nsString&)>& aCallback)
+{
+  if (!aList) {
+    RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
+    val->SetIdent(eCSSKeyword_none);
+    return val.forget();
+  }
+
+  nsAutoString result;
+  const nsCSSValue::Array* data = aList->mHead->mValue.GetArrayValue();
+  aCallback(data, result);
+
+  RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
+  val->SetString(result);
+  return val.forget();
+}
+
+already_AddRefed<CSSValue>
+nsComputedDOMStyle::DoGetTranslate()
+{
+  typedef nsStyleTransformMatrix::TransformReferenceBox TransformReferenceBox;
+
+  RefPtr<nsComputedDOMStyle> self(this);
+  return ReadIndividualTransformValue(StyleDisplay()->mSpecifiedTranslate,
+    [self](const nsCSSValue::Array* aData, nsString& aResult) {
+      GeckoStyleContext* contextIfGecko =
+        self->mStyleContext ? self->mStyleContext->GetAsGecko() : nullptr;
+      TransformReferenceBox refBox(self->mInnerFrame, nsSize(0, 0));
+      RuleNodeCacheConditions dummy;
+
+      // Even though the spec doesn't say to resolve percentage values, Blink
+      // and Edge do and so until that is clarified we do as well:
+      //
+      // https://github.com/w3c/csswg-drafts/issues/2124
+      switch (nsStyleTransformMatrix::TransformFunctionOf(aData)) {
+        /* translate : <length-percentage> */
+        case eCSSKeyword_translatex: {
+          NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
+          float tx = ProcessTranslatePart(aData->Item(1),
+                                          contextIfGecko,
+                                          self->mStyleContext->PresContext(),
+                                          dummy,
+                                          &refBox,
+                                          &TransformReferenceBox::Width);
+          aResult.AppendFloat(tx);
+          aResult.AppendLiteral("px");
+          break;
+        }
+        /* translate : <length-percentage> <length-percentage> */
+        case eCSSKeyword_translate: {
+          NS_PRECONDITION(aData->Count() == 3, "Invalid array!");
+          float tx = ProcessTranslatePart(aData->Item(1),
+                                          contextIfGecko,
+                                          self->mStyleContext->PresContext(),
+                                          dummy,
+                                          &refBox,
+                                          &TransformReferenceBox::Width);
+          aResult.AppendFloat(tx);
+          aResult.AppendLiteral("px");
+
+          float ty = ProcessTranslatePart(aData->Item(2),
+                                          contextIfGecko,
+                                          self->mStyleContext->PresContext(),
+                                          dummy,
+                                          &refBox,
+                                          &TransformReferenceBox::Height);
+          if (ty != 0) {
+            aResult.AppendLiteral(" ");
+            aResult.AppendFloat(ty);
+            aResult.AppendLiteral("px");
+          }
+          break;
+        }
+        /* translate : <length-percentage> <length-percentage> <length>*/
+        case eCSSKeyword_translate3d: {
+          NS_PRECONDITION(aData->Count() == 4, "Invalid array!");
+          float tx = ProcessTranslatePart(aData->Item(1),
+                                          contextIfGecko,
+                                          self->mStyleContext->PresContext(),
+                                          dummy,
+                                          &refBox,
+                                          &TransformReferenceBox::Width);
+          aResult.AppendFloat(tx);
+          aResult.AppendLiteral("px");
+
+          float ty = ProcessTranslatePart(aData->Item(2),
+                                          contextIfGecko,
+                                          self->mStyleContext->PresContext(),
+                                          dummy,
+                                          &refBox,
+                                          &TransformReferenceBox::Height);
+
+          float tz = ProcessTranslatePart(aData->Item(3),
+                                          contextIfGecko,
+                                          self->mStyleContext->PresContext(),
+                                          dummy,
+                                          &refBox,
+                                          nullptr);
+          if (ty != 0. || tz != 0.) {
+            aResult.AppendLiteral(" ");
+            aResult.AppendFloat(ty);
+            aResult.AppendLiteral("px");
+          }
+          if (tz != 0.) {
+            aResult.AppendLiteral(" ");
+            aResult.AppendFloat(tz);
+            aResult.AppendLiteral("px");
+          }
+
+          break;
+        }
+        default:
+          MOZ_ASSERT_UNREACHABLE("Unexpected CSS keyword.");
+      }
+    });
+}
+
+already_AddRefed<CSSValue>
+nsComputedDOMStyle::DoGetScale()
+{
+  return ReadIndividualTransformValue(StyleDisplay()->mSpecifiedScale,
+    [](const nsCSSValue::Array* aData, nsString& aResult) {
+      switch (nsStyleTransformMatrix::TransformFunctionOf(aData)) {
+        /* scale : <number> */
+        case eCSSKeyword_scalex:
+          NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
+          aResult.AppendFloat(aData->Item(1).GetFloatValue());
+          break;
+        /* scale : <number> <number>*/
+        case eCSSKeyword_scale: {
+          NS_PRECONDITION(aData->Count() == 3, "Invalid array!");
+          aResult.AppendFloat(aData->Item(1).GetFloatValue());
+
+          float sy = aData->Item(2).GetFloatValue();
+          if (sy != 1.) {
+            aResult.AppendLiteral(" ");
+            aResult.AppendFloat(sy);
+          }
+          break;
+        }
+        /* scale : <number> <number> <number> */
+        case eCSSKeyword_scale3d: {
+          NS_PRECONDITION(aData->Count() == 4, "Invalid array!");
+          aResult.AppendFloat(aData->Item(1).GetFloatValue());
+
+          float sy = aData->Item(2).GetFloatValue();
+          float sz = aData->Item(3).GetFloatValue();
+
+          if (sy != 1. || sz != 1.) {
+            aResult.AppendLiteral(" ");
+            aResult.AppendFloat(sy);
+          }
+          if (sz != 1.) {
+            aResult.AppendLiteral(" ");
+            aResult.AppendFloat(sz);
+          }
+          break;
+        }
+        default:
+          MOZ_ASSERT_UNREACHABLE("Unexpected CSS keyword.");
+      }
+    });
+}
+
+already_AddRefed<CSSValue>
+nsComputedDOMStyle::DoGetRotate()
+{
+  return ReadIndividualTransformValue(StyleDisplay()->mSpecifiedRotate,
+    [](const nsCSSValue::Array* aData, nsString& aResult) {
+
+      switch (nsStyleTransformMatrix::TransformFunctionOf(aData)) {
+        /* rotate : <angle> */
+        case eCSSKeyword_rotate: {
+          NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
+          float theta = aData->Item(1).GetAngleValueInDegrees();
+          aResult.AppendFloat(theta);
+          aResult.AppendLiteral("deg");
+          break;
+        }
+        /* rotate : <number> <number> <number> <angle> */
+        case eCSSKeyword_rotate3d: {
+          NS_PRECONDITION(aData->Count() == 5, "Invalid array!");
+          float rx = aData->Item(1).GetFloatValue();
+          float ry = aData->Item(2).GetFloatValue();
+          float rz = aData->Item(3).GetFloatValue();
+          if (rx != 0. || ry != 0. || rz != 1.) {
+            aResult.AppendFloat(rx);
+            aResult.AppendLiteral(" ");
+            aResult.AppendFloat(ry);
+            aResult.AppendLiteral(" ");
+            aResult.AppendFloat(rz);
+            aResult.AppendLiteral(" ");
+          }
+          float theta = aData->Item(4).GetAngleValueInDegrees();
+          aResult.AppendFloat(theta);
+          aResult.AppendLiteral("deg");
+          break;
+        }
+        default:
+          MOZ_ASSERT_UNREACHABLE("Unexpected CSS keyword.");
+      }
+    });
+}
+
 /* static */ already_AddRefed<nsROCSSPrimitiveValue>
 nsComputedDOMStyle::MatrixToCSSValue(const mozilla::gfx::Matrix4x4& matrix)
 {
   bool is3D = !matrix.Is2D();
 
   nsAutoString resultString(NS_LITERAL_STRING("matrix"));
   if (is3D) {
     resultString.AppendLiteral("3d");
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -499,16 +499,19 @@ private:
   already_AddRefed<CSSValue> DoGetOverflowClipBoxBlock();
   already_AddRefed<CSSValue> DoGetOverflowClipBoxInline();
   already_AddRefed<CSSValue> DoGetResize();
   already_AddRefed<CSSValue> DoGetPageBreakAfter();
   already_AddRefed<CSSValue> DoGetPageBreakBefore();
   already_AddRefed<CSSValue> DoGetPageBreakInside();
   already_AddRefed<CSSValue> DoGetTouchAction();
   already_AddRefed<CSSValue> DoGetTransform();
+  already_AddRefed<CSSValue> DoGetTranslate();
+  already_AddRefed<CSSValue> DoGetRotate();
+  already_AddRefed<CSSValue> DoGetScale();
   already_AddRefed<CSSValue> DoGetTransformBox();
   already_AddRefed<CSSValue> DoGetTransformOrigin();
   already_AddRefed<CSSValue> DoGetPerspective();
   already_AddRefed<CSSValue> DoGetBackfaceVisibility();
   already_AddRefed<CSSValue> DoGetPerspectiveOrigin();
   already_AddRefed<CSSValue> DoGetTransformStyle();
   already_AddRefed<CSSValue> DoGetOrient();
   already_AddRefed<CSSValue> DoGetScrollBehavior();
--- a/layout/style/nsComputedDOMStylePropertyList.h
+++ b/layout/style/nsComputedDOMStylePropertyList.h
@@ -217,18 +217,20 @@ COMPUTED_STYLE_PROP(page_break_before,  
 COMPUTED_STYLE_PROP(page_break_inside,             PageBreakInside)
 COMPUTED_STYLE_PROP(perspective,                   Perspective)
 COMPUTED_STYLE_PROP(perspective_origin,            PerspectiveOrigin)
 COMPUTED_STYLE_PROP(pointer_events,                PointerEvents)
 COMPUTED_STYLE_PROP(position,                      Position)
 COMPUTED_STYLE_PROP(quotes,                        Quotes)
 COMPUTED_STYLE_PROP(resize,                        Resize)
 COMPUTED_STYLE_PROP(right,                         Right)
+COMPUTED_STYLE_PROP(rotate,                        Rotate)
 COMPUTED_STYLE_PROP(ruby_align,                    RubyAlign)
 COMPUTED_STYLE_PROP(ruby_position,                 RubyPosition)
+COMPUTED_STYLE_PROP(scale,                         Scale)
 COMPUTED_STYLE_PROP(scroll_behavior,               ScrollBehavior)
 COMPUTED_STYLE_PROP(scroll_snap_coordinate,        ScrollSnapCoordinate)
 COMPUTED_STYLE_PROP(scroll_snap_destination,       ScrollSnapDestination)
 COMPUTED_STYLE_PROP(scroll_snap_points_x,          ScrollSnapPointsX)
 COMPUTED_STYLE_PROP(scroll_snap_points_y,          ScrollSnapPointsY)
 COMPUTED_STYLE_PROP(scroll_snap_type_x,            ScrollSnapTypeX)
 COMPUTED_STYLE_PROP(scroll_snap_type_y,            ScrollSnapTypeY)
 COMPUTED_STYLE_PROP(shape_image_threshold,         ShapeImageThreshold)
@@ -258,16 +260,17 @@ COMPUTED_STYLE_PROP(transform,          
 COMPUTED_STYLE_PROP(transform_box,                 TransformBox)
 COMPUTED_STYLE_PROP(transform_origin,              TransformOrigin)
 COMPUTED_STYLE_PROP(transform_style,               TransformStyle)
 //// COMPUTED_STYLE_PROP(transition,               Transition)
 COMPUTED_STYLE_PROP(transition_delay,              TransitionDelay)
 COMPUTED_STYLE_PROP(transition_duration,           TransitionDuration)
 COMPUTED_STYLE_PROP(transition_property,           TransitionProperty)
 COMPUTED_STYLE_PROP(transition_timing_function,    TransitionTimingFunction)
+COMPUTED_STYLE_PROP(translate,                     Translate)
 COMPUTED_STYLE_PROP(unicode_bidi,                  UnicodeBidi)
 COMPUTED_STYLE_PROP(vertical_align,                VerticalAlign)
 COMPUTED_STYLE_PROP(visibility,                    Visibility)
 COMPUTED_STYLE_PROP(white_space,                   WhiteSpace)
 // COMPUTED_STYLE_PROP(widows,                     Widows)
 COMPUTED_STYLE_PROP(width,                         Width)
 COMPUTED_STYLE_PROP(will_change,                   WillChange)
 COMPUTED_STYLE_PROP(word_break,                    WordBreak)