mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Implement moz-transform property
This commit is contained in:
parent
67799f9445
commit
f9225d84aa
7 changed files with 320 additions and 46 deletions
|
@ -2902,6 +2902,10 @@ impl Fragment {
|
||||||
transform::ComputedOperation::Matrix(m) => {
|
transform::ComputedOperation::Matrix(m) => {
|
||||||
m.to_gfx_matrix()
|
m.to_gfx_matrix()
|
||||||
}
|
}
|
||||||
|
transform::ComputedOperation::MatrixWithPercents(_) => {
|
||||||
|
// `-moz-transform` is not implemented in Servo yet.
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
transform::ComputedOperation::Skew(theta_x, theta_y) => {
|
transform::ComputedOperation::Skew(theta_x, theta_y) => {
|
||||||
Matrix4D::create_skew(Radians::new(theta_x.radians()),
|
Matrix4D::create_skew(Radians::new(theta_x.radians()),
|
||||||
Radians::new(theta_y.radians()))
|
Radians::new(theta_y.radians()))
|
||||||
|
|
|
@ -479,12 +479,23 @@ impl ToCss for PropertyDeclarationBlock {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Substeps 7 and 8
|
// Substeps 7 and 8
|
||||||
|
// We need to check the shorthand whether it's an alias property or not.
|
||||||
|
// If it's an alias property, it should be serialized like its longhand.
|
||||||
|
if shorthand.flags().contains(ALIAS_PROPERTY) {
|
||||||
|
append_serialization::<_, Cloned<slice::Iter< _>>, _>(
|
||||||
|
dest,
|
||||||
|
&property,
|
||||||
|
value,
|
||||||
|
importance,
|
||||||
|
&mut is_first_serialization)?;
|
||||||
|
} else {
|
||||||
append_serialization::<_, Cloned<slice::Iter< _>>, _>(
|
append_serialization::<_, Cloned<slice::Iter< _>>, _>(
|
||||||
dest,
|
dest,
|
||||||
&shorthand,
|
&shorthand,
|
||||||
value,
|
value,
|
||||||
importance,
|
importance,
|
||||||
&mut is_first_serialization)?;
|
&mut is_first_serialization)?;
|
||||||
|
}
|
||||||
|
|
||||||
for current_longhand in ¤t_longhands {
|
for current_longhand in ¤t_longhands {
|
||||||
// Substep 9
|
// Substep 9
|
||||||
|
|
|
@ -1834,12 +1834,14 @@ fn static_assert() {
|
||||||
<%def name="transform_function_arm(name, keyword, items)">
|
<%def name="transform_function_arm(name, keyword, items)">
|
||||||
<%
|
<%
|
||||||
pattern = None
|
pattern = None
|
||||||
if name == "matrix":
|
if keyword == "matrix3d":
|
||||||
# m11, m12, m13, ..
|
|
||||||
indices = [str(i) + str(j) for i in range(1, 5) for j in range(1, 5)]
|
|
||||||
# m11: number1, m12: number2, ..
|
# m11: number1, m12: number2, ..
|
||||||
single_patterns = ["m%s: number%s" % (index, i + 1) for (i, index) in enumerate(indices)]
|
single_patterns = ["m%s: %s" % (str(a / 4 + 1) + str(a % 4 + 1), b + str(a + 1)) for (a, b)
|
||||||
|
in enumerate(items)]
|
||||||
|
if name == "Matrix":
|
||||||
pattern = "ComputedMatrix { %s }" % ", ".join(single_patterns)
|
pattern = "ComputedMatrix { %s }" % ", ".join(single_patterns)
|
||||||
|
else:
|
||||||
|
pattern = "ComputedMatrixWithPercents { %s }" % ", ".join(single_patterns)
|
||||||
else:
|
else:
|
||||||
# Generate contents of pattern from items
|
# Generate contents of pattern from items
|
||||||
pattern = ", ".join([b + str(a+1) for (a,b) in enumerate(items)])
|
pattern = ", ".join([b + str(a+1) for (a,b) in enumerate(items)])
|
||||||
|
@ -1854,7 +1856,7 @@ fn static_assert() {
|
||||||
"number" : "bindings::Gecko_CSSValue_SetNumber(%s, %s)",
|
"number" : "bindings::Gecko_CSSValue_SetNumber(%s, %s)",
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
longhands::transform::computed_value::ComputedOperation::${name.title()}(${pattern}) => {
|
longhands::transform::computed_value::ComputedOperation::${name}(${pattern}) => {
|
||||||
bindings::Gecko_CSSValue_SetFunction(gecko_value, ${len(items) + 1});
|
bindings::Gecko_CSSValue_SetFunction(gecko_value, ${len(items) + 1});
|
||||||
bindings::Gecko_CSSValue_SetKeyword(
|
bindings::Gecko_CSSValue_SetKeyword(
|
||||||
bindings::Gecko_CSSValue_GetArrayItem(gecko_value, 0),
|
bindings::Gecko_CSSValue_GetArrayItem(gecko_value, 0),
|
||||||
|
@ -1873,6 +1875,7 @@ fn static_assert() {
|
||||||
use gecko_bindings::structs::nsCSSKeyword::*;
|
use gecko_bindings::structs::nsCSSKeyword::*;
|
||||||
use gecko_bindings::sugar::refptr::RefPtr;
|
use gecko_bindings::sugar::refptr::RefPtr;
|
||||||
use properties::longhands::transform::computed_value::ComputedMatrix;
|
use properties::longhands::transform::computed_value::ComputedMatrix;
|
||||||
|
use properties::longhands::transform::computed_value::ComputedMatrixWithPercents;
|
||||||
|
|
||||||
unsafe { output.clear() };
|
unsafe { output.clear() };
|
||||||
|
|
||||||
|
@ -1888,12 +1891,14 @@ fn static_assert() {
|
||||||
value list of the same length as the transform vector");
|
value list of the same length as the transform vector");
|
||||||
unsafe {
|
unsafe {
|
||||||
match servo {
|
match servo {
|
||||||
${transform_function_arm("matrix", "matrix3d", ["number"] * 16)}
|
${transform_function_arm("Matrix", "matrix3d", ["number"] * 16)}
|
||||||
${transform_function_arm("skew", "skew", ["angle"] * 2)}
|
${transform_function_arm("MatrixWithPercents", "matrix3d", ["number"] * 12 + ["lop"] * 2
|
||||||
${transform_function_arm("translate", "translate3d", ["lop", "lop", "length"])}
|
+ ["length"] + ["number"])}
|
||||||
${transform_function_arm("scale", "scale3d", ["number"] * 3)}
|
${transform_function_arm("Skew", "skew", ["angle"] * 2)}
|
||||||
${transform_function_arm("rotate", "rotate3d", ["number"] * 3 + ["angle"])}
|
${transform_function_arm("Translate", "translate3d", ["lop", "lop", "length"])}
|
||||||
${transform_function_arm("perspective", "perspective", ["length"])}
|
${transform_function_arm("Scale", "scale3d", ["number"] * 3)}
|
||||||
|
${transform_function_arm("Rotate", "rotate3d", ["number"] * 3 + ["angle"])}
|
||||||
|
${transform_function_arm("Perspective", "perspective", ["length"])}
|
||||||
}
|
}
|
||||||
cur = (*cur).mNext;
|
cur = (*cur).mNext;
|
||||||
}
|
}
|
||||||
|
@ -1929,19 +1934,19 @@ fn static_assert() {
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
eCSSKeyword_${keyword} => {
|
eCSSKeyword_${keyword} => {
|
||||||
ComputedOperation::${name.title()}(
|
ComputedOperation::${name}(
|
||||||
% if name == "matrix":
|
% if keyword == "matrix3d":
|
||||||
ComputedMatrix {
|
ComputedMatrix {
|
||||||
% endif
|
% endif
|
||||||
% for index, item in enumerate(items):
|
% for index, item in enumerate(items):
|
||||||
% if name == "matrix":
|
% if keyword == "matrix3d":
|
||||||
m${index / 4 + 1}${index % 4 + 1}:
|
m${index / 4 + 1}${index % 4 + 1}:
|
||||||
% endif
|
% endif
|
||||||
${css_value_getters[item] % (
|
${css_value_getters[item] % (
|
||||||
"bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, %d)" % (index + 1)
|
"bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, %d)" % (index + 1)
|
||||||
)},
|
)},
|
||||||
% endfor
|
% endfor
|
||||||
% if name == "matrix":
|
% if keyword == "matrix3d":
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
)
|
)
|
||||||
|
@ -1968,12 +1973,12 @@ fn static_assert() {
|
||||||
};
|
};
|
||||||
let servo = unsafe {
|
let servo = unsafe {
|
||||||
match transform_function {
|
match transform_function {
|
||||||
${computed_operation_arm("matrix", "matrix3d", ["number"] * 16)}
|
${computed_operation_arm("Matrix", "matrix3d", ["number"] * 16)}
|
||||||
${computed_operation_arm("skew", "skew", ["angle"] * 2)}
|
${computed_operation_arm("Skew", "skew", ["angle"] * 2)}
|
||||||
${computed_operation_arm("translate", "translate3d", ["lop", "lop", "length"])}
|
${computed_operation_arm("Translate", "translate3d", ["lop", "lop", "length"])}
|
||||||
${computed_operation_arm("scale", "scale3d", ["number"] * 3)}
|
${computed_operation_arm("Scale", "scale3d", ["number"] * 3)}
|
||||||
${computed_operation_arm("rotate", "rotate3d", ["number"] * 3 + ["angle"])}
|
${computed_operation_arm("Rotate", "rotate3d", ["number"] * 3 + ["angle"])}
|
||||||
${computed_operation_arm("perspective", "perspective", ["length"])}
|
${computed_operation_arm("Perspective", "perspective", ["length"])}
|
||||||
_ => panic!("We shouldn't set any other transform function types"),
|
_ => panic!("We shouldn't set any other transform function types"),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1127,6 +1127,7 @@ fn build_identity_transform_list(list: &[TransformOperation]) -> Vec<TransformOp
|
||||||
let identity = ComputedMatrix::identity();
|
let identity = ComputedMatrix::identity();
|
||||||
result.push(TransformOperation::Matrix(identity));
|
result.push(TransformOperation::Matrix(identity));
|
||||||
}
|
}
|
||||||
|
TransformOperation::MatrixWithPercents(..) => {}
|
||||||
TransformOperation::Skew(..) => {
|
TransformOperation::Skew(..) => {
|
||||||
result.push(TransformOperation::Skew(Angle::zero(), Angle::zero()))
|
result.push(TransformOperation::Skew(Angle::zero(), Angle::zero()))
|
||||||
}
|
}
|
||||||
|
@ -1167,6 +1168,12 @@ fn interpolate_transform_list(from_list: &[TransformOperation],
|
||||||
let interpolated = from.interpolate(&_to, progress).unwrap();
|
let interpolated = from.interpolate(&_to, progress).unwrap();
|
||||||
result.push(TransformOperation::Matrix(interpolated));
|
result.push(TransformOperation::Matrix(interpolated));
|
||||||
}
|
}
|
||||||
|
(&TransformOperation::MatrixWithPercents(_),
|
||||||
|
&TransformOperation::MatrixWithPercents(_)) => {
|
||||||
|
// We don't interpolate `-moz-transform` matrices yet.
|
||||||
|
// They contain percentage values.
|
||||||
|
{}
|
||||||
|
}
|
||||||
(&TransformOperation::Skew(fx, fy),
|
(&TransformOperation::Skew(fx, fy),
|
||||||
&TransformOperation::Skew(tx, ty)) => {
|
&TransformOperation::Skew(tx, ty)) => {
|
||||||
let ix = fx.interpolate(&tx, progress).unwrap();
|
let ix = fx.interpolate(&tx, progress).unwrap();
|
||||||
|
|
|
@ -1108,22 +1108,26 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<%helpers:longhand name="transform" products="gecko servo" extra_prefixes="webkit"
|
<%helpers:longhand name="transform" extra_prefixes="webkit"
|
||||||
animation_type="normal"
|
animation_type="normal"
|
||||||
flags="CREATES_STACKING_CONTEXT FIXPOS_CB"
|
flags="CREATES_STACKING_CONTEXT FIXPOS_CB"
|
||||||
spec="https://drafts.csswg.org/css-transforms/#propdef-transform">
|
spec="https://drafts.csswg.org/css-transforms/#propdef-transform">
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use values::specified::{Angle, Length, LengthOrPercentage, Number};
|
use values::computed::{LengthOrPercentageOrNumber as ComputedLoPoNumber, LengthOrNumber as ComputedLoN};
|
||||||
|
use values::computed::{LengthOrPercentage as ComputedLoP, Length as ComputedLength};
|
||||||
|
use values::specified::{Angle, Length, LengthOrPercentage};
|
||||||
|
use values::specified::{LengthOrNumber, LengthOrPercentageOrNumber as LoPoNumber, Number};
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use style_traits::values::Css;
|
use style_traits::values::Css;
|
||||||
use values::CSSFloat;
|
|
||||||
use values::HasViewportPercentage;
|
use values::HasViewportPercentage;
|
||||||
|
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
|
use app_units::Au;
|
||||||
use values::CSSFloat;
|
use values::CSSFloat;
|
||||||
use values::computed;
|
use values::computed;
|
||||||
|
use values::computed::{Length, LengthOrPercentage};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
@ -1134,6 +1138,16 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
pub m41: CSSFloat, pub m42: CSSFloat, pub m43: CSSFloat, pub m44: CSSFloat,
|
pub m41: CSSFloat, pub m42: CSSFloat, pub m43: CSSFloat, pub m44: CSSFloat,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub struct ComputedMatrixWithPercents {
|
||||||
|
pub m11: CSSFloat, pub m12: CSSFloat, pub m13: CSSFloat, pub m14: CSSFloat,
|
||||||
|
pub m21: CSSFloat, pub m22: CSSFloat, pub m23: CSSFloat, pub m24: CSSFloat,
|
||||||
|
pub m31: CSSFloat, pub m32: CSSFloat, pub m33: CSSFloat, pub m34: CSSFloat,
|
||||||
|
pub m41: LengthOrPercentage, pub m42: LengthOrPercentage,
|
||||||
|
pub m43: Length, pub m44: CSSFloat,
|
||||||
|
}
|
||||||
|
|
||||||
impl ComputedMatrix {
|
impl ComputedMatrix {
|
||||||
pub fn identity() -> ComputedMatrix {
|
pub fn identity() -> ComputedMatrix {
|
||||||
ComputedMatrix {
|
ComputedMatrix {
|
||||||
|
@ -1145,10 +1159,24 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ComputedMatrixWithPercents {
|
||||||
|
pub fn identity() -> ComputedMatrixWithPercents {
|
||||||
|
ComputedMatrixWithPercents {
|
||||||
|
m11: 1.0, m12: 0.0, m13: 0.0, m14: 0.0,
|
||||||
|
m21: 0.0, m22: 1.0, m23: 0.0, m24: 0.0,
|
||||||
|
m31: 0.0, m32: 0.0, m33: 1.0, m34: 0.0,
|
||||||
|
m41: LengthOrPercentage::zero(), m42: LengthOrPercentage::zero(),
|
||||||
|
m43: Au(0), m44: 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub enum ComputedOperation {
|
pub enum ComputedOperation {
|
||||||
Matrix(ComputedMatrix),
|
Matrix(ComputedMatrix),
|
||||||
|
// For `-moz-transform` matrix and matrix3d.
|
||||||
|
MatrixWithPercents(ComputedMatrixWithPercents),
|
||||||
Skew(computed::Angle, computed::Angle),
|
Skew(computed::Angle, computed::Angle),
|
||||||
Translate(computed::LengthOrPercentage,
|
Translate(computed::LengthOrPercentage,
|
||||||
computed::LengthOrPercentage,
|
computed::LengthOrPercentage,
|
||||||
|
@ -1174,6 +1202,9 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
pub enum SpecifiedOperation {
|
pub enum SpecifiedOperation {
|
||||||
/// Represents a 2D 2x3 matrix.
|
/// Represents a 2D 2x3 matrix.
|
||||||
Matrix { a: Number, b: Number, c: Number, d: Number, e: Number, f: Number },
|
Matrix { a: Number, b: Number, c: Number, d: Number, e: Number, f: Number },
|
||||||
|
/// Represents a 3D 4x4 matrix with percentage and length values.
|
||||||
|
/// For `moz-transform`.
|
||||||
|
PrefixedMatrix { a: Number, b: Number, c: Number, d: Number, e: LoPoNumber, f: LoPoNumber },
|
||||||
/// Represents a 3D 4x4 matrix.
|
/// Represents a 3D 4x4 matrix.
|
||||||
Matrix3D {
|
Matrix3D {
|
||||||
m11: Number, m12: Number, m13: Number, m14: Number,
|
m11: Number, m12: Number, m13: Number, m14: Number,
|
||||||
|
@ -1181,6 +1212,14 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
m31: Number, m32: Number, m33: Number, m34: Number,
|
m31: Number, m32: Number, m33: Number, m34: Number,
|
||||||
m41: Number, m42: Number, m43: Number, m44: Number,
|
m41: Number, m42: Number, m43: Number, m44: Number,
|
||||||
},
|
},
|
||||||
|
/// Represents a 3D 4x4 matrix with percentage and length values.
|
||||||
|
/// For `moz-transform`.
|
||||||
|
PrefixedMatrix3D {
|
||||||
|
m11: Number, m12: Number, m13: Number, m14: Number,
|
||||||
|
m21: Number, m22: Number, m23: Number, m24: Number,
|
||||||
|
m31: Number, m32: Number, m33: Number, m34: Number,
|
||||||
|
m41: LoPoNumber, m42: LoPoNumber, m43: LengthOrNumber, m44: Number,
|
||||||
|
},
|
||||||
/// A 2D skew.
|
/// A 2D skew.
|
||||||
///
|
///
|
||||||
/// If the second angle is not provided it is assumed zero.
|
/// If the second angle is not provided it is assumed zero.
|
||||||
|
@ -1254,6 +1293,15 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
l3.has_viewport_percentage()
|
l3.has_viewport_percentage()
|
||||||
},
|
},
|
||||||
SpecifiedOperation::Perspective(ref length) => length.has_viewport_percentage(),
|
SpecifiedOperation::Perspective(ref length) => length.has_viewport_percentage(),
|
||||||
|
SpecifiedOperation::PrefixedMatrix{ ref e, ref f, .. } => {
|
||||||
|
e.has_viewport_percentage() ||
|
||||||
|
f.has_viewport_percentage()
|
||||||
|
},
|
||||||
|
SpecifiedOperation::PrefixedMatrix3D{ ref m41, ref m42, ref m43, .. } => {
|
||||||
|
m41.has_viewport_percentage() ||
|
||||||
|
m42.has_viewport_percentage() ||
|
||||||
|
m43.has_viewport_percentage()
|
||||||
|
},
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1266,6 +1314,9 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
Matrix { a, b, c, d, e, f} => write!(
|
Matrix { a, b, c, d, e, f} => write!(
|
||||||
dest, "matrix({}, {}, {}, {}, {}, {})",
|
dest, "matrix({}, {}, {}, {}, {}, {})",
|
||||||
Css(a), Css(b), Css(c), Css(d), Css(e), Css(f)),
|
Css(a), Css(b), Css(c), Css(d), Css(e), Css(f)),
|
||||||
|
PrefixedMatrix { a, b, c, d, ref e, ref f} => write!(
|
||||||
|
dest, "matrix({}, {}, {}, {}, {}, {})",
|
||||||
|
Css(a), Css(b), Css(c), Css(d), Css(e), Css(f)),
|
||||||
Matrix3D {
|
Matrix3D {
|
||||||
m11, m12, m13, m14,
|
m11, m12, m13, m14,
|
||||||
m21, m22, m23, m24,
|
m21, m22, m23, m24,
|
||||||
|
@ -1276,6 +1327,16 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
Css(m21), Css(m22), Css(m23), Css(m24),
|
Css(m21), Css(m22), Css(m23), Css(m24),
|
||||||
Css(m31), Css(m32), Css(m33), Css(m34),
|
Css(m31), Css(m32), Css(m33), Css(m34),
|
||||||
Css(m41), Css(m42), Css(m43), Css(m44)),
|
Css(m41), Css(m42), Css(m43), Css(m44)),
|
||||||
|
PrefixedMatrix3D {
|
||||||
|
m11, m12, m13, m14,
|
||||||
|
m21, m22, m23, m24,
|
||||||
|
m31, m32, m33, m34,
|
||||||
|
ref m41, ref m42, ref m43, m44 } => write!(
|
||||||
|
dest, "matrix3d({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {})",
|
||||||
|
Css(m11), Css(m12), Css(m13), Css(m14),
|
||||||
|
Css(m21), Css(m22), Css(m23), Css(m24),
|
||||||
|
Css(m31), Css(m32), Css(m33), Css(m34),
|
||||||
|
Css(m41), Css(m42), Css(m43), Css(m44)),
|
||||||
Skew(ax, None) => write!(dest, "skew({})", Css(ax)),
|
Skew(ax, None) => write!(dest, "skew({})", Css(ax)),
|
||||||
Skew(ax, Some(ay)) => write!(dest, "skew({}, {})", Css(ax), Css(ay)),
|
Skew(ax, Some(ay)) => write!(dest, "skew({}, {})", Css(ax), Css(ay)),
|
||||||
SkewX(angle) => write!(dest, "skewX({})", Css(angle)),
|
SkewX(angle) => write!(dest, "skewX({})", Css(angle)),
|
||||||
|
@ -1341,7 +1402,8 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow unitless zero angle for rotate() and skew() to align with gecko
|
// Allow unitless zero angle for rotate() and skew() to align with gecko
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
fn parse_internal(context: &ParserContext, input: &mut Parser, prefixed: bool)
|
||||||
|
-> Result<SpecifiedValue,()> {
|
||||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok(SpecifiedValue(Vec::new()))
|
return Ok(SpecifiedValue(Vec::new()))
|
||||||
}
|
}
|
||||||
|
@ -1356,35 +1418,111 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
&name,
|
&name,
|
||||||
"matrix" => {
|
"matrix" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
|
// Standard matrix parsing.
|
||||||
|
if !prefixed {
|
||||||
let values = try!(input.parse_comma_separated(|input| {
|
let values = try!(input.parse_comma_separated(|input| {
|
||||||
specified::parse_number(context, input)
|
specified::parse_number(context, input)
|
||||||
}));
|
}));
|
||||||
if values.len() != 6 {
|
if values.len() != 6 {
|
||||||
return Err(())
|
return Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push(SpecifiedOperation::Matrix {
|
result.push(SpecifiedOperation::Matrix {
|
||||||
a: values[0],
|
a: values[0],
|
||||||
b: values[1],
|
b: values[1],
|
||||||
c: values[2],
|
c: values[2],
|
||||||
d: values[3],
|
d: values[3],
|
||||||
e: values[4],
|
e: values[4],
|
||||||
f: values[5]
|
f: values[5],
|
||||||
|
});
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-standard prefixed matrix parsing.
|
||||||
|
//
|
||||||
|
// -moz-transform accepts LengthOrPercentageOrNumber in the
|
||||||
|
// nondiagonal homogeneous components. transform accepts only number.
|
||||||
|
let mut values = Vec::with_capacity(4);
|
||||||
|
let mut lengths = Vec::with_capacity(2);
|
||||||
|
|
||||||
|
// Consume first number
|
||||||
|
values.push(specified::parse_number(context, input)?);
|
||||||
|
|
||||||
|
// Parse other 5 number/LengthOrPercentageOrNumber
|
||||||
|
for i in 0..5 {
|
||||||
|
input.expect_comma()?;
|
||||||
|
if i < 3 {
|
||||||
|
values.push(specified::parse_number(context, input)?);
|
||||||
|
} else {
|
||||||
|
// -moz-transform accepts LengthOrPercentageOrNumber in the nondiagonal
|
||||||
|
// homogeneous components. transform accepts only number.
|
||||||
|
lengths.push(LoPoNumber::parse(context, input)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push(SpecifiedOperation::PrefixedMatrix {
|
||||||
|
a: values[0],
|
||||||
|
b: values[1],
|
||||||
|
c: values[2],
|
||||||
|
d: values[3],
|
||||||
|
e: lengths[0].clone(),
|
||||||
|
f: lengths[1].clone(),
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"matrix3d" => {
|
"matrix3d" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
|
// Standard matrix3d parsing.
|
||||||
|
if !prefixed {
|
||||||
let values = try!(input.parse_comma_separated(|i| specified::parse_number(context, i)));
|
let values = try!(input.parse_comma_separated(|i| specified::parse_number(context, i)));
|
||||||
if values.len() != 16 {
|
if values.len() != 16 {
|
||||||
return Err(())
|
return Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push(SpecifiedOperation::Matrix3D {
|
result.push(SpecifiedOperation::Matrix3D {
|
||||||
m11: values[ 0], m12: values[ 1], m13: values[ 2], m14: values[ 3],
|
m11: values[ 0], m12: values[ 1], m13: values[ 2], m14: values[ 3],
|
||||||
m21: values[ 4], m22: values[ 5], m23: values[ 6], m24: values[ 7],
|
m21: values[ 4], m22: values[ 5], m23: values[ 6], m24: values[ 7],
|
||||||
m31: values[ 8], m32: values[ 9], m33: values[10], m34: values[11],
|
m31: values[ 8], m32: values[ 9], m33: values[10], m34: values[11],
|
||||||
m41: values[12], m42: values[13], m43: values[14], m44: values[15]
|
m41: values[12], m42: values[13], m43: values[14], m44: values[15]
|
||||||
});
|
});
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-standard prefixed matrix3d parsing.
|
||||||
|
//
|
||||||
|
// -moz-transform accepts LengthOrPercentageOrNumber in the
|
||||||
|
// nondiagonal homogeneous components. transform accepts only number.
|
||||||
|
let mut values = Vec::with_capacity(13);
|
||||||
|
let mut lops = Vec::with_capacity(2);
|
||||||
|
let mut length_or_number = None;
|
||||||
|
|
||||||
|
// Parse first number
|
||||||
|
values.push(specified::parse_number(context, input)?);
|
||||||
|
|
||||||
|
// Parse other 15 number/LengthOrPercentageOrNumber
|
||||||
|
for i in 0..15 {
|
||||||
|
input.expect_comma()?;
|
||||||
|
// -moz-transform accepts LengthOrPercentageOrNumber in the nondiagonal
|
||||||
|
// homogeneous components. transform accepts only number.
|
||||||
|
if i < 11 || i > 13 {
|
||||||
|
values.push(specified::parse_number(context, input)?);
|
||||||
|
} else if i == 13 {
|
||||||
|
// m43
|
||||||
|
length_or_number = Some(LengthOrNumber::parse(context, input)?);
|
||||||
|
} else {
|
||||||
|
// m41 and m42
|
||||||
|
lops.push(LoPoNumber::parse(context, input)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push(SpecifiedOperation::PrefixedMatrix3D {
|
||||||
|
m11: values[ 0], m12: values[ 1], m13: values[ 2], m14: values[ 3],
|
||||||
|
m21: values[ 4], m22: values[ 5], m23: values[ 6], m24: values[ 7],
|
||||||
|
m31: values[ 8], m32: values[ 9], m33: values[10], m34: values[11],
|
||||||
|
m41: lops[0].clone(), m42: lops[1].clone(), m43: length_or_number.unwrap(),
|
||||||
|
m44: values[12]
|
||||||
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
|
@ -1562,12 +1700,26 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parses `transform` property.
|
||||||
|
#[inline]
|
||||||
|
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||||
|
parse_internal(context, input, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses `-moz-transform` property. This prefixed property also accepts LengthOrPercentage
|
||||||
|
/// in the nondiagonal homogeneous components of matrix and matrix3d.
|
||||||
|
#[inline]
|
||||||
|
pub fn parse_prefixed(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||||
|
parse_internal(context, input, true)
|
||||||
|
}
|
||||||
|
|
||||||
impl ToComputedValue for SpecifiedValue {
|
impl ToComputedValue for SpecifiedValue {
|
||||||
type ComputedValue = computed_value::T;
|
type ComputedValue = computed_value::T;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||||
use self::SpecifiedOperation::*;
|
use self::SpecifiedOperation::*;
|
||||||
|
|
||||||
if self.0.is_empty() {
|
if self.0.is_empty() {
|
||||||
return computed_value::T(None)
|
return computed_value::T(None)
|
||||||
}
|
}
|
||||||
|
@ -1585,11 +1737,21 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
comp.m42 = f.to_computed_value(context);
|
comp.m42 = f.to_computed_value(context);
|
||||||
result.push(computed_value::ComputedOperation::Matrix(comp));
|
result.push(computed_value::ComputedOperation::Matrix(comp));
|
||||||
}
|
}
|
||||||
|
PrefixedMatrix { a, b, c, d, ref e, ref f } => {
|
||||||
|
let mut comp = computed_value::ComputedMatrixWithPercents::identity();
|
||||||
|
comp.m11 = a.to_computed_value(context);
|
||||||
|
comp.m12 = b.to_computed_value(context);
|
||||||
|
comp.m21 = c.to_computed_value(context);
|
||||||
|
comp.m22 = d.to_computed_value(context);
|
||||||
|
comp.m41 = lopon_to_lop(&e.to_computed_value(context));
|
||||||
|
comp.m42 = lopon_to_lop(&f.to_computed_value(context));
|
||||||
|
result.push(computed_value::ComputedOperation::MatrixWithPercents(comp));
|
||||||
|
}
|
||||||
Matrix3D {
|
Matrix3D {
|
||||||
m11, m12, m13, m14,
|
m11, m12, m13, m14,
|
||||||
m21, m22, m23, m24,
|
m21, m22, m23, m24,
|
||||||
m31, m32, m33, m34,
|
m31, m32, m33, m34,
|
||||||
m41, m42, m43, m44 } => {
|
ref m41, ref m42, ref m43, m44 } => {
|
||||||
let comp = computed_value::ComputedMatrix {
|
let comp = computed_value::ComputedMatrix {
|
||||||
m11: m11.to_computed_value(context),
|
m11: m11.to_computed_value(context),
|
||||||
m12: m12.to_computed_value(context),
|
m12: m12.to_computed_value(context),
|
||||||
|
@ -1610,6 +1772,31 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
};
|
};
|
||||||
result.push(computed_value::ComputedOperation::Matrix(comp));
|
result.push(computed_value::ComputedOperation::Matrix(comp));
|
||||||
}
|
}
|
||||||
|
PrefixedMatrix3D {
|
||||||
|
m11, m12, m13, m14,
|
||||||
|
m21, m22, m23, m24,
|
||||||
|
m31, m32, m33, m34,
|
||||||
|
ref m41, ref m42, ref m43, m44 } => {
|
||||||
|
let comp = computed_value::ComputedMatrixWithPercents {
|
||||||
|
m11: m11.to_computed_value(context),
|
||||||
|
m12: m12.to_computed_value(context),
|
||||||
|
m13: m13.to_computed_value(context),
|
||||||
|
m14: m14.to_computed_value(context),
|
||||||
|
m21: m21.to_computed_value(context),
|
||||||
|
m22: m22.to_computed_value(context),
|
||||||
|
m23: m23.to_computed_value(context),
|
||||||
|
m24: m24.to_computed_value(context),
|
||||||
|
m31: m31.to_computed_value(context),
|
||||||
|
m32: m32.to_computed_value(context),
|
||||||
|
m33: m33.to_computed_value(context),
|
||||||
|
m34: m34.to_computed_value(context),
|
||||||
|
m41: lopon_to_lop(&m41.to_computed_value(context)),
|
||||||
|
m42: lopon_to_lop(&m42.to_computed_value(context)),
|
||||||
|
m43: lon_to_length(&m43.to_computed_value(context)),
|
||||||
|
m44: m44.to_computed_value(context),
|
||||||
|
};
|
||||||
|
result.push(computed_value::ComputedOperation::MatrixWithPercents(comp));
|
||||||
|
}
|
||||||
Translate(ref tx, None) => {
|
Translate(ref tx, None) => {
|
||||||
let tx = tx.to_computed_value(context);
|
let tx = tx.to_computed_value(context);
|
||||||
result.push(computed_value::ComputedOperation::Translate(
|
result.push(computed_value::ComputedOperation::Translate(
|
||||||
|
@ -1755,6 +1942,26 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
m44: Number::from_computed_value(&computed.m44),
|
m44: Number::from_computed_value(&computed.m44),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
computed_value::ComputedOperation::MatrixWithPercents(ref computed) => {
|
||||||
|
result.push(SpecifiedOperation::PrefixedMatrix3D {
|
||||||
|
m11: Number::from_computed_value(&computed.m11),
|
||||||
|
m12: Number::from_computed_value(&computed.m12),
|
||||||
|
m13: Number::from_computed_value(&computed.m13),
|
||||||
|
m14: Number::from_computed_value(&computed.m14),
|
||||||
|
m21: Number::from_computed_value(&computed.m21),
|
||||||
|
m22: Number::from_computed_value(&computed.m22),
|
||||||
|
m23: Number::from_computed_value(&computed.m23),
|
||||||
|
m24: Number::from_computed_value(&computed.m24),
|
||||||
|
m31: Number::from_computed_value(&computed.m31),
|
||||||
|
m32: Number::from_computed_value(&computed.m32),
|
||||||
|
m33: Number::from_computed_value(&computed.m33),
|
||||||
|
m34: Number::from_computed_value(&computed.m34),
|
||||||
|
m41: Either::First(LengthOrPercentage::from_computed_value(&computed.m41)),
|
||||||
|
m42: Either::First(LengthOrPercentage::from_computed_value(&computed.m42)),
|
||||||
|
m43: LengthOrNumber::from_computed_value(&Either::First(computed.m43)),
|
||||||
|
m44: Number::from_computed_value(&computed.m44),
|
||||||
|
});
|
||||||
|
}
|
||||||
computed_value::ComputedOperation::Translate(ref tx, ref ty, ref tz) => {
|
computed_value::ComputedOperation::Translate(ref tx, ref ty, ref tz) => {
|
||||||
// XXXManishearth we lose information here; perhaps we should try to
|
// XXXManishearth we lose information here; perhaps we should try to
|
||||||
// recover the original function? Not sure if this can be observed.
|
// recover the original function? Not sure if this can be observed.
|
||||||
|
@ -1792,6 +1999,24 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
}).unwrap_or(Vec::new()))
|
}).unwrap_or(Vec::new()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Converts computed LengthOrPercentageOrNumber into computed
|
||||||
|
// LengthOrPercentage. Number maps into Length
|
||||||
|
fn lopon_to_lop(value: &ComputedLoPoNumber) -> ComputedLoP {
|
||||||
|
match *value {
|
||||||
|
Either::First(length_or_percentage) => length_or_percentage,
|
||||||
|
Either::Second(number) => ComputedLoP::Length(Au::from_f32_px(number)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts computed LengthOrNumber into computed Length.
|
||||||
|
// Number maps into Length.
|
||||||
|
fn lon_to_length(value: &ComputedLoN) -> ComputedLength {
|
||||||
|
match *value {
|
||||||
|
Either::First(length) => length,
|
||||||
|
Either::Second(number) => Au::from_f32_px(number),
|
||||||
|
}
|
||||||
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
// CSSOM View Module
|
// CSSOM View Module
|
||||||
|
|
|
@ -476,6 +476,8 @@ bitflags! {
|
||||||
/// This property has values that can establish a containing block for
|
/// This property has values that can establish a containing block for
|
||||||
/// absolutely positioned elements.
|
/// absolutely positioned elements.
|
||||||
const ABSPOS_CB = 1 << 2,
|
const ABSPOS_CB = 1 << 2,
|
||||||
|
/// This property(shorthand) is an alias of another property.
|
||||||
|
const ALIAS_PROPERTY = 1 << 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -288,3 +288,23 @@ macro_rules! try_parse_one {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%helpers:shorthand>
|
</%helpers:shorthand>
|
||||||
|
|
||||||
|
|
||||||
|
<%helpers:shorthand name="-moz-transform" products="gecko"
|
||||||
|
sub_properties="transform"
|
||||||
|
flags="ALIAS_PROPERTY"
|
||||||
|
spec="Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/transform">
|
||||||
|
use properties::longhands::transform;
|
||||||
|
|
||||||
|
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||||
|
Ok(Longhands {
|
||||||
|
transform: transform::parse_prefixed(context, input)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
self.transform.to_css(dest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</%helpers:shorthand>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue