Auto merge of #22352 - emilio:gecko-sync, r=emilio

style: Sync changes from mozilla-central.

See each individual commit for details.

<!-- 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/22352)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2018-12-02 19:07:23 -05:00 committed by GitHub
commit 5bdea7dc1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 2100 additions and 1984 deletions

View file

@ -1499,8 +1499,11 @@ impl FragmentDisplayListBuilding for Fragment {
let outline_style = match style.get_outline().outline_style { let outline_style = match style.get_outline().outline_style {
OutlineStyle::Auto => BorderStyle::Solid, OutlineStyle::Auto => BorderStyle::Solid,
OutlineStyle::Other(BorderStyle::None) => return, // FIXME(emilio): I don't think this border-style check is
OutlineStyle::Other(border_style) => border_style, // necessary, since border-style: none implies an outline-width of
// zero at computed value time.
OutlineStyle::BorderStyle(BorderStyle::None) => return,
OutlineStyle::BorderStyle(s) => s,
}; };
// Outlines are not accounted for in the dimensions of the border box, so adjust the // Outlines are not accounted for in the dimensions of the border box, so adjust the

View file

@ -31,6 +31,7 @@ include = ["cssparser"]
[struct] [struct]
derive_eq = true derive_eq = true
derive_neq = true
[enum] [enum]
derive_helper_methods = true derive_helper_methods = true
@ -41,6 +42,8 @@ include = [
"Appearance", "Appearance",
"BreakBetween", "BreakBetween",
"BreakWithin", "BreakWithin",
"BorderStyle",
"OutlineStyle",
"ComputedFontStretchRange", "ComputedFontStretchRange",
"ComputedFontStyleDescriptor", "ComputedFontStyleDescriptor",
"ComputedFontWeightRange", "ComputedFontWeightRange",

View file

@ -283,18 +283,32 @@ impl VariableValue {
} }
} }
fn push( fn push<'i>(
&mut self, &mut self,
input: &Parser<'i, '_>,
css: &str, css: &str,
css_first_token_type: TokenSerializationType, css_first_token_type: TokenSerializationType,
css_last_token_type: TokenSerializationType, css_last_token_type: TokenSerializationType,
) { ) -> Result<(), ParseError<'i>> {
/// Prevent values from getting terribly big since you can use custom
/// properties exponentially.
///
/// This number (1MB) is somewhat arbitrary, but silly enough that no
/// sane page would hit it. We could limit by number of total
/// substitutions, but that was very easy to work around in practice
/// (just choose a larger initial value and boom).
const MAX_VALUE_LENGTH_IN_BYTES: usize = 1024 * 1024;
if self.css.len() + css.len() > MAX_VALUE_LENGTH_IN_BYTES {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
// This happens e.g. between two subsequent var() functions: // This happens e.g. between two subsequent var() functions:
// `var(--a)var(--b)`. // `var(--a)var(--b)`.
// //
// In that case, css_*_token_type is nonsensical. // In that case, css_*_token_type is nonsensical.
if css.is_empty() { if css.is_empty() {
return; return Ok(());
} }
self.first_token_type.set_if_nothing(css_first_token_type); self.first_token_type.set_if_nothing(css_first_token_type);
@ -307,21 +321,32 @@ impl VariableValue {
self.css.push_str("/**/") self.css.push_str("/**/")
} }
self.css.push_str(css); self.css.push_str(css);
self.last_token_type = css_last_token_type self.last_token_type = css_last_token_type;
Ok(())
} }
fn push_from( fn push_from<'i>(
&mut self, &mut self,
input: &Parser<'i, '_>,
position: (SourcePosition, TokenSerializationType), position: (SourcePosition, TokenSerializationType),
input: &Parser,
last_token_type: TokenSerializationType, last_token_type: TokenSerializationType,
) { ) -> Result<(), ParseError<'i>> {
self.push(input.slice_from(position.0), position.1, last_token_type) self.push(
input,
input.slice_from(position.0),
position.1,
last_token_type,
)
} }
fn push_variable(&mut self, variable: &ComputedValue) { fn push_variable<'i>(
&mut self,
input: &Parser<'i, '_>,
variable: &ComputedValue,
) -> Result<(), ParseError<'i>> {
debug_assert!(variable.references.is_empty()); debug_assert!(variable.references.is_empty());
self.push( self.push(
input,
&variable.css, &variable.css,
variable.first_token_type, variable.first_token_type,
variable.last_token_type, variable.last_token_type,
@ -727,6 +752,7 @@ fn substitute_all(custom_properties_map: &mut CustomPropertiesMap, environment:
// title=Tarjan%27s_strongly_connected_components_algorithm&oldid=801728495 // title=Tarjan%27s_strongly_connected_components_algorithm&oldid=801728495
/// Struct recording necessary information for each variable. /// Struct recording necessary information for each variable.
#[derive(Debug)]
struct VarInfo { struct VarInfo {
/// The name of the variable. It will be taken to save addref /// The name of the variable. It will be taken to save addref
/// when the corresponding variable is popped from the stack. /// when the corresponding variable is popped from the stack.
@ -741,6 +767,7 @@ fn substitute_all(custom_properties_map: &mut CustomPropertiesMap, environment:
} }
/// Context struct for traversing the variable graph, so that we can /// Context struct for traversing the variable graph, so that we can
/// avoid referencing all the fields multiple times. /// avoid referencing all the fields multiple times.
#[derive(Debug)]
struct Context<'a> { struct Context<'a> {
/// Number of variables visited. This is used as the order index /// Number of variables visited. This is used as the order index
/// when we visit a new unresolved variable. /// when we visit a new unresolved variable.
@ -941,7 +968,7 @@ fn substitute_references_in_value<'i>(
environment, environment,
)?; )?;
computed_value.push_from(position, &input, last_token_type); computed_value.push_from(&input, position, last_token_type)?;
Ok(computed_value) Ok(computed_value)
} }
@ -955,8 +982,8 @@ fn substitute_references_in_value<'i>(
/// ///
/// Return `Err(())` if `input` is invalid at computed-value time. /// Return `Err(())` if `input` is invalid at computed-value time.
/// or `Ok(last_token_type that was pushed to partial_computed_value)` otherwise. /// or `Ok(last_token_type that was pushed to partial_computed_value)` otherwise.
fn substitute_block<'i, 't>( fn substitute_block<'i>(
input: &mut Parser<'i, 't>, input: &mut Parser<'i, '_>,
position: &mut (SourcePosition, TokenSerializationType), position: &mut (SourcePosition, TokenSerializationType),
partial_computed_value: &mut ComputedValue, partial_computed_value: &mut ComputedValue,
custom_properties: &CustomPropertiesMap, custom_properties: &CustomPropertiesMap,
@ -991,10 +1018,11 @@ fn substitute_block<'i, 't>(
let is_env = name.eq_ignore_ascii_case("env"); let is_env = name.eq_ignore_ascii_case("env");
partial_computed_value.push( partial_computed_value.push(
input,
input.slice(position.0..before_this_token), input.slice(position.0..before_this_token),
position.1, position.1,
last_token_type, last_token_type,
); )?;
input.parse_nested_block(|input| { input.parse_nested_block(|input| {
// parse_var_function() / parse_env_function() ensure neither .unwrap() will fail. // parse_var_function() / parse_env_function() ensure neither .unwrap() will fail.
let name = { let name = {
@ -1014,7 +1042,7 @@ fn substitute_block<'i, 't>(
if let Some(v) = value { if let Some(v) = value {
last_token_type = v.last_token_type; last_token_type = v.last_token_type;
partial_computed_value.push_variable(v); partial_computed_value.push_variable(input, v)?;
// Skip over the fallback, as `parse_nested_block` would return `Err` // Skip over the fallback, as `parse_nested_block` would return `Err`
// if we don't consume all of `input`. // if we don't consume all of `input`.
// FIXME: Add a specialized method to cssparser to do this with less work. // FIXME: Add a specialized method to cssparser to do this with less work.
@ -1036,7 +1064,7 @@ fn substitute_block<'i, 't>(
custom_properties, custom_properties,
env, env,
)?; )?;
partial_computed_value.push_from(position, input, last_token_type); partial_computed_value.push_from(input, position, last_token_type)?;
} }
Ok(()) Ok(())
})?; })?;
@ -1096,6 +1124,6 @@ pub fn substitute<'i>(
&custom_properties, &custom_properties,
env, env,
)?; )?;
substituted.push_from(position, &input, last_token_type); substituted.push_from(&input, position, last_token_type)?;
Ok(substituted.css) Ok(substituted.css)
} }

View file

@ -11,11 +11,13 @@
use app_units::Au; use app_units::Au;
use crate::gecko::values::GeckoStyleCoordConvertible; use crate::gecko::values::GeckoStyleCoordConvertible;
use crate::gecko_bindings::bindings; use crate::gecko_bindings::bindings;
use crate::gecko_bindings::structs::RawGeckoGfxMatrix4x4;
use crate::gecko_bindings::structs::{self, nsStyleCoord_CalcValue}; use crate::gecko_bindings::structs::{self, nsStyleCoord_CalcValue};
use crate::gecko_bindings::structs::{nsStyleImage, nsresult, SheetType}; use crate::gecko_bindings::structs::{nsStyleImage, nsresult, SheetType};
use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue}; use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
use crate::stylesheets::{Origin, RulesMutateError}; use crate::stylesheets::{Origin, RulesMutateError};
use crate::values::computed::image::LineDirection; use crate::values::computed::image::LineDirection;
use crate::values::computed::transform::Matrix3D;
use crate::values::computed::url::ComputedImageUrl; use crate::values::computed::url::ComputedImageUrl;
use crate::values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image}; use crate::values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image};
use crate::values::computed::{Integer, LengthOrPercentage}; use crate::values::computed::{Integer, LengthOrPercentage};
@ -1142,3 +1144,36 @@ pub unsafe fn string_from_chars_pointer(p: *const u16) -> String {
let char_vec = slice::from_raw_parts(p, length as usize); let char_vec = slice::from_raw_parts(p, length as usize);
String::from_utf16_lossy(char_vec) String::from_utf16_lossy(char_vec)
} }
impl<'a> From<&'a RawGeckoGfxMatrix4x4> for Matrix3D {
fn from(m: &'a RawGeckoGfxMatrix4x4) -> Matrix3D {
Matrix3D {
m11: m[0],
m12: m[1],
m13: m[2],
m14: m[3],
m21: m[4],
m22: m[5],
m23: m[6],
m24: m[7],
m31: m[8],
m32: m[9],
m33: m[10],
m34: m[11],
m41: m[12],
m42: m[13],
m43: m[14],
m44: m[15],
}
}
}
impl From<Matrix3D> for RawGeckoGfxMatrix4x4 {
fn from(matrix: Matrix3D) -> RawGeckoGfxMatrix4x4 {
[
matrix.m11, matrix.m12, matrix.m13, matrix.m14, matrix.m21, matrix.m22, matrix.m23,
matrix.m24, matrix.m31, matrix.m32, matrix.m33, matrix.m34, matrix.m41, matrix.m42,
matrix.m43, matrix.m44,
]
}
}

View file

@ -462,22 +462,6 @@ impl PropertyDeclarationBlock {
return false; return false;
} }
// As a compatibility hack, specially on Android,
// don't allow to override a prefixed webkit display
// value with an unprefixed version from parsing
// code.
//
// TODO(emilio): Unship.
if let PropertyDeclaration::Display(old_display) = *slot {
use crate::properties::longhands::display::computed_value::T as display;
if let PropertyDeclaration::Display(new_display) = declaration {
if display::should_ignore_parsed_value(old_display, new_display) {
return false;
}
}
}
index_to_remove = Some(i); index_to_remove = Some(i);
break; break;
} }
@ -933,6 +917,10 @@ impl PropertyDeclarationBlock {
} }
already_serialized.insert(shorthand.into()); already_serialized.insert(shorthand.into());
if shorthand.is_legacy_shorthand() {
continue;
}
// Substep 2 & 3 // Substep 2 & 3
let mut current_longhands = SmallVec::<[_; 10]>::new(); let mut current_longhands = SmallVec::<[_; 10]>::new();
let mut important_count = 0; let mut important_count = 0;

View file

@ -58,15 +58,14 @@ use std::mem::{forget, uninitialized, transmute, zeroed};
use std::{cmp, ops, ptr}; use std::{cmp, ops, ptr};
use crate::values::{self, CustomIdent, Either, KeyframesName, None_}; use crate::values::{self, CustomIdent, Either, KeyframesName, None_};
use crate::values::computed::{NonNegativeLength, Percentage, TransitionProperty}; use crate::values::computed::{NonNegativeLength, Percentage, TransitionProperty};
use crate::values::computed::BorderStyle;
use crate::values::computed::font::FontSize; use crate::values::computed::font::FontSize;
use crate::values::computed::effects::{BoxShadow, Filter, SimpleShadow}; use crate::values::computed::effects::{BoxShadow, Filter, SimpleShadow};
use crate::values::computed::outline::OutlineStyle;
use crate::values::generics::column::ColumnCount; use crate::values::generics::column::ColumnCount;
use crate::values::generics::position::ZIndex; use crate::values::generics::position::ZIndex;
use crate::values::generics::text::MozTabSize; use crate::values::generics::text::MozTabSize;
use crate::values::generics::transform::TransformStyle; use crate::values::generics::transform::TransformStyle;
use crate::values::generics::url::UrlOrNone; use crate::values::generics::url::UrlOrNone;
use crate::computed_values::border_style;
pub mod style_structs { pub mod style_structs {
% for style_struct in data.style_structs: % for style_struct in data.style_structs:
@ -333,13 +332,10 @@ impl ${style_struct.gecko_struct_name} {
} }
</%def> </%def>
<%def name="impl_simple_copy(ident, gecko_ffi_name, on_set=None, *kwargs)"> <%def name="impl_simple_copy(ident, gecko_ffi_name, *kwargs)">
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn copy_${ident}_from(&mut self, other: &Self) { pub fn copy_${ident}_from(&mut self, other: &Self) {
self.gecko.${gecko_ffi_name} = other.gecko.${gecko_ffi_name}; self.gecko.${gecko_ffi_name} = other.gecko.${gecko_ffi_name};
% if on_set:
self.${on_set}();
% endif
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -368,7 +364,7 @@ def set_gecko_property(ffi_name, expr):
return "self.gecko.%s = %s;" % (ffi_name, expr) return "self.gecko.%s = %s;" % (ffi_name, expr)
%> %>
<%def name="impl_keyword_setter(ident, gecko_ffi_name, keyword, cast_type='u8', on_set=None)"> <%def name="impl_keyword_setter(ident, gecko_ffi_name, keyword, cast_type='u8')">
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
use crate::properties::longhands::${ident}::computed_value::T as Keyword; use crate::properties::longhands::${ident}::computed_value::T as Keyword;
@ -380,9 +376,6 @@ def set_gecko_property(ffi_name, expr):
% endfor % endfor
}; };
${set_gecko_property(gecko_ffi_name, "result")} ${set_gecko_property(gecko_ffi_name, "result")}
% if on_set:
self.${on_set}();
% endif
} }
</%def> </%def>
@ -1515,9 +1508,6 @@ fn static_assert() {
} }
<% border_style_keyword = Keyword("border-style",
"none solid double dotted dashed hidden groove ridge inset outset") %>
<% skip_border_longhands = " ".join(["border-{0}-{1}".format(x.ident, y) <% skip_border_longhands = " ".join(["border-{0}-{1}".format(x.ident, y)
for x in SIDES for x in SIDES
for y in ["color", "style", "width"]] + for y in ["color", "style", "width"]] +
@ -1528,41 +1518,55 @@ fn static_assert() {
skip_longhands="${skip_border_longhands} border-image-source border-image-outset skip_longhands="${skip_border_longhands} border-image-source border-image-outset
border-image-repeat border-image-width border-image-slice"> border-image-repeat border-image-width border-image-slice">
% for side in SIDES: % for side in SIDES:
<% impl_keyword("border_%s_style" % side.ident, pub fn set_border_${side.ident}_style(&mut self, v: BorderStyle) {
"mBorderStyle[%s]" % side.index, self.gecko.mBorderStyle[${side.index}] = v;
border_style_keyword,
on_set="update_border_%s" % side.ident) %>
// This is needed because the initial mComputedBorder value is set to zero. // This is needed because the initial mComputedBorder value is set to
// // zero.
// In order to compute stuff, we start from the initial struct, and keep //
// going down the tree applying properties. // In order to compute stuff, we start from the initial struct, and keep
// // going down the tree applying properties.
// That means, effectively, that when we set border-style to something //
// non-hidden, we should use the initial border instead. // That means, effectively, that when we set border-style to something
// // non-hidden, we should use the initial border instead.
// Servo stores the initial border-width in the initial struct, and then //
// adjusts as needed in the fixup phase. This means that the initial struct // Servo stores the initial border-width in the initial struct, and then
// is technically not valid without fixups, and that you lose pretty much // adjusts as needed in the fixup phase. This means that the initial
// any sharing of the initial struct, which is kind of unfortunate. // struct is technically not valid without fixups, and that you lose
// // pretty much any sharing of the initial struct, which is kind of
// Gecko has two fields for this, one that stores the "specified" border, // unfortunate.
// and other that stores the actual computed one. That means that when we //
// set border-style, border-width may change and we need to sync back to the // Gecko has two fields for this, one that stores the "specified"
// specified one. This is what this function does. // border, and other that stores the actual computed one. That means
// // that when we set border-style, border-width may change and we need to
// Note that this doesn't impose any dependency in the order of computation // sync back to the specified one. This is what this function does.
// of the properties. This is only relevant if border-style is specified, //
// but border-width isn't. If border-width is specified at some point, the // Note that this doesn't impose any dependency in the order of
// two mBorder and mComputedBorder fields would be the same already. // computation of the properties. This is only relevant if border-style
// // is specified, but border-width isn't. If border-width is specified at
// Once we're here, we know that we'll run style fixups, so it's fine to // some point, the two mBorder and mComputedBorder fields would be the
// just copy the specified border here, we'll adjust it if it's incorrect // same already.
// later. //
fn update_border_${side.ident}(&mut self) { // Once we're here, we know that we'll run style fixups, so it's fine to
// just copy the specified border here, we'll adjust it if it's
// incorrect later.
self.gecko.mComputedBorder.${side.ident} = self.gecko.mBorder.${side.ident}; self.gecko.mComputedBorder.${side.ident} = self.gecko.mBorder.${side.ident};
} }
pub fn copy_border_${side.ident}_style_from(&mut self, other: &Self) {
self.gecko.mBorderStyle[${side.index}] = other.gecko.mBorderStyle[${side.index}];
self.gecko.mComputedBorder.${side.ident} = self.gecko.mBorder.${side.ident};
}
pub fn reset_border_${side.ident}_style(&mut self, other: &Self) {
self.copy_border_${side.ident}_style_from(other);
}
#[inline]
pub fn clone_border_${side.ident}_style(&self) -> BorderStyle {
self.gecko.mBorderStyle[${side.index}]
}
<% impl_color("border_%s_color" % side.ident, "mBorder%sColor" % side.name) %> <% impl_color("border_%s_color" % side.ident, "mBorder%sColor" % side.name) %>
<% impl_non_negative_length("border_%s_width" % side.ident, <% impl_non_negative_length("border_%s_width" % side.ident,
@ -2170,50 +2174,26 @@ fn static_assert() {
<%self:impl_trait style_struct_name="Outline" <%self:impl_trait style_struct_name="Outline"
skip_longhands="${skip_outline_longhands}"> skip_longhands="${skip_outline_longhands}">
#[allow(non_snake_case)]
pub fn set_outline_style(&mut self, v: longhands::outline_style::computed_value::T) { pub fn set_outline_style(&mut self, v: longhands::outline_style::computed_value::T) {
// FIXME(bholley): Align binary representations and ditch |match| for self.gecko.mOutlineStyle = v;
// cast + static_asserts
let result = match v {
% for value in border_style_keyword.values_for('gecko'):
OutlineStyle::Other(border_style::T::${to_camel_case(value)}) =>
structs::${border_style_keyword.gecko_constant(value)} ${border_style_keyword.maybe_cast("u8")},
% endfor
OutlineStyle::Auto =>
structs::${border_style_keyword.gecko_constant('auto')} ${border_style_keyword.maybe_cast("u8")},
};
${set_gecko_property("mOutlineStyle", "result")}
// NB: This is needed to correctly handling the initial value of // NB: This is needed to correctly handling the initial value of
// outline-width when outline-style changes, see the // outline-width when outline-style changes, see the
// update_border_${side.ident} comment for more details. // update_border_${side.ident} comment for more details.
self.gecko.mActualOutlineWidth = self.gecko.mOutlineWidth; self.gecko.mActualOutlineWidth = self.gecko.mOutlineWidth;
} }
#[allow(non_snake_case)]
pub fn copy_outline_style_from(&mut self, other: &Self) { pub fn copy_outline_style_from(&mut self, other: &Self) {
// FIXME(emilio): Why doesn't this need to reset mActualOutlineWidth?
// Looks fishy.
self.gecko.mOutlineStyle = other.gecko.mOutlineStyle; self.gecko.mOutlineStyle = other.gecko.mOutlineStyle;
} }
#[allow(non_snake_case)]
pub fn reset_outline_style(&mut self, other: &Self) { pub fn reset_outline_style(&mut self, other: &Self) {
self.copy_outline_style_from(other) self.copy_outline_style_from(other)
} }
#[allow(non_snake_case)]
pub fn clone_outline_style(&self) -> longhands::outline_style::computed_value::T { pub fn clone_outline_style(&self) -> longhands::outline_style::computed_value::T {
// FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts self.gecko.mOutlineStyle.clone()
match ${get_gecko_property("mOutlineStyle")} ${border_style_keyword.maybe_cast("u32")} {
% for value in border_style_keyword.values_for('gecko'):
structs::${border_style_keyword.gecko_constant(value)} => {
OutlineStyle::Other(border_style::T::${to_camel_case(value)})
},
% endfor
structs::${border_style_keyword.gecko_constant('auto')} => OutlineStyle::Auto,
% if border_style_keyword.gecko_inexhaustive:
_ => panic!("Found unexpected value in style struct for outline_style property"),
% endif
}
} }
<% impl_non_negative_length("outline_width", "mActualOutlineWidth", <% impl_non_negative_length("outline_width", "mActualOutlineWidth",
@ -5410,7 +5390,7 @@ clip-path
</%self:impl_trait> </%self:impl_trait>
<%self:impl_trait style_struct_name="Column" <%self:impl_trait style_struct_name="Column"
skip_longhands="column-count column-rule-width"> skip_longhands="column-count column-rule-width column-rule-style">
#[allow(unused_unsafe)] #[allow(unused_unsafe)]
pub fn set_column_count(&mut self, v: longhands::column_count::computed_value::T) { pub fn set_column_count(&mut self, v: longhands::column_count::computed_value::T) {
@ -5439,6 +5419,7 @@ clip-path
<% impl_non_negative_length("column_rule_width", "mColumnRuleWidth", <% impl_non_negative_length("column_rule_width", "mColumnRuleWidth",
round_to_pixels=True) %> round_to_pixels=True) %>
${impl_simple('column_rule_style', 'mColumnRuleStyle')}
</%self:impl_trait> </%self:impl_trait>
<%self:impl_trait style_struct_name="Counters" <%self:impl_trait style_struct_name="Counters"

File diff suppressed because it is too large Load diff

View file

@ -15,7 +15,8 @@ ${helpers.predefined_type(
animation_value_type="AnimatedColor", animation_value_type="AnimatedColor",
ignored_when_colors_disabled=True, ignored_when_colors_disabled=True,
allow_quirks=True, allow_quirks=True,
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER \
CAN_ANIMATE_ON_COMPOSITOR",
)} )}
${helpers.predefined_type( ${helpers.predefined_type(

View file

@ -63,7 +63,9 @@
${helpers.gecko_keyword_conversion( ${helpers.gecko_keyword_conversion(
Keyword('border-style', Keyword('border-style',
"none solid double dotted dashed hidden groove ridge inset outset"), "none solid double dotted dashed hidden groove ridge inset outset",
gecko_enum_prefix="StyleBorderStyle",
gecko_inexhaustive=True),
type="crate::values::specified::BorderStyle", type="crate::values::specified::BorderStyle",
)} )}

View file

@ -438,33 +438,33 @@ ${helpers.single_keyword(
)} )}
${helpers.predefined_type( ${helpers.predefined_type(
"page-break-after", "break-after",
"BreakBetween", "BreakBetween",
"computed::BreakBetween::Auto", "computed::BreakBetween::Auto",
needs_context=False, needs_context=False,
products="gecko", products="gecko",
spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-after", spec="https://drafts.csswg.org/css-break/#propdef-break-after",
animation_value_type="discrete", animation_value_type="discrete",
)} )}
${helpers.predefined_type( ${helpers.predefined_type(
"page-break-before", "break-before",
"BreakBetween", "BreakBetween",
"computed::BreakBetween::Auto", "computed::BreakBetween::Auto",
needs_context=False, needs_context=False,
products="gecko", products="gecko",
spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-before", spec="https://drafts.csswg.org/css-break/#propdef-break-before",
animation_value_type="discrete", animation_value_type="discrete",
)} )}
${helpers.predefined_type( ${helpers.predefined_type(
"page-break-inside", "break-inside",
"BreakWithin", "BreakWithin",
"computed::BreakWithin::Auto", "computed::BreakWithin::Auto",
gecko_ffi_name="mBreakInside",
needs_context=False, needs_context=False,
products="gecko", products="gecko",
spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-inside", alias="page-break-inside",
spec="https://drafts.csswg.org/css-break/#propdef-break-inside",
animation_value_type="discrete", animation_value_type="discrete",
)} )}

View file

@ -78,12 +78,14 @@ ${helpers.single_keyword(
extra_prefixes="moz:layout.css.column-span.enabled", extra_prefixes="moz:layout.css.column-span.enabled",
)} )}
${helpers.single_keyword( ${helpers.predefined_type(
"column-rule-style", "column-rule-style",
"none hidden dotted dashed solid double groove ridge inset outset", "BorderStyle",
"computed::BorderStyle::None",
needs_context=False,
initial_specified_value="specified::BorderStyle::None",
products="gecko", products="gecko",
extra_prefixes="moz", extra_prefixes="moz",
gecko_constant_prefix="NS_STYLE_BORDER_STYLE",
animation_value_type="discrete", animation_value_type="discrete",
spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-style", spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-style",
)} )}

View file

@ -337,6 +337,7 @@ ${helpers.single_keyword(
${helpers.single_keyword( ${helpers.single_keyword(
"text-rendering", "text-rendering",
"auto optimizespeed optimizelegibility geometricprecision", "auto optimizespeed optimizelegibility geometricprecision",
gecko_enum_prefix="StyleTextRendering",
animation_value_type="discrete", animation_value_type="discrete",
spec="https://www.w3.org/TR/SVG11/painting.html#TextRenderingProperty", spec="https://www.w3.org/TR/SVG11/painting.html#TextRenderingProperty",
servo_restyle_damage="rebuild_and_reflow", servo_restyle_damage="rebuild_and_reflow",

View file

@ -39,6 +39,7 @@ ${helpers.predefined_type(
gecko_ffi_name="mUserSelect", gecko_ffi_name="mUserSelect",
alias="-webkit-user-select", alias="-webkit-user-select",
animation_value_type="discrete", animation_value_type="discrete",
needs_context=False,
spec="https://drafts.csswg.org/css-ui-4/#propdef-user-select", spec="https://drafts.csswg.org/css-ui-4/#propdef-user-select",
)} )}

View file

@ -948,6 +948,10 @@ bitflags! {
/// This property's getComputedStyle implementation requires layout /// This property's getComputedStyle implementation requires layout
/// to be flushed. /// to be flushed.
const GETCS_NEEDS_LAYOUT_FLUSH = 1 << 6; const GETCS_NEEDS_LAYOUT_FLUSH = 1 << 6;
/// This property is a legacy shorthand.
///
/// https://drafts.csswg.org/css-cascade/#legacy-shorthand
const IS_LEGACY_SHORTHAND = 1 << 7;
/* The following flags are currently not used in Rust code, they /* The following flags are currently not used in Rust code, they
* only need to be listed in corresponding properties so that * only need to be listed in corresponding properties so that
@ -1461,17 +1465,24 @@ impl ShorthandId {
None None
} }
/// Returns PropertyFlags for given shorthand property. /// Returns PropertyFlags for the given shorthand property.
pub fn flags(&self) -> PropertyFlags { #[inline]
match *self { pub fn flags(self) -> PropertyFlags {
const FLAGS: [u8; ${len(data.shorthands)}] = [
% for property in data.shorthands: % for property in data.shorthands:
ShorthandId::${property.camel_case} => % for flag in property.flags:
% for flag in property.flags: PropertyFlags::${flag}.bits |
PropertyFlags::${flag} | % endfor
% endfor 0,
PropertyFlags::empty(),
% endfor % endfor
} ];
PropertyFlags::from_bits_truncate(FLAGS[self as usize])
}
/// Returns whether this property is a legacy shorthand.
#[inline]
pub fn is_legacy_shorthand(self) -> bool {
self.flags().contains(PropertyFlags::IS_LEGACY_SHORTHAND)
} }
/// Returns the order in which this property appears relative to other /// Returns the order in which this property appears relative to other

View file

@ -447,3 +447,51 @@ macro_rules! try_parse_one {
} }
} }
</%helpers:shorthand> </%helpers:shorthand>
<%helpers:shorthand
name="page-break-before"
products="gecko"
flags="SHORTHAND_IN_GETCS IS_LEGACY_SHORTHAND"
sub_properties="break-before"
spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-before"
>
pub fn parse_value<'i>(
_: &ParserContext,
input: &mut Parser<'i, '_>,
) -> Result<Longhands, ParseError<'i>> {
use crate::values::specified::box_::BreakBetween;
Ok(expanded! {
break_before: BreakBetween::parse_legacy(input)?,
})
}
impl<'a> ToCss for LonghandsToSerialize<'a> {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
self.break_before.to_css_legacy(dest)
}
}
</%helpers:shorthand>
<%helpers:shorthand
name="page-break-after"
products="gecko"
flags="SHORTHAND_IN_GETCS IS_LEGACY_SHORTHAND"
sub_properties="break-after"
spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-after"
>
pub fn parse_value<'i>(
_: &ParserContext,
input: &mut Parser<'i, '_>,
) -> Result<Longhands, ParseError<'i>> {
use crate::values::specified::box_::BreakBetween;
Ok(expanded! {
break_after: BreakBetween::parse_legacy(input)?,
})
}
impl<'a> ToCss for LonghandsToSerialize<'a> {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
self.break_after.to_css_legacy(dest)
}
}
</%helpers:shorthand>

View file

@ -453,6 +453,7 @@ impl RuleTree {
StyleSource::from_declarations(pdb.clone_arc()), StyleSource::from_declarations(pdb.clone_arc()),
level, level,
); );
*important_rules_changed = true;
} }
} else { } else {
if pdb.read_with(level.guard(guards)).any_normal() { if pdb.read_with(level.guard(guards)).any_normal() {

View file

@ -14,6 +14,7 @@ use crate::values::computed::length::CalcLengthOrPercentage;
use crate::values::computed::url::ComputedUrl; use crate::values::computed::url::ComputedUrl;
use crate::values::computed::Angle as ComputedAngle; use crate::values::computed::Angle as ComputedAngle;
use crate::values::computed::BorderCornerRadius as ComputedBorderCornerRadius; use crate::values::computed::BorderCornerRadius as ComputedBorderCornerRadius;
use crate::values::CSSFloat;
use euclid::{Point2D, Size2D}; use euclid::{Point2D, Size2D};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::cmp; use std::cmp;
@ -23,6 +24,7 @@ pub mod effects;
mod font; mod font;
mod length; mod length;
mod svg; mod svg;
pub mod transform;
/// The category a property falls into for ordering purposes. /// The category a property falls into for ordering purposes.
/// ///
@ -86,6 +88,15 @@ pub fn compare_property_priority(a: &PropertyId, b: &PropertyId) -> cmp::Orderin
.then_with(|| a.idl_name_sort_order().cmp(&b.idl_name_sort_order())) .then_with(|| a.idl_name_sort_order().cmp(&b.idl_name_sort_order()))
} }
/// A helper function to animate two multiplicative factor.
pub fn animate_multiplicative_factor(
this: CSSFloat,
other: CSSFloat,
procedure: Procedure,
) -> Result<CSSFloat, ()> {
Ok((this - 1.).animate(&(other - 1.), procedure)? + 1.)
}
/// Animate from one value to another. /// Animate from one value to another.
/// ///
/// This trait is derivable with `#[derive(Animate)]`. The derived /// This trait is derivable with `#[derive(Animate)]`. The derived

File diff suppressed because it is too large Load diff

View file

@ -5,6 +5,7 @@
//! Computed types for CSS values that are related to transformations. //! Computed types for CSS values that are related to transformations.
use super::CSSFloat; use super::CSSFloat;
use crate::values::animated::transform::{Perspective, Scale3D, Translate3D};
use crate::values::animated::ToAnimatedZero; use crate::values::animated::ToAnimatedZero;
use crate::values::computed::{Angle, Integer, Length, LengthOrPercentage, Number, Percentage}; use crate::values::computed::{Angle, Integer, Length, LengthOrPercentage, Number, Percentage};
use crate::values::generics::transform as generic; use crate::values::generics::transform as generic;
@ -47,8 +48,8 @@ pub type Matrix = generic::Matrix<Number>;
// matrices instead of being split across lines // matrices instead of being split across lines
#[cfg_attr(rustfmt, rustfmt_skip)] #[cfg_attr(rustfmt, rustfmt_skip)]
impl Matrix3D { impl Matrix3D {
#[inline]
/// Get an identity matrix /// Get an identity matrix
#[inline]
pub fn identity() -> Self { pub fn identity() -> Self {
Self { Self {
m11: 1.0, m12: 0.0, m13: 0.0, m14: 0.0, m11: 1.0, m12: 0.0, m13: 0.0, m14: 0.0,
@ -59,6 +60,7 @@ impl Matrix3D {
} }
/// Convert to a 2D Matrix /// Convert to a 2D Matrix
#[inline]
pub fn into_2d(self) -> Result<Matrix, ()> { pub fn into_2d(self) -> Result<Matrix, ()> {
if self.m13 == 0. && self.m23 == 0. && if self.m13 == 0. && self.m23 == 0. &&
self.m31 == 0. && self.m32 == 0. && self.m31 == 0. && self.m32 == 0. &&
@ -73,6 +75,253 @@ impl Matrix3D {
Err(()) Err(())
} }
} }
/// Return true if this has 3D components.
#[inline]
pub fn is_3d(&self) -> bool {
self.m13 != 0.0 || self.m14 != 0.0 ||
self.m23 != 0.0 || self.m24 != 0.0 ||
self.m31 != 0.0 || self.m32 != 0.0 ||
self.m33 != 1.0 || self.m34 != 0.0 ||
self.m43 != 0.0 || self.m44 != 1.0
}
/// Return determinant value.
#[inline]
pub fn determinant(&self) -> CSSFloat {
self.m14 * self.m23 * self.m32 * self.m41 -
self.m13 * self.m24 * self.m32 * self.m41 -
self.m14 * self.m22 * self.m33 * self.m41 +
self.m12 * self.m24 * self.m33 * self.m41 +
self.m13 * self.m22 * self.m34 * self.m41 -
self.m12 * self.m23 * self.m34 * self.m41 -
self.m14 * self.m23 * self.m31 * self.m42 +
self.m13 * self.m24 * self.m31 * self.m42 +
self.m14 * self.m21 * self.m33 * self.m42 -
self.m11 * self.m24 * self.m33 * self.m42 -
self.m13 * self.m21 * self.m34 * self.m42 +
self.m11 * self.m23 * self.m34 * self.m42 +
self.m14 * self.m22 * self.m31 * self.m43 -
self.m12 * self.m24 * self.m31 * self.m43 -
self.m14 * self.m21 * self.m32 * self.m43 +
self.m11 * self.m24 * self.m32 * self.m43 +
self.m12 * self.m21 * self.m34 * self.m43 -
self.m11 * self.m22 * self.m34 * self.m43 -
self.m13 * self.m22 * self.m31 * self.m44 +
self.m12 * self.m23 * self.m31 * self.m44 +
self.m13 * self.m21 * self.m32 * self.m44 -
self.m11 * self.m23 * self.m32 * self.m44 -
self.m12 * self.m21 * self.m33 * self.m44 +
self.m11 * self.m22 * self.m33 * self.m44
}
/// Transpose a matrix.
#[inline]
pub fn transpose(&self) -> Self {
Self {
m11: self.m11, m12: self.m21, m13: self.m31, m14: self.m41,
m21: self.m12, m22: self.m22, m23: self.m32, m24: self.m42,
m31: self.m13, m32: self.m23, m33: self.m33, m34: self.m43,
m41: self.m14, m42: self.m24, m43: self.m34, m44: self.m44,
}
}
/// Return inverse matrix.
pub fn inverse(&self) -> Result<Matrix3D, ()> {
let mut det = self.determinant();
if det == 0.0 {
return Err(());
}
det = 1.0 / det;
let x = Matrix3D {
m11: det *
(self.m23 * self.m34 * self.m42 - self.m24 * self.m33 * self.m42 +
self.m24 * self.m32 * self.m43 - self.m22 * self.m34 * self.m43 -
self.m23 * self.m32 * self.m44 + self.m22 * self.m33 * self.m44),
m12: det *
(self.m14 * self.m33 * self.m42 - self.m13 * self.m34 * self.m42 -
self.m14 * self.m32 * self.m43 + self.m12 * self.m34 * self.m43 +
self.m13 * self.m32 * self.m44 - self.m12 * self.m33 * self.m44),
m13: det *
(self.m13 * self.m24 * self.m42 - self.m14 * self.m23 * self.m42 +
self.m14 * self.m22 * self.m43 - self.m12 * self.m24 * self.m43 -
self.m13 * self.m22 * self.m44 + self.m12 * self.m23 * self.m44),
m14: det *
(self.m14 * self.m23 * self.m32 - self.m13 * self.m24 * self.m32 -
self.m14 * self.m22 * self.m33 + self.m12 * self.m24 * self.m33 +
self.m13 * self.m22 * self.m34 - self.m12 * self.m23 * self.m34),
m21: det *
(self.m24 * self.m33 * self.m41 - self.m23 * self.m34 * self.m41 -
self.m24 * self.m31 * self.m43 + self.m21 * self.m34 * self.m43 +
self.m23 * self.m31 * self.m44 - self.m21 * self.m33 * self.m44),
m22: det *
(self.m13 * self.m34 * self.m41 - self.m14 * self.m33 * self.m41 +
self.m14 * self.m31 * self.m43 - self.m11 * self.m34 * self.m43 -
self.m13 * self.m31 * self.m44 + self.m11 * self.m33 * self.m44),
m23: det *
(self.m14 * self.m23 * self.m41 - self.m13 * self.m24 * self.m41 -
self.m14 * self.m21 * self.m43 + self.m11 * self.m24 * self.m43 +
self.m13 * self.m21 * self.m44 - self.m11 * self.m23 * self.m44),
m24: det *
(self.m13 * self.m24 * self.m31 - self.m14 * self.m23 * self.m31 +
self.m14 * self.m21 * self.m33 - self.m11 * self.m24 * self.m33 -
self.m13 * self.m21 * self.m34 + self.m11 * self.m23 * self.m34),
m31: det *
(self.m22 * self.m34 * self.m41 - self.m24 * self.m32 * self.m41 +
self.m24 * self.m31 * self.m42 - self.m21 * self.m34 * self.m42 -
self.m22 * self.m31 * self.m44 + self.m21 * self.m32 * self.m44),
m32: det *
(self.m14 * self.m32 * self.m41 - self.m12 * self.m34 * self.m41 -
self.m14 * self.m31 * self.m42 + self.m11 * self.m34 * self.m42 +
self.m12 * self.m31 * self.m44 - self.m11 * self.m32 * self.m44),
m33: det *
(self.m12 * self.m24 * self.m41 - self.m14 * self.m22 * self.m41 +
self.m14 * self.m21 * self.m42 - self.m11 * self.m24 * self.m42 -
self.m12 * self.m21 * self.m44 + self.m11 * self.m22 * self.m44),
m34: det *
(self.m14 * self.m22 * self.m31 - self.m12 * self.m24 * self.m31 -
self.m14 * self.m21 * self.m32 + self.m11 * self.m24 * self.m32 +
self.m12 * self.m21 * self.m34 - self.m11 * self.m22 * self.m34),
m41: det *
(self.m23 * self.m32 * self.m41 - self.m22 * self.m33 * self.m41 -
self.m23 * self.m31 * self.m42 + self.m21 * self.m33 * self.m42 +
self.m22 * self.m31 * self.m43 - self.m21 * self.m32 * self.m43),
m42: det *
(self.m12 * self.m33 * self.m41 - self.m13 * self.m32 * self.m41 +
self.m13 * self.m31 * self.m42 - self.m11 * self.m33 * self.m42 -
self.m12 * self.m31 * self.m43 + self.m11 * self.m32 * self.m43),
m43: det *
(self.m13 * self.m22 * self.m41 - self.m12 * self.m23 * self.m41 -
self.m13 * self.m21 * self.m42 + self.m11 * self.m23 * self.m42 +
self.m12 * self.m21 * self.m43 - self.m11 * self.m22 * self.m43),
m44: det *
(self.m12 * self.m23 * self.m31 - self.m13 * self.m22 * self.m31 +
self.m13 * self.m21 * self.m32 - self.m11 * self.m23 * self.m32 -
self.m12 * self.m21 * self.m33 + self.m11 * self.m22 * self.m33),
};
Ok(x)
}
/// Multiply `pin * self`.
#[inline]
pub fn pre_mul_point4(&self, pin: &[f32; 4]) -> [f32; 4] {
[
pin[0] * self.m11 + pin[1] * self.m21 + pin[2] * self.m31 + pin[3] * self.m41,
pin[0] * self.m12 + pin[1] * self.m22 + pin[2] * self.m32 + pin[3] * self.m42,
pin[0] * self.m13 + pin[1] * self.m23 + pin[2] * self.m33 + pin[3] * self.m43,
pin[0] * self.m14 + pin[1] * self.m24 + pin[2] * self.m34 + pin[3] * self.m44,
]
}
/// Return the multiplication of two 4x4 matrices.
#[inline]
pub fn multiply(&self, other: &Self) -> Self {
Matrix3D {
m11: self.m11 * other.m11 + self.m12 * other.m21 +
self.m13 * other.m31 + self.m14 * other.m41,
m12: self.m11 * other.m12 + self.m12 * other.m22 +
self.m13 * other.m32 + self.m14 * other.m42,
m13: self.m11 * other.m13 + self.m12 * other.m23 +
self.m13 * other.m33 + self.m14 * other.m43,
m14: self.m11 * other.m14 + self.m12 * other.m24 +
self.m13 * other.m34 + self.m14 * other.m44,
m21: self.m21 * other.m11 + self.m22 * other.m21 +
self.m23 * other.m31 + self.m24 * other.m41,
m22: self.m21 * other.m12 + self.m22 * other.m22 +
self.m23 * other.m32 + self.m24 * other.m42,
m23: self.m21 * other.m13 + self.m22 * other.m23 +
self.m23 * other.m33 + self.m24 * other.m43,
m24: self.m21 * other.m14 + self.m22 * other.m24 +
self.m23 * other.m34 + self.m24 * other.m44,
m31: self.m31 * other.m11 + self.m32 * other.m21 +
self.m33 * other.m31 + self.m34 * other.m41,
m32: self.m31 * other.m12 + self.m32 * other.m22 +
self.m33 * other.m32 + self.m34 * other.m42,
m33: self.m31 * other.m13 + self.m32 * other.m23 +
self.m33 * other.m33 + self.m34 * other.m43,
m34: self.m31 * other.m14 + self.m32 * other.m24 +
self.m33 * other.m34 + self.m34 * other.m44,
m41: self.m41 * other.m11 + self.m42 * other.m21 +
self.m43 * other.m31 + self.m44 * other.m41,
m42: self.m41 * other.m12 + self.m42 * other.m22 +
self.m43 * other.m32 + self.m44 * other.m42,
m43: self.m41 * other.m13 + self.m42 * other.m23 +
self.m43 * other.m33 + self.m44 * other.m43,
m44: self.m41 * other.m14 + self.m42 * other.m24 +
self.m43 * other.m34 + self.m44 * other.m44,
}
}
/// Scale the matrix by a factor.
#[inline]
pub fn scale_by_factor(&mut self, scaling_factor: CSSFloat) {
self.m11 *= scaling_factor;
self.m12 *= scaling_factor;
self.m13 *= scaling_factor;
self.m14 *= scaling_factor;
self.m21 *= scaling_factor;
self.m22 *= scaling_factor;
self.m23 *= scaling_factor;
self.m24 *= scaling_factor;
self.m31 *= scaling_factor;
self.m32 *= scaling_factor;
self.m33 *= scaling_factor;
self.m34 *= scaling_factor;
self.m41 *= scaling_factor;
self.m42 *= scaling_factor;
self.m43 *= scaling_factor;
self.m44 *= scaling_factor;
}
/// Return the matrix 3x3 part (top-left corner).
/// This is used by retrieving the scale and shear factors
/// during decomposing a 3d matrix.
#[inline]
pub fn get_matrix_3x3_part(&self) -> [[f32; 3]; 3] {
[
[ self.m11, self.m12, self.m13 ],
[ self.m21, self.m22, self.m23 ],
[ self.m31, self.m32, self.m33 ],
]
}
/// Set perspective on the matrix.
#[inline]
pub fn set_perspective(&mut self, perspective: &Perspective) {
self.m14 = perspective.0;
self.m24 = perspective.1;
self.m34 = perspective.2;
self.m44 = perspective.3;
}
/// Apply translate on the matrix.
#[inline]
pub fn apply_translate(&mut self, translate: &Translate3D) {
self.m41 += translate.0 * self.m11 + translate.1 * self.m21 + translate.2 * self.m31;
self.m42 += translate.0 * self.m12 + translate.1 * self.m22 + translate.2 * self.m32;
self.m43 += translate.0 * self.m13 + translate.1 * self.m23 + translate.2 * self.m33;
self.m44 += translate.0 * self.m14 + translate.1 * self.m24 + translate.2 * self.m34;
}
/// Apply scale on the matrix.
#[inline]
pub fn apply_scale(&mut self, scale: &Scale3D) {
self.m11 *= scale.0;
self.m12 *= scale.0;
self.m13 *= scale.0;
self.m14 *= scale.0;
self.m21 *= scale.1;
self.m22 *= scale.1;
self.m23 *= scale.1;
self.m24 *= scale.1;
self.m31 *= scale.2;
self.m32 *= scale.2;
self.m33 *= scale.2;
self.m34 *= scale.2;
}
} }
#[cfg_attr(rustfmt, rustfmt_skip)] #[cfg_attr(rustfmt, rustfmt_skip)]

View file

@ -529,15 +529,7 @@ pub fn get_normalized_vector_and_angle<T: Zero>(
} }
#[derive( #[derive(
Clone, Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
ToAnimatedZero,
ToComputedValue,
)] )]
/// A value of the `Rotate` property /// A value of the `Rotate` property
/// ///
@ -599,15 +591,7 @@ where
} }
#[derive( #[derive(
Clone, Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
ToAnimatedZero,
ToComputedValue,
)] )]
/// A value of the `Scale` property /// A value of the `Scale` property
/// ///
@ -648,14 +632,7 @@ impl<Number: ToCss + PartialEq> ToCss for Scale<Number> {
} }
#[derive( #[derive(
Clone, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue,
ComputeSquaredDistance,
Debug,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
ToAnimatedZero,
ToComputedValue,
)] )]
/// A value of the `Translate` property /// A value of the `Translate` property
/// ///

View file

@ -19,6 +19,48 @@ use cssparser::Parser;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, ToCss}; use style_traits::{CssWriter, ParseError, ToCss};
/// A specified value for a single side of a `border-style` property.
///
/// The order here corresponds to the integer values from the border conflict
/// resolution rules in CSS 2.1 § 17.6.2.1. Higher values override lower values.
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(
Clone,
Copy,
Debug,
Eq,
MallocSizeOf,
Ord,
Parse,
PartialEq,
PartialOrd,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
)]
#[repr(u8)]
pub enum BorderStyle {
Hidden,
None,
Inset,
Groove,
Outset,
Ridge,
Dotted,
Dashed,
Solid,
Double,
}
impl BorderStyle {
/// Whether this border style is either none or hidden.
#[inline]
pub fn none_or_hidden(&self) -> bool {
matches!(*self, BorderStyle::None | BorderStyle::Hidden)
}
}
/// A specified value for a single side of the `border-width` property. /// A specified value for a single side of the `border-width` property.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum BorderSideWidth { pub enum BorderSideWidth {

View file

@ -178,30 +178,6 @@ impl Display {
} }
} }
/// Whether `new_display` should be ignored, given a previous
/// `old_display` value.
///
/// This is used to ignore `display: -moz-box` declarations after an
/// equivalent `display: -webkit-box` declaration, since the former
/// has a vastly different meaning. See bug 1107378 and bug 1407701.
///
/// FIXME(emilio): This is a pretty decent hack, we should try to
/// remove it.
pub fn should_ignore_parsed_value(_old_display: Self, _new_display: Self) -> bool {
#[cfg(feature = "gecko")]
{
match (_old_display, _new_display) {
(Display::WebkitBox, Display::MozBox) |
(Display::WebkitInlineBox, Display::MozInlineBox) => {
return true;
},
_ => {},
}
}
return false;
}
/// Returns whether this "display" value is one of the types for /// Returns whether this "display" value is one of the types for
/// ruby. /// ruby.
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
@ -1155,10 +1131,11 @@ pub enum Appearance {
TabScrollArrowBack, TabScrollArrowBack,
#[parse(condition = "in_ua_or_chrome_sheet")] #[parse(condition = "in_ua_or_chrome_sheet")]
TabScrollArrowForward, TabScrollArrowForward,
/// A textfield or text area. /// A multi-line text field, e.g. HTML <textarea>.
#[parse(aliases = "textfield-multiline")]
Textarea,
/// A single-line text field, e.g. HTML <input type=text>.
Textfield, Textfield,
/// A multiline text field.
TextfieldMultiline,
/// A toolbar in an application window. /// A toolbar in an application window.
#[parse(condition = "in_ua_or_chrome_sheet")] #[parse(condition = "in_ua_or_chrome_sheet")]
Toolbar, Toolbar,
@ -1309,13 +1286,58 @@ pub enum Appearance {
)] )]
#[repr(u8)] #[repr(u8)]
pub enum BreakBetween { pub enum BreakBetween {
Auto,
Always, Always,
Auto,
Page,
Avoid, Avoid,
Left, Left,
Right, Right,
} }
impl BreakBetween {
/// Parse a legacy break-between value for `page-break-*`.
///
/// See https://drafts.csswg.org/css-break/#page-break-properties.
#[inline]
pub fn parse_legacy<'i>(input: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
let location = input.current_source_location();
let ident = input.expect_ident()?;
let break_value = match BreakBetween::from_ident(ident) {
Ok(v) => v,
Err(()) => {
return Err(location
.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone())))
},
};
match break_value {
BreakBetween::Always => Ok(BreakBetween::Page),
BreakBetween::Auto | BreakBetween::Avoid | BreakBetween::Left | BreakBetween::Right => {
Ok(break_value)
},
BreakBetween::Page => {
Err(location
.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone())))
},
}
}
/// Serialize a legacy break-between value for `page-break-*`.
///
/// See https://drafts.csswg.org/css-break/#page-break-properties.
pub fn to_css_legacy<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
match *self {
BreakBetween::Auto | BreakBetween::Avoid | BreakBetween::Left | BreakBetween::Right => {
self.to_css(dest)
},
BreakBetween::Page => dest.write_str("always"),
BreakBetween::Always => Ok(()),
}
}
}
/// A kind of break within a box. /// A kind of break within a box.
/// ///
/// https://drafts.csswg.org/css-break/#break-within /// https://drafts.csswg.org/css-break/#break-within

View file

@ -34,7 +34,7 @@ pub use self::background::{BackgroundRepeat, BackgroundSize};
pub use self::basic_shape::FillRule; pub use self::basic_shape::FillRule;
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth}; pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
pub use self::border::{BorderImageRepeat, BorderImageSideWidth}; pub use self::border::{BorderImageRepeat, BorderImageSideWidth};
pub use self::border::{BorderRadius, BorderSideWidth, BorderSpacing}; pub use self::border::{BorderRadius, BorderSideWidth, BorderSpacing, BorderStyle};
pub use self::box_::{AnimationIterationCount, AnimationName, Contain, Display}; pub use self::box_::{AnimationIterationCount, AnimationName, Contain, Display};
pub use self::box_::{Appearance, BreakBetween, BreakWithin, Clear, Float}; pub use self::box_::{Appearance, BreakBetween, BreakWithin, Clear, Float};
pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize}; pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize};
@ -152,46 +152,6 @@ fn parse_number_with_clamping_mode<'i, 't>(
}) })
} }
// The integer values here correspond to the border conflict resolution rules in CSS 2.1 §
// 17.6.2.1. Higher values override lower values.
//
// FIXME(emilio): Should move to border.rs
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(
Clone,
Copy,
Debug,
Eq,
MallocSizeOf,
Ord,
Parse,
PartialEq,
PartialOrd,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
)]
pub enum BorderStyle {
None = -1,
Solid = 6,
Double = 7,
Dotted = 4,
Dashed = 5,
Hidden = -2,
Groove = 1,
Ridge = 3,
Inset = 0,
Outset = 2,
}
impl BorderStyle {
/// Whether this border style is either none or hidden.
pub fn none_or_hidden(&self) -> bool {
matches!(*self, BorderStyle::None | BorderStyle::Hidden)
}
}
/// A CSS `<number>` specified value. /// A CSS `<number>` specified value.
/// ///
/// https://drafts.csswg.org/css-values-3/#number-value /// https://drafts.csswg.org/css-values-3/#number-value

View file

@ -23,19 +23,20 @@ use style_traits::ParseError;
ToComputedValue, ToComputedValue,
ToCss, ToCss,
)] )]
#[repr(C, u8)]
/// <https://drafts.csswg.org/css-ui/#propdef-outline-style> /// <https://drafts.csswg.org/css-ui/#propdef-outline-style>
pub enum OutlineStyle { pub enum OutlineStyle {
/// auto /// auto
Auto, Auto,
/// <border-style> /// <border-style>
Other(BorderStyle), BorderStyle(BorderStyle),
} }
impl OutlineStyle { impl OutlineStyle {
#[inline] #[inline]
/// Get default value as None /// Get default value as None
pub fn none() -> OutlineStyle { pub fn none() -> OutlineStyle {
OutlineStyle::Other(BorderStyle::None) OutlineStyle::BorderStyle(BorderStyle::None)
} }
#[inline] #[inline]
@ -43,7 +44,7 @@ impl OutlineStyle {
pub fn none_or_hidden(&self) -> bool { pub fn none_or_hidden(&self) -> bool {
match *self { match *self {
OutlineStyle::Auto => false, OutlineStyle::Auto => false,
OutlineStyle::Other(ref border_style) => border_style.none_or_hidden(), OutlineStyle::BorderStyle(ref style) => style.none_or_hidden(),
} }
} }
} }
@ -59,7 +60,7 @@ impl Parse for OutlineStyle {
.new_custom_error(SelectorParseErrorKind::UnexpectedIdent("hidden".into()))); .new_custom_error(SelectorParseErrorKind::UnexpectedIdent("hidden".into())));
} }
return Ok(OutlineStyle::Other(border_style)); return Ok(OutlineStyle::BorderStyle(border_style));
} }
input.expect_ident_matching("auto")?; input.expect_ident_matching("auto")?;

View file

@ -141,11 +141,6 @@ impl Parse for ScrollbarColor {
} }
} }
fn in_ua_sheet(context: &ParserContext) -> bool {
use crate::stylesheets::Origin;
context.stylesheet_origin == Origin::UserAgent
}
/// The specified value for the `user-select` property. /// The specified value for the `user-select` property.
/// ///
/// https://drafts.csswg.org/css-ui-4/#propdef-user-select /// https://drafts.csswg.org/css-ui-4/#propdef-user-select
@ -168,15 +163,6 @@ pub enum UserSelect {
Text, Text,
#[parse(aliases = "-moz-none")] #[parse(aliases = "-moz-none")]
None, None,
/// Force selection of all children, unless an ancestor has `none` set. /// Force selection of all children.
All, All,
/// Like `text`, except that it won't get overridden by ancestors having
/// `all`.
///
/// FIXME(emilio): This only has one use in contenteditable.css, can we find
/// a better way to do this?
///
/// See bug 1181130.
#[parse(condition = "in_ua_sheet")]
MozText,
} }

View file

@ -1,2 +0,0 @@
[variable-exponential-blowup.html]
expected: TIMEOUT