Index: third_party/WebKit/Source/core/css/cssom/CSSTranslation.cpp |
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSTranslation.cpp b/third_party/WebKit/Source/core/css/cssom/CSSTranslation.cpp |
index 7948a0d3c782639172897ca405924f8b57fd416a..1df7c3b63a74d4cd739609264a79471cefa64102 100644 |
--- a/third_party/WebKit/Source/core/css/cssom/CSSTranslation.cpp |
+++ b/third_party/WebKit/Source/core/css/cssom/CSSTranslation.cpp |
@@ -8,16 +8,98 @@ |
#include "core/css/CSSPrimitiveValue.h" |
#include "core/css/cssom/CSSNumericValue.h" |
#include "core/css/cssom/CSSStyleValue.h" |
+#include "core/geometry/DOMMatrix.h" |
namespace blink { |
+namespace { |
+ |
+bool IsLengthOrPercent(const CSSNumericValue* value) { |
+ return (value->GetType() == CSSStyleValue::StyleValueType::kLengthType || |
+ value->GetType() == CSSStyleValue::StyleValueType::kPercentType); |
+} |
+ |
+bool IsLengthValue(const CSSValue& value) { |
+ return value.IsPrimitiveValue() && ToCSSPrimitiveValue(value).IsLength(); |
+} |
+ |
+CSSTranslation* FromCSSTranslate(const CSSFunctionValue& value) { |
+ DCHECK_GT(value.length(), 0UL); |
+ DCHECK(IsLengthValue(value.Item(0))); |
+ |
+ CSSNumericValue* x = |
+ CSSNumericValue::FromCSSValue(ToCSSPrimitiveValue(value.Item(0))); |
+ if (!x) |
+ return nullptr; |
+ |
+ if (value.length() == 1) { |
+ return CSSTranslation::Create( |
+ x, CSSUnitValue::Create(0, CSSPrimitiveValue::UnitType::kPixels)); |
+ } |
+ |
+ DCHECK_EQ(value.length(), 2UL); |
+ DCHECK(IsLengthValue(value.Item(1))); |
+ |
+ CSSNumericValue* y = |
+ CSSNumericValue::FromCSSValue(ToCSSPrimitiveValue(value.Item(1))); |
+ if (!y) |
+ return nullptr; |
+ return CSSTranslation::Create(x, y); |
+} |
+ |
+CSSTranslation* FromCSSTranslateXYZ(const CSSFunctionValue& value) { |
+ DCHECK_EQ(value.length(), 1UL); |
+ DCHECK(IsLengthValue(value.Item(0))); |
+ |
+ CSSNumericValue* length = |
+ CSSNumericValue::FromCSSValue(ToCSSPrimitiveValue(value.Item(0))); |
+ if (!length) |
+ return nullptr; |
+ |
+ switch (value.FunctionType()) { |
+ case CSSValueTranslateX: |
+ return CSSTranslation::Create( |
+ length, |
+ CSSUnitValue::Create(0, CSSPrimitiveValue::UnitType::kPixels)); |
+ case CSSValueTranslateY: |
+ return CSSTranslation::Create( |
+ CSSUnitValue::Create(0, CSSPrimitiveValue::UnitType::kPixels), |
+ length); |
+ case CSSValueTranslateZ: |
+ return CSSTranslation::Create( |
+ CSSUnitValue::Create(0, CSSPrimitiveValue::UnitType::kPixels), |
+ CSSUnitValue::Create(0, CSSPrimitiveValue::UnitType::kPixels), |
+ length); |
+ default: |
+ NOTREACHED(); |
+ return nullptr; |
+ } |
+} |
+ |
+CSSTranslation* FromCSSTranslate3D(const CSSFunctionValue& value) { |
+ DCHECK_EQ(value.length(), 3UL); |
+ DCHECK(IsLengthValue(value.Item(0))); |
+ DCHECK(IsLengthValue(value.Item(1))); |
+ DCHECK(IsLengthValue(value.Item(2))); |
+ |
+ CSSNumericValue* x = |
+ CSSNumericValue::FromCSSValue(ToCSSPrimitiveValue(value.Item(0))); |
+ CSSNumericValue* y = |
+ CSSNumericValue::FromCSSValue(ToCSSPrimitiveValue(value.Item(1))); |
+ CSSNumericValue* z = |
+ CSSNumericValue::FromCSSValue(ToCSSPrimitiveValue(value.Item(2))); |
+ if (!x || !y || !z) |
+ return nullptr; |
+ |
+ return CSSTranslation::Create(x, y, z); |
+} |
+ |
+} // namespace |
+ |
CSSTranslation* CSSTranslation::Create(CSSNumericValue* x, |
CSSNumericValue* y, |
ExceptionState& exception_state) { |
- if ((x->GetType() != CSSStyleValue::StyleValueType::kLengthType && |
- x->GetType() != CSSStyleValue::StyleValueType::kPercentType) || |
- (y->GetType() != CSSStyleValue::StyleValueType::kLengthType && |
- y->GetType() != CSSStyleValue::StyleValueType::kPercentType)) { |
+ if (!IsLengthOrPercent(x) || !IsLengthOrPercent(y)) { |
exception_state.ThrowTypeError( |
"Must pass length or percentage to X and Y of CSSTranslation"); |
return nullptr; |
@@ -31,10 +113,7 @@ CSSTranslation* CSSTranslation::Create(CSSNumericValue* x, |
CSSNumericValue* y, |
CSSNumericValue* z, |
ExceptionState& exception_state) { |
- if ((x->GetType() != CSSStyleValue::StyleValueType::kLengthType && |
- x->GetType() != CSSStyleValue::StyleValueType::kPercentType) || |
- (y->GetType() != CSSStyleValue::StyleValueType::kLengthType && |
- y->GetType() != CSSStyleValue::StyleValueType::kPercentType)) { |
+ if (!IsLengthOrPercent(x) || !IsLengthOrPercent(y)) { |
exception_state.ThrowTypeError( |
"Must pass length or percentage to X and Y of CSSTranslation"); |
return nullptr; |
@@ -51,6 +130,40 @@ CSSTranslation* CSSTranslation::Create(CSSNumericValue* x, |
return new CSSTranslation(x, y, z, false /* is2D */); |
} |
+CSSTranslation* CSSTranslation::Create(CSSNumericValue* x, CSSNumericValue* y) { |
+ DCHECK(IsLengthOrPercent(x)); |
+ DCHECK(IsLengthOrPercent(y)); |
+ return new CSSTranslation( |
+ x, y, CSSUnitValue::Create(0, CSSPrimitiveValue::UnitType::kPixels), |
+ true /* is2D */); |
+} |
+ |
+CSSTranslation* CSSTranslation::Create(CSSNumericValue* x, |
+ CSSNumericValue* y, |
+ CSSNumericValue* z) { |
+ DCHECK(IsLengthOrPercent(x)); |
+ DCHECK(IsLengthOrPercent(y)); |
+ DCHECK_EQ(z->GetType(), CSSStyleValue::StyleValueType::kLengthType); |
+ DCHECK(!z->ContainsPercent()); |
+ return new CSSTranslation(x, y, z, false /* is2D */); |
+} |
+ |
+CSSTranslation* CSSTranslation::FromCSSValue(const CSSFunctionValue& value) { |
+ switch (value.FunctionType()) { |
+ case CSSValueTranslateX: |
+ case CSSValueTranslateY: |
+ case CSSValueTranslateZ: |
+ return FromCSSTranslateXYZ(value); |
+ case CSSValueTranslate: |
+ return FromCSSTranslate(value); |
+ case CSSValueTranslate3d: |
+ return FromCSSTranslate3D(value); |
+ default: |
+ NOTREACHED(); |
+ return nullptr; |
+ } |
+} |
+ |
void CSSTranslation::setX(CSSNumericValue* x, ExceptionState& exception_state) { |
if (x->GetType() != CSSStyleValue::StyleValueType::kLengthType && |
x->GetType() != CSSStyleValue::StyleValueType::kPercentType) { |
@@ -72,11 +185,11 @@ void CSSTranslation::setY(CSSNumericValue* y, ExceptionState& exception_state) { |
} |
void CSSTranslation::setZ(CSSNumericValue* z, ExceptionState& exception_state) { |
- if (z && z->GetType() != CSSStyleValue::StyleValueType::kLengthType) { |
+ if (z->GetType() != CSSStyleValue::StyleValueType::kLengthType) { |
exception_state.ThrowTypeError("Must pass length to Z of CSSTranslation"); |
return; |
} |
- if (z && z->ContainsPercent()) { |
+ if (z->ContainsPercent()) { |
exception_state.ThrowTypeError( |
"CSSTranslation does not support z CSSNumericValue with percent units"); |
return; |
@@ -84,6 +197,20 @@ void CSSTranslation::setZ(CSSNumericValue* z, ExceptionState& exception_state) { |
z_ = z; |
} |
+DOMMatrix* CSSTranslation::AsMatrix() const { |
+ CSSUnitValue* x = x_->to(CSSPrimitiveValue::UnitType::kPixels); |
+ CSSUnitValue* y = y_->to(CSSPrimitiveValue::UnitType::kPixels); |
+ CSSUnitValue* z = z_->to(CSSPrimitiveValue::UnitType::kPixels); |
+ // TODO(meade): What should happen when the translation contains relative |
+ // lengths here? |
+ // https://github.com/w3c/css-houdini-drafts/issues/421 |
+ if (!x || !y || !z) |
+ return nullptr; |
+ |
+ DOMMatrix* matrix = DOMMatrix::Create(); |
+ return matrix->translate(x->value(), y->value(), z->value()); |
+} |
+ |
CSSFunctionValue* CSSTranslation::ToCSSValue() const { |
CSSFunctionValue* result = CSSFunctionValue::Create( |
is2D() ? CSSValueTranslate : CSSValueTranslate3d); |