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

style: Sync changes from mozilla-central.

See individual commits 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/22930)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2019-02-24 08:31:08 -05:00 committed by GitHub
commit 427003210b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
72 changed files with 846 additions and 1175 deletions

View file

@ -2,8 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
// FIXME(rust-lang/rust#26264): Remove GenericBackgroundSize.
use crate::display_list::border;
use app_units::Au;
use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
@ -12,7 +10,6 @@ use style::computed_values::background_clip::single_value::T as BackgroundClip;
use style::computed_values::background_origin::single_value::T as BackgroundOrigin;
use style::properties::style_structs::Background;
use style::values::computed::{BackgroundSize, NonNegativeLengthPercentageOrAuto};
use style::values::generics::background::BackgroundSize as GenericBackgroundSize;
use style::values::specified::background::BackgroundRepeatKeyword;
use webrender_api::BorderRadius;
@ -56,8 +53,8 @@ fn compute_background_image_size(
) -> Size2D<Au> {
match intrinsic_size {
None => match bg_size {
GenericBackgroundSize::Cover | GenericBackgroundSize::Contain => bounds_size,
GenericBackgroundSize::Explicit { width, height } => Size2D::new(
BackgroundSize::Cover | BackgroundSize::Contain => bounds_size,
BackgroundSize::ExplicitSize { width, height } => Size2D::new(
width
.to_used_value(bounds_size.width)
.unwrap_or(bounds_size.width),
@ -73,20 +70,16 @@ fn compute_background_image_size(
let bounds_aspect_ratio =
bounds_size.width.to_f32_px() / bounds_size.height.to_f32_px();
match (bg_size, image_aspect_ratio < bounds_aspect_ratio) {
(GenericBackgroundSize::Contain, false) | (GenericBackgroundSize::Cover, true) => {
Size2D::new(
bounds_size.width,
bounds_size.width.scale_by(image_aspect_ratio.recip()),
)
},
(GenericBackgroundSize::Contain, true) | (GenericBackgroundSize::Cover, false) => {
Size2D::new(
bounds_size.height.scale_by(image_aspect_ratio),
bounds_size.height,
)
},
(BackgroundSize::Contain, false) | (BackgroundSize::Cover, true) => Size2D::new(
bounds_size.width,
bounds_size.width.scale_by(image_aspect_ratio.recip()),
),
(BackgroundSize::Contain, true) | (BackgroundSize::Cover, false) => Size2D::new(
bounds_size.height.scale_by(image_aspect_ratio),
bounds_size.height,
),
(
GenericBackgroundSize::Explicit {
BackgroundSize::ExplicitSize {
width,
height: NonNegativeLengthPercentageOrAuto::Auto,
},
@ -98,7 +91,7 @@ fn compute_background_image_size(
Size2D::new(width, width.scale_by(image_aspect_ratio.recip()))
},
(
GenericBackgroundSize::Explicit {
BackgroundSize::ExplicitSize {
width: NonNegativeLengthPercentageOrAuto::Auto,
height,
},
@ -109,7 +102,7 @@ fn compute_background_image_size(
.unwrap_or(own_size.height);
Size2D::new(height.scale_by(image_aspect_ratio), height)
},
(GenericBackgroundSize::Explicit { width, height }, _) => Size2D::new(
(BackgroundSize::ExplicitSize { width, height }, _) => Size2D::new(
width
.to_used_value(bounds_size.width)
.unwrap_or(own_size.width),

View file

@ -2,8 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
// FIXME(rust-lang/rust#26264): Remove GenericBorderImageSideWidth.
use crate::display_list::ToLayout;
use app_units::Au;
use euclid::{Rect, SideOffsets2D, Size2D};
@ -11,11 +9,9 @@ use style::computed_values::border_image_outset::T as BorderImageOutset;
use style::properties::style_structs::Border;
use style::values::computed::NumberOrPercentage;
use style::values::computed::{BorderCornerRadius, BorderImageWidth};
use style::values::computed::{BorderImageSideWidth, LengthOrNumber};
use style::values::generics::border::BorderImageSideWidth as GenericBorderImageSideWidth;
use style::values::computed::{BorderImageSideWidth, NonNegativeLengthOrNumber};
use style::values::generics::rect::Rect as StyleRect;
use style::values::generics::NonNegative;
use style::values::Either;
use webrender_api::{BorderRadius, BorderSide, BorderStyle, ColorF};
use webrender_api::{LayoutSideOffsets, LayoutSize, NormalBorder};
@ -140,10 +136,10 @@ pub fn simple(color: ColorF, style: BorderStyle) -> NormalBorder {
}
}
fn side_image_outset(outset: LengthOrNumber, border_width: Au) -> Au {
fn side_image_outset(outset: NonNegativeLengthOrNumber, border_width: Au) -> Au {
match outset {
Either::First(length) => length.into(),
Either::Second(factor) => border_width.scale_by(factor),
NonNegativeLengthOrNumber::Length(length) => length.into(),
NonNegativeLengthOrNumber::Number(factor) => border_width.scale_by(factor.0),
}
}
@ -163,9 +159,9 @@ fn side_image_width(
total_length: Au,
) -> f32 {
match border_image_width {
GenericBorderImageSideWidth::Length(v) => v.to_used_value(total_length).to_f32_px(),
GenericBorderImageSideWidth::Number(x) => border_width * x.0,
GenericBorderImageSideWidth::Auto => border_width,
BorderImageSideWidth::Length(v) => v.to_used_value(total_length).to_f32_px(),
BorderImageSideWidth::Number(x) => border_width * x.0,
BorderImageSideWidth::Auto => border_width,
}
}

View file

@ -763,7 +763,7 @@ impl Fragment {
let background_size =
get_cyclic(&style.get_background().background_size.0, i).clone();
let size = match background_size {
BackgroundSize::Explicit { width, height } => Size2D::new(
BackgroundSize::ExplicitSize { width, height } => Size2D::new(
width
.to_used_value(bounding_box_size.width)
.unwrap_or(bounding_box_size.width),

View file

@ -30,7 +30,6 @@ use style::properties::ComputedValues;
use style::servo::restyle_damage::ServoRestyleDamage;
use style::values::computed::flex::FlexBasis;
use style::values::computed::{MaxSize, Size};
use style::values::generics::flex::FlexBasis as GenericFlexBasis;
/// The size of an axis. May be a specified size, a min/max
/// constraint, or an unlimited size
@ -61,8 +60,8 @@ impl AxisSize {
/// is definite after flex size resolving.
fn from_flex_basis(flex_basis: FlexBasis, main_length: Size, containing_length: Au) -> MaybeAuto {
let width = match flex_basis {
GenericFlexBasis::Content => return MaybeAuto::Auto,
GenericFlexBasis::Width(width) => width,
FlexBasis::Content => return MaybeAuto::Auto,
FlexBasis::Size(width) => width,
};
let width = match width {

View file

@ -57,6 +57,7 @@ include = [
"CursorKind",
"Display",
"DisplayMode",
"PrefersColorScheme",
"ExtremumLength",
"FillRule",
"FontDisplay",
@ -69,6 +70,7 @@ include = [
"UserSelect",
"Float",
"OverscrollBehavior",
"ScrollSnapAlign",
"ScrollSnapType",
"OverflowAnchor",
"OverflowClipBox",
@ -77,32 +79,97 @@ include = [
"LengthPercentage",
"NonNegativeLengthPercentage",
"LengthPercentageOrAuto",
"NonNegativeLengthPercentageOrAuto",
"Rect",
"IntersectionObserverRootMargin",
"Size",
"MaxSize",
"FlexBasis",
"Position",
"BackgroundSize",
"BorderImageSlice",
"NonNegativeLengthOrNumberRect",
"Perspective",
"ZIndex",
"TransformOrigin",
]
item_types = ["enums", "structs", "typedefs"]
[export.body]
"CSSPixelLength" = """
inline nscoord ToAppUnits() const;
"""
"LengthPercentage" = """
// Defined in nsStyleCoord.h
static constexpr inline StyleLengthPercentage Zero();
static inline StyleLengthPercentage FromAppUnits(nscoord);
static inline StyleLengthPercentage FromPixels(CSSCoord);
static inline StyleLengthPercentage FromPercentage(float);
inline CSSCoord LengthInCSSPixels() const;
inline float Percentage() const;
inline bool HasPercent() const;
inline bool ConvertsToLength() const;
inline nscoord ToLength() const;
inline bool ConvertsToPercentage() const;
inline bool HasLengthAndPercentage() const;
inline float ToPercentage() const;
inline CSSCoord LengthInCSSPixels() const;
inline float Percentage() const;
inline CSSCoord ResolveToCSSPixels(CSSCoord aPercentageBasisInCSSPixels) const;
template<typename T> inline CSSCoord ResolveToCSSPixelsWith(T aPercentageGetter) const;
template<typename T, typename U>
inline nscoord Resolve(T aPercentageGetter, U aPercentRoundingFunction) const;
template<typename T>
inline nscoord Resolve(nscoord aPercentageBasis, T aPercentRoundingFunction) const;
template<typename T> inline nscoord Resolve(T aPercentageGetter) const;
inline nscoord Resolve(nscoord aPercentageBasis) const;
template<typename T> inline nscoord ResolveWith(T aPercentageGetter) const;
"""
"GenericLengthPercentageOrAuto" = """
inline const StyleLengthPercentage& AsLengthPercentage() const;
inline bool HasPercent() const;
inline bool ConvertsToLength() const;
inline nscoord ToLength() const;
inline bool ConvertsToPercentage() const;
inline float ToPercentage() const;
inline bool HasPercent() const;
inline bool HasLengthAndPercentage() const;
"""
"GenericSize" = """
inline const StyleLengthPercentage& AsLengthPercentage() const;
inline StyleExtremumLength AsExtremumLength() const;
inline bool ConvertsToLength() const;
inline nscoord ToLength() const;
inline bool ConvertsToPercentage() const;
inline float ToPercentage() const;
inline bool HasPercent() const;
inline bool HasLengthAndPercentage() const;
inline bool BehavesLikeInitialValueOnBlockAxis() const;
"""
"GenericFlexBasis" = """
inline bool IsAuto() const;
inline const StyleSize& AsSize() const;
"""
"GenericMaxSize" = """
inline const StyleLengthPercentage& AsLengthPercentage() const;
inline StyleExtremumLength AsExtremumLength() const;
inline bool ConvertsToLength() const;
inline nscoord ToLength() const;
inline bool ConvertsToPercentage() const;
inline float ToPercentage() const;
inline bool HasPercent() const;
inline bool HasLengthAndPercentage() const;
inline bool BehavesLikeInitialValueOnBlockAxis() const;
"""
"GenericPosition" = """
inline bool DependsOnPositioningAreaSize() const;
static inline StyleGenericPosition FromPercentage(float);
"""
"GenericBackgroundSize" = """
bool IsInitialValue() const;
"""
"Rect" = """

View file

@ -23,13 +23,10 @@ use crate::values::computed::url::ComputedImageUrl;
use crate::values::computed::{Angle, Gradient, Image};
use crate::values::computed::{Integer, LengthPercentage};
use crate::values::computed::{Length, Percentage, TextAlign};
use crate::values::computed::{LengthPercentageOrAuto, NonNegativeLengthPercentageOrAuto};
use crate::values::generics::box_::VerticalAlign;
use crate::values::generics::grid::{TrackListValue, TrackSize};
use crate::values::generics::image::{CompatMode, GradientItem, Image as GenericImage};
use crate::values::generics::length::LengthPercentageOrAuto as GenericLengthPercentageOrAuto;
use crate::values::generics::rect::Rect;
use crate::values::generics::NonNegative;
use app_units::Au;
use std::f32::consts::PI;
use style_traits::values::specified::AllowedNumericType;
@ -62,42 +59,6 @@ impl From<nsStyleCoord_CalcValue> for LengthPercentage {
)
}
}
impl NonNegativeLengthPercentageOrAuto {
/// Convert this value in an appropriate `nsStyleCoord::CalcValue`.
pub fn to_calc_value(&self) -> Option<nsStyleCoord_CalcValue> {
match *self {
GenericLengthPercentageOrAuto::LengthPercentage(ref len) => Some(From::from(len.0)),
GenericLengthPercentageOrAuto::Auto => None,
}
}
}
impl From<nsStyleCoord_CalcValue> for LengthPercentageOrAuto {
fn from(other: nsStyleCoord_CalcValue) -> LengthPercentageOrAuto {
GenericLengthPercentageOrAuto::LengthPercentage(LengthPercentage::from(other))
}
}
// FIXME(emilio): A lot of these impl From should probably become explicit or
// disappear as we move more stuff to cbindgen.
impl From<nsStyleCoord_CalcValue> for NonNegativeLengthPercentageOrAuto {
fn from(other: nsStyleCoord_CalcValue) -> Self {
GenericLengthPercentageOrAuto::LengthPercentage(NonNegative(
LengthPercentage::with_clamping_mode(
Au(other.mLength).into(),
if other.mHasPercent {
Some(Percentage(other.mPercent))
} else {
None
},
AllowedNumericType::NonNegative,
/* was_calc = */ true,
),
))
}
}
impl From<Angle> for CoordDataValue {
fn from(reference: Angle) -> Self {
CoordDataValue::Degree(reference.degrees())
@ -614,7 +575,6 @@ pub mod basic_shape {
//! Conversions from and to CSS shape representations.
use crate::gecko::values::GeckoStyleCoordConvertible;
use crate::gecko_bindings::structs;
use crate::gecko_bindings::structs::{nsStyleCoord, nsStyleCorners};
use crate::gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType};
use crate::gecko_bindings::structs::{
@ -628,7 +588,6 @@ pub mod basic_shape {
use crate::values::computed::border::{BorderCornerRadius, BorderRadius};
use crate::values::computed::length::LengthPercentage;
use crate::values::computed::motion::OffsetPath;
use crate::values::computed::position;
use crate::values::computed::url::ComputedUrl;
use crate::values::generics::basic_shape::{
BasicShape as GenericBasicShape, InsetRect, Polygon,
@ -759,12 +718,12 @@ pub mod basic_shape {
},
StyleBasicShapeType::Circle => GenericBasicShape::Circle(Circle {
radius: (&other.mCoordinates[0]).into(),
position: (&other.mPosition).into(),
position: other.mPosition,
}),
StyleBasicShapeType::Ellipse => GenericBasicShape::Ellipse(Ellipse {
semiaxis_x: (&other.mCoordinates[0]).into(),
semiaxis_y: (&other.mCoordinates[1]).into(),
position: (&other.mPosition).into(),
position: other.mPosition,
}),
StyleBasicShapeType::Polygon => {
let mut coords = Vec::with_capacity(other.mCoordinates.len() / 2);
@ -852,17 +811,6 @@ pub mod basic_shape {
}
}
// Can't be a From impl since we need to set an existing
// Position, not create a new one
impl From<position::Position> for structs::Position {
fn from(other: position::Position) -> Self {
structs::Position {
mXPosition: other.horizontal.into(),
mYPosition: other.vertical.into(),
}
}
}
impl<'a> From<&'a nsStyleCoord> for ShapeRadius {
fn from(other: &'a nsStyleCoord) -> Self {
let other = other.borrow();
@ -871,15 +819,6 @@ pub mod basic_shape {
}
}
impl<'a> From<&'a structs::Position> for position::Position {
fn from(other: &'a structs::Position) -> Self {
position::Position {
horizontal: other.mXPosition.into(),
vertical: other.mYPosition.into(),
}
}
}
impl From<ShapeBox> for StyleGeometryBox {
fn from(reference: ShapeBox) -> Self {
use crate::gecko_bindings::structs::StyleGeometryBox::*;

View file

@ -280,6 +280,16 @@ enum PrefersReducedMotion {
Reduce,
}
/// Values for the prefers-color-scheme media feature.
#[derive(Clone, Copy, Debug, FromPrimitive, Parse, PartialEq, ToCss)]
#[repr(u8)]
#[allow(missing_docs)]
pub enum PrefersColorScheme {
Light,
Dark,
NoPreference,
}
/// https://drafts.csswg.org/mediaqueries-5/#prefers-reduced-motion
fn eval_prefers_reduced_motion(device: &Device, query_value: Option<PrefersReducedMotion>) -> bool {
let prefers_reduced =
@ -348,6 +358,16 @@ fn eval_overflow_inline(device: &Device, query_value: Option<OverflowInline>) ->
}
}
/// https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme
fn eval_prefers_color_scheme(device: &Device, query_value: Option<PrefersColorScheme>) -> bool {
let prefers_color_scheme =
unsafe { bindings::Gecko_MediaFeatures_PrefersColorScheme(device.document()) };
match query_value {
Some(v) => prefers_color_scheme == v,
None => prefers_color_scheme != PrefersColorScheme::NoPreference,
}
}
/// https://drafts.csswg.org/mediaqueries-4/#mf-interaction
bitflags! {
struct PointerCapabilities: u8 {
@ -441,7 +461,7 @@ fn eval_moz_is_glyph(
query_value: Option<bool>,
_: Option<RangeOrOperator>,
) -> bool {
let is_glyph = unsafe { (*device.document()).mIsSVGGlyphsDocument() };
let is_glyph = device.document().mIsSVGGlyphsDocument();
query_value.map_or(is_glyph, |v| v == is_glyph)
}
@ -526,7 +546,7 @@ lazy_static! {
/// to support new types in these entries and (2) ensuring that either
/// nsPresContext::MediaFeatureValuesChanged is called when the value that
/// would be returned by the evaluator function could change.
pub static ref MEDIA_FEATURES: [MediaFeatureDescription; 52] = [
pub static ref MEDIA_FEATURES: [MediaFeatureDescription; 53] = [
feature!(
atom!("width"),
AllowsRanges::Yes,
@ -657,6 +677,12 @@ lazy_static! {
keyword_evaluator!(eval_overflow_inline, OverflowInline),
ParsingRequirements::empty(),
),
feature!(
atom!("prefers-color-scheme"),
AllowsRanges::No,
keyword_evaluator!(eval_prefers_color_scheme, PrefersColorScheme),
ParsingRequirements::empty(),
),
feature!(
atom!("pointer"),
AllowsRanges::No,

View file

@ -85,7 +85,9 @@ impl Device {
assert!(!pres_context.is_null());
Device {
pres_context,
default_values: ComputedValues::default_values(unsafe { &*pres_context }),
default_values: ComputedValues::default_values(unsafe {
&*(*pres_context).mDocument.mRawPtr
}),
// FIXME(bz): Seems dubious?
root_font_size: AtomicIsize::new(FontSize::medium().size().0 as isize),
body_text_color: AtomicUsize::new(unsafe { &*pres_context }.mDefaultColor as usize),
@ -162,13 +164,13 @@ impl Device {
/// Gets the document pointer.
#[inline]
pub fn document(&self) -> *mut structs::Document {
self.pres_context().mDocument.mRawPtr
pub fn document(&self) -> &structs::Document {
unsafe { &*self.pres_context().mDocument.mRawPtr }
}
/// Recreates the default computed values.
pub fn reset_computed_values(&mut self) {
self.default_values = ComputedValues::default_values(self.pres_context());
self.default_values = ComputedValues::default_values(self.document());
}
/// Rebuild all the cached data.

View file

@ -8,7 +8,7 @@
//! `pseudo_element_definition.mako.rs`. If you touch that file, you probably
//! need to update the checked-in files for Servo.
use crate::gecko_bindings::structs::{self, CSSPseudoElementType};
use crate::gecko_bindings::structs::{self, PseudoStyleType};
use crate::properties::longhands::display::computed_value::T as Display;
use crate::properties::{ComputedValues, PropertyFlags};
use crate::selector_parser::{NonTSPseudoClass, PseudoElementCascadeType, SelectorImpl};

View file

@ -48,17 +48,6 @@ PseudoElement::${pseudo.capitalized_pseudo()}${"({})".format(tree_arg) if pseudo
</%def>
impl PseudoElement {
/// Get the pseudo-element as an atom.
#[inline]
fn atom(&self) -> Atom {
match *self {
% for pseudo in PSEUDOS:
${pseudo_element_variant(pseudo)} => atom!("${pseudo.value}"),
% endfor
PseudoElement::UnknownWebkit(..) => unreachable!(),
}
}
/// Returns an index of the pseudo-element.
#[inline]
pub fn index(&self) -> usize {
@ -138,45 +127,36 @@ impl PseudoElement {
}
}
/// Construct a pseudo-element from a `CSSPseudoElementType`.
/// Construct a pseudo-element from a `PseudoStyleType`.
#[inline]
pub fn from_pseudo_type(type_: CSSPseudoElementType) -> Option<Self> {
pub fn from_pseudo_type(type_: PseudoStyleType) -> Option<Self> {
match type_ {
% for pseudo in PSEUDOS:
% if not pseudo.is_anon_box():
CSSPseudoElementType::${pseudo.pseudo_ident} => {
Some(${pseudo_element_variant(pseudo)})
},
% endif
% if not pseudo.is_tree_pseudo_element():
PseudoStyleType::${pseudo.pseudo_ident} => {
Some(${pseudo_element_variant(pseudo)})
},
% endif
% endfor
_ => None,
}
}
/// Construct a `CSSPseudoElementType` from a pseudo-element
/// Construct a `PseudoStyleType` from a pseudo-element
#[inline]
fn pseudo_type(&self) -> CSSPseudoElementType {
pub fn pseudo_type(&self) -> PseudoStyleType {
match *self {
% for pseudo in PSEUDOS:
% if not pseudo.is_anon_box():
PseudoElement::${pseudo.capitalized_pseudo()} => CSSPseudoElementType::${pseudo.pseudo_ident},
% elif pseudo.is_tree_pseudo_element():
PseudoElement::${pseudo.capitalized_pseudo()}(..) => CSSPseudoElementType::XULTree,
% elif pseudo.is_inheriting_anon_box():
PseudoElement::${pseudo.capitalized_pseudo()} => CSSPseudoElementType::InheritingAnonBox,
% else:
PseudoElement::${pseudo.capitalized_pseudo()} => CSSPseudoElementType::NonInheritingAnonBox,
% endif
% if pseudo.is_tree_pseudo_element():
PseudoElement::${pseudo.capitalized_pseudo()}(..) => PseudoStyleType::XULTree,
% else:
PseudoElement::${pseudo.capitalized_pseudo()} => PseudoStyleType::${pseudo.pseudo_ident},
% endif
% endfor
PseudoElement::UnknownWebkit(..) => unreachable!(),
}
}
/// Get a PseudoInfo for a pseudo
pub fn pseudo_info(&self) -> (*mut structs::nsAtom, CSSPseudoElementType) {
(self.atom().as_ptr(), self.pseudo_type())
}
/// Get the argument list of a tree pseudo-element.
#[inline]
pub fn tree_pseudo_args(&self) -> Option<<&[Atom]> {
@ -188,45 +168,15 @@ impl PseudoElement {
}
}
/// Construct a pseudo-element from an `Atom`.
#[inline]
pub fn from_atom(atom: &Atom) -> Option<Self> {
% for pseudo in PSEUDOS:
% if pseudo.is_tree_pseudo_element():
// We cannot generate ${pseudo_element_variant(pseudo)} from just an atom.
% else:
if atom == &atom!("${pseudo.value}") {
return Some(${pseudo_element_variant(pseudo)});
}
% endif
% endfor
None
}
/// Construct a pseudo-element from an anonymous box `Atom`.
#[inline]
pub fn from_anon_box_atom(atom: &Atom) -> Option<Self> {
% for pseudo in PSEUDOS:
% if pseudo.is_tree_pseudo_element():
// We cannot generate ${pseudo_element_variant(pseudo)} from just an atom.
% elif pseudo.is_anon_box():
if atom == &atom!("${pseudo.value}") {
return Some(${pseudo_element_variant(pseudo)});
}
% endif
% endfor
None
}
/// Construct a tree pseudo-element from atom and args.
#[inline]
pub fn from_tree_pseudo_atom(atom: &Atom, args: Box<[Atom]>) -> Option<Self> {
% for pseudo in PSEUDOS:
% if pseudo.is_tree_pseudo_element():
if atom == &atom!("${pseudo.value}") {
return Some(PseudoElement::${pseudo.capitalized_pseudo()}(args.into()));
}
% endif
% if pseudo.is_tree_pseudo_element():
if atom == &atom!("${pseudo.value}") {
return Some(PseudoElement::${pseudo.capitalized_pseudo()}(args.into()));
}
% endif
% endfor
None
}

View file

@ -41,8 +41,10 @@ class Atom:
# The type of atom: "Atom", "PseudoElement", "NonInheritingAnonBox",
# or "InheritingAnonBox".
self.atom_type = atom_type
if self.is_pseudo() or self.is_anon_box():
if self.is_pseudo_element() or self.is_anon_box() or self.is_tree_pseudo_element():
self.pseudo_ident = (ident.split("_", 1))[1]
if self.is_anon_box():
assert self.is_inheriting_anon_box() or self.is_non_inheriting_anon_box()
@ -52,16 +54,21 @@ class Atom:
def capitalized_pseudo(self):
return self.pseudo_ident[0].upper() + self.pseudo_ident[1:]
def is_pseudo(self):
def is_pseudo_element(self):
return self.atom_type == "PseudoElementAtom"
def is_anon_box(self):
if self.is_tree_pseudo_element():
return False
return self.is_non_inheriting_anon_box() or self.is_inheriting_anon_box()
def is_non_inheriting_anon_box(self):
assert not self.is_tree_pseudo_element()
return self.atom_type == "NonInheritingAnonBoxAtom"
def is_inheriting_anon_box(self):
if self.is_tree_pseudo_element():
return False
return self.atom_type == "InheritingAnonBoxAtom"
def is_tree_pseudo_element(self):

View file

@ -7,22 +7,16 @@
//! Different kind of helpers to interact with Gecko values.
use crate::counter_style::{Symbol, Symbols};
use crate::gecko_bindings::structs::{self, nsStyleCoord, CounterStylePtr};
use crate::gecko_bindings::structs::{nsStyleCoord, CounterStylePtr};
use crate::gecko_bindings::structs::{StyleGridTrackBreadth, StyleShapeRadius};
use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
use crate::media_queries::Device;
use crate::values::computed::basic_shape::ShapeRadius as ComputedShapeRadius;
use crate::values::computed::FlexBasis as ComputedFlexBasis;
use crate::values::computed::{Angle, ExtremumLength, Length, LengthPercentage};
use crate::values::computed::{MaxSize as ComputedMaxSize, Size as ComputedSize};
use crate::values::computed::{NonNegativeLengthPercentage, Percentage};
use crate::values::computed::{Number, NumberOrPercentage};
use crate::values::computed::{Angle, Length, LengthPercentage};
use crate::values::computed::{Number, NumberOrPercentage, Percentage};
use crate::values::generics::basic_shape::ShapeRadius;
use crate::values::generics::box_::Perspective;
use crate::values::generics::flex::FlexBasis;
use crate::values::generics::gecko::ScrollSnapPoint;
use crate::values::generics::grid::{TrackBreadth, TrackKeyword};
use crate::values::generics::length::{LengthPercentageOrAuto, MaxSize, Size};
use crate::values::generics::length::LengthPercentageOrAuto;
use crate::values::generics::{CounterStyleOrNone, NonNegative};
use crate::values::{Auto, Either, None_, Normal};
use crate::Atom;
@ -80,29 +74,6 @@ where
}
}
impl GeckoStyleCoordConvertible for ComputedFlexBasis {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
FlexBasis::Content => coord.set_value(CoordDataValue::Enumerated(
structs::NS_STYLE_FLEX_BASIS_CONTENT,
)),
FlexBasis::Width(ref w) => w.to_gecko_style_coord(coord),
}
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
if let Some(width) = ComputedSize::from_gecko_style_coord(coord) {
return Some(FlexBasis::Width(width));
}
if let CoordDataValue::Enumerated(structs::NS_STYLE_FLEX_BASIS_CONTENT) = coord.as_value() {
return Some(FlexBasis::Content);
}
None
}
}
impl GeckoStyleCoordConvertible for Number {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
coord.set_value(CoordDataValue::Factor(*self));
@ -336,60 +307,6 @@ impl GeckoStyleCoordConvertible for Normal {
}
}
impl GeckoStyleCoordConvertible for ExtremumLength {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
coord.set_value(CoordDataValue::Enumerated(*self as u32));
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
use num_traits::FromPrimitive;
match coord.as_value() {
CoordDataValue::Enumerated(v) => ExtremumLength::from_u32(v),
_ => None,
}
}
}
impl GeckoStyleCoordConvertible for ComputedSize {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
Size::LengthPercentage(ref lpoa) => lpoa.to_gecko_style_coord(coord),
Size::Auto => coord.set_value(CoordDataValue::Auto),
Size::ExtremumLength(ref e) => e.to_gecko_style_coord(coord),
}
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
if let CoordDataValue::Auto = coord.as_value() {
return Some(Size::Auto);
}
if let Some(lp) = NonNegativeLengthPercentage::from_gecko_style_coord(coord) {
return Some(Size::LengthPercentage(lp));
}
ExtremumLength::from_gecko_style_coord(coord).map(Size::ExtremumLength)
}
}
impl GeckoStyleCoordConvertible for ComputedMaxSize {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
MaxSize::LengthPercentage(ref lpon) => lpon.to_gecko_style_coord(coord),
MaxSize::None => coord.set_value(CoordDataValue::None),
MaxSize::ExtremumLength(ref e) => e.to_gecko_style_coord(coord),
}
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
if let CoordDataValue::None = coord.as_value() {
return Some(MaxSize::None);
}
if let Some(lp) = NonNegativeLengthPercentage::from_gecko_style_coord(coord) {
return Some(MaxSize::LengthPercentage(lp));
}
ExtremumLength::from_gecko_style_coord(coord).map(MaxSize::ExtremumLength)
}
}
impl GeckoStyleCoordConvertible for ScrollSnapPoint<LengthPercentage> {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match self.repeated() {
@ -412,27 +329,6 @@ impl GeckoStyleCoordConvertible for ScrollSnapPoint<LengthPercentage> {
}
}
impl<L> GeckoStyleCoordConvertible for Perspective<L>
where
L: GeckoStyleCoordConvertible,
{
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
Perspective::None => coord.set_value(CoordDataValue::None),
Perspective::Length(ref l) => l.to_gecko_style_coord(coord),
};
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
use crate::gecko_bindings::structs::root::nsStyleUnit;
if coord.unit() == nsStyleUnit::eStyleUnit_None {
return Some(Perspective::None);
}
Some(Perspective::Length(L::from_gecko_style_coord(coord)?))
}
}
/// Convert a given RGBA value to `nscolor`.
pub fn convert_rgba_to_nscolor(rgba: &RGBA) -> u32 {
((rgba.alpha as u32) << 24) |
@ -468,16 +364,15 @@ pub fn round_border_to_device_pixels(width: Au, au_per_device_px: Au) -> Au {
impl CounterStyleOrNone {
/// Convert this counter style to a Gecko CounterStylePtr.
pub fn to_gecko_value(self, gecko_value: &mut CounterStylePtr, device: &Device) {
pub fn to_gecko_value(self, gecko_value: &mut CounterStylePtr) {
use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToName as set_name;
use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToSymbols as set_symbols;
let pres_context = device.pres_context();
match self {
CounterStyleOrNone::None => unsafe {
set_name(gecko_value, atom!("none").into_addrefed(), pres_context);
set_name(gecko_value, atom!("none").into_addrefed());
},
CounterStyleOrNone::Name(name) => unsafe {
set_name(gecko_value, name.0.into_addrefed(), pres_context);
set_name(gecko_value, name.0.into_addrefed());
},
CounterStyleOrNone::Symbols(symbols_type, symbols) => {
let symbols: Vec<_> = symbols

View file

@ -7,10 +7,10 @@
use crate::gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
use crate::gecko_bindings::structs::StyleComplexColor;
use crate::gecko_bindings::structs::StyleComplexColor_Tag as Tag;
use crate::values::computed::ui::ColorOrAuto;
use crate::values::computed::{Color as ComputedColor, RGBAColor as ComputedRGBA};
use crate::values::generics::color::{Color as GenericColor, ComplexColorRatios};
use crate::values::{Auto, Either};
use crate::values::computed::{Color as ComputedColor, ColorOrAuto, RGBAColor as ComputedRGBA};
use crate::values::generics::color::{
Color as GenericColor, ColorOrAuto as GenericColorOrAuto, ComplexColorRatios,
};
impl StyleComplexColor {
/// Create a `StyleComplexColor` value that represents `currentColor`.
@ -94,8 +94,8 @@ impl From<StyleComplexColor> for ComputedColor {
impl From<ColorOrAuto> for StyleComplexColor {
fn from(other: ColorOrAuto) -> Self {
match other {
Either::First(color) => color.into(),
Either::Second(_) => StyleComplexColor::auto(),
GenericColorOrAuto::Color(color) => color.into(),
GenericColorOrAuto::Auto => StyleComplexColor::auto(),
}
}
}
@ -103,9 +103,9 @@ impl From<ColorOrAuto> for StyleComplexColor {
impl From<StyleComplexColor> for ColorOrAuto {
fn from(other: StyleComplexColor) -> Self {
if other.mTag != Tag::eAuto {
Either::First(other.into())
GenericColorOrAuto::Color(other.into())
} else {
Either::Second(Auto)
GenericColorOrAuto::Auto
}
}
}

View file

@ -236,7 +236,7 @@ where
parent_style.unwrap(),
parent_style_ignoring_first_line.unwrap()
) ||
parent_style.unwrap().pseudo() == Some(PseudoElement::FirstLine)
parent_style.unwrap().is_first_line_style()
);
let inherited_style = parent_style.unwrap_or(device.default_computed_values());
@ -745,13 +745,13 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
// FIXME(emilio): Why both setting the generic and passing it
// down?
let pres_context = self.context.builder.device.pres_context();
let doc = self.context.builder.device.document();
let gecko_font = self.context.builder.mutate_font().gecko_mut();
gecko_font.mGenericID = generic;
unsafe {
crate::gecko_bindings::bindings::Gecko_nsStyleFont_PrefillDefaultForGeneric(
gecko_font,
pres_context,
doc,
generic,
);
}

View file

@ -339,6 +339,7 @@ class Longhand(object):
"Resize",
"SVGOpacity",
"SVGPaintOrder",
"ScrollSnapAlign",
"ScrollSnapType",
"TextAlign",
"TextDecorationLine",

View file

@ -35,10 +35,9 @@ use crate::gecko_bindings::bindings::Gecko_SetListStyleImageNone;
use crate::gecko_bindings::bindings::Gecko_SetListStyleImageImageValue;
use crate::gecko_bindings::bindings::Gecko_SetNullImageValue;
use crate::gecko_bindings::bindings::{Gecko_ResetFilters, Gecko_CopyFiltersFrom};
use crate::gecko_bindings::bindings::RawGeckoPresContextBorrowed;
use crate::gecko_bindings::structs;
use crate::gecko_bindings::structs::nsCSSPropertyID;
use crate::gecko_bindings::structs::mozilla::CSSPseudoElementType;
use crate::gecko_bindings::structs::mozilla::PseudoStyleType;
use crate::gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
use crate::gecko_bindings::sugar::refptr::RefPtr;
use crate::gecko::values::convert_nscolor_to_rgba;
@ -61,8 +60,6 @@ use crate::values::computed::BorderStyle;
use crate::values::computed::font::FontSize;
use crate::values::computed::effects::{BoxShadow, Filter, SimpleShadow};
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;
@ -102,7 +99,7 @@ impl ComputedValues {
).to_outer(pseudo)
}
pub fn default_values(pres_context: RawGeckoPresContextBorrowed) -> Arc<Self> {
pub fn default_values(doc: &structs::Document) -> Arc<Self> {
ComputedValuesInner::new(
/* custom_properties = */ None,
/* writing_mode = */ WritingMode::empty(), // FIXME(bz): This seems dubious
@ -110,31 +107,22 @@ impl ComputedValues {
/* rules = */ None,
/* visited_style = */ None,
% for style_struct in data.style_structs:
style_structs::${style_struct.name}::default(pres_context),
style_structs::${style_struct.name}::default(doc),
% endfor
).to_outer(None)
}
#[inline]
pub fn pseudo(&self) -> Option<PseudoElement> {
let atom = (self.0).mPseudoTag.mRawPtr;
if atom.is_null() {
if self.0.mPseudoType == PseudoStyleType::NotPseudo {
return None;
}
let atom = unsafe { Atom::from_raw(atom) };
PseudoElement::from_atom(&atom)
PseudoElement::from_pseudo_type(self.0.mPseudoType)
}
#[inline]
fn get_pseudo_type(&self) -> CSSPseudoElementType {
self.0.mPseudoType
}
#[inline]
pub fn is_anon_box(&self) -> bool {
let our_type = self.get_pseudo_type();
return our_type == CSSPseudoElementType::InheritingAnonBox ||
our_type == CSSPseudoElementType::NonInheritingAnonBox;
pub fn is_first_line_style(&self) -> bool {
self.pseudo() == Some(PseudoElement::FirstLine)
}
/// Returns true if the display property is changed from 'none' to others.
@ -213,9 +201,9 @@ impl ComputedValuesInner {
self,
pseudo: Option<<&PseudoElement>,
) -> Arc<ComputedValues> {
let (pseudo_tag, pseudo_ty) = match pseudo {
Some(p) => p.pseudo_info(),
None => (ptr::null_mut(), structs::CSSPseudoElementType::NotPseudo),
let pseudo_ty = match pseudo {
Some(p) => p.pseudo_type(),
None => structs::PseudoStyleType::NotPseudo,
};
let arc = unsafe {
let arc: Arc<ComputedValues> = Arc::new(uninitialized());
@ -223,7 +211,6 @@ impl ComputedValuesInner {
&arc.0 as *const _ as *mut _,
&self,
pseudo_ty,
pseudo_tag
);
// We're simulating a move by having C++ do a memcpy and then forgetting
// it on this end.
@ -453,22 +440,6 @@ def set_gecko_property(ffi_name, expr):
}
</%def>
<%def name="impl_position(ident, gecko_ffi_name)">
#[allow(non_snake_case)]
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
${set_gecko_property("%s.mXPosition" % gecko_ffi_name, "v.horizontal.into()")}
${set_gecko_property("%s.mYPosition" % gecko_ffi_name, "v.vertical.into()")}
}
<%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call>
#[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
longhands::${ident}::computed_value::T {
horizontal: self.gecko.${gecko_ffi_name}.mXPosition.into(),
vertical: self.gecko.${gecko_ffi_name}.mYPosition.into(),
}
}
</%def>
<%def name="impl_color(ident, gecko_ffi_name)">
<%call expr="impl_color_setter(ident, gecko_ffi_name)"></%call>
<%call expr="impl_color_copy(ident, gecko_ffi_name)"></%call>
@ -1217,55 +1188,6 @@ pub fn clone_transform_from_list(
}
</%def>
<%def name="impl_transform_origin(ident, gecko_ffi_name)">
#[allow(non_snake_case)]
pub fn set_${ident}(&mut self, v: values::computed::TransformOrigin) {
self.gecko.${gecko_ffi_name}[0].set(v.horizontal);
self.gecko.${gecko_ffi_name}[1].set(v.vertical);
// transform-origin supports the third value for depth, while
// -moz-window-transform-origin doesn't. The following code is
// for handling this difference. If we can have more knowledge
// about the type here, we may want to check that the length is
// exactly either 2 or 3 in compile time.
if let Some(third) = self.gecko.${gecko_ffi_name}.get_mut(2) {
third.set(v.depth);
}
}
#[allow(non_snake_case)]
pub fn copy_${ident}_from(&mut self, other: &Self) {
self.gecko.${gecko_ffi_name}[0].copy_from(&other.gecko.${gecko_ffi_name}[0]);
self.gecko.${gecko_ffi_name}[1].copy_from(&other.gecko.${gecko_ffi_name}[1]);
if let (Some(self_third), Some(other_third)) =
(self.gecko.${gecko_ffi_name}.get_mut(2), other.gecko.${gecko_ffi_name}.get(2))
{
self_third.copy_from(other_third)
}
}
#[allow(non_snake_case)]
pub fn reset_${ident}(&mut self, other: &Self) {
self.copy_${ident}_from(other)
}
#[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> values::computed::TransformOrigin {
use crate::values::computed::{Length, LengthPercentage, TransformOrigin};
TransformOrigin {
horizontal: LengthPercentage::from_gecko_style_coord(&self.gecko.${gecko_ffi_name}[0])
.expect("clone for LengthPercentage failed"),
vertical: LengthPercentage::from_gecko_style_coord(&self.gecko.${gecko_ffi_name}[1])
.expect("clone for LengthPercentage failed"),
depth: if let Some(third) = self.gecko.${gecko_ffi_name}.get(2) {
Length::from_gecko_style_coord(third)
.expect("clone for Length failed")
} else {
Length::new(0.)
},
}
}
</%def>
<%def name="impl_logical(name, **kwargs)">
${helpers.logical_setter(name)}
</%def>
@ -1273,11 +1195,13 @@ pub fn clone_transform_from_list(
<%def name="impl_style_struct(style_struct)">
impl ${style_struct.gecko_struct_name} {
#[allow(dead_code, unused_variables)]
pub fn default(pres_context: RawGeckoPresContextBorrowed) -> Arc<Self> {
pub fn default(document: &structs::Document) -> Arc<Self> {
let mut result = Arc::new(${style_struct.gecko_struct_name} { gecko: unsafe { zeroed() } });
unsafe {
Gecko_Construct_Default_${style_struct.gecko_ffi_name}(&mut Arc::get_mut(&mut result).unwrap().gecko,
pres_context);
Gecko_Construct_Default_${style_struct.gecko_ffi_name}(
&mut Arc::get_mut(&mut result).unwrap().gecko,
document,
);
}
result
}
@ -1370,6 +1294,7 @@ impl Clone for ${style_struct.gecko_struct_name} {
"Appearance": impl_simple,
"OverscrollBehavior": impl_simple,
"OverflowClipBox": impl_simple,
"ScrollSnapAlign": impl_simple,
"ScrollSnapType": impl_simple,
"Float": impl_simple,
"Overflow": impl_simple,
@ -1385,32 +1310,36 @@ impl Clone for ${style_struct.gecko_struct_name} {
"length::NonNegativeLengthOrAuto": impl_style_coord,
"length::NonNegativeLengthPercentageOrNormal": impl_style_coord,
"FillRule": impl_simple,
"FlexBasis": impl_style_coord,
"FlexBasis": impl_simple,
"Length": impl_absolute_length,
"LengthOrNormal": impl_style_coord,
"LengthPercentage": impl_simple,
"LengthPercentageOrAuto": impl_style_coord,
"MaxSize": impl_style_coord,
"Size": impl_style_coord,
"MaxSize": impl_simple,
"Size": impl_simple,
"MozScriptMinSize": impl_absolute_length,
"MozScriptSizeMultiplier": impl_simple,
"NonNegativeLengthPercentage": impl_simple,
"NonNegativeLengthOrNumber": impl_simple,
"NonNegativeLengthOrNumberRect": impl_simple,
"BorderImageSlice": impl_simple,
"NonNegativeNumber": impl_simple,
"Number": impl_simple,
"Opacity": impl_simple,
"OverflowWrap": impl_simple,
"OverflowAnchor": impl_simple,
"Perspective": impl_style_coord,
"Position": impl_position,
"Perspective": impl_simple,
"Position": impl_simple,
"RGBAColor": impl_rgba_color,
"SVGLength": impl_svg_length,
"SVGOpacity": impl_svg_opacity,
"SVGPaint": impl_svg_paint,
"SVGWidth": impl_svg_length,
"Transform": impl_transform,
"TransformOrigin": impl_transform_origin,
"TransformOrigin": impl_simple,
"UserSelect": impl_simple,
"url::UrlOrNone": impl_css_url,
"ZIndex": impl_simple,
}
def longhand_method(longhand):
@ -1500,8 +1429,8 @@ fn static_assert() {
for x in CORNERS]) %>
<%self:impl_trait style_struct_name="Border"
skip_longhands="${skip_border_longhands} border-image-source border-image-outset
border-image-repeat border-image-width border-image-slice">
skip_longhands="${skip_border_longhands} border-image-source
border-image-repeat border-image-width">
% for side in SIDES:
pub fn set_border_${side.ident}_style(&mut self, v: BorderStyle) {
self.gecko.mBorderStyle[${side.index}] = v;
@ -1602,8 +1531,6 @@ fn static_assert() {
}
}
<% impl_style_sides("border_image_outset") %>
<%
border_image_repeat_keywords = ["Stretch", "Repeat", "Round", "Space"]
%>
@ -1645,63 +1572,41 @@ fn static_assert() {
}
<% impl_style_sides("border_image_width") %>
pub fn set_border_image_slice(&mut self, v: longhands::border_image_slice::computed_value::T) {
use crate::gecko_bindings::structs::{NS_STYLE_BORDER_IMAGE_SLICE_NOFILL, NS_STYLE_BORDER_IMAGE_SLICE_FILL};
v.offsets.to_gecko_rect(&mut self.gecko.mBorderImageSlice);
let fill = if v.fill {
NS_STYLE_BORDER_IMAGE_SLICE_FILL
} else {
NS_STYLE_BORDER_IMAGE_SLICE_NOFILL
};
self.gecko.mBorderImageFill = fill as u8;
}
<%self:copy_sides_style_coord ident="border_image_slice">
self.gecko.mBorderImageFill = other.gecko.mBorderImageFill;
</%self:copy_sides_style_coord>
pub fn clone_border_image_slice(&self) -> longhands::border_image_slice::computed_value::T {
use crate::gecko_bindings::structs::NS_STYLE_BORDER_IMAGE_SLICE_FILL;
use crate::values::computed::{BorderImageSlice, NonNegativeNumberOrPercentage};
type NumberOrPercentageRect = crate::values::generics::rect::Rect<NonNegativeNumberOrPercentage>;
BorderImageSlice {
offsets:
NumberOrPercentageRect::from_gecko_rect(&self.gecko.mBorderImageSlice)
.expect("mBorderImageSlice[${side}] could not convert to NumberOrPercentageRect"),
fill: self.gecko.mBorderImageFill as u32 == NS_STYLE_BORDER_IMAGE_SLICE_FILL
}
}
</%self:impl_trait>
<% skip_scroll_margin_longhands = " ".join(["scroll-margin-%s" % x.ident for x in SIDES]) %>
<% skip_margin_longhands = " ".join(["margin-%s" % x.ident for x in SIDES]) %>
<%self:impl_trait style_struct_name="Margin"
skip_longhands="${skip_margin_longhands}">
skip_longhands="${skip_margin_longhands}
${skip_scroll_margin_longhands}">
% for side in SIDES:
<% impl_split_style_coord("margin_%s" % side.ident,
"mMargin",
side.index) %>
<% impl_split_style_coord("scroll_margin_%s" % side.ident,
"mScrollMargin",
side.index) %>
% endfor
</%self:impl_trait>
<% skip_scroll_padding_longhands = " ".join(["scroll-padding-%s" % x.ident for x in SIDES]) %>
<% skip_padding_longhands = " ".join(["padding-%s" % x.ident for x in SIDES]) %>
<%self:impl_trait style_struct_name="Padding"
skip_longhands="${skip_padding_longhands}">
skip_longhands="${skip_padding_longhands}
${skip_scroll_padding_longhands}">
% for side in SIDES:
<% impl_split_style_coord("padding_%s" % side.ident,
"mPadding",
side.index) %>
<% impl_split_style_coord("scroll_padding_%s" % side.ident, "mScrollPadding", side.index) %>
% endfor
</%self:impl_trait>
<% skip_position_longhands = " ".join(x.ident for x in SIDES + GRID_LINES) %>
<%self:impl_trait style_struct_name="Position"
skip_longhands="${skip_position_longhands} z-index order
skip_longhands="${skip_position_longhands} order
align-content justify-content align-self
justify-self align-items justify-items
grid-auto-rows grid-auto-columns
@ -1711,38 +1616,6 @@ fn static_assert() {
<% impl_split_style_coord(side.ident, "mOffset", side.index) %>
% endfor
pub fn set_z_index(&mut self, v: longhands::z_index::computed_value::T) {
match v {
ZIndex::Integer(n) => self.gecko.mZIndex.set_value(CoordDataValue::Integer(n)),
ZIndex::Auto => self.gecko.mZIndex.set_value(CoordDataValue::Auto),
}
}
pub fn copy_z_index_from(&mut self, other: &Self) {
use crate::gecko_bindings::structs::nsStyleUnit;
// z-index is never a calc(). If it were, we'd be leaking here, so
// assert that it isn't.
debug_assert_ne!(self.gecko.mZIndex.unit(), nsStyleUnit::eStyleUnit_Calc);
unsafe {
self.gecko.mZIndex.copy_from_unchecked(&other.gecko.mZIndex);
}
}
pub fn reset_z_index(&mut self, other: &Self) {
self.copy_z_index_from(other)
}
pub fn clone_z_index(&self) -> longhands::z_index::computed_value::T {
return match self.gecko.mZIndex.as_value() {
CoordDataValue::Integer(n) => ZIndex::Integer(n),
CoordDataValue::Auto => ZIndex::Auto,
_ => {
debug_assert!(false);
ZIndex::Integer(0)
}
}
}
% for kind in ["align", "justify"]:
${impl_simple_type_with_conversion(kind + "_content")}
${impl_simple_type_with_conversion(kind + "_self")}
@ -2216,7 +2089,7 @@ fn static_assert() {
pub fn fixup_none_generic(&mut self, device: &Device) {
self.gecko.mFont.systemFont = false;
unsafe {
bindings::Gecko_nsStyleFont_FixupNoneGeneric(&mut self.gecko, device.pres_context())
bindings::Gecko_nsStyleFont_FixupNoneGeneric(&mut self.gecko, device.document())
}
}
@ -2332,7 +2205,7 @@ fn static_assert() {
}
pub fn fixup_font_min_size(&mut self, device: &Device) {
unsafe { bindings::Gecko_nsStyleFont_FixupMinFontSize(&mut self.gecko, device.pres_context()) }
unsafe { bindings::Gecko_nsStyleFont_FixupMinFontSize(&mut self.gecko, device.document()) }
}
pub fn apply_unconstrained_font_size(&mut self, v: NonNegativeLength) {
@ -2654,12 +2527,11 @@ fn static_assert() {
${impl_simple("_moz_script_level", "mScriptLevel")}
<% impl_simple_type_with_conversion("font_language_override", "mFont.languageOverride") %>
pub fn set_font_variant_alternates(&mut self,
v: values::computed::font::FontVariantAlternates,
device: &Device) {
pub fn set_font_variant_alternates(
&mut self,
v: values::computed::font::FontVariantAlternates,
) {
use crate::gecko_bindings::bindings::{Gecko_ClearAlternateValues, Gecko_AppendAlternateValues};
use crate::gecko_bindings::bindings::Gecko_nsFont_ResetFontFeatureValuesLookup;
use crate::gecko_bindings::bindings::Gecko_nsFont_SetFontFeatureValuesLookup;
% for value in "normal swash stylistic ornaments annotation styleset character_variant historical".split():
use crate::gecko_bindings::structs::NS_FONT_VARIANT_ALTERNATES_${value.upper()};
% endfor
@ -2671,7 +2543,6 @@ fn static_assert() {
if v.0.is_empty() {
self.gecko.mFont.variantAlternates = NS_FONT_VARIANT_ALTERNATES_NORMAL as u16;
unsafe { Gecko_nsFont_ResetFontFeatureValuesLookup(&mut self.gecko.mFont); }
return;
}
@ -2704,10 +2575,6 @@ fn static_assert() {
}
}
}
unsafe {
Gecko_nsFont_SetFontFeatureValuesLookup(&mut self.gecko.mFont, device.pres_context());
}
}
#[allow(non_snake_case)]
@ -2997,10 +2864,8 @@ fn static_assert() {
clear transition-duration transition-delay
transition-timing-function transition-property
rotate scroll-snap-points-x scroll-snap-points-y
scroll-snap-coordinate
perspective-origin -moz-binding will-change
offset-path perspective-origin -moz-binding
will-change shape-outside contain touch-action
scroll-snap-coordinate -moz-binding will-change
offset-path shape-outside contain touch-action
translate scale""" %>
<%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}">
#[inline]
@ -3095,11 +2960,7 @@ fn static_assert() {
where I: IntoIterator<Item = longhands::scroll_snap_coordinate::computed_value::single_value::T>,
I::IntoIter: ExactSizeIterator
{
let iter = v.into_iter().map(|c| structs::mozilla::Position {
mXPosition: c.horizontal.into(),
mYPosition: c.vertical.into(),
});
self.gecko.mScrollSnapCoordinate.assign_from_iter_pod(iter);
self.gecko.mScrollSnapCoordinate.assign_from_iter_pod(v.into_iter());
}
pub fn copy_scroll_snap_coordinate_from(&mut self, other: &Self) {
@ -3112,7 +2973,7 @@ fn static_assert() {
}
pub fn clone_scroll_snap_coordinate(&self) -> longhands::scroll_snap_coordinate::computed_value::T {
let vec = self.gecko.mScrollSnapCoordinate.iter().map(|f| f.into()).collect();
let vec = self.gecko.mScrollSnapCoordinate.iter().cloned().collect();
longhands::scroll_snap_coordinate::computed_value::List(vec)
}
@ -3356,31 +3217,6 @@ fn static_assert() {
${impl_animation_timing_function()}
pub fn set_perspective_origin(&mut self, v: longhands::perspective_origin::computed_value::T) {
self.gecko.mPerspectiveOrigin[0].set(v.horizontal);
self.gecko.mPerspectiveOrigin[1].set(v.vertical);
}
pub fn copy_perspective_origin_from(&mut self, other: &Self) {
self.gecko.mPerspectiveOrigin[0].copy_from(&other.gecko.mPerspectiveOrigin[0]);
self.gecko.mPerspectiveOrigin[1].copy_from(&other.gecko.mPerspectiveOrigin[1]);
}
pub fn reset_perspective_origin(&mut self, other: &Self) {
self.copy_perspective_origin_from(other)
}
pub fn clone_perspective_origin(&self) -> longhands::perspective_origin::computed_value::T {
use crate::properties::longhands::perspective_origin::computed_value::T;
use crate::values::computed::LengthPercentage;
T {
horizontal: LengthPercentage::from_gecko_style_coord(&self.gecko.mPerspectiveOrigin[0])
.expect("Expected length or percentage for horizontal value of perspective-origin"),
vertical: LengthPercentage::from_gecko_style_coord(&self.gecko.mPerspectiveOrigin[1])
.expect("Expected length or percentage for vertical value of perspective-origin"),
}
}
${impl_individual_transform('rotate', 'Rotate', 'mSpecifiedRotate')}
${impl_individual_transform('translate', 'Translate', 'mSpecifiedTranslate')}
${impl_individual_transform('scale', 'Scale', 'mSpecifiedScale')}
@ -3759,7 +3595,7 @@ fn static_assert() {
<% impl_simple_image_array_property("clip", shorthand, image_layers_field, "mClip", struct_name) %>
<% impl_simple_image_array_property("origin", shorthand, image_layers_field, "mOrigin", struct_name) %>
% for orientation in ["x", "y"]:
% for (orientation, keyword) in [("x", "horizontal"), ("y", "vertical")]:
pub fn copy_${shorthand}_position_${orientation}_from(&mut self, other: &Self) {
use crate::gecko_bindings::structs::nsStyleImageLayers_LayerType as LayerType;
@ -3774,8 +3610,7 @@ fn static_assert() {
for (layer, other) in self.gecko.${image_layers_field}.mLayers.iter_mut()
.zip(other.gecko.${image_layers_field}.mLayers.iter())
.take(count as usize) {
layer.mPosition.m${orientation.upper()}Position
= other.mPosition.m${orientation.upper()}Position;
layer.mPosition.${keyword} = other.mPosition.${keyword};
}
self.gecko.${image_layers_field}.mPosition${orientation.upper()}Count = count;
}
@ -3789,7 +3624,7 @@ fn static_assert() {
longhands::${shorthand}_position_${orientation}::computed_value::List(
self.gecko.${image_layers_field}.mLayers.iter()
.take(self.gecko.${image_layers_field}.mPosition${orientation.upper()}Count as usize)
.map(|position| position.mPosition.m${orientation.upper()}Position.into())
.map(|position| position.mPosition.${keyword})
.collect()
)
}
@ -3812,86 +3647,18 @@ fn static_assert() {
self.gecko.${image_layers_field}.mPosition${orientation[0].upper()}Count = v.len() as u32;
for (servo, geckolayer) in v.zip(self.gecko.${image_layers_field}
.mLayers.iter_mut()) {
geckolayer.mPosition.m${orientation[0].upper()}Position = servo.into();
geckolayer.mPosition.${keyword} = servo;
}
}
% endfor
<%self:simple_image_array_property name="size" shorthand="${shorthand}" field_name="mSize">
use crate::gecko_bindings::structs::nsStyleImageLayers_Size_Dimension;
use crate::gecko_bindings::structs::nsStyleImageLayers_Size_DimensionType;
use crate::gecko_bindings::structs::{nsStyleCoord_CalcValue, nsStyleImageLayers_Size};
use crate::values::generics::background::BackgroundSize;
let mut width = nsStyleCoord_CalcValue::new();
let mut height = nsStyleCoord_CalcValue::new();
let (w_type, h_type) = match servo {
BackgroundSize::Explicit { width: explicit_width, height: explicit_height } => {
let mut w_type = nsStyleImageLayers_Size_DimensionType::eAuto;
let mut h_type = nsStyleImageLayers_Size_DimensionType::eAuto;
if let Some(w) = explicit_width.to_calc_value() {
width = w;
w_type = nsStyleImageLayers_Size_DimensionType::eLengthPercentage;
}
if let Some(h) = explicit_height.to_calc_value() {
height = h;
h_type = nsStyleImageLayers_Size_DimensionType::eLengthPercentage;
}
(w_type, h_type)
}
BackgroundSize::Cover => {
(
nsStyleImageLayers_Size_DimensionType::eCover,
nsStyleImageLayers_Size_DimensionType::eCover,
)
},
BackgroundSize::Contain => {
(
nsStyleImageLayers_Size_DimensionType::eContain,
nsStyleImageLayers_Size_DimensionType::eContain,
)
},
};
nsStyleImageLayers_Size {
mWidth: nsStyleImageLayers_Size_Dimension { _base: width },
mHeight: nsStyleImageLayers_Size_Dimension { _base: height },
mWidthType: w_type as u8,
mHeightType: h_type as u8,
}
servo
</%self:simple_image_array_property>
pub fn clone_${shorthand}_size(&self) -> longhands::${shorthand}_size::computed_value::T {
use crate::gecko_bindings::structs::nsStyleCoord_CalcValue as CalcValue;
use crate::gecko_bindings::structs::nsStyleImageLayers_Size_DimensionType as DimensionType;
use crate::values::computed::NonNegativeLengthPercentageOrAuto;
use crate::values::generics::background::BackgroundSize;
fn to_servo(value: CalcValue, ty: u8) -> NonNegativeLengthPercentageOrAuto {
if ty == DimensionType::eAuto as u8 {
NonNegativeLengthPercentageOrAuto::auto()
} else {
debug_assert_eq!(ty, DimensionType::eLengthPercentage as u8);
value.into()
}
}
longhands::${shorthand}_size::computed_value::List(
self.gecko.${image_layers_field}.mLayers.iter().map(|ref layer| {
if DimensionType::eCover as u8 == layer.mSize.mWidthType {
debug_assert_eq!(layer.mSize.mHeightType, DimensionType::eCover as u8);
return BackgroundSize::Cover
}
if DimensionType::eContain as u8 == layer.mSize.mWidthType {
debug_assert_eq!(layer.mSize.mHeightType, DimensionType::eContain as u8);
return BackgroundSize::Contain
}
BackgroundSize::Explicit {
width: to_servo(layer.mSize.mWidth._base, layer.mSize.mWidthType),
height: to_servo(layer.mSize.mHeight._base, layer.mSize.mHeightType),
}
}).collect()
self.gecko.${image_layers_field}.mLayers.iter().map(|layer| layer.mSize).collect()
)
}
@ -4043,12 +3810,12 @@ fn static_assert() {
}
}
pub fn set_list_style_type(&mut self, v: longhands::list_style_type::computed_value::T, device: &Device) {
pub fn set_list_style_type(&mut self, v: longhands::list_style_type::computed_value::T) {
use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToString;
use nsstring::{nsACString, nsCStr};
use self::longhands::list_style_type::computed_value::T;
match v {
T::CounterStyle(s) => s.to_gecko_value(&mut self.gecko.mCounterStyle, device),
T::CounterStyle(s) => s.to_gecko_value(&mut self.gecko.mCounterStyle),
T::String(s) => unsafe {
Gecko_SetCounterStyleToString(&mut self.gecko.mCounterStyle,
&nsCStr::from(&s) as &nsACString)
@ -4472,7 +4239,7 @@ fn static_assert() {
<%self:impl_trait style_struct_name="InheritedText"
skip_longhands="text-align text-emphasis-style text-shadow line-height letter-spacing word-spacing
-webkit-text-stroke-width text-emphasis-position -moz-tab-size">
-webkit-text-stroke-width text-emphasis-position">
<% text_align_keyword = Keyword("text-align",
"start end left right center justify -moz-center -moz-left -moz-right char",
@ -4661,28 +4428,6 @@ fn static_assert() {
${impl_non_negative_length('_webkit_text_stroke_width',
'mWebkitTextStrokeWidth')}
#[allow(non_snake_case)]
pub fn set__moz_tab_size(&mut self, v: longhands::_moz_tab_size::computed_value::T) {
match v {
MozTabSize::Number(non_negative_number) => {
self.gecko.mTabSize.set_value(CoordDataValue::Factor(non_negative_number.0));
}
MozTabSize::Length(non_negative_length) => {
self.gecko.mTabSize.set(non_negative_length);
}
}
}
#[allow(non_snake_case)]
pub fn clone__moz_tab_size(&self) -> longhands::_moz_tab_size::computed_value::T {
match self.gecko.mTabSize.as_value() {
CoordDataValue::Coord(coord) => MozTabSize::Length(Au(coord).into()),
CoordDataValue::Factor(number) => MozTabSize::Number(From::from(number)),
_ => unreachable!(),
}
}
<%call expr="impl_coord_copy('_moz_tab_size', 'mTabSize')"></%call>
</%self:impl_trait>
<%self:impl_trait style_struct_name="Text"
@ -5290,7 +5035,7 @@ clip-path
self.gecko.mContents.is_empty()
}
pub fn set_content(&mut self, v: longhands::content::computed_value::T, device: &Device) {
pub fn set_content(&mut self, v: longhands::content::computed_value::T) {
use crate::values::CustomIdent;
use crate::values::generics::counters::{Content, ContentItem};
use crate::values::generics::CounterStyleOrNone;
@ -5315,7 +5060,6 @@ clip-path
name: &CustomIdent,
sep: &str,
style: CounterStyleOrNone,
device: &Device,
) {
debug_assert!(content_type == StyleContentType::Counter ||
content_type == StyleContentType::Counters);
@ -5326,7 +5070,7 @@ clip-path
if content_type == StyleContentType::Counters {
counter_func.mSeparator.assign_str(sep);
}
style.to_gecko_value(&mut counter_func.mCounterStyle, device);
style.to_gecko_value(&mut counter_func.mCounterStyle);
}
match v {
@ -5401,7 +5145,6 @@ clip-path
&name,
"",
style.clone(),
device,
);
}
ContentItem::Counters(ref name, ref sep, ref style) => {
@ -5411,7 +5154,6 @@ clip-path
&name,
&sep,
style.clone(),
device,
);
}
ContentItem::Url(ref url) => {

View file

@ -119,10 +119,9 @@ ${helpers.predefined_type(
${helpers.predefined_type(
"border-image-outset",
"LengthOrNumberRect",
parse_method="parse_non_negative",
initial_value="computed::LengthOrNumberRect::all(computed::LengthOrNumber::zero())",
initial_specified_value="specified::LengthOrNumberRect::all(specified::LengthOrNumber::zero())",
"NonNegativeLengthOrNumberRect",
initial_value="generics::rect::Rect::all(computed::NonNegativeLengthOrNumber::zero())",
initial_specified_value="generics::rect::Rect::all(specified::NonNegativeLengthOrNumber::zero())",
spec="https://drafts.csswg.org/css-backgrounds/#border-image-outset",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER",

View file

@ -417,6 +417,16 @@ ${helpers.single_keyword(
animation_value_type="discrete",
)}
${helpers.predefined_type(
"scroll-snap-align",
"ScrollSnapAlign",
"computed::ScrollSnapAlign::none()",
products="gecko",
gecko_pref="layout.css.scroll-snap-v1.enabled",
spec="https://drafts.csswg.org/css-scroll-snap-1/#scroll-snap-align",
animation_value_type="discrete",
)}
% for axis in ["x", "y"]:
${helpers.predefined_type(
"scroll-snap-type-" + axis,

View file

@ -98,7 +98,7 @@ pub mod system_colors {
unsafe {
Gecko_GetLookAndFeelSystemColor(
*self as i32,
cx.device().pres_context(),
cx.device().document(),
)
}
}

View file

@ -396,7 +396,7 @@ ${helpers.predefined_type(
&mut system,
id as i32,
cx.style().get_font().gecko(),
cx.device().pres_context()
cx.device().document()
)
}
let font_weight = longhands::font_weight::computed_value::T::from_gecko_weight(system.weight);

View file

@ -257,10 +257,10 @@ ${helpers.predefined_type(
${helpers.predefined_type(
"-moz-tab-size",
"MozTabSize",
"generics::text::MozTabSize::Number(From::from(8.0))",
"NonNegativeLengthOrNumber",
"generics::length::LengthOrNumber::Number(From::from(8.0))",
products="gecko",
animation_value_type="AnimatedMozTabSize",
animation_value_type="LengthOrNumber",
spec="https://drafts.csswg.org/css-text-3/#tab-size-property",
)}
@ -349,8 +349,8 @@ ${helpers.single_keyword(
"-moz-control-character-visibility",
"hidden visible",
gecko_constant_prefix="NS_STYLE_CONTROL_CHARACTER_VISIBILITY",
gecko_ffi_name="mControlCharacterVisibility",
animation_value_type="none",
gecko_ffi_name="mControlCharacterVisibility",
products="gecko",
spec="Nonstandard",
)}

View file

@ -60,7 +60,7 @@ ${helpers.single_keyword(
${helpers.predefined_type(
"caret-color",
"ColorOrAuto",
"Either::Second(Auto)",
"generics::color::ColorOrAuto::Auto",
spec="https://drafts.csswg.org/css-ui/#caret-color",
animation_value_type="AnimatedCaretColor",
ignored_when_colors_disabled=True,

View file

@ -27,3 +27,18 @@
servo_restyle_damage="reflow"
)}
% endfor
% for side in ALL_SIDES:
${helpers.predefined_type(
"scroll-margin-%s" % side[0],
"Length",
"computed::Length::zero()",
products="gecko",
gecko_pref="layout.css.scroll-snap-v1.enabled",
logical=side[1],
logical_group="scroll-margin",
spec="https://drafts.csswg.org/css-scroll-snap-1/#propdef-scroll-margin-%s" % side[0],
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE",
animation_value_type="ComputedValue",
)}
% endfor

View file

@ -28,3 +28,17 @@
servo_restyle_damage="reflow rebuild_and_reflow_inline"
)}
% endfor
% for side in ALL_SIDES:
${helpers.predefined_type(
"scroll-padding-%s" % side[0],
"NonNegativeLengthPercentageOrAuto",
"computed::NonNegativeLengthPercentageOrAuto::auto()",
products="gecko",
gecko_pref="layout.css.scroll-snap-v1.enabled",
logical=side[1],
logical_group="scroll-padding",
spec="https://drafts.csswg.org/css-scroll-snap-1/#propdef-scroll-padding-%s" % side[0],
animation_value_type="ComputedValue",
)}
% endfor

View file

@ -75,6 +75,7 @@ ${helpers.single_keyword(
extra_prefixes="webkit",
animation_value_type="discrete",
servo_restyle_damage = "reflow",
gecko_enum_prefix = "StyleFlexDirection",
)}
${helpers.single_keyword(
@ -225,7 +226,7 @@ ${helpers.predefined_type(
extra_prefixes="webkit",
animation_value_type="ComputedValue",
spec="https://drafts.csswg.org/css-flexbox/#order-property",
servo_restyle_damage = "reflow",
servo_restyle_damage="reflow",
)}
${helpers.predefined_type(
@ -235,7 +236,8 @@ ${helpers.predefined_type(
spec="https://drafts.csswg.org/css-flexbox/#flex-basis-property",
extra_prefixes="webkit",
animation_value_type="FlexBasis",
servo_restyle_damage = "reflow",
servo_restyle_damage="reflow",
boxed=True,
)}
% for (size, logical) in ALL_SIZES:

View file

@ -96,6 +96,7 @@ ${helpers.predefined_type(
${helpers.single_keyword(
"mask-mode",
"match-source alpha luminance",
gecko_enum_prefix="StyleMaskMode",
vector=True,
products="gecko",
animation_value_type="discrete",

View file

@ -3358,7 +3358,7 @@ impl<'a> StyleBuilder<'a> {
debug_assert!(parent_style.is_none() ||
std::ptr::eq(parent_style.unwrap(),
parent_style_ignoring_first_line.unwrap()) ||
parent_style.unwrap().pseudo() == Some(PseudoElement::FirstLine));
parent_style.unwrap().is_first_line_style());
let reset_style = device.default_computed_values();
let inherited_style = parent_style.unwrap_or(reset_style);
let inherited_style_ignoring_first_line = parent_style_ignoring_first_line.unwrap_or(reset_style);
@ -3402,7 +3402,7 @@ impl<'a> StyleBuilder<'a> {
let inherited_style = parent_style.unwrap_or(reset_style);
#[cfg(feature = "gecko")]
debug_assert!(parent_style.is_none() ||
parent_style.unwrap().pseudo() != Some(PseudoElement::FirstLine));
!parent_style.unwrap().is_first_line_style());
StyleBuilder {
device,
inherited_style,
@ -3507,14 +3507,11 @@ impl<'a> StyleBuilder<'a> {
self.modified_reset = true;
% endif
<% props_need_device = ["content", "list_style_type", "font_variant_alternates"] %>
self.${property.style_struct.ident}.mutate()
.set_${property.ident}(
value,
% if property.logical:
self.writing_mode,
% elif product == "gecko" and property.ident in props_need_device:
self.device,
% endif
);
}

View file

@ -28,3 +28,32 @@ ${helpers.two_properties_shorthand(
"specified::LengthPercentageOrAuto::parse",
spec="https://drafts.csswg.org/css-logical/#propdef-margin-inline"
)}
${helpers.four_sides_shorthand(
"scroll-margin",
"scroll-margin-%s",
"specified::Length::parse",
spec="https://drafts.csswg.org/css-scroll-snap-1/#propdef-scroll-margin",
products="gecko",
gecko_pref="layout.css.scroll-snap-v1.enabled",
)}
${helpers.two_properties_shorthand(
"scroll-margin-block",
"scroll-margin-block-start",
"scroll-margin-block-end",
"specified::Length::parse",
spec="https://drafts.csswg.org/css-scroll-snap-1/#propdef-scroll-margin-block",
products="gecko",
gecko_pref="layout.css.scroll-snap-v1.enabled",
)}
${helpers.two_properties_shorthand(
"scroll-margin-inline",
"scroll-margin-inline-start",
"scroll-margin-inline-end",
"specified::Length::parse",
spec="https://drafts.csswg.org/css-scroll-snap-1/#propdef-scroll-margin-inline",
products="gecko",
gecko_pref="layout.css.scroll-snap-v1.enabled",
)}

View file

@ -27,3 +27,33 @@ ${helpers.two_properties_shorthand(
"specified::NonNegativeLengthPercentage::parse",
spec="https://drafts.csswg.org/css-logical/#propdef-padding-inline"
)}
${helpers.four_sides_shorthand(
"scroll-padding",
"scroll-padding-%s",
"specified::NonNegativeLengthPercentageOrAuto::parse",
products="gecko",
gecko_pref="layout.css.scroll-snap-v1.enabled",
spec="https://drafts.csswg.org/css-scroll-snap-1/#propdef-scroll-padding"
)}
${helpers.two_properties_shorthand(
"scroll-padding-block",
"scroll-padding-block-start",
"scroll-padding-block-end",
"specified::NonNegativeLengthPercentageOrAuto::parse",
products="gecko",
gecko_pref="layout.css.scroll-snap-v1.enabled",
spec="https://drafts.csswg.org/css-scroll-snap-1/#propdef-scroll-padding-block"
)}
${helpers.two_properties_shorthand(
"scroll-padding-inline",
"scroll-padding-inline-start",
"scroll-padding-inline-end",
"specified::NonNegativeLengthPercentageOrAuto::parse",
products="gecko",
gecko_pref="layout.css.scroll-snap-v1.enabled",
spec="https://drafts.csswg.org/css-scroll-snap-1/#propdef-scroll-padding-inline"
)}

View file

@ -766,6 +766,11 @@ impl<E: TElement> StyleSharingCache<E> {
return None;
}
if target.element.has_animations() {
trace!("Miss: Has Animations");
return None;
}
if target.matches_user_and_author_rules() !=
candidate.element.matches_user_and_author_rules()
{

View file

@ -198,7 +198,7 @@ impl DocumentMatchingFunction {
MediaDocumentKind::Video => "video",
},
});
unsafe { Gecko_DocumentRule_UseForPresentation(device.pres_context(), &*pattern, func) }
unsafe { Gecko_DocumentRule_UseForPresentation(device.document(), &*pattern, func) }
}
#[cfg(not(feature = "gecko"))]

View file

@ -6,19 +6,8 @@
use crate::values::computed::length::NonNegativeLengthPercentage;
use crate::values::generics::background::BackgroundSize as GenericBackgroundSize;
use crate::values::generics::length::LengthPercentageOrAuto;
pub use crate::values::specified::background::BackgroundRepeat;
/// A computed value for the `background-size` property.
pub type BackgroundSize = GenericBackgroundSize<NonNegativeLengthPercentage>;
impl BackgroundSize {
/// Returns `auto auto`.
pub fn auto() -> Self {
GenericBackgroundSize::Explicit {
width: LengthPercentageOrAuto::auto(),
height: LengthPercentageOrAuto::auto(),
}
}
}

View file

@ -15,7 +15,7 @@ pub use crate::values::specified::box_::{AnimationName, Appearance, BreakBetween
pub use crate::values::specified::box_::{Clear as SpecifiedClear, Float as SpecifiedFloat};
pub use crate::values::specified::box_::{Contain, Display, Overflow};
pub use crate::values::specified::box_::{OverflowAnchor, OverflowClipBox};
pub use crate::values::specified::box_::{OverscrollBehavior, ScrollSnapType};
pub use crate::values::specified::box_::{OverscrollBehavior, ScrollSnapAlign, ScrollSnapType};
pub use crate::values::specified::box_::{TouchAction, TransitionProperty, WillChange};
/// A computed value for the `vertical-align` property.

View file

@ -6,7 +6,7 @@
use crate::values::animated::color::RGBA as AnimatedRGBA;
use crate::values::animated::ToAnimatedValue;
use crate::values::generics::color::Color as GenericColor;
use crate::values::generics::color::{Color as GenericColor, ColorOrAuto as GenericColorOrAuto};
use cssparser::{Color as CSSParserColor, RGBA};
use std::fmt;
use style_traits::{CssWriter, ToCss};
@ -101,3 +101,6 @@ impl ToAnimatedValue for RGBA {
RGBA::from_floats(animated.red, animated.green, animated.blue, animated.alpha)
}
}
/// auto | <color>
pub type ColorOrAuto = GenericColorOrAuto<Color>;

View file

@ -14,6 +14,6 @@ impl FlexBasis {
/// `auto`
#[inline]
pub fn auto() -> Self {
GenericFlexBasis::Width(Size::auto())
GenericFlexBasis::Size(Size::auto())
}
}

View file

@ -6,9 +6,12 @@
use super::{Context, Number, Percentage, ToComputedValue};
use crate::values::animated::ToAnimatedValue;
use crate::values::computed::NonNegativeNumber;
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
use crate::values::generics::length as generics;
use crate::values::generics::length::{MaxSize as GenericMaxSize, Size as GenericSize};
use crate::values::generics::length::{
GenericLengthOrNumber, MaxSize as GenericMaxSize, Size as GenericSize,
};
use crate::values::generics::transform::IsZeroLength;
use crate::values::generics::NonNegative;
use crate::values::specified::length::ViewportPercentageLength;
@ -503,7 +506,7 @@ impl LengthPercentageOrAuto {
/// A wrapper of LengthPercentageOrAuto, whose value must be >= 0.
pub type NonNegativeLengthPercentageOrAuto =
generics::LengthPercentageOrAuto<NonNegativeLengthPercentage>;
generics::GenericLengthPercentageOrAuto<NonNegativeLengthPercentage>;
impl NonNegativeLengthPercentageOrAuto {
computed_length_percentage_or_auto!(NonNegativeLengthPercentage);
@ -678,6 +681,15 @@ impl ToCss for CSSPixelLength {
}
}
impl Add for CSSPixelLength {
type Output = Self;
#[inline]
fn add(self, other: Self) -> Self {
Self::new(self.px() + other.px())
}
}
impl Neg for CSSPixelLength {
type Output = Self;
@ -708,15 +720,7 @@ pub type Length = CSSPixelLength;
pub type LengthOrAuto = Either<Length, Auto>;
/// Either a computed `<length>` or a `<number>` value.
pub type LengthOrNumber = Either<Length, Number>;
impl LengthOrNumber {
/// Returns `0`.
#[inline]
pub fn zero() -> Self {
Either::Second(0.)
}
}
pub type LengthOrNumber = GenericLengthOrNumber<Length, Number>;
/// Either a computed `<length>` or the `normal` keyword.
pub type LengthOrNormal = Either<Length, Normal>;
@ -776,13 +780,6 @@ impl NonNegativeLength {
}
}
impl Add<NonNegativeLength> for NonNegativeLength {
type Output = Self;
fn add(self, other: Self) -> Self {
NonNegativeLength::new(self.px() + other.px())
}
}
impl From<Length> for NonNegativeLength {
#[inline]
fn from(len: Length) -> Self {
@ -813,6 +810,9 @@ pub type NonNegativeLengthOrNormal = Either<NonNegativeLength, Normal>;
/// Either a computed NonNegativeLengthPercentage or the `normal` keyword.
pub type NonNegativeLengthPercentageOrNormal = Either<NonNegativeLengthPercentage, Normal>;
/// Either a non-negative `<length>` or a `<number>`.
pub type NonNegativeLengthOrNumber = GenericLengthOrNumber<NonNegativeLength, NonNegativeNumber>;
/// A type for possible values for min- and max- flavors of width, height,
/// block-size, and inline-size.
#[allow(missing_docs)]

View file

@ -44,8 +44,8 @@ pub use self::box_::{AnimationIterationCount, AnimationName, Contain};
pub use self::box_::{Appearance, BreakBetween, BreakWithin, Clear, Float};
pub use self::box_::{Display, Overflow, OverflowAnchor, TransitionProperty};
pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize};
pub use self::box_::{ScrollSnapType, TouchAction, VerticalAlign, WillChange};
pub use self::color::{Color, ColorPropertyValue, RGBAColor};
pub use self::box_::{ScrollSnapAlign, ScrollSnapType, TouchAction, VerticalAlign, WillChange};
pub use self::color::{Color, ColorOrAuto, ColorPropertyValue, RGBAColor};
pub use self::column::ColumnCount;
pub use self::counters::{Content, ContentItem, CounterIncrement, CounterReset};
pub use self::easing::TimingFunction;
@ -61,7 +61,7 @@ pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier,
pub use self::gecko::ScrollSnapPoint;
pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect};
pub use self::length::{CSSPixelLength, ExtremumLength, NonNegativeLength};
pub use self::length::{Length, LengthOrNumber, LengthPercentage};
pub use self::length::{Length, LengthOrNumber, LengthPercentage, NonNegativeLengthOrNumber};
pub use self::length::{LengthPercentageOrAuto, MaxSize, Size};
pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto};
#[cfg(feature = "gecko")]
@ -71,13 +71,13 @@ pub use self::motion::OffsetPath;
pub use self::outline::OutlineStyle;
pub use self::percentage::{NonNegativePercentage, Percentage};
pub use self::position::{GridAutoFlow, GridTemplateAreas, Position, ZIndex};
pub use self::rect::LengthOrNumberRect;
pub use self::rect::NonNegativeLengthOrNumberRect;
pub use self::resolution::Resolution;
pub use self::svg::MozContextProperties;
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind};
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
pub use self::table::XSpan;
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, MozTabSize};
pub use self::text::{InitialLetter, LetterSpacing, LineHeight};
pub use self::text::{OverflowWrap, TextOverflow, WordSpacing};
pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle};
pub use self::time::Time;
@ -85,7 +85,7 @@ pub use self::transform::{Rotate, Scale, Transform, TransformOperation};
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
#[cfg(feature = "gecko")]
pub use self::ui::CursorImage;
pub use self::ui::{ColorOrAuto, Cursor, MozForceBrokenImageIcon, UserSelect};
pub use self::ui::{Cursor, MozForceBrokenImageIcon, UserSelect};
pub use super::specified::{BorderStyle, TextDecorationLine};
pub use super::{Auto, Either, None_};
pub use app_units::Au;
@ -536,6 +536,7 @@ impl From<GreaterThanOrEqualToOneNumber> for CSSFloat {
#[allow(missing_docs)]
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
#[repr(C, u8)]
pub enum NumberOrPercentage {
Percentage(Percentage),
Number(Number),

View file

@ -4,8 +4,8 @@
//! Computed types for CSS borders.
use crate::values::computed::length::LengthOrNumber;
use crate::values::computed::length::NonNegativeLengthOrNumber;
use crate::values::generics::rect::Rect;
/// A specified rectangle made of four `<length-or-number>` values.
pub type LengthOrNumberRect = Rect<LengthOrNumber>;
pub type NonNegativeLengthOrNumberRect = Rect<NonNegativeLengthOrNumber>;

View file

@ -10,7 +10,6 @@ use crate::values::computed::length::{Length, LengthPercentage};
use crate::values::computed::{NonNegativeLength, NonNegativeNumber};
use crate::values::generics::text::InitialLetter as GenericInitialLetter;
use crate::values::generics::text::LineHeight as GenericLineHeight;
use crate::values::generics::text::MozTabSize as GenericMozTabSize;
use crate::values::generics::text::Spacing;
use crate::values::specified::text::TextOverflowSide;
use crate::values::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword};
@ -124,9 +123,6 @@ impl TextDecorationsInEffect {
}
}
/// A specified value for the `-moz-tab-size` property.
pub type MozTabSize = GenericMozTabSize<NonNegativeNumber, NonNegativeLength>;
/// computed value for the text-emphasis-style property
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
pub enum TextEmphasisStyle {

View file

@ -21,7 +21,8 @@ pub type TransformOperation =
pub type Transform = generic::Transform<TransformOperation>;
/// The computed value of a CSS `<transform-origin>`
pub type TransformOrigin = generic::TransformOrigin<LengthPercentage, LengthPercentage, Length>;
pub type TransformOrigin =
generic::GenericTransformOrigin<LengthPercentage, LengthPercentage, Length>;
/// A vector to represent the direction vector (rotate axis) for Rotate3D.
pub type DirectionVector = Vector3D<CSSFloat>;

View file

@ -8,14 +8,10 @@ use crate::values::computed::color::Color;
use crate::values::computed::url::ComputedImageUrl;
use crate::values::computed::Number;
use crate::values::generics::ui as generics;
use crate::values::{Auto, Either};
pub use crate::values::specified::ui::CursorKind;
pub use crate::values::specified::ui::{MozForceBrokenImageIcon, UserSelect};
/// auto | <color>
pub type ColorOrAuto = Either<Color, Auto>;
/// A computed value for the `cursor` property.
pub type Cursor = generics::Cursor<CursorImage>;

View file

@ -4,7 +4,7 @@
//! Generic types for CSS values related to backgrounds.
use crate::values::generics::length::LengthPercentageOrAuto;
use crate::values::generics::length::{GenericLengthPercentageOrAuto, LengthPercentageOrAuto};
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
@ -22,13 +22,14 @@ use style_traits::{CssWriter, ToCss};
ToAnimatedZero,
ToComputedValue,
)]
pub enum BackgroundSize<LengthPercentage> {
#[repr(C, u8)]
pub enum GenericBackgroundSize<LengthPercent> {
/// `<width> <height>`
Explicit {
ExplicitSize {
/// Explicit width.
width: LengthPercentageOrAuto<LengthPercentage>,
width: GenericLengthPercentageOrAuto<LengthPercent>,
/// Explicit height.
height: LengthPercentageOrAuto<LengthPercentage>,
height: GenericLengthPercentageOrAuto<LengthPercent>,
},
/// `cover`
#[animation(error)]
@ -38,6 +39,8 @@ pub enum BackgroundSize<LengthPercentage> {
Contain,
}
pub use self::GenericBackgroundSize as BackgroundSize;
impl<LengthPercentage> ToCss for BackgroundSize<LengthPercentage>
where
LengthPercentage: ToCss,
@ -47,7 +50,7 @@ where
W: Write,
{
match self {
BackgroundSize::Explicit { width, height } => {
BackgroundSize::ExplicitSize { width, height } => {
width.to_css(dest)?;
// NOTE(emilio): We should probably simplify all these in case
// `width == `height`, but all other browsers agree on only
@ -63,3 +66,13 @@ where
}
}
}
impl<LengthPercentage> BackgroundSize<LengthPercentage> {
/// Returns `auto auto`.
pub fn auto() -> Self {
GenericBackgroundSize::ExplicitSize {
width: LengthPercentageOrAuto::Auto,
height: LengthPercentageOrAuto::Auto,
}
}
}

View file

@ -26,7 +26,8 @@ pub enum BorderImageSideWidth<LengthPercentage, Number> {
#[derive(
Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
)]
pub struct BorderImageSlice<NumberOrPercentage> {
#[repr(C)]
pub struct GenericBorderImageSlice<NumberOrPercentage> {
/// The offsets.
#[css(field_bound)]
pub offsets: Rect<NumberOrPercentage>,
@ -35,6 +36,8 @@ pub struct BorderImageSlice<NumberOrPercentage> {
pub fill: bool,
}
pub use self::GenericBorderImageSlice as BorderImageSlice;
/// A generic value for the `border-*-radius` longhand properties.
#[derive(
Animate,

View file

@ -74,6 +74,7 @@ pub enum AnimationIterationCount<Number> {
Copy,
Debug,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToAnimatedValue,
@ -81,13 +82,16 @@ pub enum AnimationIterationCount<Number> {
ToComputedValue,
ToCss,
)]
pub enum Perspective<NonNegativeLength> {
#[repr(C, u8)]
pub enum GenericPerspective<NonNegativeLength> {
/// A non-negative length.
Length(NonNegativeLength),
/// The keyword `none`.
None,
}
pub use self::GenericPerspective as Perspective;
impl<L> Perspective<L> {
/// Returns `none`.
#[inline]

View file

@ -74,3 +74,26 @@ impl<RGBA> From<RGBA> for Color<RGBA> {
Self::rgba(color)
}
}
/// Either `<color>` or `auto`.
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
PartialEq,
Parse,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToCss,
)]
pub enum ColorOrAuto<C> {
/// A `<color>
Color(C),
/// `auto`
Auto,
}

View file

@ -12,6 +12,7 @@
Copy,
Debug,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToAnimatedValue,

View file

@ -12,6 +12,7 @@
ComputeSquaredDistance,
Copy,
Debug,
Parse,
PartialEq,
SpecifiedValueInfo,
ToAnimatedValue,
@ -19,9 +20,12 @@
ToComputedValue,
ToCss,
)]
pub enum FlexBasis<Width> {
#[repr(C)]
pub enum GenericFlexBasis<S> {
/// `content`
Content,
/// `<width>`
Width(Width),
Size(S),
}
pub use self::GenericFlexBasis as FlexBasis;

View file

@ -192,10 +192,7 @@ impl<L> TrackBreadth<L> {
/// <https://drafts.csswg.org/css-grid/#typedef-fixed-breadth>
#[inline]
pub fn is_fixed(&self) -> bool {
match *self {
TrackBreadth::Breadth(ref _lp) => true,
_ => false,
}
matches!(*self, TrackBreadth::Breadth(..))
}
}

View file

@ -8,6 +8,7 @@ use crate::parser::{Parse, ParserContext};
#[cfg(feature = "gecko")]
use crate::values::computed::ExtremumLength;
use cssparser::Parser;
use num_traits::Zero;
use style_traits::ParseError;
/// A `<length-percentage> | auto` value.
@ -96,14 +97,17 @@ impl<LengthPercentage: Parse> Parse for LengthPercentageOrAuto<LengthPercentage>
ToComputedValue,
ToCss,
)]
pub enum Size<LengthPercentage> {
LengthPercentage(LengthPercentage),
#[repr(C, u8)]
pub enum GenericSize<LengthPercent> {
LengthPercentage(LengthPercent),
Auto,
#[cfg(feature = "gecko")]
#[animation(error)]
ExtremumLength(ExtremumLength),
}
pub use self::GenericSize as Size;
impl<LengthPercentage> Size<LengthPercentage> {
/// `auto` value.
#[inline]
@ -134,14 +138,17 @@ impl<LengthPercentage> Size<LengthPercentage> {
ToComputedValue,
ToCss,
)]
pub enum MaxSize<LengthPercentage> {
LengthPercentage(LengthPercentage),
#[repr(C, u8)]
pub enum GenericMaxSize<LengthPercent> {
LengthPercentage(LengthPercent),
None,
#[cfg(feature = "gecko")]
#[animation(error)]
ExtremumLength(ExtremumLength),
}
pub use self::GenericMaxSize as MaxSize;
impl<LengthPercentage> MaxSize<LengthPercentage> {
/// `none` value.
#[inline]
@ -149,3 +156,42 @@ impl<LengthPercentage> MaxSize<LengthPercentage> {
MaxSize::None
}
}
/// A generic `<length>` | `<number>` value for the `-moz-tab-size` property.
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToCss,
)]
#[repr(C, u8)]
pub enum GenericLengthOrNumber<L, N> {
/// A number.
///
/// NOTE: Numbers need to be before lengths, in order to parse them
/// first, since `0` should be a number, not the `0px` length.
Number(N),
/// A length.
Length(L),
}
pub use self::GenericLengthOrNumber as LengthOrNumber;
impl<L, N> LengthOrNumber<L, N> {
/// Returns `0`.
pub fn zero() -> Self
where
N: Zero,
{
LengthOrNumber::Number(num_traits::Zero::zero())
}
}

View file

@ -9,6 +9,8 @@ use super::CustomIdent;
use crate::counter_style::{parse_counter_style_name, Symbols};
use crate::parser::{Parse, ParserContext};
use cssparser::Parser;
use num_traits::Zero;
use std::ops::Add;
use style_traits::{KeywordsCollectFn, ParseError};
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind};
@ -117,27 +119,25 @@ impl Parse for CounterStyleOrNone {
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
return Ok(CounterStyleOrNone::None);
}
if input.try(|i| i.expect_function_matching("symbols")).is_ok() {
return input.parse_nested_block(|input| {
let symbols_type = input
.try(|i| SymbolsType::parse(i))
.unwrap_or(SymbolsType::Symbolic);
let symbols = Symbols::parse(context, input)?;
// There must be at least two symbols for alphabetic or
// numeric system.
if (symbols_type == SymbolsType::Alphabetic ||
symbols_type == SymbolsType::Numeric) && symbols.0.len() < 2
{
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
// Identifier is not allowed in symbols() function.
if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
Ok(CounterStyleOrNone::Symbols(symbols_type, symbols))
});
}
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
input.expect_function_matching("symbols")?;
input.parse_nested_block(|input| {
let symbols_type = input
.try(SymbolsType::parse)
.unwrap_or(SymbolsType::Symbolic);
let symbols = Symbols::parse(context, input)?;
// There must be at least two symbols for alphabetic or
// numeric system.
if (symbols_type == SymbolsType::Alphabetic || symbols_type == SymbolsType::Numeric) &&
symbols.0.len() < 2
{
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
// Identifier is not allowed in symbols() function.
if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
Ok(CounterStyleOrNone::Symbols(symbols_type, symbols))
})
}
}
@ -177,6 +177,24 @@ impl SpecifiedValueInfo for CounterStyleOrNone {
#[repr(transparent)]
pub struct NonNegative<T>(pub T);
impl<T: Add<Output = T>> Add<NonNegative<T>> for NonNegative<T> {
type Output = Self;
fn add(self, other: Self) -> Self {
NonNegative(self.0 + other.0)
}
}
impl<T: Zero> Zero for NonNegative<T> {
fn is_zero(&self) -> bool {
self.0.is_zero()
}
fn zero() -> Self {
NonNegative(T::zero())
}
}
/// A wrapper of greater-than-or-equal-to-one values.
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(

View file

@ -19,19 +19,22 @@
ToAnimatedZero,
ToComputedValue,
)]
pub struct Position<H, V> {
#[repr(C)]
pub struct GenericPosition<H, V> {
/// The horizontal component of position.
pub horizontal: H,
/// The vertical component of position.
pub vertical: V,
}
pub use self::GenericPosition as Position;
impl<H, V> Position<H, V> {
/// Returns a new position.
pub fn new(horizontal: H, vertical: V) -> Self {
Self {
horizontal: horizontal,
vertical: vertical,
horizontal,
vertical,
}
}
}
@ -45,18 +48,22 @@ impl<H, V> Position<H, V> {
Debug,
MallocSizeOf,
PartialEq,
Parse,
SpecifiedValueInfo,
ToAnimatedZero,
ToComputedValue,
ToCss,
)]
pub enum ZIndex<Integer> {
#[repr(C, u8)]
pub enum GenericZIndex<I> {
/// An integer value.
Integer(Integer),
Integer(I),
/// The keyword `auto`.
Auto,
}
pub use self::GenericZIndex as ZIndex;
impl<Integer> ZIndex<Integer> {
/// Returns `auto`
#[inline]

View file

@ -136,6 +136,7 @@ impl<ColorType: Parse, UrlPaintServer: Parse> Parse for SVGPaint<ColorType, UrlP
Debug,
MallocSizeOf,
PartialEq,
Parse,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
@ -143,28 +144,26 @@ impl<ColorType: Parse, UrlPaintServer: Parse> Parse for SVGPaint<ColorType, UrlP
ToCss,
)]
pub enum SvgLengthPercentageOrNumber<LengthPercentage, Number> {
/// <number>
///
/// Note that this needs to be before, so it gets parsed before the length,
/// to handle `0` correctly as a number instead of a `<length>`.
Number(Number),
/// <length> | <percentage>
LengthPercentage(LengthPercentage),
/// <number>
Number(Number),
}
/// Parsing the SvgLengthPercentageOrNumber. At first, we need to parse number
/// since prevent converting to the length.
impl<LengthPercentageType: Parse, NumberType: Parse> Parse
for SvgLengthPercentageOrNumber<LengthPercentageType, NumberType>
{
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if let Ok(num) = input.try(|i| NumberType::parse(context, i)) {
return Ok(SvgLengthPercentageOrNumber::Number(num));
}
/// Whether the `context-value` value is enabled.
#[cfg(feature = "gecko")]
pub fn is_context_value_enabled(_: &ParserContext) -> bool {
use crate::gecko_bindings::structs::mozilla;
unsafe { mozilla::StaticPrefs_sVarCache_gfx_font_rendering_opentype_svg_enabled }
}
let lp = LengthPercentageType::parse(context, input)?;
Ok(SvgLengthPercentageOrNumber::LengthPercentage(lp))
}
/// Whether the `context-value` value is enabled.
#[cfg(not(feature = "gecko"))]
pub fn is_context_value_enabled(_: &ParserContext) -> bool {
false
}
/// An SVG length value supports `context-value` in addition to length.
@ -175,6 +174,7 @@ impl<LengthPercentageType: Parse, NumberType: Parse> Parse
Debug,
MallocSizeOf,
PartialEq,
Parse,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
@ -185,6 +185,7 @@ pub enum SVGLength<LengthType> {
/// `<length> | <percentage> | <number>`
Length(LengthType),
/// `context-value`
#[parse(condition = "is_context_value_enabled")]
ContextValue,
}
@ -216,6 +217,7 @@ pub enum SVGStrokeDashArray<LengthType> {
Debug,
MallocSizeOf,
PartialEq,
Parse,
SpecifiedValueInfo,
ToAnimatedZero,
ToComputedValue,

View file

@ -149,25 +149,3 @@ impl<N, L> LineHeight<N, L> {
LineHeight::Normal
}
}
/// A generic value for the `-moz-tab-size` property.
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToCss,
)]
pub enum MozTabSize<Number, Length> {
/// A number.
Number(Number),
/// A length.
Length(Length),
}

View file

@ -83,7 +83,8 @@ impl<T: Into<f64>> From<Matrix3D<T>> for Transform3D<f64> {
ToComputedValue,
ToCss,
)]
pub struct TransformOrigin<H, V, Depth> {
#[repr(C)]
pub struct GenericTransformOrigin<H, V, Depth> {
/// The horizontal origin.
pub horizontal: H,
/// The vertical origin.
@ -92,13 +93,15 @@ pub struct TransformOrigin<H, V, Depth> {
pub depth: Depth,
}
pub use self::GenericTransformOrigin as TransformOrigin;
impl<H, V, D> TransformOrigin<H, V, D> {
/// Returns a new transform origin.
pub fn new(horizontal: H, vertical: V, depth: D) -> Self {
Self {
horizontal: horizontal,
vertical: vertical,
depth: depth,
horizontal,
vertical,
depth,
}
}
}

View file

@ -4,10 +4,6 @@
//! Generic types for url properties.
use crate::parser::{Parse, ParserContext};
use cssparser::Parser;
use style_traits::ParseError;
/// An image url or none, used for example in list-style-image
#[derive(
Animate,
@ -16,6 +12,7 @@ use style_traits::ParseError;
Debug,
MallocSizeOf,
PartialEq,
Parse,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
@ -35,19 +32,3 @@ impl<Url> UrlOrNone<Url> {
UrlOrNone::None
}
}
impl<Url> Parse for UrlOrNone<Url>
where
Url: Parse,
{
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<UrlOrNone<Url>, ParseError<'i>> {
if let Ok(url) = input.try(|input| Url::parse(context, input)) {
return Ok(UrlOrNone::Url(url));
}
input.expect_ident_matching("none")?;
Ok(UrlOrNone::None)
}
}

View file

@ -125,6 +125,7 @@ impl Parse for Impossible {
Copy,
MallocSizeOf,
PartialEq,
Parse,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
@ -147,19 +148,6 @@ impl<A: Debug, B: Debug> Debug for Either<A, B> {
}
}
impl<A: Parse, B: Parse> Parse for Either<A, B> {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Either<A, B>, ParseError<'i>> {
if let Ok(v) = input.try(|i| A::parse(context, i)) {
Ok(Either::First(v))
} else {
B::parse(context, input).map(Either::Second)
}
}
}
/// <https://drafts.csswg.org/css-values-4/#custom-idents>
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
pub struct CustomIdent(pub Atom);

View file

@ -26,7 +26,7 @@ impl Parse for BackgroundSize {
let height = input
.try(|i| NonNegativeLengthPercentageOrAuto::parse(context, i))
.unwrap_or(NonNegativeLengthPercentageOrAuto::auto());
return Ok(GenericBackgroundSize::Explicit { width, height });
return Ok(GenericBackgroundSize::ExplicitSize { width, height });
}
Ok(try_match_ident_ignore_ascii_case! { input,
"cover" => GenericBackgroundSize::Cover,
@ -35,16 +35,6 @@ impl Parse for BackgroundSize {
}
}
impl BackgroundSize {
/// Returns `auto auto`.
pub fn auto() -> Self {
GenericBackgroundSize::Explicit {
width: NonNegativeLengthPercentageOrAuto::auto(),
height: NonNegativeLengthPercentageOrAuto::auto(),
}
}
}
/// One of the keywords for `background-repeat`.
#[derive(
Clone,

View file

@ -392,6 +392,76 @@ pub enum ScrollSnapType {
Proximity,
}
/// Specified value of scroll-snap-align keyword value.
#[allow(missing_docs)]
#[derive(
Clone,
Copy,
Debug,
Eq,
FromPrimitive,
Hash,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
)]
#[repr(u8)]
pub enum ScrollSnapAlignKeyword {
None,
Start,
End,
Center,
}
/// https://drafts.csswg.org/css-scroll-snap-1/#scroll-snap-align
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
#[repr(C)]
pub struct ScrollSnapAlign {
block: ScrollSnapAlignKeyword,
inline: ScrollSnapAlignKeyword,
}
impl ScrollSnapAlign {
/// Returns `none`.
#[inline]
pub fn none() -> Self {
ScrollSnapAlign {
block: ScrollSnapAlignKeyword::None,
inline: ScrollSnapAlignKeyword::None,
}
}
}
impl Parse for ScrollSnapAlign {
/// [ none | start | end | center ]{1,2}
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<ScrollSnapAlign, ParseError<'i>> {
let block = ScrollSnapAlignKeyword::parse(input)?;
let inline = input.try(ScrollSnapAlignKeyword::parse).unwrap_or(block);
Ok(ScrollSnapAlign { block, inline })
}
}
impl ToCss for ScrollSnapAlign {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
self.block.to_css(dest)?;
if self.block != self.inline {
dest.write_str(" ")?;
self.inline.to_css(dest)?;
}
Ok(())
}
}
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(
@ -782,20 +852,6 @@ impl Parse for Contain {
/// A specified value for the `perspective` property.
pub type Perspective = GenericPerspective<NonNegativeLength>;
impl Parse for Perspective {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
return Ok(GenericPerspective::None);
}
Ok(GenericPerspective::Length(NonNegativeLength::parse(
context, input,
)?))
}
}
/// A given transition property, that is either `All`, a longhand or shorthand
/// property, or an unsupported or custom property.
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue)]

View file

@ -11,7 +11,7 @@ use crate::parser::{Parse, ParserContext};
#[cfg(feature = "gecko")]
use crate::properties::longhands::system_colors::SystemColor;
use crate::values::computed::{Color as ComputedColor, Context, ToComputedValue};
use crate::values::generics::color::Color as GenericColor;
use crate::values::generics::color::{Color as GenericColor, ColorOrAuto as GenericColorOrAuto};
use crate::values::specified::calc::CalcNode;
use cssparser::{AngleOrNumber, Color as CSSParserColor, Parser, Token, RGBA};
use cssparser::{BasicParseErrorKind, NumberOrPercentage, ParseErrorKind};
@ -469,3 +469,6 @@ impl Parse for ColorPropertyValue {
Color::parse_quirky(context, input, AllowQuirks::Yes).map(ColorPropertyValue)
}
}
/// auto | <color>
pub type ColorOrAuto = GenericColorOrAuto<Color>;

View file

@ -4,25 +4,8 @@
//! Specified types for the column properties.
use crate::parser::{Parse, ParserContext};
use crate::values::generics::column::ColumnCount as GenericColumnCount;
use crate::values::specified::PositiveInteger;
use cssparser::Parser;
use style_traits::ParseError;
/// A specified type for `column-count` values.
pub type ColumnCount = GenericColumnCount<PositiveInteger>;
impl Parse for ColumnCount {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
return Ok(GenericColumnCount::Auto);
}
Ok(GenericColumnCount::Integer(PositiveInteger::parse(
context, input,
)?))
}
}

View file

@ -4,39 +4,22 @@
//! Specified types for CSS values related to flexbox.
use crate::parser::{Parse, ParserContext};
use crate::values::generics::flex::FlexBasis as GenericFlexBasis;
use crate::values::specified::Size;
use cssparser::Parser;
use style_traits::ParseError;
/// A specified value for the `flex-basis` property.
pub type FlexBasis = GenericFlexBasis<Size>;
impl Parse for FlexBasis {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if let Ok(width) = input.try(|i| Size::parse(context, i)) {
return Ok(GenericFlexBasis::Width(width));
}
try_match_ident_ignore_ascii_case! { input,
"content" => Ok(GenericFlexBasis::Content),
}
}
}
impl FlexBasis {
/// `auto`
#[inline]
pub fn auto() -> Self {
GenericFlexBasis::Width(Size::auto())
GenericFlexBasis::Size(Size::auto())
}
/// `0%`
#[inline]
pub fn zero_percent() -> Self {
GenericFlexBasis::Width(Size::zero_percent())
GenericFlexBasis::Size(Size::zero_percent())
}
}

View file

@ -17,7 +17,7 @@ use crate::values::generics::font::{KeywordSize, VariationValue};
use crate::values::generics::NonNegative;
use crate::values::specified::length::{FontBaseSize, AU_PER_PT, AU_PER_PX};
use crate::values::specified::{AllowQuirks, Angle, Integer, LengthPercentage};
use crate::values::specified::{NoCalcLength, Number, Percentage};
use crate::values::specified::{NoCalcLength, NonNegativeNumber, Number, Percentage};
use crate::values::CustomIdent;
use crate::Atom;
use app_units::Au;
@ -81,7 +81,7 @@ pub const MAX_FONT_WEIGHT: f32 = 1000.;
/// A specified font-weight value.
///
/// https://drafts.csswg.org/css-fonts-4/#propdef-font-weight
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum FontWeight {
/// `<font-weight-absolute>`
Absolute(AbsoluteFontWeight),
@ -111,22 +111,6 @@ impl FontWeight {
}
}
impl Parse for FontWeight {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<FontWeight, ParseError<'i>> {
if let Ok(absolute) = input.try(|input| AbsoluteFontWeight::parse(context, input)) {
return Ok(FontWeight::Absolute(absolute));
}
Ok(try_match_ident_ignore_ascii_case! { input,
"bolder" => FontWeight::Bolder,
"lighter" => FontWeight::Lighter,
})
}
}
impl ToComputedValue for FontWeight {
type ComputedValue = computed::FontWeight;
@ -335,7 +319,7 @@ impl SpecifiedFontStyle {
}
/// The specified value of the `font-style` property.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)]
#[allow(missing_docs)]
pub enum FontStyle {
Specified(SpecifiedFontStyle),
@ -368,20 +352,11 @@ impl ToComputedValue for FontStyle {
}
}
impl Parse for FontStyle {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Ok(FontStyle::Specified(SpecifiedFontStyle::parse(
context, input,
)?))
}
}
/// A value for the `font-stretch` property.
///
/// https://drafts.csswg.org/css-fonts-4/#font-stretch-prop
///
/// TODO(emilio): We could derive Parse if we had NonNegativePercentage.
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
#[repr(u8)]
@ -628,13 +603,13 @@ impl Parse for FamilyName {
}
}
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)]
/// Preserve the readability of text when font fallback occurs
pub enum FontSizeAdjust {
/// None variant
None,
/// Number variant
Number(Number),
Number(NonNegativeNumber),
/// system font
#[css(skip)]
System(SystemFont),
@ -657,7 +632,9 @@ impl ToComputedValue for FontSizeAdjust {
match *self {
FontSizeAdjust::None => computed::FontSizeAdjust::None,
FontSizeAdjust::Number(ref n) => {
computed::FontSizeAdjust::Number(n.to_computed_value(context))
// The computed version handles clamping of animated values
// itself.
computed::FontSizeAdjust::Number(n.to_computed_value(context).0)
},
FontSizeAdjust::System(_) => self.compute_system(context),
}
@ -666,32 +643,13 @@ impl ToComputedValue for FontSizeAdjust {
fn from_computed_value(computed: &computed::FontSizeAdjust) -> Self {
match *computed {
computed::FontSizeAdjust::None => FontSizeAdjust::None,
computed::FontSizeAdjust::Number(ref v) => {
FontSizeAdjust::Number(Number::from_computed_value(v))
computed::FontSizeAdjust::Number(v) => {
FontSizeAdjust::Number(NonNegativeNumber::from_computed_value(&v.into()))
},
}
}
}
impl Parse for FontSizeAdjust {
/// none | <number>
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<FontSizeAdjust, ParseError<'i>> {
if input
.try(|input| input.expect_ident_matching("none"))
.is_ok()
{
return Ok(FontSizeAdjust::None);
}
Ok(FontSizeAdjust::Number(Number::parse_non_negative(
context, input,
)?))
}
}
/// Additional information for specified keyword-derived font sizes.
pub type KeywordInfo = generics::KeywordInfo<NonNegativeLength>;

View file

@ -305,7 +305,7 @@ impl Gradient {
) -> Result<Self, ParseError<'i>> {
type Point = GenericPosition<Component<X>, Component<Y>>;
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Parse)]
enum Component<S> {
Center,
Number(NumberOrPercentage),
@ -408,22 +408,6 @@ impl Gradient {
}
}
impl<S: Parse> Parse for Component<S> {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if let Ok(side) = input.try(|i| S::parse(context, i)) {
return Ok(Component::Side(side));
}
if let Ok(number) = input.try(|i| NumberOrPercentage::parse(context, i)) {
return Ok(Component::Number(number));
}
input.try(|i| i.expect_ident_matching("center"))?;
Ok(Component::Center)
}
}
let ident = input.expect_ident_cloned()?;
input.expect_comma()?;

View file

@ -11,10 +11,13 @@ use crate::font_metrics::FontMetricsQueryResult;
use crate::parser::{Parse, ParserContext};
use crate::values::computed::{self, CSSPixelLength, Context};
use crate::values::generics::length as generics;
use crate::values::generics::length::{MaxSize as GenericMaxSize, Size as GenericSize};
use crate::values::generics::length::{
GenericLengthOrNumber, MaxSize as GenericMaxSize, Size as GenericSize,
};
use crate::values::generics::transform::IsZeroLength;
use crate::values::generics::NonNegative;
use crate::values::specified::calc::CalcNode;
use crate::values::specified::NonNegativeNumber;
use crate::values::{Auto, CSSFloat, Either, Normal};
use app_units::Au;
use cssparser::{Parser, Token};
@ -1023,30 +1026,7 @@ pub type LengthOrNormal = Either<Length, Normal>;
pub type LengthOrAuto = Either<Length, Auto>;
/// Either a `<length>` or a `<number>`.
pub type LengthOrNumber = Either<Length, Number>;
impl LengthOrNumber {
/// Parse a non-negative LengthOrNumber.
pub fn parse_non_negative<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
// We try to parse as a Number first because, for cases like
// LengthOrNumber, we want "0" to be parsed as a plain Number rather
// than a Length (0px); this matches the behaviour of all major browsers
if let Ok(v) = input.try(|i| Number::parse_non_negative(context, i)) {
return Ok(Either::Second(v));
}
Length::parse_non_negative(context, input).map(Either::First)
}
/// Returns `0`.
#[inline]
pub fn zero() -> Self {
Either::Second(Number::new(0.))
}
}
pub type LengthOrNumber = GenericLengthOrNumber<Length, Number>;
/// A specified value for `min-width`, `min-height`, `width` or `height` property.
pub type Size = GenericSize<NonNegativeLengthPercentage>;
@ -1123,3 +1103,6 @@ impl MaxSize {
Ok(GenericMaxSize::LengthPercentage(length))
}
}
/// A specified non-negative `<length>` | `<number>`.
pub type NonNegativeLengthOrNumber = GenericLengthOrNumber<NonNegativeLength, NonNegativeNumber>;

View file

@ -19,9 +19,10 @@ use crate::values::serialize_atom_identifier;
use crate::values::specified::calc::CalcNode;
use crate::{Atom, Namespace, Prefix};
use cssparser::{Parser, Token};
use num_traits::One;
use num_traits::{One, Zero};
use std::f32;
use std::fmt::{self, Write};
use std::ops::Add;
use style_traits::values::specified::AllowedNumericType;
use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, StyleParseErrorKind, ToCss};
@ -39,8 +40,9 @@ pub use self::box_::{AnimationIterationCount, AnimationName, Contain, Display};
pub use self::box_::{Appearance, BreakBetween, BreakWithin};
pub use self::box_::{Clear, Float, Overflow, OverflowAnchor};
pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize};
pub use self::box_::{ScrollSnapType, TouchAction, TransitionProperty, VerticalAlign, WillChange};
pub use self::color::{Color, ColorPropertyValue, RGBAColor};
pub use self::box_::{ScrollSnapAlign, ScrollSnapType};
pub use self::box_::{TouchAction, TransitionProperty, VerticalAlign, WillChange};
pub use self::color::{Color, ColorOrAuto, ColorPropertyValue, RGBAColor};
pub use self::column::ColumnCount;
pub use self::counters::{Content, ContentItem, CounterIncrement, CounterReset};
pub use self::easing::TimingFunction;
@ -57,7 +59,7 @@ pub use self::gecko::ScrollSnapPoint;
pub use self::image::{ColorStop, EndingShape as GradientEndingShape, Gradient};
pub use self::image::{GradientItem, GradientKind, Image, ImageLayer, MozImageRect};
pub use self::length::{AbsoluteLength, CalcLengthPercentage, CharacterWidth};
pub use self::length::{FontRelativeLength, Length, LengthOrNumber};
pub use self::length::{FontRelativeLength, Length, LengthOrNumber, NonNegativeLengthOrNumber};
pub use self::length::{LengthPercentage, LengthPercentageOrAuto};
pub use self::length::{MaxSize, Size};
pub use self::length::{NoCalcLength, ViewportPercentageLength};
@ -70,14 +72,14 @@ pub use self::outline::OutlineStyle;
pub use self::percentage::Percentage;
pub use self::position::{GridAutoFlow, GridTemplateAreas, Position};
pub use self::position::{PositionComponent, ZIndex};
pub use self::rect::LengthOrNumberRect;
pub use self::rect::NonNegativeLengthOrNumberRect;
pub use self::resolution::Resolution;
pub use self::svg::MozContextProperties;
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind};
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
pub use self::svg_path::SVGPathData;
pub use self::table::XSpan;
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, MozTabSize, TextAlign};
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextAlign};
pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle};
pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing};
pub use self::time::Time;
@ -85,7 +87,7 @@ pub use self::transform::{Rotate, Scale, Transform};
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
#[cfg(feature = "gecko")]
pub use self::ui::CursorImage;
pub use self::ui::{ColorOrAuto, Cursor, MozForceBrokenImageIcon, UserSelect};
pub use self::ui::{Cursor, MozForceBrokenImageIcon, UserSelect};
pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent;
#[cfg(feature = "gecko")]
@ -270,6 +272,26 @@ impl IsParallelTo for (Number, Number, Number) {
impl SpecifiedValueInfo for Number {}
impl Add for Number {
type Output = Self;
fn add(self, other: Self) -> Self {
Self::new(self.get() + other.get())
}
}
impl Zero for Number {
#[inline]
fn zero() -> Self {
Self::new(0.)
}
#[inline]
fn is_zero(&self) -> bool {
self.get() == 0.
}
}
impl From<Number> for f32 {
#[inline]
fn from(n: Number) -> Self {
@ -563,7 +585,7 @@ impl Parse for PositiveInteger {
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Integer::parse_positive(context, input).map(GreaterThanOrEqualToOne::<Integer>)
Integer::parse_positive(context, input).map(GreaterThanOrEqualToOne)
}
}

View file

@ -731,15 +731,3 @@ impl GridTemplateAreas {
/// A specified value for the `z-index` property.
pub type ZIndex = GenericZIndex<Integer>;
impl Parse for ZIndex {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
return Ok(GenericZIndex::Auto);
}
Ok(GenericZIndex::Integer(Integer::parse(context, input)?))
}
}

View file

@ -4,22 +4,8 @@
//! Specified types for CSS borders.
use crate::parser::ParserContext;
use crate::values::generics::rect::Rect;
use crate::values::specified::length::LengthOrNumber;
use cssparser::Parser;
use style_traits::ParseError;
use crate::values::specified::length::NonNegativeLengthOrNumber;
/// A specified rectangle made of four `<length-or-number>` values.
pub type LengthOrNumberRect = Rect<LengthOrNumber>;
impl LengthOrNumberRect {
/// Parses a `LengthOrNumberRect`, rejecting negative values.
#[inline]
pub fn parse_non_negative<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Rect::parse_with(context, input, LengthOrNumber::parse_non_negative)
}
}
pub type NonNegativeLengthOrNumberRect = Rect<NonNegativeLengthOrNumber>;

View file

@ -23,31 +23,6 @@ pub type SVGPaint = generic::SVGPaint<Color, SpecifiedUrl>;
/// Specified SVG Paint Kind value
pub type SVGPaintKind = generic::SVGPaintKind<Color, SpecifiedUrl>;
#[cfg(feature = "gecko")]
fn is_context_value_enabled() -> bool {
// The prefs can only be mutated on the main thread, so it is safe
// to read whenever we are on the main thread or the main thread is
// blocked.
use crate::gecko_bindings::structs::mozilla;
unsafe { mozilla::StaticPrefs_sVarCache_gfx_font_rendering_opentype_svg_enabled }
}
#[cfg(not(feature = "gecko"))]
fn is_context_value_enabled() -> bool {
false
}
fn parse_context_value<'i, 't, T>(
input: &mut Parser<'i, 't>,
value: T,
) -> Result<T, ParseError<'i>> {
if !is_context_value_enabled() {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
input.expect_ident_matching("context-value")?;
Ok(value)
}
/// A value of <length> | <percentage> | <number> for stroke-dashoffset.
/// <https://www.w3.org/TR/SVG11/painting.html#StrokeProperties>
pub type SvgLengthPercentageOrNumber =
@ -56,18 +31,6 @@ pub type SvgLengthPercentageOrNumber =
/// <length> | <percentage> | <number> | context-value
pub type SVGLength = generic::SVGLength<SvgLengthPercentageOrNumber>;
impl Parse for SVGLength {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
input
.try(|i| SvgLengthPercentageOrNumber::parse(context, i))
.map(Into::into)
.or_else(|_| parse_context_value(input, generic::SVGLength::ContextValue))
}
}
impl From<SvgLengthPercentageOrNumber> for SVGLength {
fn from(length: SvgLengthPercentageOrNumber) -> Self {
generic::SVGLength::Length(length)
@ -82,18 +45,6 @@ pub type NonNegativeSvgLengthPercentageOrNumber =
/// A non-negative version of SVGLength.
pub type SVGWidth = generic::SVGLength<NonNegativeSvgLengthPercentageOrNumber>;
impl Parse for SVGWidth {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
input
.try(|i| NonNegativeSvgLengthPercentageOrNumber::parse(context, i))
.map(Into::into)
.or_else(|_| parse_context_value(input, generic::SVGLength::ContextValue))
}
}
impl From<NonNegativeSvgLengthPercentageOrNumber> for SVGWidth {
fn from(length: NonNegativeSvgLengthPercentageOrNumber) -> Self {
generic::SVGLength::Length(length)
@ -113,11 +64,14 @@ impl Parse for SVGStrokeDashArray {
NonNegativeSvgLengthPercentageOrNumber::parse(context, i)
})
}) {
Ok(generic::SVGStrokeDashArray::Values(values))
} else if let Ok(_) = input.try(|i| i.expect_ident_matching("none")) {
Ok(generic::SVGStrokeDashArray::Values(vec![]))
} else {
parse_context_value(input, generic::SVGStrokeDashArray::ContextValue)
return Ok(generic::SVGStrokeDashArray::Values(values));
}
try_match_ident_ignore_ascii_case! { input,
"context-value" if generic::is_context_value_enabled(context) => {
Ok(generic::SVGStrokeDashArray::ContextValue)
},
"none" => Ok(generic::SVGStrokeDashArray::Values(vec![])),
}
}
}
@ -125,22 +79,6 @@ impl Parse for SVGStrokeDashArray {
/// <opacity-value> | context-fill-opacity | context-stroke-opacity
pub type SVGOpacity = generic::SVGOpacity<Opacity>;
impl Parse for SVGOpacity {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if let Ok(opacity) = input.try(|i| Opacity::parse(context, i)) {
return Ok(generic::SVGOpacity::Opacity(opacity));
}
try_match_ident_ignore_ascii_case! { input,
"context-fill-opacity" => Ok(generic::SVGOpacity::ContextFillOpacity),
"context-stroke-opacity" => Ok(generic::SVGOpacity::ContextStrokeOpacity),
}
}
}
/// The specified value for a single CSS paint-order property.
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, ToCss)]

View file

@ -13,11 +13,10 @@ use crate::values::computed::text::TextOverflow as ComputedTextOverflow;
use crate::values::computed::{Context, ToComputedValue};
use crate::values::generics::text::InitialLetter as GenericInitialLetter;
use crate::values::generics::text::LineHeight as GenericLineHeight;
use crate::values::generics::text::MozTabSize as GenericMozTabSize;
use crate::values::generics::text::Spacing;
use crate::values::specified::length::NonNegativeLengthPercentage;
use crate::values::specified::length::{FontRelativeLength, Length};
use crate::values::specified::length::{LengthPercentage, NoCalcLength};
use crate::values::specified::length::{NonNegativeLength, NonNegativeLengthPercentage};
use crate::values::specified::{AllowQuirks, Integer, NonNegativeNumber, Number};
use cssparser::{Parser, Token};
use selectors::parser::SelectorParseErrorKind;
@ -420,7 +419,7 @@ pub enum TextAlignKeyword {
/// Specified value of text-align property.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, SpecifiedValueInfo, ToCss)]
#[derive(Clone, Copy, Debug, Eq, Hash, Parse, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum TextAlign {
/// Keyword value of text-align property.
Keyword(TextAlignKeyword),
@ -436,27 +435,6 @@ pub enum TextAlign {
MozCenterOrInherit,
}
impl Parse for TextAlign {
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
// MozCenterOrInherit cannot be parsed, only set directly on the elements
if let Ok(key) = input.try(TextAlignKeyword::parse) {
return Ok(TextAlign::Keyword(key));
}
#[cfg(feature = "gecko")]
{
input.expect_ident_matching("match-parent")?;
return Ok(TextAlign::MatchParent);
}
#[cfg(feature = "servo")]
{
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
}
}
impl TextAlign {
/// Convert an enumerated value coming from Gecko to a `TextAlign`.
#[cfg(feature = "gecko")]
@ -835,25 +813,6 @@ impl From<TextEmphasisPosition> for u8 {
}
}
/// A specified value for the `-moz-tab-size` property.
pub type MozTabSize = GenericMozTabSize<NonNegativeNumber, NonNegativeLength>;
impl Parse for MozTabSize {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if let Ok(number) = input.try(|i| NonNegativeNumber::parse(context, i)) {
// Numbers need to be parsed first because `0` must be recognised
// as the number `0` and not the length `0px`.
return Ok(GenericMozTabSize::Number(number));
}
Ok(GenericMozTabSize::Length(NonNegativeLength::parse(
context, input,
)?))
}
}
/// Values for the `overflow-wrap` property.
#[repr(u8)]
#[derive(

View file

@ -231,7 +231,7 @@ impl Parse for Transform {
}
/// The specified value of a component of a CSS `<transform-origin>`.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum OriginComponent<S> {
/// `center`
Center,
@ -295,25 +295,6 @@ impl Parse for TransformOrigin {
}
}
impl<S> Parse for OriginComponent<S>
where
S: Parse,
{
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("center")).is_ok() {
return Ok(OriginComponent::Center);
}
if let Ok(lp) = input.try(|i| LengthPercentage::parse(context, i)) {
return Ok(OriginComponent::Length(lp));
}
let keyword = S::parse(context, input)?;
Ok(OriginComponent::Side(keyword))
}
}
impl<S> ToComputedValue for OriginComponent<S>
where
S: Side,

View file

@ -9,14 +9,10 @@ use crate::values::generics::ui as generics;
use crate::values::specified::color::Color;
use crate::values::specified::url::SpecifiedImageUrl;
use crate::values::specified::Number;
use crate::values::{Auto, Either};
use cssparser::Parser;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
/// auto | <color>
pub type ColorOrAuto = Either<Color, Auto>;
/// A specified value for the `cursor` property.
pub type Cursor = generics::Cursor<CursorImage>;

View file

@ -5,8 +5,8 @@
use crate::cg;
use crate::to_css::CssVariantAttrs;
use proc_macro2::TokenStream;
use syn::{DeriveInput, Path};
use synstructure;
use syn::{self, DeriveInput, Path};
use synstructure::{Structure, VariantInfo};
#[darling(attributes(parse), default)]
#[derive(Default, FromVariant)]
@ -15,22 +15,90 @@ pub struct ParseVariantAttrs {
pub condition: Option<Path>,
}
pub fn derive(input: DeriveInput) -> TokenStream {
fn parse_non_keyword_variant(
name: &syn::Ident,
variant: &VariantInfo,
variant_attrs: &CssVariantAttrs,
parse_attrs: &ParseVariantAttrs,
skip_try: bool,
) -> TokenStream {
let bindings = variant.bindings();
assert!(parse_attrs.aliases.is_none());
assert!(variant_attrs.function.is_none());
assert!(variant_attrs.keyword.is_none());
assert_eq!(
bindings.len(),
1,
"We only support deriving parse for simple variants"
);
let variant_name = &variant.ast().ident;
let ty = &bindings[0].ast().ty;
let mut parse = if skip_try {
quote! {
let v = <#ty as crate::parser::Parse>::parse(context, input)?;
return Ok(#name::#variant_name(v));
}
} else {
quote! {
if let Ok(v) = input.try(|i| <#ty as crate::parser::Parse>::parse(context, i)) {
return Ok(#name::#variant_name(v));
}
}
};
if let Some(ref condition) = parse_attrs.condition {
parse = quote! {
if #condition(context) {
#parse
}
};
if skip_try {
// We're the last variant and we can fail to parse due to the
// condition clause. If that happens, we need to return an error.
parse = quote! {
#parse
Err(input.new_custom_error(style_traits::StyleParseErrorKind::UnspecifiedError))
};
}
}
parse
}
pub fn derive(mut input: DeriveInput) -> TokenStream {
{
let mut where_clause = input.generics.where_clause.take();
for param in input.generics.type_params() {
cg::add_predicate(
&mut where_clause,
parse_quote!(#param: crate::parser::Parse),
);
}
input.generics.where_clause = where_clause;
}
let name = &input.ident;
let s = synstructure::Structure::new(&input);
let s = Structure::new(&input);
let mut saw_condition = false;
let match_body = s.variants().iter().fold(quote!(), |match_body, variant| {
let bindings = variant.bindings();
assert!(
bindings.is_empty(),
"Parse is only supported for single-variant enums for now"
);
let mut match_keywords = quote! {};
let mut non_keywords = vec![];
let mut effective_variants = 0;
for variant in s.variants().iter() {
let css_variant_attrs = cg::parse_variant_attrs_from_ast::<CssVariantAttrs>(&variant.ast());
let parse_attrs = cg::parse_variant_attrs_from_ast::<ParseVariantAttrs>(&variant.ast());
if css_variant_attrs.skip {
return match_body;
continue;
}
effective_variants += 1;
saw_condition |= parse_attrs.condition.is_some();
if !variant.bindings().is_empty() {
non_keywords.push((variant, css_variant_attrs, parse_attrs));
continue;
}
let identifier = cg::to_css_identifier(
@ -40,55 +108,73 @@ pub fn derive(input: DeriveInput) -> TokenStream {
);
let ident = &variant.ast().ident;
saw_condition |= parse_attrs.condition.is_some();
let condition = match parse_attrs.condition {
Some(ref p) => quote! { if #p(context) },
None => quote! {},
};
let mut body = quote! {
#match_body
match_keywords.extend(quote! {
#identifier #condition => Ok(#name::#ident),
};
});
let aliases = match parse_attrs.aliases {
Some(aliases) => aliases,
None => return body,
None => continue,
};
for alias in aliases.split(',') {
body = quote! {
#body
match_keywords.extend(quote! {
#alias #condition => Ok(#name::#ident),
};
});
}
}
body
});
let needs_context = saw_condition || !non_keywords.is_empty();
let context_ident = if saw_condition {
let context_ident = if needs_context {
quote! { context }
} else {
quote! { _ }
};
let parse_body = if saw_condition {
quote! {
let location = input.current_source_location();
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
#match_body
_ => Err(location.new_unexpected_token_error(
cssparser::Token::Ident(ident.clone())
))
let has_keywords = non_keywords.len() != effective_variants;
let mut parse_non_keywords = quote! {};
for (i, (variant, css_attrs, parse_attrs)) in non_keywords.iter().enumerate() {
let skip_try = !has_keywords && i == non_keywords.len() - 1;
let parse_variant =
parse_non_keyword_variant(name, variant, css_attrs, parse_attrs, skip_try);
parse_non_keywords.extend(parse_variant);
}
let parse_body = if needs_context {
let parse_keywords = if has_keywords {
quote! {
let location = input.current_source_location();
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
#match_keywords
_ => Err(location.new_unexpected_token_error(
cssparser::Token::Ident(ident.clone())
))
}
}
} else {
quote! {}
};
quote! {
#parse_non_keywords
#parse_keywords
}
} else {
quote! { Self::parse(input) }
};
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let parse_trait_impl = quote! {
impl crate::parser::Parse for #name {
impl #impl_generics crate::parser::Parse for #name #ty_generics #where_clause {
#[inline]
fn parse<'i, 't>(
#context_ident: &crate::parser::ParserContext,
@ -99,10 +185,12 @@ pub fn derive(input: DeriveInput) -> TokenStream {
}
};
if saw_condition {
if needs_context {
return parse_trait_impl;
}
assert!(non_keywords.is_empty());
// TODO(emilio): It'd be nice to get rid of these, but that makes the
// conversion harder...
let methods_impl = quote! {
@ -125,7 +213,7 @@ pub fn derive(input: DeriveInput) -> TokenStream {
#[inline]
pub fn from_ident(ident: &str) -> Result<Self, ()> {
match_ignore_ascii_case! { ident,
#match_body
#match_keywords
_ => Err(()),
}
}