mirror of
https://github.com/servo/servo.git
synced 2025-06-11 10:00:18 +00:00
Implement rotate property styling
This commit is contained in:
parent
a8c133d07e
commit
62c0c6feee
9 changed files with 113 additions and 16 deletions
|
@ -189,6 +189,7 @@ partial interface CSSStyleDeclaration {
|
|||
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString transform-style;
|
||||
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString backfaceVisibility;
|
||||
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString backface-visibility;
|
||||
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString rotate;
|
||||
|
||||
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString direction;
|
||||
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString unicodeBidi;
|
||||
|
|
|
@ -3016,13 +3016,45 @@ fn static_assert() {
|
|||
${impl_copy_animation_value(ident, gecko_ffi_name)}
|
||||
</%def>
|
||||
|
||||
<%def name="impl_individual_transform(ident, type, gecko_ffi_name)">
|
||||
pub fn set_${ident}(&mut self, other: values::computed::${type}) {
|
||||
unsafe { self.gecko.${gecko_ffi_name}.clear() };
|
||||
|
||||
if let Some(operation) = other.to_transform_operation() {
|
||||
convert_transform(&[operation], &mut self.gecko.${gecko_ffi_name})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
||||
unsafe { self.gecko.${gecko_ffi_name}.set(&other.gecko.${gecko_ffi_name}); }
|
||||
}
|
||||
|
||||
pub fn reset_${ident}(&mut self, other: &Self) {
|
||||
self.copy_${ident}_from(other)
|
||||
}
|
||||
|
||||
pub fn clone_${ident}(&self) -> values::computed::${type} {
|
||||
use values::generics::transform::${type};
|
||||
|
||||
if self.gecko.${gecko_ffi_name}.mRawPtr.is_null() {
|
||||
return ${type}::None;
|
||||
}
|
||||
|
||||
let list = unsafe { (*self.gecko.${gecko_ffi_name}.to_safe().get()).mHead.as_ref() };
|
||||
|
||||
let mut transform = clone_transform_from_list(list);
|
||||
debug_assert_eq!(transform.0.len(), 1);
|
||||
${type}::from_transform_operation(&transform.0.pop().unwrap())
|
||||
}
|
||||
</%def>
|
||||
|
||||
<% skip_box_longhands= """display overflow-y vertical-align
|
||||
animation-name animation-delay animation-duration
|
||||
animation-direction animation-fill-mode animation-play-state
|
||||
animation-iteration-count animation-timing-function
|
||||
transition-duration transition-delay
|
||||
transition-timing-function transition-property
|
||||
page-break-before page-break-after
|
||||
page-break-before page-break-after rotate
|
||||
scroll-snap-points-x scroll-snap-points-y
|
||||
scroll-snap-type-x scroll-snap-type-y scroll-snap-coordinate
|
||||
perspective-origin -moz-binding will-change
|
||||
|
@ -3454,6 +3486,8 @@ fn static_assert() {
|
|||
}
|
||||
}
|
||||
|
||||
${impl_individual_transform('rotate', 'Rotate', 'mSpecifiedRotate')}
|
||||
|
||||
pub fn set_will_change(&mut self, v: longhands::will_change::computed_value::T) {
|
||||
use gecko_bindings::bindings::{Gecko_AppendWillChange, Gecko_ClearWillChange};
|
||||
use gecko_bindings::structs::NS_STYLE_WILL_CHANGE_OPACITY;
|
||||
|
|
|
@ -390,6 +390,14 @@ ${helpers.predefined_type("transform", "Transform",
|
|||
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
|
||||
spec="https://drafts.csswg.org/css-transforms/#propdef-transform")}
|
||||
|
||||
${helpers.predefined_type("rotate", "Rotate",
|
||||
"generics::transform::Rotate::None",
|
||||
animation_value_type="ComputedValue",
|
||||
boxed=True,
|
||||
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
|
||||
gecko_pref="layout.css.individual-transform.enabled",
|
||||
spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms")}
|
||||
|
||||
// CSSOM View Module
|
||||
// https://www.w3.org/TR/cssom-view-1/
|
||||
${helpers.single_keyword("scroll-behavior",
|
||||
|
|
|
@ -73,7 +73,7 @@ pub use self::svg::MozContextProperties;
|
|||
pub use self::table::XSpan;
|
||||
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextAlign, TextOverflow, WordSpacing};
|
||||
pub use self::time::Time;
|
||||
pub use self::transform::{TimingFunction, Transform, TransformOperation, TransformOrigin};
|
||||
pub use self::transform::{TimingFunction, Transform, TransformOperation, TransformOrigin, Rotate};
|
||||
pub use self::ui::MozForceBrokenImageIcon;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
|
|
|
@ -12,6 +12,7 @@ use values::computed::{Angle, Integer, Length, LengthOrPercentage, Number, Perce
|
|||
use values::computed::{LengthOrNumber, LengthOrPercentageOrNumber};
|
||||
use values::generics::transform::{self, Matrix as GenericMatrix, Matrix3D as GenericMatrix3D};
|
||||
use values::generics::transform::{Transform as GenericTransform, TransformOperation as GenericTransformOperation};
|
||||
use values::generics::transform::Rotate as GenericRotate;
|
||||
use values::generics::transform::TimingFunction as GenericTimingFunction;
|
||||
use values::generics::transform::TransformOrigin as GenericTransformOrigin;
|
||||
|
||||
|
@ -293,3 +294,27 @@ impl ToAnimatedZero for Transform {
|
|||
.collect::<Result<Vec<_>, _>>()?))
|
||||
}
|
||||
}
|
||||
|
||||
/// A computed CSS `rotate`
|
||||
pub type Rotate = GenericRotate<Number, Angle>;
|
||||
|
||||
impl Rotate {
|
||||
/// Convert TransformOperation to Rotate.
|
||||
pub fn to_transform_operation(&self) -> Option<TransformOperation> {
|
||||
match *self {
|
||||
GenericRotate::None => None,
|
||||
GenericRotate::Rotate(angle) => Some(GenericTransformOperation::Rotate(angle)),
|
||||
GenericRotate::Rotate3D(rx, ry, rz, angle) => Some(GenericTransformOperation::Rotate3D(rx, ry, rz, angle)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert Rotate to TransformOperation.
|
||||
pub fn from_transform_operation(operation: &TransformOperation) -> Rotate {
|
||||
match *operation {
|
||||
GenericTransformOperation::Rotate(angle) => GenericRotate::Rotate(angle),
|
||||
GenericTransformOperation::Rotate3D(rx, ry, rz, angle) =>
|
||||
GenericRotate::Rotate3D(rx, ry, rz, angle),
|
||||
_ => unreachable!("Found unexpected value for rotate property"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -668,3 +668,17 @@ pub fn get_normalized_vector_and_angle<T: Zero>(
|
|||
(vector.x, vector.y, vector.z, angle)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Animate, ComputeSquaredDistance, ToAnimatedZero, ToComputedValue)]
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
|
||||
/// A value of the `Rotate` property
|
||||
///
|
||||
/// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
|
||||
pub enum Rotate<Number, Angle> {
|
||||
/// 'none'
|
||||
None,
|
||||
/// '<angle>'
|
||||
Rotate(Angle),
|
||||
/// '<number>{3} <angle>'
|
||||
Rotate3D(Number, Number, Number, Angle),
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ pub use self::table::XSpan;
|
|||
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextDecorationLine};
|
||||
pub use self::text::{TextAlign, TextAlignKeyword, TextOverflow, WordSpacing};
|
||||
pub use self::time::Time;
|
||||
pub use self::transform::{TimingFunction, Transform, TransformOrigin};
|
||||
pub use self::transform::{TimingFunction, Transform, TransformOrigin, Rotate};
|
||||
pub use self::ui::MozForceBrokenImageIcon;
|
||||
pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent;
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ use values::computed::transform::TimingFunction as ComputedTimingFunction;
|
|||
use values::generics::transform::{Matrix3D, Transform as GenericTransform};
|
||||
use values::generics::transform::{StepPosition, TimingFunction as GenericTimingFunction, Matrix};
|
||||
use values::generics::transform::{TimingKeyword, TransformOrigin as GenericTransformOrigin};
|
||||
use values::generics::transform::Rotate as GenericRotate;
|
||||
use values::generics::transform::TransformOperation as GenericTransformOperation;
|
||||
use values::specified::{self, Angle, Number, Length, Integer};
|
||||
use values::specified::{LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrNumber};
|
||||
|
@ -508,3 +509,30 @@ impl ToComputedValue for TimingFunction {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A specified CSS `rotate`
|
||||
pub type Rotate = GenericRotate<Number, Angle>;
|
||||
|
||||
impl Parse for Rotate {
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(GenericRotate::None);
|
||||
}
|
||||
|
||||
if let Some(rx) = input.try(|i| Number::parse(context, i)).ok() {
|
||||
// 'rotate: <number>{3} <angle>'
|
||||
let ry = Number::parse(context, input)?;
|
||||
let rz = Number::parse(context, input)?;
|
||||
let angle = specified::Angle::parse(context, input)?;
|
||||
return Ok(GenericRotate::Rotate3D(rx, ry, rz, angle));
|
||||
}
|
||||
|
||||
// 'rotate: <angle>'
|
||||
let angle = specified::Angle::parse(context, input)?;
|
||||
Ok(GenericRotate::Rotate(angle))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
[rotate-parsing-invalid.html]
|
||||
[e.style['rotate'\] = "100px" should not set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['rotate'\] = "100 400deg" should not set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['rotate'\] = "100 200 400deg" should not set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['rotate'\] = "100 200 300 500 400deg" should not set the property value]
|
||||
expected: FAIL
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue