mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
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:
commit
5bdea7dc1c
26 changed files with 2100 additions and 1984 deletions
|
@ -1499,8 +1499,11 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
|
||||
let outline_style = match style.get_outline().outline_style {
|
||||
OutlineStyle::Auto => BorderStyle::Solid,
|
||||
OutlineStyle::Other(BorderStyle::None) => return,
|
||||
OutlineStyle::Other(border_style) => border_style,
|
||||
// FIXME(emilio): I don't think this border-style check is
|
||||
// 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
|
||||
|
|
|
@ -31,6 +31,7 @@ include = ["cssparser"]
|
|||
|
||||
[struct]
|
||||
derive_eq = true
|
||||
derive_neq = true
|
||||
|
||||
[enum]
|
||||
derive_helper_methods = true
|
||||
|
@ -41,6 +42,8 @@ include = [
|
|||
"Appearance",
|
||||
"BreakBetween",
|
||||
"BreakWithin",
|
||||
"BorderStyle",
|
||||
"OutlineStyle",
|
||||
"ComputedFontStretchRange",
|
||||
"ComputedFontStyleDescriptor",
|
||||
"ComputedFontWeightRange",
|
||||
|
|
|
@ -283,18 +283,32 @@ impl VariableValue {
|
|||
}
|
||||
}
|
||||
|
||||
fn push(
|
||||
fn push<'i>(
|
||||
&mut self,
|
||||
input: &Parser<'i, '_>,
|
||||
css: &str,
|
||||
css_first_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:
|
||||
// `var(--a)var(--b)`.
|
||||
//
|
||||
// In that case, css_*_token_type is nonsensical.
|
||||
if css.is_empty() {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
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(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,
|
||||
input: &Parser<'i, '_>,
|
||||
position: (SourcePosition, TokenSerializationType),
|
||||
input: &Parser,
|
||||
last_token_type: TokenSerializationType,
|
||||
) {
|
||||
self.push(input.slice_from(position.0), position.1, last_token_type)
|
||||
) -> Result<(), ParseError<'i>> {
|
||||
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());
|
||||
self.push(
|
||||
input,
|
||||
&variable.css,
|
||||
variable.first_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
|
||||
|
||||
/// Struct recording necessary information for each variable.
|
||||
#[derive(Debug)]
|
||||
struct VarInfo {
|
||||
/// The name of the variable. It will be taken to save addref
|
||||
/// 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
|
||||
/// avoid referencing all the fields multiple times.
|
||||
#[derive(Debug)]
|
||||
struct Context<'a> {
|
||||
/// Number of variables visited. This is used as the order index
|
||||
/// when we visit a new unresolved variable.
|
||||
|
@ -941,7 +968,7 @@ fn substitute_references_in_value<'i>(
|
|||
environment,
|
||||
)?;
|
||||
|
||||
computed_value.push_from(position, &input, last_token_type);
|
||||
computed_value.push_from(&input, position, last_token_type)?;
|
||||
Ok(computed_value)
|
||||
}
|
||||
|
||||
|
@ -955,8 +982,8 @@ fn substitute_references_in_value<'i>(
|
|||
///
|
||||
/// Return `Err(())` if `input` is invalid at computed-value time.
|
||||
/// or `Ok(last_token_type that was pushed to partial_computed_value)` otherwise.
|
||||
fn substitute_block<'i, 't>(
|
||||
input: &mut Parser<'i, 't>,
|
||||
fn substitute_block<'i>(
|
||||
input: &mut Parser<'i, '_>,
|
||||
position: &mut (SourcePosition, TokenSerializationType),
|
||||
partial_computed_value: &mut ComputedValue,
|
||||
custom_properties: &CustomPropertiesMap,
|
||||
|
@ -991,10 +1018,11 @@ fn substitute_block<'i, 't>(
|
|||
let is_env = name.eq_ignore_ascii_case("env");
|
||||
|
||||
partial_computed_value.push(
|
||||
input,
|
||||
input.slice(position.0..before_this_token),
|
||||
position.1,
|
||||
last_token_type,
|
||||
);
|
||||
)?;
|
||||
input.parse_nested_block(|input| {
|
||||
// parse_var_function() / parse_env_function() ensure neither .unwrap() will fail.
|
||||
let name = {
|
||||
|
@ -1014,7 +1042,7 @@ fn substitute_block<'i, 't>(
|
|||
|
||||
if let Some(v) = value {
|
||||
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`
|
||||
// if we don't consume all of `input`.
|
||||
// FIXME: Add a specialized method to cssparser to do this with less work.
|
||||
|
@ -1036,7 +1064,7 @@ fn substitute_block<'i, 't>(
|
|||
custom_properties,
|
||||
env,
|
||||
)?;
|
||||
partial_computed_value.push_from(position, input, last_token_type);
|
||||
partial_computed_value.push_from(input, position, last_token_type)?;
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
@ -1096,6 +1124,6 @@ pub fn substitute<'i>(
|
|||
&custom_properties,
|
||||
env,
|
||||
)?;
|
||||
substituted.push_from(position, &input, last_token_type);
|
||||
substituted.push_from(&input, position, last_token_type)?;
|
||||
Ok(substituted.css)
|
||||
}
|
||||
|
|
|
@ -11,11 +11,13 @@
|
|||
use app_units::Au;
|
||||
use crate::gecko::values::GeckoStyleCoordConvertible;
|
||||
use crate::gecko_bindings::bindings;
|
||||
use crate::gecko_bindings::structs::RawGeckoGfxMatrix4x4;
|
||||
use crate::gecko_bindings::structs::{self, nsStyleCoord_CalcValue};
|
||||
use crate::gecko_bindings::structs::{nsStyleImage, nsresult, SheetType};
|
||||
use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
|
||||
use crate::stylesheets::{Origin, RulesMutateError};
|
||||
use crate::values::computed::image::LineDirection;
|
||||
use crate::values::computed::transform::Matrix3D;
|
||||
use crate::values::computed::url::ComputedImageUrl;
|
||||
use crate::values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image};
|
||||
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);
|
||||
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,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -462,22 +462,6 @@ impl PropertyDeclarationBlock {
|
|||
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);
|
||||
break;
|
||||
}
|
||||
|
@ -933,6 +917,10 @@ impl PropertyDeclarationBlock {
|
|||
}
|
||||
already_serialized.insert(shorthand.into());
|
||||
|
||||
if shorthand.is_legacy_shorthand() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Substep 2 & 3
|
||||
let mut current_longhands = SmallVec::<[_; 10]>::new();
|
||||
let mut important_count = 0;
|
||||
|
|
|
@ -58,15 +58,14 @@ use std::mem::{forget, uninitialized, transmute, zeroed};
|
|||
use std::{cmp, ops, ptr};
|
||||
use crate::values::{self, CustomIdent, Either, KeyframesName, None_};
|
||||
use crate::values::computed::{NonNegativeLength, Percentage, TransitionProperty};
|
||||
use crate::values::computed::BorderStyle;
|
||||
use crate::values::computed::font::FontSize;
|
||||
use crate::values::computed::effects::{BoxShadow, Filter, SimpleShadow};
|
||||
use crate::values::computed::outline::OutlineStyle;
|
||||
use crate::values::generics::column::ColumnCount;
|
||||
use crate::values::generics::position::ZIndex;
|
||||
use crate::values::generics::text::MozTabSize;
|
||||
use crate::values::generics::transform::TransformStyle;
|
||||
use crate::values::generics::url::UrlOrNone;
|
||||
use crate::computed_values::border_style;
|
||||
|
||||
pub mod style_structs {
|
||||
% for style_struct in data.style_structs:
|
||||
|
@ -333,13 +332,10 @@ impl ${style_struct.gecko_struct_name} {
|
|||
}
|
||||
</%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)]
|
||||
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
||||
self.gecko.${gecko_ffi_name} = other.gecko.${gecko_ffi_name};
|
||||
% if on_set:
|
||||
self.${on_set}();
|
||||
% endif
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
|
@ -368,7 +364,7 @@ def set_gecko_property(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)]
|
||||
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
||||
use crate::properties::longhands::${ident}::computed_value::T as Keyword;
|
||||
|
@ -380,9 +376,6 @@ def set_gecko_property(ffi_name, expr):
|
|||
% endfor
|
||||
};
|
||||
${set_gecko_property(gecko_ffi_name, "result")}
|
||||
% if on_set:
|
||||
self.${on_set}();
|
||||
% endif
|
||||
}
|
||||
</%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)
|
||||
for x in SIDES
|
||||
for y in ["color", "style", "width"]] +
|
||||
|
@ -1528,41 +1518,55 @@ fn static_assert() {
|
|||
skip_longhands="${skip_border_longhands} border-image-source border-image-outset
|
||||
border-image-repeat border-image-width border-image-slice">
|
||||
% for side in SIDES:
|
||||
<% impl_keyword("border_%s_style" % side.ident,
|
||||
"mBorderStyle[%s]" % side.index,
|
||||
border_style_keyword,
|
||||
on_set="update_border_%s" % side.ident) %>
|
||||
pub fn set_border_${side.ident}_style(&mut self, v: BorderStyle) {
|
||||
self.gecko.mBorderStyle[${side.index}] = v;
|
||||
|
||||
// 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.
|
||||
//
|
||||
// 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
|
||||
// is technically not valid without fixups, and that you lose pretty much
|
||||
// any sharing of the initial struct, which is kind of unfortunate.
|
||||
//
|
||||
// Gecko has two fields for this, one that stores the "specified" 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 sync back to the
|
||||
// specified one. This is what this function does.
|
||||
//
|
||||
// Note that this doesn't impose any dependency in the order of computation
|
||||
// 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
|
||||
// two mBorder and mComputedBorder fields would be the same already.
|
||||
//
|
||||
// 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.
|
||||
fn update_border_${side.ident}(&mut self) {
|
||||
// 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.
|
||||
//
|
||||
// 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 is technically not valid without fixups, and that you lose
|
||||
// pretty much any sharing of the initial struct, which is kind of
|
||||
// unfortunate.
|
||||
//
|
||||
// Gecko has two fields for this, one that stores the "specified"
|
||||
// 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
|
||||
// sync back to the specified one. This is what this function does.
|
||||
//
|
||||
// Note that this doesn't impose any dependency in the order of
|
||||
// computation 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 two mBorder and mComputedBorder fields would be the
|
||||
// same already.
|
||||
//
|
||||
// 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};
|
||||
}
|
||||
|
||||
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_non_negative_length("border_%s_width" % side.ident,
|
||||
|
@ -2170,50 +2174,26 @@ fn static_assert() {
|
|||
<%self:impl_trait style_struct_name="Outline"
|
||||
skip_longhands="${skip_outline_longhands}">
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn set_outline_style(&mut self, v: longhands::outline_style::computed_value::T) {
|
||||
// FIXME(bholley): Align binary representations and ditch |match| for
|
||||
// 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")}
|
||||
|
||||
self.gecko.mOutlineStyle = v;
|
||||
// NB: This is needed to correctly handling the initial value of
|
||||
// outline-width when outline-style changes, see the
|
||||
// update_border_${side.ident} comment for more details.
|
||||
self.gecko.mActualOutlineWidth = self.gecko.mOutlineWidth;
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
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;
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn reset_outline_style(&mut self, other: &Self) {
|
||||
self.copy_outline_style_from(other)
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn clone_outline_style(&self) -> longhands::outline_style::computed_value::T {
|
||||
// FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
|
||||
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
|
||||
}
|
||||
self.gecko.mOutlineStyle.clone()
|
||||
}
|
||||
|
||||
<% impl_non_negative_length("outline_width", "mActualOutlineWidth",
|
||||
|
@ -5410,7 +5390,7 @@ clip-path
|
|||
</%self:impl_trait>
|
||||
|
||||
<%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)]
|
||||
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",
|
||||
round_to_pixels=True) %>
|
||||
${impl_simple('column_rule_style', 'mColumnRuleStyle')}
|
||||
</%self:impl_trait>
|
||||
|
||||
<%self:impl_trait style_struct_name="Counters"
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -15,7 +15,8 @@ ${helpers.predefined_type(
|
|||
animation_value_type="AnimatedColor",
|
||||
ignored_when_colors_disabled=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(
|
||||
|
|
|
@ -63,7 +63,9 @@
|
|||
|
||||
${helpers.gecko_keyword_conversion(
|
||||
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",
|
||||
)}
|
||||
|
||||
|
|
|
@ -438,33 +438,33 @@ ${helpers.single_keyword(
|
|||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
"page-break-after",
|
||||
"break-after",
|
||||
"BreakBetween",
|
||||
"computed::BreakBetween::Auto",
|
||||
needs_context=False,
|
||||
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",
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
"page-break-before",
|
||||
"break-before",
|
||||
"BreakBetween",
|
||||
"computed::BreakBetween::Auto",
|
||||
needs_context=False,
|
||||
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",
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
"page-break-inside",
|
||||
"break-inside",
|
||||
"BreakWithin",
|
||||
"computed::BreakWithin::Auto",
|
||||
gecko_ffi_name="mBreakInside",
|
||||
needs_context=False,
|
||||
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",
|
||||
)}
|
||||
|
||||
|
|
|
@ -78,12 +78,14 @@ ${helpers.single_keyword(
|
|||
extra_prefixes="moz:layout.css.column-span.enabled",
|
||||
)}
|
||||
|
||||
${helpers.single_keyword(
|
||||
${helpers.predefined_type(
|
||||
"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",
|
||||
extra_prefixes="moz",
|
||||
gecko_constant_prefix="NS_STYLE_BORDER_STYLE",
|
||||
animation_value_type="discrete",
|
||||
spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-style",
|
||||
)}
|
||||
|
|
|
@ -337,6 +337,7 @@ ${helpers.single_keyword(
|
|||
${helpers.single_keyword(
|
||||
"text-rendering",
|
||||
"auto optimizespeed optimizelegibility geometricprecision",
|
||||
gecko_enum_prefix="StyleTextRendering",
|
||||
animation_value_type="discrete",
|
||||
spec="https://www.w3.org/TR/SVG11/painting.html#TextRenderingProperty",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
|
|
|
@ -39,6 +39,7 @@ ${helpers.predefined_type(
|
|||
gecko_ffi_name="mUserSelect",
|
||||
alias="-webkit-user-select",
|
||||
animation_value_type="discrete",
|
||||
needs_context=False,
|
||||
spec="https://drafts.csswg.org/css-ui-4/#propdef-user-select",
|
||||
)}
|
||||
|
||||
|
|
|
@ -948,6 +948,10 @@ bitflags! {
|
|||
/// This property's getComputedStyle implementation requires layout
|
||||
/// to be flushed.
|
||||
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
|
||||
* only need to be listed in corresponding properties so that
|
||||
|
@ -1461,17 +1465,24 @@ impl ShorthandId {
|
|||
None
|
||||
}
|
||||
|
||||
/// Returns PropertyFlags for given shorthand property.
|
||||
pub fn flags(&self) -> PropertyFlags {
|
||||
match *self {
|
||||
/// Returns PropertyFlags for the given shorthand property.
|
||||
#[inline]
|
||||
pub fn flags(self) -> PropertyFlags {
|
||||
const FLAGS: [u8; ${len(data.shorthands)}] = [
|
||||
% for property in data.shorthands:
|
||||
ShorthandId::${property.camel_case} =>
|
||||
% for flag in property.flags:
|
||||
PropertyFlags::${flag} |
|
||||
% endfor
|
||||
PropertyFlags::empty(),
|
||||
% for flag in property.flags:
|
||||
PropertyFlags::${flag}.bits |
|
||||
% endfor
|
||||
0,
|
||||
% 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
|
||||
|
|
|
@ -447,3 +447,51 @@ macro_rules! try_parse_one {
|
|||
}
|
||||
}
|
||||
</%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>
|
||||
|
|
|
@ -453,6 +453,7 @@ impl RuleTree {
|
|||
StyleSource::from_declarations(pdb.clone_arc()),
|
||||
level,
|
||||
);
|
||||
*important_rules_changed = true;
|
||||
}
|
||||
} else {
|
||||
if pdb.read_with(level.guard(guards)).any_normal() {
|
||||
|
|
|
@ -14,6 +14,7 @@ use crate::values::computed::length::CalcLengthOrPercentage;
|
|||
use crate::values::computed::url::ComputedUrl;
|
||||
use crate::values::computed::Angle as ComputedAngle;
|
||||
use crate::values::computed::BorderCornerRadius as ComputedBorderCornerRadius;
|
||||
use crate::values::CSSFloat;
|
||||
use euclid::{Point2D, Size2D};
|
||||
use smallvec::SmallVec;
|
||||
use std::cmp;
|
||||
|
@ -23,6 +24,7 @@ pub mod effects;
|
|||
mod font;
|
||||
mod length;
|
||||
mod svg;
|
||||
pub mod transform;
|
||||
|
||||
/// 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()))
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// This trait is derivable with `#[derive(Animate)]`. The derived
|
||||
|
|
1502
components/style/values/animated/transform.rs
Normal file
1502
components/style/values/animated/transform.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -5,6 +5,7 @@
|
|||
//! Computed types for CSS values that are related to transformations.
|
||||
|
||||
use super::CSSFloat;
|
||||
use crate::values::animated::transform::{Perspective, Scale3D, Translate3D};
|
||||
use crate::values::animated::ToAnimatedZero;
|
||||
use crate::values::computed::{Angle, Integer, Length, LengthOrPercentage, Number, Percentage};
|
||||
use crate::values::generics::transform as generic;
|
||||
|
@ -47,8 +48,8 @@ pub type Matrix = generic::Matrix<Number>;
|
|||
// matrices instead of being split across lines
|
||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||
impl Matrix3D {
|
||||
#[inline]
|
||||
/// Get an identity matrix
|
||||
#[inline]
|
||||
pub fn identity() -> Self {
|
||||
Self {
|
||||
m11: 1.0, m12: 0.0, m13: 0.0, m14: 0.0,
|
||||
|
@ -59,6 +60,7 @@ impl Matrix3D {
|
|||
}
|
||||
|
||||
/// Convert to a 2D Matrix
|
||||
#[inline]
|
||||
pub fn into_2d(self) -> Result<Matrix, ()> {
|
||||
if self.m13 == 0. && self.m23 == 0. &&
|
||||
self.m31 == 0. && self.m32 == 0. &&
|
||||
|
@ -73,6 +75,253 @@ impl Matrix3D {
|
|||
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)]
|
||||
|
|
|
@ -529,15 +529,7 @@ pub fn get_normalized_vector_and_angle<T: Zero>(
|
|||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
ComputeSquaredDistance,
|
||||
Copy,
|
||||
Debug,
|
||||
MallocSizeOf,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToAnimatedZero,
|
||||
ToComputedValue,
|
||||
Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue,
|
||||
)]
|
||||
/// A value of the `Rotate` property
|
||||
///
|
||||
|
@ -599,15 +591,7 @@ where
|
|||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
ComputeSquaredDistance,
|
||||
Copy,
|
||||
Debug,
|
||||
MallocSizeOf,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToAnimatedZero,
|
||||
ToComputedValue,
|
||||
Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue,
|
||||
)]
|
||||
/// A value of the `Scale` property
|
||||
///
|
||||
|
@ -648,14 +632,7 @@ impl<Number: ToCss + PartialEq> ToCss for Scale<Number> {
|
|||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
ComputeSquaredDistance,
|
||||
Debug,
|
||||
MallocSizeOf,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToAnimatedZero,
|
||||
ToComputedValue,
|
||||
Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue,
|
||||
)]
|
||||
/// A value of the `Translate` property
|
||||
///
|
||||
|
|
|
@ -19,6 +19,48 @@ use cssparser::Parser;
|
|||
use std::fmt::{self, Write};
|
||||
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.
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
|
||||
pub enum BorderSideWidth {
|
||||
|
|
|
@ -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
|
||||
/// ruby.
|
||||
#[cfg(feature = "gecko")]
|
||||
|
@ -1155,10 +1131,11 @@ pub enum Appearance {
|
|||
TabScrollArrowBack,
|
||||
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||
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,
|
||||
/// A multiline text field.
|
||||
TextfieldMultiline,
|
||||
/// A toolbar in an application window.
|
||||
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||
Toolbar,
|
||||
|
@ -1309,13 +1286,58 @@ pub enum Appearance {
|
|||
)]
|
||||
#[repr(u8)]
|
||||
pub enum BreakBetween {
|
||||
Auto,
|
||||
Always,
|
||||
Auto,
|
||||
Page,
|
||||
Avoid,
|
||||
Left,
|
||||
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.
|
||||
///
|
||||
/// https://drafts.csswg.org/css-break/#break-within
|
||||
|
|
|
@ -34,7 +34,7 @@ pub use self::background::{BackgroundRepeat, BackgroundSize};
|
|||
pub use self::basic_shape::FillRule;
|
||||
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
|
||||
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_::{Appearance, BreakBetween, BreakWithin, Clear, Float};
|
||||
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.
|
||||
///
|
||||
/// https://drafts.csswg.org/css-values-3/#number-value
|
||||
|
|
|
@ -23,19 +23,20 @@ use style_traits::ParseError;
|
|||
ToComputedValue,
|
||||
ToCss,
|
||||
)]
|
||||
#[repr(C, u8)]
|
||||
/// <https://drafts.csswg.org/css-ui/#propdef-outline-style>
|
||||
pub enum OutlineStyle {
|
||||
/// auto
|
||||
Auto,
|
||||
/// <border-style>
|
||||
Other(BorderStyle),
|
||||
BorderStyle(BorderStyle),
|
||||
}
|
||||
|
||||
impl OutlineStyle {
|
||||
#[inline]
|
||||
/// Get default value as None
|
||||
pub fn none() -> OutlineStyle {
|
||||
OutlineStyle::Other(BorderStyle::None)
|
||||
OutlineStyle::BorderStyle(BorderStyle::None)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -43,7 +44,7 @@ impl OutlineStyle {
|
|||
pub fn none_or_hidden(&self) -> bool {
|
||||
match *self {
|
||||
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())));
|
||||
}
|
||||
|
||||
return Ok(OutlineStyle::Other(border_style));
|
||||
return Ok(OutlineStyle::BorderStyle(border_style));
|
||||
}
|
||||
|
||||
input.expect_ident_matching("auto")?;
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
/// https://drafts.csswg.org/css-ui-4/#propdef-user-select
|
||||
|
@ -168,15 +163,6 @@ pub enum UserSelect {
|
|||
Text,
|
||||
#[parse(aliases = "-moz-none")]
|
||||
None,
|
||||
/// Force selection of all children, unless an ancestor has `none` set.
|
||||
/// Force selection of all children.
|
||||
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,
|
||||
}
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[variable-exponential-blowup.html]
|
||||
expected: TIMEOUT
|
Loading…
Add table
Add a link
Reference in a new issue