mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
style: Make will-change honor prefs properly, and clean it up while at it.
Bug: 1466008 Reviewed-by: xidorn MozReview-Commit-ID: JyzwaRgf5Ct
This commit is contained in:
parent
93472bcdea
commit
5db1387f39
3 changed files with 103 additions and 66 deletions
|
@ -3515,77 +3515,27 @@ fn static_assert() {
|
||||||
|
|
||||||
pub fn set_will_change(&mut self, v: longhands::will_change::computed_value::T) {
|
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::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;
|
use properties::longhands::will_change::computed_value::T;
|
||||||
|
|
||||||
fn will_change_bitfield_from_prop_flags(prop: LonghandId) -> u8 {
|
|
||||||
use properties::PropertyFlags;
|
|
||||||
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(PropertyFlags::CREATES_STACKING_CONTEXT) {
|
|
||||||
bitfield |= NS_STYLE_WILL_CHANGE_STACKING_CONTEXT;
|
|
||||||
}
|
|
||||||
if servo_flags.contains(PropertyFlags::FIXPOS_CB) {
|
|
||||||
bitfield |= NS_STYLE_WILL_CHANGE_FIXPOS_CB;
|
|
||||||
}
|
|
||||||
if servo_flags.contains(PropertyFlags::ABSPOS_CB) {
|
|
||||||
bitfield |= NS_STYLE_WILL_CHANGE_ABSPOS_CB;
|
|
||||||
}
|
|
||||||
|
|
||||||
bitfield as u8
|
|
||||||
}
|
|
||||||
|
|
||||||
self.gecko.mWillChangeBitField = 0;
|
|
||||||
|
|
||||||
match v {
|
match v {
|
||||||
T::AnimateableFeatures(features) => {
|
T::AnimateableFeatures { features, bits } => {
|
||||||
unsafe {
|
unsafe {
|
||||||
Gecko_ClearWillChange(&mut self.gecko, features.len());
|
Gecko_ClearWillChange(&mut self.gecko, features.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
for feature in features.iter() {
|
for feature in features.iter() {
|
||||||
if feature.0 == atom!("scroll-position") {
|
|
||||||
self.gecko.mWillChangeBitField |= NS_STYLE_WILL_CHANGE_SCROLL as u8;
|
|
||||||
} else if feature.0 == atom!("opacity") {
|
|
||||||
self.gecko.mWillChangeBitField |= NS_STYLE_WILL_CHANGE_OPACITY as u8;
|
|
||||||
} else if feature.0 == atom!("transform") {
|
|
||||||
self.gecko.mWillChangeBitField |= NS_STYLE_WILL_CHANGE_TRANSFORM as u8;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
Gecko_AppendWillChange(&mut self.gecko, feature.0.as_ptr());
|
Gecko_AppendWillChange(&mut self.gecko, feature.0.as_ptr())
|
||||||
}
|
|
||||||
|
|
||||||
if let Ok(prop_id) = PropertyId::parse(&feature.0.to_string()) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.gecko.mWillChangeBitField = bits.bits();
|
||||||
},
|
},
|
||||||
T::Auto => {
|
T::Auto => {
|
||||||
unsafe {
|
unsafe {
|
||||||
Gecko_ClearWillChange(&mut self.gecko, 0);
|
Gecko_ClearWillChange(&mut self.gecko, 0);
|
||||||
}
|
}
|
||||||
|
self.gecko.mWillChangeBitField = 0;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -3607,6 +3557,7 @@ fn static_assert() {
|
||||||
use properties::longhands::will_change::computed_value::T;
|
use properties::longhands::will_change::computed_value::T;
|
||||||
use gecko_bindings::structs::nsAtom;
|
use gecko_bindings::structs::nsAtom;
|
||||||
use values::CustomIdent;
|
use values::CustomIdent;
|
||||||
|
use values::specified::box_::WillChangeBits;
|
||||||
|
|
||||||
if self.gecko.mWillChange.len() == 0 {
|
if self.gecko.mWillChange.len() == 0 {
|
||||||
return T::Auto
|
return T::Auto
|
||||||
|
@ -3618,7 +3569,10 @@ fn static_assert() {
|
||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
T::AnimateableFeatures(custom_idents.into_boxed_slice())
|
T::AnimateableFeatures {
|
||||||
|
features: custom_idents.into_boxed_slice(),
|
||||||
|
bits: WillChangeBits::from_bits_truncate(self.gecko.mWillChangeBitField),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<% impl_shape_source("shape_outside", "mShapeOutside") %>
|
<% impl_shape_source("shape_outside", "mShapeOutside") %>
|
||||||
|
|
|
@ -1715,7 +1715,8 @@ impl PropertyId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn non_custom_id(&self) -> Option<NonCustomPropertyId> {
|
/// Returns the non-custom property id for this property.
|
||||||
|
pub fn non_custom_id(&self) -> Option<NonCustomPropertyId> {
|
||||||
Some(match *self {
|
Some(match *self {
|
||||||
PropertyId::Custom(_) => return None,
|
PropertyId::Custom(_) => return None,
|
||||||
PropertyId::Shorthand(shorthand_id) => shorthand_id.into(),
|
PropertyId::Shorthand(shorthand_id) => shorthand_id.into(),
|
||||||
|
@ -1750,7 +1751,8 @@ impl PropertyId {
|
||||||
id.enabled_for_all_content()
|
id.enabled_for_all_content()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allowed_in(&self, context: &ParserContext) -> bool {
|
/// Returns whether the property is allowed in a given context.
|
||||||
|
pub fn allowed_in(&self, context: &ParserContext) -> bool {
|
||||||
let id = match self.non_custom_id() {
|
let id = match self.non_custom_id() {
|
||||||
// Custom properties are allowed everywhere
|
// Custom properties are allowed everywhere
|
||||||
None => return true,
|
None => return true,
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
use Atom;
|
use Atom;
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
use properties::{LonghandId, PropertyId, PropertyFlags, PropertyDeclarationId};
|
||||||
use selectors::parser::SelectorParseErrorKind;
|
use selectors::parser::SelectorParseErrorKind;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||||
|
@ -382,7 +383,15 @@ pub enum WillChange {
|
||||||
Auto,
|
Auto,
|
||||||
/// <custom-ident>
|
/// <custom-ident>
|
||||||
#[css(comma)]
|
#[css(comma)]
|
||||||
AnimateableFeatures(#[css(iterable)] Box<[CustomIdent]>),
|
AnimateableFeatures {
|
||||||
|
/// The features that are supposed to change.
|
||||||
|
#[css(iterable)]
|
||||||
|
features: Box<[CustomIdent]>,
|
||||||
|
/// A bitfield with the kind of change that the value will create, based
|
||||||
|
/// on the above field.
|
||||||
|
#[css(skip)]
|
||||||
|
bits: WillChangeBits,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WillChange {
|
impl WillChange {
|
||||||
|
@ -393,10 +402,72 @@ impl WillChange {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
/// The change bits that we care about.
|
||||||
|
///
|
||||||
|
/// These need to be in sync with NS_STYLE_WILL_CHANGE_*.
|
||||||
|
#[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue)]
|
||||||
|
pub struct WillChangeBits: u8 {
|
||||||
|
/// Whether the stacking context will change.
|
||||||
|
const STACKING_CONTEXT = 1 << 0;
|
||||||
|
/// Whether `transform` will change.
|
||||||
|
const TRANSFORM = 1 << 1;
|
||||||
|
/// Whether `scroll-position` will change.
|
||||||
|
const SCROLL = 1 << 2;
|
||||||
|
/// Whether `opacity` will change.
|
||||||
|
const OPACITY = 1 << 3;
|
||||||
|
/// Fixed pos containing block.
|
||||||
|
const FIXPOS_CB = 1 << 4;
|
||||||
|
/// Abs pos containing block.
|
||||||
|
const ABSPOS_CB = 1 << 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn change_bits_for_longhand(longhand: LonghandId) -> WillChangeBits {
|
||||||
|
let mut flags = match longhand {
|
||||||
|
LonghandId::Opacity => WillChangeBits::OPACITY,
|
||||||
|
LonghandId::Transform => WillChangeBits::TRANSFORM,
|
||||||
|
_ => WillChangeBits::empty(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let property_flags = longhand.flags();
|
||||||
|
if property_flags.contains(PropertyFlags::CREATES_STACKING_CONTEXT) {
|
||||||
|
flags |= WillChangeBits::STACKING_CONTEXT;
|
||||||
|
}
|
||||||
|
if property_flags.contains(PropertyFlags::FIXPOS_CB) {
|
||||||
|
flags |= WillChangeBits::FIXPOS_CB;
|
||||||
|
}
|
||||||
|
if property_flags.contains(PropertyFlags::ABSPOS_CB) {
|
||||||
|
flags |= WillChangeBits::ABSPOS_CB;
|
||||||
|
}
|
||||||
|
flags
|
||||||
|
}
|
||||||
|
|
||||||
|
fn change_bits_for_maybe_property(ident: &str, context: &ParserContext) -> WillChangeBits {
|
||||||
|
let id = match PropertyId::parse(ident) {
|
||||||
|
Ok(id) => id,
|
||||||
|
Err(..) => return WillChangeBits::empty(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if !id.allowed_in(context) {
|
||||||
|
return WillChangeBits::empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
match id.as_shorthand() {
|
||||||
|
Ok(shorthand) => {
|
||||||
|
shorthand.longhands().fold(WillChangeBits::empty(), |flags, p| {
|
||||||
|
flags | change_bits_for_longhand(p)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Err(PropertyDeclarationId::Longhand(longhand)) => change_bits_for_longhand(longhand),
|
||||||
|
Err(PropertyDeclarationId::Custom(..)) => WillChangeBits::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Parse for WillChange {
|
impl Parse for WillChange {
|
||||||
/// auto | <animateable-feature>#
|
/// auto | <animateable-feature>#
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
_context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<WillChange, ParseError<'i>> {
|
) -> Result<WillChange, ParseError<'i>> {
|
||||||
if input
|
if input
|
||||||
|
@ -406,18 +477,28 @@ impl Parse for WillChange {
|
||||||
return Ok(WillChange::Auto);
|
return Ok(WillChange::Auto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut bits = WillChangeBits::empty();
|
||||||
let custom_idents = input.parse_comma_separated(|i| {
|
let custom_idents = input.parse_comma_separated(|i| {
|
||||||
let location = i.current_source_location();
|
let location = i.current_source_location();
|
||||||
CustomIdent::from_ident(
|
let parser_ident = i.expect_ident()?;
|
||||||
|
let ident = CustomIdent::from_ident(
|
||||||
location,
|
location,
|
||||||
i.expect_ident()?,
|
parser_ident,
|
||||||
&["will-change", "none", "all", "auto"],
|
&["will-change", "none", "all", "auto"],
|
||||||
)
|
)?;
|
||||||
|
|
||||||
|
if ident.0 == atom!("scroll-position") {
|
||||||
|
bits |= WillChangeBits::SCROLL;
|
||||||
|
} else {
|
||||||
|
bits |= change_bits_for_maybe_property(&parser_ident, context);
|
||||||
|
}
|
||||||
|
Ok(ident)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(WillChange::AnimateableFeatures(
|
Ok(WillChange::AnimateableFeatures {
|
||||||
custom_idents.into_boxed_slice(),
|
features: custom_idents.into_boxed_slice(),
|
||||||
))
|
bits,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue