Bug 1207734 - Part 5. Implement the getComputedStyle API for individual transform. r=birtles
MozReview-Commit-ID: 3w1kA6VCXsg
--- 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)