servo: Merge #15813 - Implement parsing/serialization and glue for will-change property (from canaltinova:will-change); r=upsuper,emilio

Implement parsing/serialization  and glue for will-change property

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #15706 (github issue number if applicable).

<!-- Either: -->
- [x] There are tests for these changes

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

Source-Repo: https://github.com/servo/servo
Source-Revision: cb1438e44f0550378867a308494e4f84b1e00478

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : caf2bb046a96cc073eace38d7c14a3a819d8a111
This commit is contained in:
Nazım Can Altınova 2017-03-21 21:56:23 -07:00
Родитель 16207207f1
Коммит 7eea9c3295
10 изменённых файлов: 246 добавлений и 3 удалений

Просмотреть файл

@ -781,6 +781,17 @@ extern "C" {
*mut ::std::os::raw::c_void,
len: usize);
}
extern "C" {
pub fn Gecko_ClearWillChange(display: *mut nsStyleDisplay, length: usize);
}
extern "C" {
pub fn Gecko_AppendWillChange(display: *mut nsStyleDisplay,
atom: *mut nsIAtom);
}
extern "C" {
pub fn Gecko_CopyWillChangeFrom(dest: *mut nsStyleDisplay,
src: *mut nsStyleDisplay);
}
extern "C" {
pub fn Gecko_AnimationAppendKeyframe(keyframes:
RawGeckoKeyframeListBorrowedMut,

Просмотреть файл

@ -96,7 +96,8 @@ class Longhand(object):
predefined_type=None, custom_cascade=False, experimental=False, internal=False,
need_clone=False, need_index=False, gecko_ffi_name=None, depend_on_viewport_size=False,
allowed_in_keyframe_block=True, complex_color=False, cast_type='u8',
has_uncacheable_values=False, logical=False, alias=None, extra_prefixes=None, boxed=False):
has_uncacheable_values=False, logical=False, alias=None, extra_prefixes=None, boxed=False,
creates_stacking_context=False, fixpos_cb=False, abspos_cb=False):
self.name = name
if not spec:
raise TypeError("Spec should be specified for %s" % name)
@ -120,6 +121,9 @@ class Longhand(object):
self.alias = alias.split() if alias else []
self.extra_prefixes = extra_prefixes.split() if extra_prefixes else []
self.boxed = arg_to_bool(boxed)
self.creates_stacking_context = arg_to_bool(creates_stacking_context)
self.fixpos_cb = arg_to_bool(fixpos_cb)
self.abspos_cb = arg_to_bool(abspos_cb)
# https://drafts.csswg.org/css-animations/#keyframes
# > The <declaration-list> inside of <keyframe-block> accepts any CSS property

Просмотреть файл

@ -1423,7 +1423,7 @@ fn static_assert() {
page-break-before page-break-after
scroll-snap-points-x scroll-snap-points-y transform
scroll-snap-type-y scroll-snap-coordinate
perspective-origin transform-origin -moz-binding""" %>
perspective-origin transform-origin -moz-binding will-change""" %>
<%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}">
// We manually-implement the |display| property until we get general
@ -1918,6 +1918,92 @@ fn static_assert() {
.expect("clone for Length failed"),
}
}
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;
use gecko_bindings::structs::NS_STYLE_WILL_CHANGE_SCROLL;
use gecko_bindings::structs::NS_STYLE_WILL_CHANGE_TRANSFORM;
use properties::PropertyId;
use properties::longhands::will_change::computed_value::T;
fn will_change_bitfield_from_prop_flags(prop: &LonghandId) -> u8 {
use properties::{ABSPOS_CB, CREATES_STACKING_CONTEXT, FIXPOS_CB};
use gecko_bindings::structs::NS_STYLE_WILL_CHANGE_ABSPOS_CB;
use gecko_bindings::structs::NS_STYLE_WILL_CHANGE_FIXPOS_CB;
use gecko_bindings::structs::NS_STYLE_WILL_CHANGE_STACKING_CONTEXT;
let servo_flags = prop.flags();
let mut bitfield = 0;
if servo_flags.contains(CREATES_STACKING_CONTEXT) {
bitfield |= NS_STYLE_WILL_CHANGE_STACKING_CONTEXT;
}
if servo_flags.contains(FIXPOS_CB) {
bitfield |= NS_STYLE_WILL_CHANGE_FIXPOS_CB;
}
if servo_flags.contains(ABSPOS_CB) {
bitfield |= NS_STYLE_WILL_CHANGE_ABSPOS_CB;
}
bitfield as u8
}
self.gecko.mWillChangeBitField = 0;
match v {
T::AnimateableFeatures(features) => {
unsafe {
Gecko_ClearWillChange(&mut self.gecko, features.len());
}
for feature in features.iter() {
if feature == &atom!("scroll-position") {
self.gecko.mWillChangeBitField |= NS_STYLE_WILL_CHANGE_SCROLL as u8;
} else if feature == &atom!("opacity") {
self.gecko.mWillChangeBitField |= NS_STYLE_WILL_CHANGE_OPACITY as u8;
} else if feature == &atom!("transform") {
self.gecko.mWillChangeBitField |= NS_STYLE_WILL_CHANGE_TRANSFORM as u8;
}
unsafe {
Gecko_AppendWillChange(&mut self.gecko, feature.as_ptr());
}
if let Ok(prop_id) = PropertyId::parse(feature.to_string().into()) {
match prop_id.as_shorthand() {
Ok(shorthand) => {
for longhand in shorthand.longhands() {
self.gecko.mWillChangeBitField |=
will_change_bitfield_from_prop_flags(longhand);
}
},
Err(longhand_or_custom) => {
if let PropertyDeclarationId::Longhand(longhand)
= longhand_or_custom {
self.gecko.mWillChangeBitField |=
will_change_bitfield_from_prop_flags(&longhand);
}
},
}
}
}
},
T::Auto => {
unsafe {
Gecko_ClearWillChange(&mut self.gecko, 0);
}
},
};
}
pub fn copy_will_change_from(&mut self, other: &Self) {
use gecko_bindings::bindings::Gecko_CopyWillChangeFrom;
self.gecko.mWillChangeBitField = other.gecko.mWillChangeBitField;
unsafe {
Gecko_CopyWillChangeFrom(&mut self.gecko, &other.gecko as *const _ as *mut _);
}
}
</%self:impl_trait>
<%def name="simple_image_array_property(name, shorthand, field_name)">

Просмотреть файл

@ -108,6 +108,8 @@ ${helpers.single_keyword("-moz-top-layer", "none top",
need_clone="True"
extra_gecko_values="sticky"
animatable="False"
creates_stacking_context="True"
abspos_cb="True"
spec="https://drafts.csswg.org/css-position/#position-property">
impl SpecifiedValue {
pub fn is_absolutely_positioned_style(&self) -> bool {
@ -1116,6 +1118,8 @@ ${helpers.predefined_type("scroll-snap-coordinate",
<%helpers:longhand name="transform" products="gecko servo" extra_prefixes="webkit"
animatable="True"
creates_stacking_context="True"
fixpos_cb="True"
spec="https://drafts.csswg.org/css-transforms/#propdef-transform">
use app_units::Au;
use style_traits::ToCss;
@ -1672,6 +1676,7 @@ ${helpers.single_keyword("isolation",
"auto isolate",
products="gecko",
spec="https://drafts.fxtf.org/compositing/#isolation",
creates_stacking_context=True,
animatable=False)}
// TODO add support for logical values recto and verso
@ -1710,6 +1715,8 @@ ${helpers.predefined_type("perspective",
spec="https://drafts.csswg.org/css-transforms/#perspective",
extra_prefixes="moz webkit",
boxed=True,
creates_stacking_context=True,
fixpos_cb=True,
animatable=True)}
// FIXME: This prop should be animatable
@ -1819,6 +1826,8 @@ ${helpers.single_keyword("transform-style",
"flat preserve-3d",
spec="https://drafts.csswg.org/css-transforms/#transform-style-property",
extra_prefixes="moz webkit",
creates_stacking_context=True,
fixpos_cb=True,
animatable=False)}
<%helpers:longhand name="transform-origin" animatable="True" extra_prefixes="moz webkit" boxed="True"
@ -1973,3 +1982,67 @@ ${helpers.single_keyword("-moz-orient",
gecko_enum_prefix="StyleOrient",
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-orient)",
animatable=False)}
<%helpers:longhand name="will-change" products="gecko" animatable="False"
spec="https://drafts.csswg.org/css-will-change/#will-change">
use cssparser::serialize_identifier;
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {}
no_viewport_percentage!(SpecifiedValue);
pub mod computed_value {
pub use super::SpecifiedValue as T;
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum SpecifiedValue {
Auto,
AnimateableFeatures(Vec<Atom>),
}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
SpecifiedValue::Auto => dest.write_str("auto"),
SpecifiedValue::AnimateableFeatures(ref features) => {
let (first, rest) = features.split_first().unwrap();
// handle head element
serialize_identifier(&*first.to_string(), dest)?;
// handle tail, precede each with a delimiter
for feature in rest {
dest.write_str(", ")?;
serialize_identifier(&*feature.to_string(), dest)?;
}
Ok(())
}
}
}
}
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T::Auto
}
/// auto | <animateable-feature>#
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
Ok(computed_value::T::Auto)
} else {
input.parse_comma_separated(|i| {
let ident = i.expect_ident()?;
match_ignore_ascii_case! { &ident,
"will-change" | "none" | "all" | "auto" |
"initial" | "inherit" | "unset" | "default" => return Err(()),
_ => {},
}
Ok((Atom::from(ident)))
}).map(SpecifiedValue::AnimateableFeatures)
}
}
</%helpers:longhand>

Просмотреть файл

@ -11,6 +11,7 @@ ${helpers.predefined_type("opacity",
"Opacity",
"1.0",
animatable=True,
creates_stacking_context=True,
spec="https://drafts.csswg.org/css-color/#opacity")}
<%helpers:vector_longhand name="box-shadow" allow_empty="True"
@ -86,6 +87,8 @@ ${helpers.predefined_type("clip",
// FIXME: This prop should be animatable
<%helpers:longhand name="filter" animatable="False" extra_prefixes="webkit"
creates_stacking_context="True"
fixpos_cb="True"
spec="https://drafts.fxtf.org/filters/#propdef-filter">
//pub use self::computed_value::T as SpecifiedValue;
use cssparser;
@ -516,4 +519,5 @@ ${helpers.single_keyword("mix-blend-mode",
color-burn hard-light soft-light difference exclusion hue
saturation color luminosity""", gecko_constant_prefix="NS_STYLE_BLEND",
animatable=False,
creates_stacking_context=True,
spec="https://drafts.fxtf.org/compositing/#propdef-mix-blend-mode")}

Просмотреть файл

@ -26,6 +26,7 @@
${helpers.predefined_type("z-index", "IntegerOrAuto",
"Either::Second(Auto)",
spec="https://www.w3.org/TR/CSS2/visuren.html#z-index",
creates_stacking_context=True,
animatable="True")}
// CSS Flexible Box Layout Module Level 1

Просмотреть файл

@ -59,6 +59,7 @@ ${helpers.single_keyword("mask-type", "luminance alpha",
spec="https://drafts.fxtf.org/css-masking/#propdef-mask-type")}
<%helpers:longhand name="clip-path" animatable="False" products="gecko" boxed="True"
creates_stacking_context="True"
spec="https://drafts.fxtf.org/css-masking/#propdef-clip-path">
use std::fmt;
use style_traits::ToCss;
@ -189,7 +190,8 @@ ${helpers.single_keyword("mask-composite",
spec="https://drafts.fxtf.org/css-masking/#propdef-mask-composite")}
<%helpers:vector_longhand name="mask-image" products="gecko" animatable="False" extra_prefixes="webkit"
has_uncacheable_values="${product == 'gecko'}",
has_uncacheable_values="${product == 'gecko'}"
creates_stacking_context="True"
spec="https://drafts.fxtf.org/css-masking/#propdef-mask-image">
use std::fmt;
use style_traits::ToCss;

Просмотреть файл

@ -420,6 +420,20 @@ impl Parse for CSSWideKeyword {
}
}
bitflags! {
/// A set of flags for properties.
pub flags PropertyFlags: u8 {
/// This property requires a stacking context.
const CREATES_STACKING_CONTEXT = 0x01,
/// This property has values that can establish a containing block for
/// fixed positioned and absolutely positioned elements.
const FIXPOS_CB = 0x02,
/// This property has values that can establish a containing block for
/// absolutely positioned elements.
const ABSPOS_CB = 0x04,
}
}
/// An identifier for a given longhand property.
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -458,6 +472,25 @@ impl LonghandId {
_ => *self
}
}
/// Returns PropertyFlags for given property.
pub fn flags(&self) -> PropertyFlags {
match *self {
% for property in data.longhands:
LonghandId::${property.camel_case} =>
%if property.creates_stacking_context:
CREATES_STACKING_CONTEXT |
%endif
%if property.fixpos_cb:
FIXPOS_CB |
%endif
%if property.abspos_cb:
ABSPOS_CB |
%endif
PropertyFlags::empty(),
% endfor
}
}
}
/// An identifier for a given shorthand property.

Просмотреть файл

@ -0,0 +1,28 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cssparser::Parser;
use media_queries::CSSErrorReporterTest;
use parsing::parse;
use style::parser::ParserContext;
use style::stylesheets::Origin;
use style_traits::ToCss;
#[test]
fn test_will_change() {
use style::properties::longhands::will_change;
assert_roundtrip_with_context!(will_change::parse, "auto");
assert_roundtrip_with_context!(will_change::parse, "scroll-position");
assert_roundtrip_with_context!(will_change::parse, "contents");
assert_roundtrip_with_context!(will_change::parse, "transition");
assert_roundtrip_with_context!(will_change::parse, "opacity, transform");
assert!(parse(will_change::parse, "will-change").is_err());
assert!(parse(will_change::parse, "all").is_err());
assert!(parse(will_change::parse, "none").is_err());
assert!(parse(will_change::parse, "contents, auto").is_err());
assert!(parse(will_change::parse, "contents, inherit, initial").is_err());
assert!(parse(will_change::parse, "transform scroll-position").is_err());
}

Просмотреть файл

@ -85,6 +85,7 @@ mod animation;
mod background;
mod basic_shape;
mod border;
mod box_;
mod column;
mod effects;
mod font;