Auto merge of #13163 - Manishearth:conditional-compilation, r=bholley

Use conditional compilation for stylo properties; output unimplemented logs for all properties

Till now we were only emitting unimplemented property logs for properties which servo implements but stylo doesn't.
This list is getting smaller, and we really should be emitting this for any unexpected property we encounter.

I also made it so that longhands which stylo does not implement will not be compiled in stylo builds; instead of what we currently do,
which is to parse them and then basically ignore the result.

There are still a few exceptions -- we generate stubs for properties that are parts of shorthands because otherwise we'd have to add fiddly conditional compilation to the shorthand code.

r? @bholley

cc @emilio

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13163)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-09-02 21:45:08 -05:00 committed by GitHub
commit 58205f1a78
12 changed files with 279 additions and 234 deletions

View file

@ -468,39 +468,70 @@ impl Debug for ${style_struct.gecko_struct_name} {
<%def name="raw_impl_trait(style_struct, skip_longhands='', skip_additionals='')">
<%
longhands = [x for x in style_struct.longhands
longhands = [x for x in style_struct.longhands
if not (skip_longhands == "*" or x.name in skip_longhands.split())]
#
# Make a list of types we can't auto-generate.
#
force_stub = [];
# These are currently being shuffled to a different style struct on the gecko side.
force_stub += ["backface-visibility", "transform-box", "transform-style"]
# These live in an nsFont member in Gecko. Should be straightforward to do manually.
force_stub += ["font-kerning", "font-stretch", "font-variant"]
# These have unusual representations in gecko.
force_stub += ["list-style-type", "text-overflow"]
# In a nsTArray, have to be done manually, but probably not too much work
# (the "filling them", not the "making them work")
force_stub += ["animation-name", "animation-duration",
#
# Make a list of types we can't auto-generate.
#
force_stub = [];
# These are currently being shuffled to a different style struct on the gecko side.
force_stub += ["backface-visibility", "transform-box", "transform-style"]
# These live in an nsFont member in Gecko. Should be straightforward to do manually.
force_stub += ["font-kerning", "font-stretch", "font-variant"]
# These have unusual representations in gecko.
force_stub += ["list-style-type", "text-overflow"]
# In a nsTArray, have to be done manually, but probably not too much work
# (the "filling them", not the "making them work")
force_stub += ["animation-name", "animation-duration",
"animation-timing-function", "animation-iteration-count",
"animation-direction", "animation-play-state",
"animation-fill-mode", "animation-delay"]
# Types used with predefined_type()-defined properties that we can auto-generate.
predefined_types = {
# These are part of shorthands so we must include them in stylo builds,
# but we haven't implemented the stylo glue for the longhand
# so we generate a stub
force_stub += ["list-style-image", # box
"flex-basis", # position
# transition
"transition-duration", "transition-timing-function",
"transition-property", "transition-delay",
"background-size", # background
"column-count", # column
]
# Types used with predefined_type()-defined properties that we can auto-generate.
predefined_types = {
"LengthOrPercentage": impl_style_coord,
"LengthOrPercentageOrAuto": impl_style_coord,
"LengthOrPercentageOrNone": impl_style_coord,
"Number": impl_simple,
"Opacity": impl_simple,
}
}
keyword_longhands = [x for x in longhands if x.keyword and not x.name in force_stub]
predefined_longhands = [x for x in longhands
keyword_longhands = [x for x in longhands if x.keyword and not x.name in force_stub]
predefined_longhands = [x for x in longhands
if x.predefined_type in predefined_types and not x.name in force_stub]
stub_longhands = [x for x in longhands if x not in keyword_longhands + predefined_longhands]
stub_longhands = [x for x in longhands if x not in keyword_longhands + predefined_longhands]
# If one of the longhands is not handled
# by either:
# - being a keyword
# - being a predefined longhand
# - being a longhand with manual glue code (i.e. in skip_longhands)
# - being generated as a stub
#
# then we raise an error here.
#
# If you hit this error, please add `product="servo"` to the longhand.
# In case the longhand is used in a shorthand, add it to the force_stub
# list above.
for stub in stub_longhands:
if stub.name not in force_stub:
raise Exception("Don't know what to do with longhand %s in style struct %s"
% (stub.name,style_struct. gecko_struct_name))
%>
impl ${style_struct.gecko_struct_name} {
/*

View file

@ -9,18 +9,12 @@ use properties::PropertyDeclaration;
use properties::longhands;
use properties::longhands::background_position::computed_value::T as BackgroundPosition;
use properties::longhands::background_size::computed_value::T as BackgroundSize;
use properties::longhands::border_spacing::computed_value::T as BorderSpacing;
use properties::longhands::clip::computed_value::ClipRect;
use properties::longhands::font_weight::computed_value::T as FontWeight;
use properties::longhands::line_height::computed_value::T as LineHeight;
use properties::longhands::text_shadow::computed_value::T as TextShadowList;
use properties::longhands::text_shadow::computed_value::TextShadow;
use properties::longhands::box_shadow::computed_value::T as BoxShadowList;
use properties::longhands::box_shadow::single_value::computed_value::T as BoxShadow;
use properties::longhands::transform::computed_value::ComputedMatrix;
use properties::longhands::transform::computed_value::ComputedOperation as TransformOperation;
use properties::longhands::transform::computed_value::T as TransformList;
use properties::longhands::transform_origin::computed_value::T as TransformOrigin;
use properties::longhands::vertical_align::computed_value::T as VerticalAlign;
use properties::longhands::visibility::computed_value::T as Visibility;
use properties::longhands::z_index::computed_value::T as ZIndex;
@ -32,6 +26,8 @@ use values::computed::{BorderRadiusSize, LengthOrNone};
use values::computed::{CalcLengthOrPercentage, LengthOrPercentage};
use values::computed::position::Position;
// NB: This needs to be here because it needs all the longhands generated
// beforehand.
#[derive(Copy, Clone, Debug, PartialEq)]
@ -296,18 +292,6 @@ impl Interpolate for VerticalAlign {
}
}
}
/// https://drafts.csswg.org/css-transitions/#animtype-simple-list
impl Interpolate for BorderSpacing {
#[inline]
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
Ok(BorderSpacing {
horizontal: try!(self.horizontal.interpolate(&other.horizontal, time)),
vertical: try!(self.vertical.interpolate(&other.vertical, time)),
})
}
}
impl Interpolate for BackgroundSize {
#[inline]
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
@ -492,19 +476,6 @@ impl Interpolate for FontWeight {
}
}
/// https://drafts.csswg.org/css-transitions/#animtype-rect
impl Interpolate for ClipRect {
#[inline]
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
Ok(ClipRect {
top: try!(self.top.interpolate(&other.top, time)),
right: try!(self.right.interpolate(&other.right, time)),
bottom: try!(self.bottom.interpolate(&other.bottom, time)),
left: try!(self.left.interpolate(&other.left, time)),
})
}
}
/// https://drafts.csswg.org/css-transitions/#animtype-simple-list
impl Interpolate for Position {
#[inline]
@ -573,138 +544,6 @@ impl Interpolate for TextShadowList {
}
}
/// Check if it's possible to do a direct numerical interpolation
/// between these two transform lists.
/// http://dev.w3.org/csswg/css-transforms/#transform-transform-animation
fn can_interpolate_list(from_list: &[TransformOperation],
to_list: &[TransformOperation]) -> bool {
// Lists must be equal length
if from_list.len() != to_list.len() {
return false;
}
// Each transform operation must match primitive type in other list
for (from, to) in from_list.iter().zip(to_list) {
match (from, to) {
(&TransformOperation::Matrix(..), &TransformOperation::Matrix(..)) |
(&TransformOperation::Skew(..), &TransformOperation::Skew(..)) |
(&TransformOperation::Translate(..), &TransformOperation::Translate(..)) |
(&TransformOperation::Scale(..), &TransformOperation::Scale(..)) |
(&TransformOperation::Rotate(..), &TransformOperation::Rotate(..)) |
(&TransformOperation::Perspective(..), &TransformOperation::Perspective(..)) => {}
_ => {
return false;
}
}
}
true
}
/// Interpolate two transform lists.
/// http://dev.w3.org/csswg/css-transforms/#interpolation-of-transforms
fn interpolate_transform_list(from_list: &[TransformOperation],
to_list: &[TransformOperation],
time: f64) -> TransformList {
let mut result = vec![];
if can_interpolate_list(from_list, to_list) {
for (from, to) in from_list.iter().zip(to_list) {
match (from, to) {
(&TransformOperation::Matrix(from),
&TransformOperation::Matrix(_to)) => {
// TODO(gw): Implement matrix decomposition and interpolation
result.push(TransformOperation::Matrix(from));
}
(&TransformOperation::Skew(fx, fy),
&TransformOperation::Skew(tx, ty)) => {
let ix = fx.interpolate(&tx, time).unwrap();
let iy = fy.interpolate(&ty, time).unwrap();
result.push(TransformOperation::Skew(ix, iy));
}
(&TransformOperation::Translate(fx, fy, fz),
&TransformOperation::Translate(tx, ty, tz)) => {
let ix = fx.interpolate(&tx, time).unwrap();
let iy = fy.interpolate(&ty, time).unwrap();
let iz = fz.interpolate(&tz, time).unwrap();
result.push(TransformOperation::Translate(ix, iy, iz));
}
(&TransformOperation::Scale(fx, fy, fz),
&TransformOperation::Scale(tx, ty, tz)) => {
let ix = fx.interpolate(&tx, time).unwrap();
let iy = fy.interpolate(&ty, time).unwrap();
let iz = fz.interpolate(&tz, time).unwrap();
result.push(TransformOperation::Scale(ix, iy, iz));
}
(&TransformOperation::Rotate(fx, fy, fz, fa),
&TransformOperation::Rotate(tx, ty, tz, ta)) => {
let norm_f = ((fx * fx) + (fy * fy) + (fz * fz)).sqrt();
let norm_t = ((tx * tx) + (ty * ty) + (tz * tz)).sqrt();
let (fx, fy, fz) = (fx / norm_f, fy / norm_f, fz / norm_f);
let (tx, ty, tz) = (tx / norm_t, ty / norm_t, tz / norm_t);
if fx == tx && fy == ty && fz == tz {
let ia = fa.interpolate(&ta, time).unwrap();
result.push(TransformOperation::Rotate(fx, fy, fz, ia));
} else {
// TODO(gw): Implement matrix decomposition and interpolation
result.push(TransformOperation::Rotate(fx, fy, fz, fa));
}
}
(&TransformOperation::Perspective(fd),
&TransformOperation::Perspective(_td)) => {
// TODO(gw): Implement matrix decomposition and interpolation
result.push(TransformOperation::Perspective(fd));
}
_ => {
// This should be unreachable due to the can_interpolate_list() call.
unreachable!();
}
}
}
} else {
// TODO(gw): Implement matrix decomposition and interpolation
result.extend_from_slice(from_list);
}
TransformList(Some(result))
}
/// Build an equivalent 'identity transform function list' based
/// on an existing transform list.
/// http://dev.w3.org/csswg/css-transforms/#none-transform-animation
fn build_identity_transform_list(list: &[TransformOperation]) -> Vec<TransformOperation> {
let mut result = vec!();
for operation in list {
match *operation {
TransformOperation::Matrix(..) => {
let identity = ComputedMatrix::identity();
result.push(TransformOperation::Matrix(identity));
}
TransformOperation::Skew(..) => {
result.push(TransformOperation::Skew(Angle(0.0), Angle(0.0)));
}
TransformOperation::Translate(..) => {
result.push(TransformOperation::Translate(LengthOrPercentage::zero(),
LengthOrPercentage::zero(),
Au(0)));
}
TransformOperation::Scale(..) => {
result.push(TransformOperation::Scale(1.0, 1.0, 1.0));
}
TransformOperation::Rotate(..) => {
result.push(TransformOperation::Rotate(0.0, 0.0, 1.0, Angle(0.0)));
}
TransformOperation::Perspective(..) => {
// http://dev.w3.org/csswg/css-transforms/#identity-transform-function
let identity = ComputedMatrix::identity();
result.push(TransformOperation::Matrix(identity));
}
}
}
result
}
impl Interpolate for BoxShadowList {
#[inline]
@ -780,42 +619,173 @@ impl Interpolate for LengthOrNone {
}
}
impl Interpolate for TransformOrigin {
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
Ok(TransformOrigin {
horizontal: try!(self.horizontal.interpolate(&other.horizontal, time)),
vertical: try!(self.vertical.interpolate(&other.vertical, time)),
depth: try!(self.depth.interpolate(&other.depth, time)),
})
}
}
% if product == "servo":
use properties::longhands::transform::computed_value::ComputedMatrix;
use properties::longhands::transform::computed_value::ComputedOperation as TransformOperation;
use properties::longhands::transform::computed_value::T as TransformList;
/// https://drafts.csswg.org/css-transforms/#interpolation-of-transforms
impl Interpolate for TransformList {
#[inline]
fn interpolate(&self, other: &TransformList, time: f64) -> Result<Self, ()> {
// http://dev.w3.org/csswg/css-transforms/#interpolation-of-transforms
let result = match (&self.0, &other.0) {
(&Some(ref from_list), &Some(ref to_list)) => {
// Two lists of transforms
interpolate_transform_list(from_list, &to_list, time)
}
(&Some(ref from_list), &None) => {
// http://dev.w3.org/csswg/css-transforms/#none-transform-animation
let to_list = build_identity_transform_list(from_list);
interpolate_transform_list(from_list, &to_list, time)
}
(&None, &Some(ref to_list)) => {
// http://dev.w3.org/csswg/css-transforms/#none-transform-animation
let from_list = build_identity_transform_list(to_list);
interpolate_transform_list(&from_list, to_list, time)
}
_ => {
// http://dev.w3.org/csswg/css-transforms/#none-none-animation
TransformList(None)
}
};
/// Check if it's possible to do a direct numerical interpolation
/// between these two transform lists.
/// http://dev.w3.org/csswg/css-transforms/#transform-transform-animation
fn can_interpolate_list(from_list: &[TransformOperation],
to_list: &[TransformOperation]) -> bool {
// Lists must be equal length
if from_list.len() != to_list.len() {
return false;
}
Ok(result)
// Each transform operation must match primitive type in other list
for (from, to) in from_list.iter().zip(to_list) {
match (from, to) {
(&TransformOperation::Matrix(..), &TransformOperation::Matrix(..)) |
(&TransformOperation::Skew(..), &TransformOperation::Skew(..)) |
(&TransformOperation::Translate(..), &TransformOperation::Translate(..)) |
(&TransformOperation::Scale(..), &TransformOperation::Scale(..)) |
(&TransformOperation::Rotate(..), &TransformOperation::Rotate(..)) |
(&TransformOperation::Perspective(..), &TransformOperation::Perspective(..)) => {}
_ => {
return false;
}
}
}
true
}
}
/// Build an equivalent 'identity transform function list' based
/// on an existing transform list.
/// http://dev.w3.org/csswg/css-transforms/#none-transform-animation
fn build_identity_transform_list(list: &[TransformOperation]) -> Vec<TransformOperation> {
let mut result = vec!();
for operation in list {
match *operation {
TransformOperation::Matrix(..) => {
let identity = ComputedMatrix::identity();
result.push(TransformOperation::Matrix(identity));
}
TransformOperation::Skew(..) => {
result.push(TransformOperation::Skew(Angle(0.0), Angle(0.0)));
}
TransformOperation::Translate(..) => {
result.push(TransformOperation::Translate(LengthOrPercentage::zero(),
LengthOrPercentage::zero(),
Au(0)));
}
TransformOperation::Scale(..) => {
result.push(TransformOperation::Scale(1.0, 1.0, 1.0));
}
TransformOperation::Rotate(..) => {
result.push(TransformOperation::Rotate(0.0, 0.0, 1.0, Angle(0.0)));
}
TransformOperation::Perspective(..) => {
// http://dev.w3.org/csswg/css-transforms/#identity-transform-function
let identity = ComputedMatrix::identity();
result.push(TransformOperation::Matrix(identity));
}
}
}
result
}
/// Interpolate two transform lists.
/// http://dev.w3.org/csswg/css-transforms/#interpolation-of-transforms
fn interpolate_transform_list(from_list: &[TransformOperation],
to_list: &[TransformOperation],
time: f64) -> TransformList {
let mut result = vec![];
if can_interpolate_list(from_list, to_list) {
for (from, to) in from_list.iter().zip(to_list) {
match (from, to) {
(&TransformOperation::Matrix(from),
&TransformOperation::Matrix(_to)) => {
// TODO(gw): Implement matrix decomposition and interpolation
result.push(TransformOperation::Matrix(from));
}
(&TransformOperation::Skew(fx, fy),
&TransformOperation::Skew(tx, ty)) => {
let ix = fx.interpolate(&tx, time).unwrap();
let iy = fy.interpolate(&ty, time).unwrap();
result.push(TransformOperation::Skew(ix, iy));
}
(&TransformOperation::Translate(fx, fy, fz),
&TransformOperation::Translate(tx, ty, tz)) => {
let ix = fx.interpolate(&tx, time).unwrap();
let iy = fy.interpolate(&ty, time).unwrap();
let iz = fz.interpolate(&tz, time).unwrap();
result.push(TransformOperation::Translate(ix, iy, iz));
}
(&TransformOperation::Scale(fx, fy, fz),
&TransformOperation::Scale(tx, ty, tz)) => {
let ix = fx.interpolate(&tx, time).unwrap();
let iy = fy.interpolate(&ty, time).unwrap();
let iz = fz.interpolate(&tz, time).unwrap();
result.push(TransformOperation::Scale(ix, iy, iz));
}
(&TransformOperation::Rotate(fx, fy, fz, fa),
&TransformOperation::Rotate(tx, ty, tz, ta)) => {
let norm_f = ((fx * fx) + (fy * fy) + (fz * fz)).sqrt();
let norm_t = ((tx * tx) + (ty * ty) + (tz * tz)).sqrt();
let (fx, fy, fz) = (fx / norm_f, fy / norm_f, fz / norm_f);
let (tx, ty, tz) = (tx / norm_t, ty / norm_t, tz / norm_t);
if fx == tx && fy == ty && fz == tz {
let ia = fa.interpolate(&ta, time).unwrap();
result.push(TransformOperation::Rotate(fx, fy, fz, ia));
} else {
// TODO(gw): Implement matrix decomposition and interpolation
result.push(TransformOperation::Rotate(fx, fy, fz, fa));
}
}
(&TransformOperation::Perspective(fd),
&TransformOperation::Perspective(_td)) => {
// TODO(gw): Implement matrix decomposition and interpolation
result.push(TransformOperation::Perspective(fd));
}
_ => {
// This should be unreachable due to the can_interpolate_list() call.
unreachable!();
}
}
}
} else {
// TODO(gw): Implement matrix decomposition and interpolation
result.extend_from_slice(from_list);
}
TransformList(Some(result))
}
/// https://drafts.csswg.org/css-transforms/#interpolation-of-transforms
impl Interpolate for TransformList {
#[inline]
fn interpolate(&self, other: &TransformList, time: f64) -> Result<Self, ()> {
// http://dev.w3.org/csswg/css-transforms/#interpolation-of-transforms
let result = match (&self.0, &other.0) {
(&Some(ref from_list), &Some(ref to_list)) => {
// Two lists of transforms
interpolate_transform_list(from_list, &to_list, time)
}
(&Some(ref from_list), &None) => {
// http://dev.w3.org/csswg/css-transforms/#none-transform-animation
let to_list = build_identity_transform_list(from_list);
interpolate_transform_list(from_list, &to_list, time)
}
(&None, &Some(ref to_list)) => {
// http://dev.w3.org/csswg/css-transforms/#none-transform-animation
let from_list = build_identity_transform_list(to_list);
interpolate_transform_list(&from_list, to_list, time)
}
_ => {
// http://dev.w3.org/csswg/css-transforms/#none-none-animation
TransformList(None)
}
};
Ok(result)
}
}
% endif

View file

@ -153,7 +153,7 @@
</%helpers:longhand>
// FIXME: This prop should be animatable.
<%helpers:longhand name="column-gap" experimental="True" animatable="False">
<%helpers:longhand name="column-gap" experimental="True" products="servo" animatable="False">
use cssparser::ToCss;
use std::fmt;
use values::LocalToCss;

View file

@ -173,7 +173,7 @@
}
</%helpers:longhand>
<%helpers:longhand name="counter-increment" animatable="False">
<%helpers:longhand name="counter-increment" products="servo" animatable="False">
use std::fmt;
use super::content;
use values::NoViewportPercentage;
@ -245,7 +245,7 @@
}
</%helpers:longhand>
<%helpers:longhand name="counter-reset" animatable="False">
<%helpers:longhand name="counter-reset" products="servo" animatable="False">
pub use super::counter_increment::{SpecifiedValue, computed_value, get_initial_value};
use super::counter_increment::{parse_common};

View file

@ -175,7 +175,7 @@ ${helpers.predefined_type("opacity",
</%helpers:vector_longhand>
// FIXME: This prop should be animatable
<%helpers:longhand name="clip" animatable="False">
<%helpers:longhand name="clip" products="servo" animatable="False">
use cssparser::ToCss;
use std::fmt;
use values::LocalToCss;
@ -185,6 +185,7 @@ ${helpers.predefined_type("opacity",
pub mod computed_value {
use app_units::Au;
use properties::animated_properties::Interpolate;
#[derive(Clone, PartialEq, Eq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -198,6 +199,20 @@ ${helpers.predefined_type("opacity",
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct T(pub Option<ClipRect>);
/// https://drafts.csswg.org/css-transitions/#animtype-rect
impl Interpolate for ClipRect {
#[inline]
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
Ok(ClipRect {
top: try!(self.top.interpolate(&other.top, time)),
right: try!(self.right.interpolate(&other.right, time)),
bottom: try!(self.bottom.interpolate(&other.bottom, time)),
left: try!(self.left.interpolate(&other.left, time)),
})
}
}
}
impl ToCss for computed_value::T {
@ -364,7 +379,7 @@ ${helpers.predefined_type("opacity",
</%helpers:longhand>
// FIXME: This prop should be animatable
<%helpers:longhand name="filter" animatable="False">
<%helpers:longhand name="filter" products="servo" animatable="False">
//pub use self::computed_value::T as SpecifiedValue;
use cssparser::ToCss;
use std::fmt;
@ -617,7 +632,7 @@ ${helpers.predefined_type("opacity",
}
</%helpers:longhand>
<%helpers:longhand name="transform" animatable="True">
<%helpers:longhand name="transform" products="servo" animatable="True">
use app_units::Au;
use values::CSSFloat;
use values::HasViewportPercentage;
@ -1196,7 +1211,7 @@ ${helpers.single_keyword("transform-style",
"auto flat preserve-3d",
animatable=False)}
<%helpers:longhand name="transform-origin" animatable="True">
<%helpers:longhand name="transform-origin" products="servo" animatable="True">
use app_units::Au;
use values::LocalToCss;
use values::HasViewportPercentage;
@ -1206,6 +1221,7 @@ ${helpers.single_keyword("transform-style",
use std::fmt;
pub mod computed_value {
use properties::animated_properties::Interpolate;
use values::computed::{Length, LengthOrPercentage};
#[derive(Clone, Copy, Debug, PartialEq)]
@ -1215,6 +1231,16 @@ ${helpers.single_keyword("transform-style",
pub vertical: LengthOrPercentage,
pub depth: Length,
}
impl Interpolate for T {
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
Ok(T {
horizontal: try!(self.horizontal.interpolate(&other.horizontal, time)),
vertical: try!(self.vertical.interpolate(&other.vertical, time)),
depth: try!(self.depth.interpolate(&other.depth, time)),
})
}
}
}
impl HasViewportPercentage for SpecifiedValue {
@ -1288,10 +1314,11 @@ ${helpers.single_keyword("transform-style",
${helpers.predefined_type("perspective",
"LengthOrNone",
"computed::LengthOrNone::None",
products="servo",
animatable=True)}
// FIXME: This prop should be animatable
<%helpers:longhand name="perspective-origin" animatable="False">
<%helpers:longhand name="perspective-origin" products="servo" animatable="False">
use values::HasViewportPercentage;
use values::specified::{LengthOrPercentage, Percentage};

View file

@ -40,7 +40,7 @@ ${helpers.single_keyword("color-adjust",
"economy exact", products="gecko",
animatable=False)}
<%helpers:longhand name="image-rendering" animatable="False">
<%helpers:longhand name="image-rendering" products="servo" animatable="False">
pub mod computed_value {
use cssparser::ToCss;
use std::fmt;

View file

@ -16,7 +16,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
extra_gecko_values="right left top-outside bottom-outside",
animatable=False)}
<%helpers:longhand name="border-spacing" animatable="False">
<%helpers:longhand name="border-spacing" products="servo" animatable="False">
use app_units::Au;
use values::LocalToCss;
use values::HasViewportPercentage;
@ -26,6 +26,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
pub mod computed_value {
use app_units::Au;
use properties::animated_properties::Interpolate;
#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -33,6 +34,17 @@ ${helpers.single_keyword("caption-side", "top bottom",
pub horizontal: Au,
pub vertical: Au,
}
/// https://drafts.csswg.org/css-transitions/#animtype-simple-list
impl Interpolate for T {
#[inline]
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
Ok(T {
horizontal: try!(self.horizontal.interpolate(&other.horizontal, time)),
vertical: try!(self.vertical.interpolate(&other.vertical, time)),
})
}
}
}
impl HasViewportPercentage for SpecifiedValue {

View file

@ -192,7 +192,7 @@
</%helpers:longhand>
// FIXME: This prop should be animatable.
<%helpers:longhand name="letter-spacing" animatable="False">
<%helpers:longhand name="letter-spacing" products="servo" animatable="False">
use cssparser::ToCss;
use std::fmt;
use values::LocalToCss;

View file

@ -96,7 +96,7 @@ ${helpers.single_keyword("list-style-type", """
}
</%helpers:longhand>
<%helpers:longhand name="quotes" animatable="False">
<%helpers:longhand name="quotes" products="servo" animatable="False">
use std::borrow::Cow;
use std::fmt;
use values::NoViewportPercentage;

View file

@ -78,4 +78,4 @@ ${helpers.predefined_type("outline-color", "CSSColor", "::cssparser::Color::Curr
animatable=False)}
% endfor
${helpers.predefined_type("outline-offset", "Length", "Au(0)", animatable=True)}
${helpers.predefined_type("outline-offset", "Length", "Au(0)", products="servo", animatable=True)}

View file

@ -110,7 +110,7 @@ ${helpers.single_keyword("align-self", "auto stretch flex-start flex-end center
animatable=False)}
// https://drafts.csswg.org/css-flexbox/#propdef-order
<%helpers:longhand name="order" animatable="True">
<%helpers:longhand name="order" products="servo" animatable="True">
use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {}

View file

@ -1152,7 +1152,12 @@ impl PropertyDeclaration {
},
% endfor
_ => PropertyDeclarationParseResult::UnknownProperty
_ => {
if cfg!(all(debug_assertions, feature = "gecko")) && !name.starts_with('-') {
println!("stylo: Unimplemented property setter: {}", name);
}
PropertyDeclarationParseResult::UnknownProperty
}
}
}