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

style: Sync changes from mozilla-central.

See each individual commit for details.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23727)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2019-07-08 11:29:33 -04:00 committed by GitHub
commit 3e88f63693
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
52 changed files with 654 additions and 1396 deletions

View file

@ -182,7 +182,7 @@ impl<T> Arc<T> {
// FIXME(emilio): Would be so amazing to have
// std::intrinsics::type_name() around, so that we could also report
// a real size.
NS_LogCtor(ptr as *const _, b"ServoArc\0".as_ptr() as *const _, 8);
NS_LogCtor(ptr as *mut _, b"ServoArc\0".as_ptr() as *const _, 8);
}
unsafe {
@ -314,11 +314,7 @@ impl<T: ?Sized> Arc<T> {
fn record_drop(&self) {
#[cfg(feature = "gecko_refcount_logging")]
unsafe {
NS_LogDtor(
self.ptr() as *const _,
b"ServoArc\0".as_ptr() as *const _,
8,
);
NS_LogDtor(self.ptr() as *mut _, b"ServoArc\0".as_ptr() as *const _, 8);
}
}
@ -355,12 +351,12 @@ impl<T: ?Sized> Arc<T> {
#[cfg(feature = "gecko_refcount_logging")]
extern "C" {
fn NS_LogCtor(
aPtr: *const std::os::raw::c_void,
aPtr: *mut std::os::raw::c_void,
aTypeName: *const std::os::raw::c_char,
aSize: u32,
);
fn NS_LogDtor(
aPtr: *const std::os::raw::c_void,
aPtr: *mut std::os::raw::c_void,
aTypeName: *const std::os::raw::c_char,
aSize: u32,
);
@ -762,7 +758,7 @@ impl<H, T> Arc<HeaderSlice<H, [T]>> {
if !is_static {
// FIXME(emilio): Would be so amazing to have
// std::intrinsics::type_name() around.
NS_LogCtor(ptr as *const _, b"ServoArc\0".as_ptr() as *const _, 8)
NS_LogCtor(ptr as *mut _, b"ServoArc\0".as_ptr() as *const _, 8)
}
}

View file

@ -416,13 +416,13 @@ macro_rules! is_descriptor_enabled {
("font-display") => {
unsafe {
use crate::gecko_bindings::structs::mozilla;
mozilla::StaticPrefs_sVarCache_layout_css_font_display_enabled
mozilla::StaticPrefs::sVarCache_layout_css_font_display_enabled
}
};
("font-variation-settings") => {
unsafe {
use crate::gecko_bindings::structs::mozilla;
mozilla::StaticPrefs_sVarCache_layout_css_font_variations_enabled != 0
mozilla::StaticPrefs::sVarCache_layout_css_font_variations_enabled != 0
}
};
($name:tt) => {

View file

@ -10,57 +10,15 @@
#![allow(unsafe_code)]
use crate::gecko::values::GeckoStyleCoordConvertible;
use crate::gecko_bindings::bindings;
use crate::gecko_bindings::structs::{self, nsStyleCoord_CalcValue, Matrix4x4Components};
use crate::gecko_bindings::structs::{self, Matrix4x4Components};
use crate::gecko_bindings::structs::{nsStyleImage, nsresult};
use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
use crate::stylesheets::RulesMutateError;
use crate::values::computed::transform::Matrix3D;
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::generics::grid::{TrackListValue, TrackSize};
use crate::values::computed::{Gradient, Image, TextAlign};
use crate::values::generics::image::GenericImage;
use crate::values::generics::rect::Rect;
use crate::Zero;
use app_units::Au;
use style_traits::values::specified::AllowedNumericType;
impl From<LengthPercentage> for nsStyleCoord_CalcValue {
fn from(other: LengthPercentage) -> nsStyleCoord_CalcValue {
debug_assert!(
other.was_calc || !other.has_percentage || other.unclamped_length() == Length::zero()
);
nsStyleCoord_CalcValue {
mLength: other.unclamped_length().to_i32_au(),
mPercent: other.percentage(),
mHasPercent: other.has_percentage,
}
}
}
impl From<nsStyleCoord_CalcValue> for LengthPercentage {
fn from(other: nsStyleCoord_CalcValue) -> LengthPercentage {
let percentage = if other.mHasPercent {
Some(Percentage(other.mPercent))
} else {
None
};
Self::with_clamping_mode(
Au(other.mLength).into(),
percentage,
AllowedNumericType::All,
/* was_calc = */ true,
)
}
}
impl From<Angle> for CoordDataValue {
fn from(reference: Angle) -> Self {
CoordDataValue::Degree(reference.degrees())
}
}
impl nsStyleImage {
/// Set a given Servo `Image` value into this `nsStyleImage`.
@ -77,18 +35,12 @@ impl nsStyleImage {
// Set CropRect
let ref mut rect = *self.mCropRect.mPtr;
image_rect
.top
.to_gecko_style_coord(&mut rect.data_at_mut(0));
image_rect
.right
.to_gecko_style_coord(&mut rect.data_at_mut(1));
image_rect
.bottom
.to_gecko_style_coord(&mut rect.data_at_mut(2));
image_rect
.left
.to_gecko_style_coord(&mut rect.data_at_mut(3));
*rect = Rect(
image_rect.top,
image_rect.right,
image_rect.bottom,
image_rect.left,
);
}
},
GenericImage::Element(ref element) => unsafe {
@ -106,7 +58,7 @@ impl nsStyleImage {
/// Converts into Image.
pub unsafe fn into_image(self: &nsStyleImage) -> Option<Image> {
use crate::gecko_bindings::structs::nsStyleImageType;
use crate::values::computed::{MozImageRect, NumberOrPercentage};
use crate::values::computed::MozImageRect;
match self.mType {
nsStyleImageType::eStyleImageType_Null => None,
@ -115,30 +67,14 @@ impl nsStyleImage {
if self.mCropRect.mPtr.is_null() {
Some(GenericImage::Url(url))
} else {
let ref rect = *self.mCropRect.mPtr;
match (
NumberOrPercentage::from_gecko_style_coord(&rect.data_at(0)),
NumberOrPercentage::from_gecko_style_coord(&rect.data_at(1)),
NumberOrPercentage::from_gecko_style_coord(&rect.data_at(2)),
NumberOrPercentage::from_gecko_style_coord(&rect.data_at(3)),
) {
(Some(top), Some(right), Some(bottom), Some(left)) => {
let rect = &*self.mCropRect.mPtr;
Some(GenericImage::Rect(Box::new(MozImageRect {
url,
top,
right,
bottom,
left,
top: rect.0,
right: rect.1,
bottom: rect.2,
left: rect.3,
})))
},
_ => {
debug_assert!(
false,
"mCropRect could not convert to NumberOrPercentage"
);
None
},
}
}
},
nsStyleImageType::eStyleImageType_Gradient => {
@ -331,98 +267,6 @@ impl From<RulesMutateError> for nsresult {
}
}
impl TrackSize<LengthPercentage> {
/// Return TrackSize from given two nsStyleCoord
pub fn from_gecko_style_coords<T: CoordData>(gecko_min: &T, gecko_max: &T) -> Self {
use crate::gecko_bindings::structs::root::nsStyleUnit;
use crate::values::generics::grid::TrackBreadth;
if gecko_min.unit() == nsStyleUnit::eStyleUnit_None {
debug_assert!(
gecko_max.unit() == nsStyleUnit::eStyleUnit_Coord ||
gecko_max.unit() == nsStyleUnit::eStyleUnit_Percent ||
gecko_max.unit() == nsStyleUnit::eStyleUnit_Calc
);
return TrackSize::FitContent(
LengthPercentage::from_gecko_style_coord(gecko_max)
.expect("gecko_max could not convert to LengthPercentage"),
);
}
let min = TrackBreadth::from_gecko_style_coord(gecko_min)
.expect("gecko_min could not convert to TrackBreadth");
let max = TrackBreadth::from_gecko_style_coord(gecko_max)
.expect("gecko_max could not convert to TrackBreadth");
if min == max {
TrackSize::Breadth(max)
} else {
TrackSize::Minmax(min, max)
}
}
/// Save TrackSize to given gecko fields.
pub fn to_gecko_style_coords<T: CoordDataMut>(&self, gecko_min: &mut T, gecko_max: &mut T) {
match *self {
TrackSize::FitContent(ref lop) => {
// Gecko sets min value to None and max value to the actual value in fit-content
// https://searchfox.org/mozilla-central/rev/c05d9d61188d32b8/layout/style/nsRuleNode.cpp#7910
gecko_min.set_value(CoordDataValue::None);
lop.to_gecko_style_coord(gecko_max);
},
TrackSize::Breadth(ref breadth) => {
// Set the value to both fields if there's one breadth value
// https://searchfox.org/mozilla-central/rev/c05d9d61188d32b8/layout/style/nsRuleNode.cpp#7919
breadth.to_gecko_style_coord(gecko_min);
breadth.to_gecko_style_coord(gecko_max);
},
TrackSize::Minmax(ref min, ref max) => {
min.to_gecko_style_coord(gecko_min);
max.to_gecko_style_coord(gecko_max);
},
}
}
}
impl TrackListValue<LengthPercentage, Integer> {
/// Return TrackSize from given two nsStyleCoord
pub fn from_gecko_style_coords<T: CoordData>(gecko_min: &T, gecko_max: &T) -> Self {
TrackListValue::TrackSize(TrackSize::from_gecko_style_coords(gecko_min, gecko_max))
}
/// Save TrackSize to given gecko fields.
pub fn to_gecko_style_coords<T: CoordDataMut>(&self, gecko_min: &mut T, gecko_max: &mut T) {
match *self {
TrackListValue::TrackSize(ref size) => size.to_gecko_style_coords(gecko_min, gecko_max),
_ => unreachable!("Should only transform from track-size computed values"),
}
}
}
impl<T> Rect<T>
where
T: GeckoStyleCoordConvertible,
{
/// Convert this generic Rect to given Gecko fields.
pub fn to_gecko_rect(&self, sides: &mut crate::gecko_bindings::structs::nsStyleSides) {
self.0.to_gecko_style_coord(&mut sides.data_at_mut(0));
self.1.to_gecko_style_coord(&mut sides.data_at_mut(1));
self.2.to_gecko_style_coord(&mut sides.data_at_mut(2));
self.3.to_gecko_style_coord(&mut sides.data_at_mut(3));
}
/// Convert from given Gecko data to generic Rect.
pub fn from_gecko_rect(
sides: &crate::gecko_bindings::structs::nsStyleSides,
) -> Option<crate::values::generics::rect::Rect<T>> {
Some(Rect::new(
T::from_gecko_style_coord(&sides.data_at(0)).expect("coord[0] cound not convert"),
T::from_gecko_style_coord(&sides.data_at(1)).expect("coord[1] cound not convert"),
T::from_gecko_style_coord(&sides.data_at(2)).expect("coord[2] cound not convert"),
T::from_gecko_style_coord(&sides.data_at(3)).expect("coord[3] cound not convert"),
))
}
}
impl TextAlign {
/// Obtain a specified value from a Gecko keyword value
///

View file

@ -271,7 +271,7 @@ impl Device {
return true;
}
let document_color_use =
unsafe { structs::StaticPrefs_sVarCache_browser_display_document_color_use };
unsafe { structs::StaticPrefs::sVarCache_browser_display_document_color_use };
let prefs = self.pref_sheet_prefs();
match document_color_use {
1 => true,

View file

@ -182,12 +182,18 @@ impl PseudoElement {
/// Property flag that properties must have to apply to this pseudo-element.
#[inline]
pub fn property_restriction(&self) -> Option<PropertyFlags> {
match *self {
PseudoElement::FirstLetter => Some(PropertyFlags::APPLIES_TO_FIRST_LETTER),
PseudoElement::FirstLine => Some(PropertyFlags::APPLIES_TO_FIRST_LINE),
PseudoElement::Placeholder => Some(PropertyFlags::APPLIES_TO_PLACEHOLDER),
_ => None,
}
Some(match *self {
PseudoElement::FirstLetter => PropertyFlags::APPLIES_TO_FIRST_LETTER,
PseudoElement::FirstLine => PropertyFlags::APPLIES_TO_FIRST_LINE,
PseudoElement::Placeholder => PropertyFlags::APPLIES_TO_PLACEHOLDER,
PseudoElement::Cue => PropertyFlags::APPLIES_TO_CUE,
PseudoElement::Marker
if unsafe { structs::StaticPrefs::sVarCache_layout_css_marker_restricted } =>
{
PropertyFlags::APPLIES_TO_MARKER
},
_ => return None,
})
}
/// Whether this pseudo-element should actually exist if it has

View file

@ -112,7 +112,7 @@ impl PseudoElement {
% for pseudo in PSEUDOS:
${pseudo_element_variant(pseudo)} =>
% if pseudo.is_tree_pseudo_element():
if unsafe { structs::StaticPrefs_sVarCache_layout_css_xul_tree_pseudos_content_enabled } {
if unsafe { structs::StaticPrefs::sVarCache_layout_css_xul_tree_pseudos_content_enabled } {
0
} else {
structs::CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS_AND_CHROME
@ -210,7 +210,7 @@ impl PseudoElement {
return PseudoElement::tree_pseudo_element(name, Box::new([]))
}
if unsafe {
structs::StaticPrefs_sVarCache_layout_css_unknown_webkit_pseudo_element
structs::StaticPrefs::sVarCache_layout_css_unknown_webkit_pseudo_element
} {
const WEBKIT_PREFIX: &str = "-webkit-";
if starts_with_ignore_ascii_case(name, WEBKIT_PREFIX) {

View file

@ -175,7 +175,7 @@ impl NonTSPseudoClass {
// For pseudo-classes with pref, the availability in content
// depends on the pref.
NonTSPseudoClass::Fullscreen => unsafe {
mozilla::StaticPrefs_sVarCache_full_screen_api_unprefix_enabled
mozilla::StaticPrefs::sVarCache_full_screen_api_unprefix_enabled
},
// Otherwise, a pseudo-class is enabled in content when it
// doesn't have any enabled flag.
@ -355,7 +355,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
#[inline]
fn parse_part(&self) -> bool {
self.chrome_rules_enabled() ||
unsafe { structs::StaticPrefs_sVarCache_layout_css_shadow_parts_enabled }
unsafe { structs::StaticPrefs::sVarCache_layout_css_shadow_parts_enabled }
}
fn parse_non_ts_pseudo_class(

View file

@ -7,215 +7,15 @@
//! Different kind of helpers to interact with Gecko values.
use crate::counter_style::{Symbol, Symbols};
use crate::gecko_bindings::structs::StyleGridTrackBreadth;
use crate::gecko_bindings::structs::{nsStyleCoord, CounterStylePtr};
use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
use crate::values::computed::{Angle, Length, LengthPercentage};
use crate::values::computed::{Number, NumberOrPercentage, Percentage};
use crate::values::generics::grid::{TrackBreadth, TrackKeyword};
use crate::values::generics::length::LengthPercentageOrAuto;
use crate::values::generics::{CounterStyleOrNone, NonNegative};
use crate::gecko_bindings::structs::CounterStylePtr;
use crate::values::generics::CounterStyleOrNone;
use crate::values::Either;
use crate::{Atom, Zero};
use crate::Atom;
use app_units::Au;
use cssparser::RGBA;
use nsstring::{nsACString, nsCStr};
use std::cmp::max;
/// A trait that defines an interface to convert from and to `nsStyleCoord`s.
///
/// TODO(emilio): Almost everything that is in this file should be somehow
/// switched to cbindgen.
pub trait GeckoStyleCoordConvertible: Sized {
/// Convert this to a `nsStyleCoord`.
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T);
/// Given a `nsStyleCoord`, try to get a value of this type..
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self>;
}
impl nsStyleCoord {
#[inline]
/// Set this `nsStyleCoord` value to `val`.
pub fn set<T: GeckoStyleCoordConvertible>(&mut self, val: T) {
val.to_gecko_style_coord(self);
}
}
impl<Inner> GeckoStyleCoordConvertible for NonNegative<Inner>
where
Inner: GeckoStyleCoordConvertible,
{
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
self.0.to_gecko_style_coord(coord)
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
Some(NonNegative(Inner::from_gecko_style_coord(coord)?))
}
}
impl GeckoStyleCoordConvertible for Number {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
coord.set_value(CoordDataValue::Factor(*self));
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
match coord.as_value() {
CoordDataValue::Factor(f) => Some(f),
_ => None,
}
}
}
impl GeckoStyleCoordConvertible for Percentage {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
coord.set_value(CoordDataValue::Percent(self.0));
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
match coord.as_value() {
CoordDataValue::Percent(p) => Some(Percentage(p)),
_ => None,
}
}
}
impl GeckoStyleCoordConvertible for NumberOrPercentage {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
NumberOrPercentage::Number(ref n) => n.to_gecko_style_coord(coord),
NumberOrPercentage::Percentage(ref p) => p.to_gecko_style_coord(coord),
}
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
match coord.as_value() {
CoordDataValue::Factor(f) => Some(NumberOrPercentage::Number(f)),
CoordDataValue::Percent(p) => Some(NumberOrPercentage::Percentage(Percentage(p))),
_ => None,
}
}
}
impl GeckoStyleCoordConvertible for LengthPercentage {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
if self.was_calc {
return coord.set_value(CoordDataValue::Calc((*self).into()));
}
debug_assert!(!self.has_percentage || self.unclamped_length() == Length::zero());
if self.has_percentage {
return coord.set_value(CoordDataValue::Percent(self.percentage()));
}
coord.set_value(CoordDataValue::Coord(self.unclamped_length().to_i32_au()))
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
match coord.as_value() {
CoordDataValue::Coord(coord) => Some(LengthPercentage::new(Au(coord).into(), None)),
CoordDataValue::Percent(p) => {
Some(LengthPercentage::new(Au(0).into(), Some(Percentage(p))))
},
CoordDataValue::Calc(calc) => Some(calc.into()),
_ => None,
}
}
}
impl GeckoStyleCoordConvertible for Length {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
coord.set_value(CoordDataValue::Coord(self.to_i32_au()));
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
match coord.as_value() {
CoordDataValue::Coord(coord) => Some(Au(coord).into()),
_ => None,
}
}
}
impl<LengthPercentage> GeckoStyleCoordConvertible for LengthPercentageOrAuto<LengthPercentage>
where
LengthPercentage: GeckoStyleCoordConvertible,
{
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
LengthPercentageOrAuto::Auto => coord.set_value(CoordDataValue::Auto),
LengthPercentageOrAuto::LengthPercentage(ref lp) => lp.to_gecko_style_coord(coord),
}
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
match coord.as_value() {
CoordDataValue::Auto => Some(LengthPercentageOrAuto::Auto),
_ => LengthPercentage::from_gecko_style_coord(coord)
.map(LengthPercentageOrAuto::LengthPercentage),
}
}
}
impl<L: GeckoStyleCoordConvertible> GeckoStyleCoordConvertible for TrackBreadth<L> {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
TrackBreadth::Breadth(ref lp) => lp.to_gecko_style_coord(coord),
TrackBreadth::Fr(fr) => coord.set_value(CoordDataValue::FlexFraction(fr)),
TrackBreadth::Keyword(TrackKeyword::Auto) => coord.set_value(CoordDataValue::Auto),
TrackBreadth::Keyword(TrackKeyword::MinContent) => coord.set_value(
CoordDataValue::Enumerated(StyleGridTrackBreadth::MinContent as u32),
),
TrackBreadth::Keyword(TrackKeyword::MaxContent) => coord.set_value(
CoordDataValue::Enumerated(StyleGridTrackBreadth::MaxContent as u32),
),
}
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
L::from_gecko_style_coord(coord)
.map(TrackBreadth::Breadth)
.or_else(|| match coord.as_value() {
CoordDataValue::Enumerated(v) => {
if v == StyleGridTrackBreadth::MinContent as u32 {
Some(TrackBreadth::Keyword(TrackKeyword::MinContent))
} else if v == StyleGridTrackBreadth::MaxContent as u32 {
Some(TrackBreadth::Keyword(TrackKeyword::MaxContent))
} else {
None
}
},
CoordDataValue::FlexFraction(fr) => Some(TrackBreadth::Fr(fr)),
CoordDataValue::Auto => Some(TrackBreadth::Keyword(TrackKeyword::Auto)),
_ => L::from_gecko_style_coord(coord).map(TrackBreadth::Breadth),
})
}
}
impl<T: GeckoStyleCoordConvertible> GeckoStyleCoordConvertible for Option<T> {
fn to_gecko_style_coord<U: CoordDataMut>(&self, coord: &mut U) {
if let Some(ref me) = *self {
me.to_gecko_style_coord(coord);
} else {
coord.set_value(CoordDataValue::None);
}
}
fn from_gecko_style_coord<U: CoordData>(coord: &U) -> Option<Self> {
Some(T::from_gecko_style_coord(coord))
}
}
impl GeckoStyleCoordConvertible for Angle {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
coord.set_value(CoordDataValue::from(*self));
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
match coord.as_value() {
CoordDataValue::Degree(val) => Some(Angle::from_degrees(val)),
_ => None,
}
}
}
/// Convert a given RGBA value to `nscolor`.
pub fn convert_rgba_to_nscolor(rgba: &RGBA) -> u32 {
((rgba.alpha as u32) << 24) |

View file

@ -7,7 +7,6 @@
mod ns_com_ptr;
mod ns_compatibility;
mod ns_style_auto_array;
pub mod ns_style_coord;
mod ns_t_array;
pub mod origin_flags;
pub mod ownership;

View file

@ -1,369 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
//! Rust helpers for Gecko's `nsStyleCoord`.
use crate::gecko_bindings::bindings;
use crate::gecko_bindings::structs::nsStyleSides;
use crate::gecko_bindings::structs::{nsStyleCoord, nsStyleCoord_Calc, nsStyleCoord_CalcValue};
use crate::gecko_bindings::structs::{nsStyleUnion, nsStyleUnit, nscoord};
use std::mem;
impl nsStyleCoord {
#[inline]
/// Get a `null` nsStyleCoord.
pub fn null() -> Self {
// Can't construct directly because it has private fields
let mut coord: Self = unsafe { mem::zeroed() };
coord.leaky_set_null();
coord
}
}
unsafe impl CoordData for nsStyleCoord {
#[inline]
fn unit(&self) -> nsStyleUnit {
unsafe { *self.get_mUnit() }
}
#[inline]
fn union(&self) -> nsStyleUnion {
unsafe { *self.get_mValue() }
}
}
unsafe impl CoordDataMut for nsStyleCoord {
unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion) {
let unit = self.get_mUnit_mut() as *mut _;
let value = self.get_mValue_mut() as *mut _;
(&mut *unit, &mut *value)
}
}
impl nsStyleCoord_CalcValue {
/// Create an "empty" CalcValue (whose value is `0`).
pub fn new() -> Self {
nsStyleCoord_CalcValue {
mLength: 0,
mPercent: 0.0,
mHasPercent: false,
}
}
}
impl PartialEq for nsStyleCoord_CalcValue {
fn eq(&self, other: &Self) -> bool {
self.mLength == other.mLength &&
self.mPercent == other.mPercent &&
self.mHasPercent == other.mHasPercent
}
}
impl nsStyleSides {
/// Immutably get the `nsStyleCoord`-like object representing the side at
/// index `index`.
#[inline]
pub fn data_at(&self, index: usize) -> SidesData {
SidesData {
sides: self,
index: index,
}
}
/// Mutably get the `nsStyleCoord`-like object representing the side at
/// index `index`.
#[inline]
pub fn data_at_mut(&mut self, index: usize) -> SidesDataMut {
SidesDataMut {
sides: self,
index: index,
}
}
}
/// A `nsStyleCoord`-like object on top of an immutable reference to
/// `nsStyleSides`.
pub struct SidesData<'a> {
sides: &'a nsStyleSides,
index: usize,
}
/// A `nsStyleCoord`-like object on top of an mutable reference to
/// `nsStyleSides`.
pub struct SidesDataMut<'a> {
sides: &'a mut nsStyleSides,
index: usize,
}
unsafe impl<'a> CoordData for SidesData<'a> {
#[inline]
fn unit(&self) -> nsStyleUnit {
unsafe { self.sides.get_mUnits()[self.index] }
}
#[inline]
fn union(&self) -> nsStyleUnion {
unsafe { self.sides.get_mValues()[self.index] }
}
}
unsafe impl<'a> CoordData for SidesDataMut<'a> {
#[inline]
fn unit(&self) -> nsStyleUnit {
unsafe { self.sides.get_mUnits()[self.index] }
}
#[inline]
fn union(&self) -> nsStyleUnion {
unsafe { self.sides.get_mValues()[self.index] }
}
}
unsafe impl<'a> CoordDataMut for SidesDataMut<'a> {
unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion) {
let unit = &mut self.sides.get_mUnits_mut()[self.index] as *mut _;
let value = &mut self.sides.get_mValues_mut()[self.index] as *mut _;
(&mut *unit, &mut *value)
}
}
/// Enum representing the tagged union that is CoordData.
///
/// In release mode this should never actually exist in the code, and will be
/// optimized out by threading matches and inlining.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum CoordDataValue {
/// eStyleUnit_Null
Null,
/// eStyleUnit_Normal
Normal,
/// eStyleUnit_Auto
Auto,
/// eStyleUnit_None
None,
/// eStyleUnit_Percent
Percent(f32),
/// eStyleUnit_Factor
Factor(f32),
/// eStyleUnit_Degree
Degree(f32),
/// eStyleUnit_FlexFraction
FlexFraction(f32),
/// eStyleUnit_Coord
Coord(nscoord),
/// eStyleUnit_Integer
Integer(i32),
/// eStyleUnit_Enumerated
Enumerated(u32),
/// eStyleUnit_Calc
Calc(nsStyleCoord_CalcValue),
}
/// A trait to abstract on top of a mutable `nsStyleCoord`-like object.
pub unsafe trait CoordDataMut: CoordData {
/// Get mutably the unit and the union.
///
/// This is unsafe since it's possible to modify the unit without changing
/// the union.
///
/// NB: This can't be two methods since we can't mutably borrow twice
unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion);
/// Clean up any resources used by the union.
///
/// Currently, this only happens if the nsStyleUnit is a Calc.
#[inline]
fn reset(&mut self) {
unsafe {
if self.unit() == nsStyleUnit::eStyleUnit_Calc {
let (unit, union) = self.values_mut();
bindings::Gecko_ResetStyleCoord(unit, union);
}
}
}
#[inline]
/// Copies the unit and value from another `CoordData` type.
fn copy_from<T: CoordData>(&mut self, other: &T) {
unsafe {
self.reset();
self.copy_from_unchecked(other);
self.addref_if_calc();
}
}
#[inline]
/// Moves the unit and value from another `CoordData` type.
fn move_from<T: CoordData>(&mut self, other: T) {
unsafe {
self.reset();
self.copy_from_unchecked(&other);
}
}
#[inline]
/// Copies the unit and value from another `CoordData` type without checking
/// the type of the value (so refcounted values like calc may leak).
unsafe fn copy_from_unchecked<T: CoordData>(&mut self, other: &T) {
let (unit, union) = self.values_mut();
*unit = other.unit();
*union = other.union();
}
/// Useful for initializing uninits, given that `set_value` may segfault on
/// uninits.
fn leaky_set_null(&mut self) {
use crate::gecko_bindings::structs::nsStyleUnit::*;
unsafe {
let (unit, union) = self.values_mut();
*unit = eStyleUnit_Null;
*union.mInt.as_mut() = 0;
}
}
#[inline(always)]
/// Sets the inner value.
fn set_value(&mut self, value: CoordDataValue) {
use self::CoordDataValue::*;
use crate::gecko_bindings::structs::nsStyleUnit::*;
self.reset();
unsafe {
let (unit, union) = self.values_mut();
match value {
Null => {
*unit = eStyleUnit_Null;
*union.mInt.as_mut() = 0;
},
Normal => {
*unit = eStyleUnit_Normal;
*union.mInt.as_mut() = 0;
},
Auto => {
*unit = eStyleUnit_Auto;
*union.mInt.as_mut() = 0;
},
None => {
*unit = eStyleUnit_None;
*union.mInt.as_mut() = 0;
},
Percent(f) => {
*unit = eStyleUnit_Percent;
*union.mFloat.as_mut() = f;
},
Factor(f) => {
*unit = eStyleUnit_Factor;
*union.mFloat.as_mut() = f;
},
Degree(f) => {
*unit = eStyleUnit_Degree;
*union.mFloat.as_mut() = f;
},
FlexFraction(f) => {
*unit = eStyleUnit_FlexFraction;
*union.mFloat.as_mut() = f;
},
Coord(coord) => {
*unit = eStyleUnit_Coord;
*union.mInt.as_mut() = coord;
},
Integer(i) => {
*unit = eStyleUnit_Integer;
*union.mInt.as_mut() = i;
},
Enumerated(i) => {
*unit = eStyleUnit_Enumerated;
*union.mInt.as_mut() = i as i32;
},
Calc(calc) => {
// Gecko_SetStyleCoordCalcValue changes the unit internally
bindings::Gecko_SetStyleCoordCalcValue(unit, union, calc);
},
}
}
}
#[inline]
/// Gets the `Calc` value mutably, asserts in debug builds if the unit is
/// not `Calc`.
unsafe fn as_calc_mut(&mut self) -> &mut nsStyleCoord_Calc {
debug_assert_eq!(self.unit(), nsStyleUnit::eStyleUnit_Calc);
&mut *(*self.union().mPointer.as_mut() as *mut nsStyleCoord_Calc)
}
#[inline]
/// Does what it promises, if the unit is `calc`, it bumps the reference
/// count _of the calc expression_.
fn addref_if_calc(&mut self) {
unsafe {
if self.unit() == nsStyleUnit::eStyleUnit_Calc {
bindings::Gecko_AddRefCalcArbitraryThread(self.as_calc_mut());
}
}
}
}
/// A trait to abstract on top of a `nsStyleCoord`-like object.
pub unsafe trait CoordData {
/// Get the unit of this object.
fn unit(&self) -> nsStyleUnit;
/// Get the `nsStyleUnion` for this object.
fn union(&self) -> nsStyleUnion;
#[inline(always)]
/// Get the appropriate value for this object.
fn as_value(&self) -> CoordDataValue {
use self::CoordDataValue::*;
use crate::gecko_bindings::structs::nsStyleUnit::*;
unsafe {
match self.unit() {
eStyleUnit_Null => Null,
eStyleUnit_Normal => Normal,
eStyleUnit_Auto => Auto,
eStyleUnit_None => None,
eStyleUnit_Percent => Percent(self.get_float()),
eStyleUnit_Factor => Factor(self.get_float()),
eStyleUnit_Degree => Degree(self.get_float()),
eStyleUnit_FlexFraction => FlexFraction(self.get_float()),
eStyleUnit_Coord => Coord(self.get_integer()),
eStyleUnit_Integer => Integer(self.get_integer()),
eStyleUnit_Enumerated => Enumerated(self.get_integer() as u32),
eStyleUnit_Calc => Calc(self.get_calc_value()),
}
}
}
#[inline]
/// Pretend inner value is a float; obtain it.
unsafe fn get_float(&self) -> f32 {
use crate::gecko_bindings::structs::nsStyleUnit::*;
debug_assert!(
self.unit() == eStyleUnit_Percent ||
self.unit() == eStyleUnit_Factor ||
self.unit() == eStyleUnit_Degree ||
self.unit() == eStyleUnit_FlexFraction
);
*self.union().mFloat.as_ref()
}
#[inline]
/// Pretend inner value is an int; obtain it.
unsafe fn get_integer(&self) -> i32 {
use crate::gecko_bindings::structs::nsStyleUnit::*;
debug_assert!(
self.unit() == eStyleUnit_Coord ||
self.unit() == eStyleUnit_Integer ||
self.unit() == eStyleUnit_Enumerated
);
*self.union().mInt.as_ref()
}
#[inline]
/// Pretend inner value is a calc; obtain it.
/// Ensure that the unit is Calc before calling this.
unsafe fn get_calc_value(&self) -> nsStyleCoord_CalcValue {
debug_assert_eq!(self.unit(), nsStyleUnit::eStyleUnit_Calc);
(*self.as_calc())._base
}
#[inline]
/// Pretend the inner value is a calc expression, and obtain it.
unsafe fn as_calc(&self) -> &nsStyleCoord_Calc {
debug_assert_eq!(self.unit(), nsStyleUnit::eStyleUnit_Calc);
&*(*self.union().mPointer.as_ref() as *const nsStyleCoord_Calc)
}
}

View file

@ -503,23 +503,24 @@ trait PrivateMatchMethods: TElement {
let old_display = old_values.get_box().clone_display();
let new_display = new_values.get_box().clone_display();
// If we used to be a display: none element, and no longer are,
// our children need to be restyled because they're unstyled.
//
// NOTE(emilio): Gecko has the special-case of -moz-binding, but
// that gets handled on the frame constructor when processing
// the reframe, so no need to handle that here.
if old_display == Display::None && old_display != new_display {
if old_display != new_display {
// If we used to be a display: none element, and no longer are, our
// children need to be restyled because they're unstyled.
if old_display == Display::None {
return ChildCascadeRequirement::MustCascadeChildren;
}
// Blockification of children may depend on our display value,
// so we need to actually do the recascade. We could potentially
// do better, but it doesn't seem worth it.
if old_display.is_item_container() != new_display.is_item_container() {
return ChildCascadeRequirement::MustCascadeChildren;
}
// We may also need to blockify and un-blockify descendants if our
// display goes from / to display: contents, since the "layout
// parent style" changes.
if old_display.is_contents() || new_display.is_contents() {
return ChildCascadeRequirement::MustCascadeChildren;
}
// Line break suppression may also be affected if the display
// type changes from ruby to non-ruby.
#[cfg(feature = "gecko")]
@ -528,6 +529,7 @@ trait PrivateMatchMethods: TElement {
return ChildCascadeRequirement::MustCascadeChildren;
}
}
}
// Children with justify-items: auto may depend on our
// justify-items property value.

View file

@ -302,7 +302,7 @@ impl MediaFeatureExpression {
feature_name = &feature_name[8..];
requirements.insert(ParsingRequirements::WEBKIT_PREFIX);
if unsafe {
structs::StaticPrefs_sVarCache_layout_css_prefixes_device_pixel_ratio_webkit
structs::StaticPrefs::sVarCache_layout_css_prefixes_device_pixel_ratio_webkit
} {
requirements.insert(
ParsingRequirements::WEBKIT_DEVICE_PIXEL_RATIO_PREF_ENABLED,

View file

@ -686,7 +686,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
return;
}
let use_document_fonts = unsafe { structs::StaticPrefs_sVarCache_browser_display_use_document_fonts != 0 };
let use_document_fonts = unsafe { structs::StaticPrefs::sVarCache_browser_display_use_document_fonts != 0 };
let builder = &mut self.context.builder;
let (default_font_type, prioritize_user_fonts) = {
let font = builder.get_font().gecko();

View file

@ -336,7 +336,9 @@ class Longhand(object):
"MozScriptLevel",
"MozScriptMinSize",
"MozScriptSizeMultiplier",
"TextDecorationSkipInk",
"NonNegativeNumber",
"Number",
"OffsetRotate",
"Opacity",
"OutlineStyle",
@ -556,7 +558,7 @@ class PropertiesData(object):
longhand = Longhand(self.current_style_struct, name, **kwargs)
self.add_prefixed_aliases(longhand)
longhand.alias = list(map(lambda (x, p): Alias(x, longhand, p), longhand.alias))
longhand.alias = list(map(lambda xp: Alias(xp[0], longhand, xp[1]), longhand.alias))
self.longhand_aliases += longhand.alias
self.current_style_struct.longhands.append(longhand)
self.longhands.append(longhand)
@ -572,7 +574,7 @@ class PropertiesData(object):
sub_properties = [self.longhands_by_name[s] for s in sub_properties]
shorthand = Shorthand(name, sub_properties, *args, **kwargs)
self.add_prefixed_aliases(shorthand)
shorthand.alias = list(map(lambda (x, p): Alias(x, shorthand, p), shorthand.alias))
shorthand.alias = list(map(lambda xp: Alias(xp[0], shorthand, xp[1]), shorthand.alias))
self.shorthand_aliases += shorthand.alias
self.shorthands.append(shorthand)
return shorthand

View file

@ -36,7 +36,6 @@ use crate::gecko_bindings::bindings::Gecko_SetNullImageValue;
use crate::gecko_bindings::structs;
use crate::gecko_bindings::structs::nsCSSPropertyID;
use crate::gecko_bindings::structs::mozilla::PseudoStyleType;
use crate::gecko_bindings::sugar::ns_style_coord::CoordDataMut;
use crate::gecko_bindings::sugar::refptr::RefPtr;
use crate::gecko::values::round_border_to_device_pixels;
use crate::logical_geometry::WritingMode;
@ -524,107 +523,6 @@ def set_gecko_property(ffi_name, expr):
}
</%def>
<%def name="impl_svg_paint(ident, gecko_ffi_name)">
#[allow(non_snake_case)]
pub fn set_${ident}(&mut self, mut v: longhands::${ident}::computed_value::T) {
use crate::values::generics::svg::SVGPaintKind;
use self::structs::nsStyleSVGPaintType;
use self::structs::nsStyleSVGFallbackType;
let ref mut paint = ${get_gecko_property(gecko_ffi_name)};
unsafe {
bindings::Gecko_nsStyleSVGPaint_Reset(paint);
}
let fallback = v.fallback.take();
match v.kind {
SVGPaintKind::None => return,
SVGPaintKind::ContextFill => {
paint.mType = nsStyleSVGPaintType::eStyleSVGPaintType_ContextFill;
}
SVGPaintKind::ContextStroke => {
paint.mType = nsStyleSVGPaintType::eStyleSVGPaintType_ContextStroke;
}
SVGPaintKind::PaintServer(url) => {
unsafe {
bindings::Gecko_nsStyleSVGPaint_SetURLValue(
paint,
&url
)
}
}
SVGPaintKind::Color(color) => {
paint.mType = nsStyleSVGPaintType::eStyleSVGPaintType_Color;
unsafe {
*paint.mPaint.mColor.as_mut() = color.into();
}
}
}
paint.mFallbackType = match fallback {
Some(Either::First(color)) => {
paint.mFallbackColor = color.into();
nsStyleSVGFallbackType::eStyleSVGFallbackType_Color
},
Some(Either::Second(_)) => {
nsStyleSVGFallbackType::eStyleSVGFallbackType_None
},
None => nsStyleSVGFallbackType::eStyleSVGFallbackType_NotSet
};
}
#[allow(non_snake_case)]
pub fn copy_${ident}_from(&mut self, other: &Self) {
unsafe {
bindings::Gecko_nsStyleSVGPaint_CopyFrom(
&mut ${get_gecko_property(gecko_ffi_name)},
& ${get_gecko_property(gecko_ffi_name, "other")}
);
}
}
#[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) -> longhands::${ident}::computed_value::T {
use crate::values::generics::svg::{SVGPaint, SVGPaintKind};
use self::structs::nsStyleSVGPaintType;
use self::structs::nsStyleSVGFallbackType;
let ref paint = ${get_gecko_property(gecko_ffi_name)};
let fallback = match paint.mFallbackType {
nsStyleSVGFallbackType::eStyleSVGFallbackType_Color => {
Some(Either::First(paint.mFallbackColor.into()))
},
nsStyleSVGFallbackType::eStyleSVGFallbackType_None => {
Some(Either::Second(None_))
},
nsStyleSVGFallbackType::eStyleSVGFallbackType_NotSet => None,
};
let kind = match paint.mType {
nsStyleSVGPaintType::eStyleSVGPaintType_None => SVGPaintKind::None,
nsStyleSVGPaintType::eStyleSVGPaintType_ContextFill => SVGPaintKind::ContextFill,
nsStyleSVGPaintType::eStyleSVGPaintType_ContextStroke => SVGPaintKind::ContextStroke,
nsStyleSVGPaintType::eStyleSVGPaintType_Server => {
SVGPaintKind::PaintServer(unsafe {
paint.mPaint.mPaintServer.as_ref().clone()
})
}
nsStyleSVGPaintType::eStyleSVGPaintType_Color => {
let col = unsafe { *paint.mPaint.mColor.as_ref() };
SVGPaintKind::Color(col.into())
}
};
SVGPaint {
kind: kind,
fallback: fallback,
}
}
</%def>
<%def name="impl_non_negative_length(ident, gecko_ffi_name, inherit_from=None,
round_to_pixels=False)">
#[allow(non_snake_case)]
@ -834,7 +732,6 @@ impl Clone for ${style_struct.gecko_struct_name} {
"MozScriptMinSize": impl_absolute_length,
"SVGLength": impl_svg_length,
"SVGOpacity": impl_svg_opacity,
"SVGPaint": impl_svg_paint,
"SVGWidth": impl_svg_length,
}
@ -880,15 +777,8 @@ class Side(object):
self.ident = name.lower()
self.index = index
class GridLine(object):
def __init__(self, name):
self.ident = "grid-" + name.lower()
self.name = self.ident.replace('-', '_')
self.gecko = "m" + to_camel_case(self.ident)
SIDES = [Side("Top", 0), Side("Right", 1), Side("Bottom", 2), Side("Left", 3)]
CORNERS = ["top_left", "top_right", "bottom_right", "bottom_left"]
GRID_LINES = map(GridLine, ["row-start", "row-end", "column-start", "column-end"])
%>
#[allow(dead_code)]
@ -1077,12 +967,11 @@ fn static_assert() {
% endfor
</%self:impl_trait>
<% skip_position_longhands = " ".join(x.ident for x in SIDES + GRID_LINES) %>
<% skip_position_longhands = " ".join(x.ident for x in SIDES) %>
<%self:impl_trait style_struct_name="Position"
skip_longhands="${skip_position_longhands} order
align-content justify-content align-self
justify-self align-items justify-items
grid-auto-rows grid-auto-columns
grid-auto-flow grid-template-rows
grid-template-columns">
% for side in SIDES:
@ -1132,92 +1021,14 @@ fn static_assert() {
${impl_simple_copy('order', 'mOrder')}
% for value in GRID_LINES:
pub fn set_${value.name}(&mut self, v: longhands::${value.name}::computed_value::T) {
use crate::gecko_bindings::structs::{nsStyleGridLine_kMinLine, nsStyleGridLine_kMaxLine};
let line = &mut self.gecko.${value.gecko};
line.mLineName.set_move(unsafe {
RefPtr::from_addrefed(match v.ident {
Some(i) => i.0,
None => atom!(""),
}.into_addrefed())
});
line.mHasSpan = v.is_span;
if let Some(integer) = v.line_num {
// clamping the integer between a range
line.mInteger = cmp::max(
nsStyleGridLine_kMinLine,
cmp::min(integer, nsStyleGridLine_kMaxLine),
);
}
}
pub fn copy_${value.name}_from(&mut self, other: &Self) {
self.gecko.${value.gecko}.mHasSpan = other.gecko.${value.gecko}.mHasSpan;
self.gecko.${value.gecko}.mInteger = other.gecko.${value.gecko}.mInteger;
unsafe {
self.gecko.${value.gecko}.mLineName.set(&other.gecko.${value.gecko}.mLineName);
}
}
pub fn reset_${value.name}(&mut self, other: &Self) {
self.copy_${value.name}_from(other)
}
pub fn clone_${value.name}(&self) -> longhands::${value.name}::computed_value::T {
use crate::gecko_bindings::structs::{nsStyleGridLine_kMinLine, nsStyleGridLine_kMaxLine};
longhands::${value.name}::computed_value::T {
is_span: self.gecko.${value.gecko}.mHasSpan,
ident: {
let name = unsafe { Atom::from_raw(self.gecko.${value.gecko}.mLineName.mRawPtr) };
if name == atom!("") {
None
} else {
Some(CustomIdent(name))
}
},
line_num:
if self.gecko.${value.gecko}.mInteger == 0 {
None
} else {
debug_assert!(nsStyleGridLine_kMinLine <= self.gecko.${value.gecko}.mInteger);
debug_assert!(self.gecko.${value.gecko}.mInteger <= nsStyleGridLine_kMaxLine);
Some(self.gecko.${value.gecko}.mInteger)
},
}
}
% endfor
% for kind in ["rows", "columns"]:
pub fn set_grid_auto_${kind}(&mut self, v: longhands::grid_auto_${kind}::computed_value::T) {
let gecko = &mut *self.gecko;
v.to_gecko_style_coords(&mut gecko.mGridAuto${kind.title()}Min,
&mut gecko.mGridAuto${kind.title()}Max)
}
pub fn copy_grid_auto_${kind}_from(&mut self, other: &Self) {
self.gecko.mGridAuto${kind.title()}Min.copy_from(&other.gecko.mGridAuto${kind.title()}Min);
self.gecko.mGridAuto${kind.title()}Max.copy_from(&other.gecko.mGridAuto${kind.title()}Max);
}
pub fn reset_grid_auto_${kind}(&mut self, other: &Self) {
self.copy_grid_auto_${kind}_from(other)
}
pub fn clone_grid_auto_${kind}(&self) -> longhands::grid_auto_${kind}::computed_value::T {
crate::values::generics::grid::TrackSize::from_gecko_style_coords(&self.gecko.mGridAuto${kind.title()}Min,
&self.gecko.mGridAuto${kind.title()}Max)
}
pub fn set_grid_template_${kind}(&mut self, v: longhands::grid_template_${kind}::computed_value::T) {
<% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %>
use crate::gecko_bindings::structs::{nsTArray, nsStyleGridLine_kMaxLine};
use crate::gecko_bindings::structs::nsTArray;
use std::usize;
use crate::values::CustomIdent;
use crate::values::generics::grid::TrackListType::Auto;
use crate::values::generics::grid::{GridTemplateComponent, RepeatCount};
use crate::values::generics::grid::{GridTemplateComponent, RepeatCount, TrackListValue, MAX_GRID_LINE};
#[inline]
fn set_line_names(servo_names: &[CustomIdent], gecko_names: &mut nsTArray<structs::RefPtr<structs::nsAtom>>) {
@ -1232,7 +1043,7 @@ fn static_assert() {
}
}
let max_lines = nsStyleGridLine_kMaxLine as usize - 1; // for accounting the final <line-names>
let max_lines = MAX_GRID_LINE as usize - 1; // for accounting the final <line-names>
let result = match v {
GridTemplateComponent::None => ptr::null_mut(),
@ -1276,20 +1087,21 @@ fn static_assert() {
let mut line_names = track.line_names.into_iter();
let mut values_iter = track.values.into_iter();
{
let min_max_iter = value.mMinTrackSizingFunctions.iter_mut()
.zip(value.mMaxTrackSizingFunctions.iter_mut());
for (i, (gecko_min, gecko_max)) in min_max_iter.enumerate().take(max_lines) {
for (i, track_size) in value.mTrackSizingFunctions.iter_mut().enumerate().take(max_lines) {
let name_list = line_names.next().expect("expected line-names");
set_line_names(&name_list, &mut value.mLineNameLists[i]);
if i == auto_idx {
let track_size = auto_track_size.take()
.expect("expected <track-size> for <auto-track-repeat>");
track_size.to_gecko_style_coords(gecko_min, gecko_max);
continue
*track_size = if i == auto_idx {
auto_track_size.take().expect("expected <track-size> for <auto-track-repeat>")
} else {
match values_iter.next().expect("expected <track-size> value") {
TrackListValue::TrackSize(size) => size,
// FIXME(emilio): This shouldn't be
// representable in the first place.
TrackListValue::TrackRepeat(..) => {
unreachable!("Shouldn't have track-repeats in computed track lists")
}
let track_size = values_iter.next().expect("expected <track-size> value");
track_size.to_gecko_style_coords(gecko_min, gecko_max);
}
};
}
}
@ -1344,7 +1156,7 @@ fn static_assert() {
use crate::gecko_bindings::structs::nsTArray;
use crate::values::CustomIdent;
use crate::values::generics::grid::{GridTemplateComponent, LineNameList, RepeatCount};
use crate::values::generics::grid::{TrackList, TrackListType, TrackListValue, TrackRepeat, TrackSize};
use crate::values::generics::grid::{TrackList, TrackListType, TrackListValue, TrackRepeat};
let value = match unsafe { ${self_grid}.mPtr.as_ref() } {
None => return GridTemplateComponent::None,
@ -1386,13 +1198,8 @@ fn static_assert() {
let mut auto_repeat = None;
let mut list_type = TrackListType::Normal;
let line_names = to_line_names_vec(&value.mLineNameLists).into_boxed_slice();
let mut values = Vec::with_capacity(value.mMinTrackSizingFunctions.len());
let min_max_iter = value.mMinTrackSizingFunctions.iter()
.zip(value.mMaxTrackSizingFunctions.iter());
for (i, (gecko_min, gecko_max)) in min_max_iter.enumerate() {
let track_size = TrackSize::from_gecko_style_coords(gecko_min, gecko_max);
let mut values = Vec::with_capacity(value.mTrackSizingFunctions.len());
for (i, track_size) in value.mTrackSizingFunctions.iter().enumerate() {
if i == repeat_auto_index {
list_type = TrackListType::Auto(repeat_auto_index as u16);
@ -1411,11 +1218,11 @@ fn static_assert() {
vec.into_boxed_slice()
};
let track_sizes = vec!(track_size);
let track_sizes = vec!(track_size.clone());
auto_repeat = Some(TrackRepeat{count, line_names, track_sizes});
} else {
values.push(TrackListValue::TrackSize(track_size));
values.push(TrackListValue::TrackSize(track_size.clone()));
}
}

View file

@ -15,7 +15,7 @@ ${helpers.predefined_type(
animation_value_type="AnimatedColor",
ignored_when_colors_disabled=True,
allow_quirks="Yes",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER \
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER \
CAN_ANIMATE_ON_COMPOSITOR",
)}
@ -28,7 +28,7 @@ ${helpers.predefined_type(
vector="True",
animation_value_type="discrete",
ignored_when_colors_disabled="True",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}
% for (axis, direction, initial) in [("x", "Horizontal", "left"), ("y", "Vertical", "top")]:
@ -41,7 +41,7 @@ ${helpers.predefined_type(
animation_value_type="ComputedValue",
vector=True,
vector_animation_type="repeatable_list",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}
% endfor
@ -53,7 +53,7 @@ ${helpers.predefined_type(
animation_value_type="discrete",
vector=True,
spec="https://drafts.csswg.org/css-backgrounds/#the-background-repeat",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}
${helpers.single_keyword(
@ -63,7 +63,7 @@ ${helpers.single_keyword(
gecko_enum_prefix="StyleImageLayerAttachment",
spec="https://drafts.csswg.org/css-backgrounds/#the-background-attachment",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}
${helpers.single_keyword(
@ -75,7 +75,7 @@ ${helpers.single_keyword(
gecko_inexhaustive=True,
spec="https://drafts.csswg.org/css-backgrounds/#the-background-clip",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}
${helpers.single_keyword(
@ -86,7 +86,7 @@ ${helpers.single_keyword(
gecko_inexhaustive=True,
spec="https://drafts.csswg.org/css-backgrounds/#the-background-origin",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
)}
${helpers.predefined_type(
@ -98,7 +98,7 @@ ${helpers.predefined_type(
vector=True,
vector_animation_type="repeatable_list",
animation_value_type="BackgroundSizeList",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
extra_prefixes="webkit")}
// https://drafts.fxtf.org/compositing/#background-blend-mode
@ -110,5 +110,5 @@ ${helpers.single_keyword(
gecko_constant_prefix="NS_STYLE_BLEND",
vector=True, products="gecko", animation_value_type="discrete",
spec="https://drafts.fxtf.org/compositing/#background-blend-mode",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}

View file

@ -13,6 +13,7 @@ ${helpers.predefined_type(
initial_specified_value="specified::Content::normal()",
animation_value_type="discrete",
spec="https://drafts.csswg.org/css-content/#propdef-content",
flags="APPLIES_TO_MARKER",
servo_restyle_damage="rebuild_and_reflow",
)}

View file

@ -12,7 +12,7 @@ ${helpers.predefined_type(
"Opacity",
"1.0",
animation_value_type="ComputedValue",
flags="CREATES_STACKING_CONTEXT APPLIES_TO_PLACEHOLDER \
flags="APPLIES_TO_CUE CREATES_STACKING_CONTEXT APPLIES_TO_PLACEHOLDER \
CAN_ANIMATE_ON_COMPOSITOR",
spec="https://drafts.csswg.org/css-color/#opacity",
servo_restyle_damage = "reflow_out_of_flow",
@ -57,6 +57,22 @@ ${helpers.predefined_type(
spec="https://drafts.fxtf.org/filters/#propdef-filter",
)}
${helpers.predefined_type(
"backdrop-filter",
"Filter",
None,
vector=True,
simple_vector_bindings=True,
gecko_ffi_name="mBackdropFilters",
separator="Space",
animation_value_type="AnimatedFilterList",
vector_animation_type="with_zero",
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
gecko_pref="layout.css.backdrop-filter.enabled",
spec="https://drafts.fxtf.org/filter-effects-2/#propdef-backdrop-filter",
products="gecko",
)}
${helpers.single_keyword(
"mix-blend-mode",
"""normal multiply screen overlay darken lighten color-dodge

View file

@ -12,7 +12,7 @@ ${helpers.predefined_type(
"FontFamily",
initial_value="computed::FontFamily::serif()",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-family",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -23,7 +23,7 @@ ${helpers.predefined_type(
initial_value="computed::FontStyle::normal()",
initial_specified_value="specified::FontStyle::normal()",
animation_value_type="FontStyle",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-style",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -42,7 +42,7 @@ ${helpers.single_keyword_system(
gecko_ffi_name="mFont.variantCaps",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-caps",
custom_consts=font_variant_caps_custom_consts,
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
animation_value_type="discrete",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -53,7 +53,7 @@ ${helpers.predefined_type(
initial_value="computed::FontWeight::normal()",
initial_specified_value="specified::FontWeight::normal()",
animation_value_type="Number",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-weight",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -65,7 +65,7 @@ ${helpers.predefined_type(
initial_specified_value="specified::FontSize::medium()",
animation_value_type="NonNegativeLength",
allow_quirks="Yes",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -77,7 +77,7 @@ ${helpers.predefined_type(
initial_value="computed::FontSizeAdjust::none()",
initial_specified_value="specified::FontSizeAdjust::none()",
animation_value_type="ComputedValue",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust",
)}
@ -87,7 +87,7 @@ ${helpers.predefined_type(
products="gecko",
initial_value="specified::FontSynthesis::get_initial_value()",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-synthesis",
)}
@ -97,7 +97,7 @@ ${helpers.predefined_type(
initial_value="computed::FontStretch::hundred()",
initial_specified_value="specified::FontStretch::normal()",
animation_value_type="Percentage",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-stretch",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -109,7 +109,7 @@ ${helpers.single_keyword_system(
gecko_ffi_name="mFont.kerning",
gecko_constant_prefix="NS_FONT_KERNING",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-kerning",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
animation_value_type="discrete",
)}
@ -120,7 +120,7 @@ ${helpers.predefined_type(
initial_value="computed::FontVariantAlternates::get_initial_value()",
initial_specified_value="specified::FontVariantAlternates::get_initial_specified_value()",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-alternates",
)}
@ -131,7 +131,7 @@ ${helpers.predefined_type(
initial_value="computed::FontVariantEastAsian::empty()",
initial_specified_value="specified::FontVariantEastAsian::empty()",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-east-asian",
)}
@ -142,7 +142,7 @@ ${helpers.predefined_type(
initial_value="computed::FontVariantLigatures::empty()",
initial_specified_value="specified::FontVariantLigatures::empty()",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-ligatures",
)}
@ -153,7 +153,7 @@ ${helpers.predefined_type(
initial_value="computed::FontVariantNumeric::empty()",
initial_specified_value="specified::FontVariantNumeric::empty()",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-numeric",
)}
@ -164,7 +164,7 @@ ${helpers.single_keyword_system(
gecko_ffi_name="mFont.variantPosition",
gecko_constant_prefix="NS_FONT_VARIANT_POSITION",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-position",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
animation_value_type="discrete",
)}
@ -176,7 +176,7 @@ ${helpers.predefined_type(
initial_specified_value="specified::FontFeatureSettings::normal()",
extra_prefixes="moz:layout.css.prefixes.font-features",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-feature-settings",
)}
@ -195,7 +195,7 @@ ${helpers.predefined_type(
initial_value="computed::FontVariationSettings::normal()",
initial_specified_value="specified::FontVariationSettings::normal()",
animation_value_type="ComputedValue",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="${variation_spec}",
)}
@ -207,7 +207,7 @@ ${helpers.predefined_type(
initial_specified_value="specified::FontLanguageOverride::normal()",
animation_value_type="discrete",
extra_prefixes="moz:layout.css.prefixes.font-features",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override",
)}
@ -219,7 +219,7 @@ ${helpers.single_keyword_system(
gecko_ffi_name="mFont.opticalSizing",
gecko_constant_prefix="NS_FONT_OPTICAL_SIZING",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://www.w3.org/TR/css-fonts-4/#font-optical-sizing-def",
)}
@ -412,7 +412,7 @@ ${helpers.predefined_type(
is_system_font: true,
},
font_size: FontSize {
size: Au(system.size).into(),
size: cx.maybe_zoom_text(Au(system.size).into()),
keyword_info: None
},
font_weight,
@ -514,7 +514,7 @@ ${helpers.single_keyword(
gecko_pref="layout.css.osx-font-smoothing.enabled",
products="gecko",
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth)",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
animation_value_type="discrete",
)}

View file

@ -14,6 +14,7 @@ ${helpers.single_keyword(
gecko_ffi_name="mVisible",
animation_value_type="ComputedValue",
spec="https://drafts.csswg.org/css-box/#propdef-visibility",
flags="APPLIES_TO_CUE",
)}
// CSS Writing Modes Level 3
@ -37,6 +38,7 @@ ${helpers.single_keyword(
animation_value_type="none",
spec="https://drafts.csswg.org/css-writing-modes/#propdef-direction",
needs_conversion=True,
flags="APPLIES_TO_MARKER",
servo_restyle_damage="rebuild_and_reflow",
)}

View file

@ -11,7 +11,7 @@ ${helpers.predefined_type(
"ColorPropertyValue",
"::cssparser::RGBA::new(0, 0, 0, 255)",
animation_value_type="AnimatedRGBA",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
ignored_when_colors_disabled="True",
spec="https://drafts.csswg.org/css-color/#color",
)}
@ -21,7 +21,7 @@ ${helpers.predefined_type(
"LineHeight",
"computed::LineHeight::normal()",
animation_value_type="LineHeight",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE \
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE \
APPLIES_TO_PLACEHOLDER GETCS_NEEDS_LAYOUT_FLUSH",
spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height",
servo_restyle_damage="reflow"
@ -181,7 +181,7 @@ ${helpers.predefined_type(
needs_conversion="True"
animation_value_type="discrete"
// Only allowed for UA sheets, which set it !important.
flags="APPLIES_TO_PLACEHOLDER"
flags="APPLIES_TO_CUE APPLIES_TO_PLACEHOLDER"
spec="https://drafts.csswg.org/css-text/#propdef-white-space"
servo_restyle_damage="rebuild_and_reflow"
>
@ -229,7 +229,7 @@ ${helpers.predefined_type(
animation_value_type="AnimatedTextShadowList",
ignored_when_colors_disabled=True,
simple_vector_bindings=True,
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-text-decor-3/#text-shadow-property",
)}
@ -337,6 +337,7 @@ ${helpers.single_keyword(
products="gecko",
animation_value_type="discrete",
spec="https://drafts.csswg.org/css-ruby/#ruby-position-property",
flags="APPLIES_TO_CUE",
)}
// CSS Writing Modes Module Level 3
@ -348,6 +349,7 @@ ${helpers.single_keyword(
products="gecko",
animation_value_type="discrete",
spec="https://drafts.csswg.org/css-writing-modes-3/#text-combine-upright",
flags="APPLIES_TO_CUE APPLIES_TO_MARKER",
)}
// SVG 1.1: Section 11 - Painting: Filling, Stroking and Marker Symbols
@ -382,3 +384,15 @@ ${helpers.predefined_type(
gecko_pref="layout.css.text-underline-offset.enabled",
spec="https://drafts.csswg.org/css-text-decor-4/#underline-offset",
)}
// text decoration skip ink
${helpers.predefined_type(
"text-decoration-skip-ink",
"TextDecorationSkipInk",
"computed::TextDecorationSkipInk::Auto",
products="gecko",
needs_context=False,
animation_value_type="discrete",
gecko_pref="layout.css.text-decoration-skip-ink.enabled",
spec="https://drafts.csswg.org/css-text-decor-4/#text-decoration-skip-ink-property",
)}

View file

@ -18,6 +18,7 @@ ${helpers.predefined_type(
animation_value_type="AnimatedColor",
ignored_when_colors_disabled=True,
spec="https://drafts.csswg.org/css-ui/#propdef-outline-color",
flags="APPLIES_TO_CUE",
)}
${helpers.predefined_type(
@ -27,6 +28,7 @@ ${helpers.predefined_type(
initial_specified_value="specified::OutlineStyle::none()",
animation_value_type="discrete",
spec="https://drafts.csswg.org/css-ui/#propdef-outline-style",
flags="APPLIES_TO_CUE",
)}
${helpers.predefined_type(
@ -37,6 +39,7 @@ ${helpers.predefined_type(
computed_type="crate::values::computed::NonNegativeLength",
animation_value_type="NonNegativeLength",
spec="https://drafts.csswg.org/css-ui/#propdef-outline-width",
flags="APPLIES_TO_CUE",
)}
// The -moz-outline-radius-* properties are non-standard and not on a standards track.

View file

@ -322,7 +322,6 @@ ${helpers.predefined_type(
animation_value_type="discrete",
spec="https://drafts.csswg.org/css-grid/#propdef-grid-%s-%s" % (kind, range),
products="gecko",
boxed=True,
)}
% endfor
@ -392,3 +391,17 @@ ${helpers.predefined_type(
animation_value_type="NonNegativeLengthPercentageOrNormal",
servo_restyle_damage="reflow",
)}
// NOTE(emilio): Before exposing this property to content, we probably need to
// change syntax and such, and make it apply to more elements.
//
// For now, it's used only for mapped attributes.
${helpers.predefined_type(
"aspect-ratio",
"Number",
"computed::Number::zero()",
animation_value_type="ComputedValue",
spec="Internal, for now",
enabled_in="",
servo_restyle_damage="reflow",
)}

View file

@ -23,6 +23,7 @@ ${helpers.single_keyword(
"normal embed isolate bidi-override isolate-override plaintext",
animation_value_type="none",
spec="https://drafts.csswg.org/css-writing-modes/#propdef-unicode-bidi",
flags="APPLIES_TO_MARKER",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -32,7 +33,7 @@ ${helpers.predefined_type(
"specified::TextDecorationLine::none()",
initial_specified_value="specified::TextDecorationLine::none()",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -42,7 +43,7 @@ ${helpers.single_keyword(
"solid double dotted dashed wavy -moz-none",
products="gecko",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style",
)}
@ -54,7 +55,7 @@ ${helpers.predefined_type(
products="gecko",
animation_value_type="AnimatedColor",
ignored_when_colors_disabled=True,
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-color",
)}

View file

@ -939,7 +939,7 @@ impl CSSWideKeyword {
bitflags! {
/// A set of flags for properties.
pub struct PropertyFlags: u8 {
pub struct PropertyFlags: u16 {
/// This property requires a stacking context.
const CREATES_STACKING_CONTEXT = 1 << 0;
/// This property has values that can establish a containing block for
@ -954,13 +954,17 @@ bitflags! {
const APPLIES_TO_FIRST_LINE = 1 << 4;
/// This longhand property applies to ::placeholder.
const APPLIES_TO_PLACEHOLDER = 1 << 5;
/// This longhand property applies to ::cue.
const APPLIES_TO_CUE = 1 << 6;
/// This longhand property applies to ::marker.
const APPLIES_TO_MARKER = 1 << 7;
/// This property's getComputedStyle implementation requires layout
/// to be flushed.
const GETCS_NEEDS_LAYOUT_FLUSH = 1 << 6;
const GETCS_NEEDS_LAYOUT_FLUSH = 1 << 8;
/// This property is a legacy shorthand.
///
/// https://drafts.csswg.org/css-cascade/#legacy-shorthand
const IS_LEGACY_SHORTHAND = 1 << 7;
const IS_LEGACY_SHORTHAND = 1 << 9;
/* The following flags are currently not used in Rust code, they
* only need to be listed in corresponding properties so that
@ -1184,7 +1188,7 @@ impl LonghandId {
pub fn flags(self) -> PropertyFlags {
// TODO(emilio): This can be simplified further as Rust gains more
// constant expression support.
const FLAGS: [u8; ${len(data.longhands)}] = [
const FLAGS: [u16; ${len(data.longhands)}] = [
% for property in data.longhands:
% for flag in property.flags:
PropertyFlags::${flag}.bits |
@ -1446,7 +1450,7 @@ impl ShorthandId {
/// Returns PropertyFlags for the given shorthand property.
#[inline]
pub fn flags(self) -> PropertyFlags {
const FLAGS: [u8; ${len(data.shorthands)}] = [
const FLAGS: [u16; ${len(data.shorthands)}] = [
% for property in data.shorthands:
% for flag in property.flags:
PropertyFlags::${flag}.bits |
@ -2834,6 +2838,19 @@ impl ComputedValues {
pub fn resolve_color(&self, color: computed::Color) -> RGBA {
color.to_rgba(self.get_inherited_text().clone_color())
}
/// Returns which longhand properties have different values in the two
/// ComputedValues.
#[cfg(feature = "gecko_debug")]
pub fn differing_properties(&self, other: &ComputedValues) -> LonghandIdSet {
let mut set = LonghandIdSet::new();
% for prop in data.longhands:
if self.clone_${prop.ident}() != other.clone_${prop.ident}() {
set.insert(LonghandId::${prop.camel_case});
}
% endfor
set
}
}
#[cfg(feature = "servo")]

View file

@ -144,6 +144,7 @@
products="gecko">
use crate::values::specified::GridLine;
use crate::parser::Parse;
use crate::Zero;
// NOTE: Since both the shorthands have the same code, we should (re-)use code from one to implement
// the other. This might not be a big deal for now, but we should consider looking into this in the future
@ -157,7 +158,7 @@
GridLine::parse(context, input)?
} else {
let mut line = GridLine::auto();
if start.line_num.is_none() && !start.is_span {
if start.line_num.is_zero() && !start.is_span {
line.ident = start.ident.clone(); // ident from start value should be taken
}
@ -186,6 +187,7 @@
products="gecko">
use crate::values::specified::GridLine;
use crate::parser::Parse;
use crate::Zero;
// The code is the same as `grid-{row,column}` except that this can have four values at most.
pub fn parse_value<'i, 't>(
@ -194,7 +196,7 @@
) -> Result<Longhands, ParseError<'i>> {
fn line_with_ident_from(other: &GridLine) -> GridLine {
let mut this = GridLine::auto();
if other.line_num.is_none() && !other.is_span {
if other.line_num.is_zero() && !other.is_span {
this.ident = other.ident.clone();
}

View file

@ -950,8 +950,8 @@ mod gecko_leak_checking {
use std::os::raw::{c_char, c_void};
extern "C" {
pub fn NS_LogCtor(aPtr: *const c_void, aTypeName: *const c_char, aSize: u32);
pub fn NS_LogDtor(aPtr: *const c_void, aTypeName: *const c_char, aSize: u32);
fn NS_LogCtor(aPtr: *mut c_void, aTypeName: *const c_char, aSize: u32);
fn NS_LogDtor(aPtr: *mut c_void, aTypeName: *const c_char, aSize: u32);
}
static NAME: &'static [u8] = b"RuleNode\0";
@ -960,7 +960,7 @@ mod gecko_leak_checking {
pub fn log_ctor(ptr: *const RuleNode) {
let s = NAME as *const [u8] as *const u8 as *const c_char;
unsafe {
NS_LogCtor(ptr as *const c_void, s, size_of::<RuleNode>() as u32);
NS_LogCtor(ptr as *mut c_void, s, size_of::<RuleNode>() as u32);
}
}
@ -968,7 +968,7 @@ mod gecko_leak_checking {
pub fn log_dtor(ptr: *const RuleNode) {
let s = NAME as *const [u8] as *const u8 as *const c_char;
unsafe {
NS_LogDtor(ptr as *const c_void, s, size_of::<RuleNode>() as u32);
NS_LogDtor(ptr as *mut c_void, s, size_of::<RuleNode>() as u32);
}
}

View file

@ -260,12 +260,12 @@ impl DocumentCondition {
return true;
}
if unsafe { structs::StaticPrefs_sVarCache_layout_css_moz_document_content_enabled } {
if unsafe { structs::StaticPrefs::sVarCache_layout_css_moz_document_content_enabled } {
return true;
}
if !unsafe {
structs::StaticPrefs_sVarCache_layout_css_moz_document_url_prefix_hack_enabled
structs::StaticPrefs::sVarCache_layout_css_moz_document_url_prefix_hack_enabled
} {
return false;
}

View file

@ -324,7 +324,7 @@ impl RawSelector {
#[cfg(feature = "gecko")]
{
if unsafe {
!crate::gecko_bindings::structs::StaticPrefs_sVarCache_layout_css_supports_selector_enabled
!crate::gecko_bindings::structs::StaticPrefs::sVarCache_layout_css_supports_selector_enabled
} {
return false;
}

View file

@ -19,8 +19,9 @@ pub type AnimatedSimpleShadow = GenericSimpleShadow<Color, Length, Length>;
/// An animated value for a single `filter`.
#[cfg(feature = "gecko")]
pub type AnimatedFilter = GenericFilter<Angle, Number, Length, AnimatedSimpleShadow, ComputedUrl>;
pub type AnimatedFilter =
GenericFilter<Angle, Number, Number, Length, AnimatedSimpleShadow, ComputedUrl>;
/// An animated value for a single `filter`.
#[cfg(not(feature = "gecko"))]
pub type AnimatedFilter = GenericFilter<Angle, Number, Length, Impossible, Impossible>;
pub type AnimatedFilter = GenericFilter<Angle, Number, Number, Length, Impossible, Impossible>;

View file

@ -62,10 +62,7 @@ impl Animate for TrackSize {
}
}
impl Animate for generics::TrackRepeat<LengthPercentage, Integer>
where
generics::RepeatCount<Integer>: PartialEq,
{
impl Animate for generics::TrackRepeat<LengthPercentage, Integer> {
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
// If the keyword, auto-fit/fill, is the same it can result in different
// number of tracks. For both auto-fit/fill, the number of columns isn't

View file

@ -447,17 +447,13 @@ where
}
}
impl<T> ToAnimatedZero for Box<[T]>
impl<T> ToAnimatedZero for crate::OwnedSlice<T>
where
T: ToAnimatedZero,
{
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
let v = self
.iter()
.map(|v| v.to_animated_zero())
.collect::<Result<Vec<_>, _>>()?;
Ok(v.into_boxed_slice())
self.iter().map(|v| v.to_animated_zero()).collect()
}
}

View file

@ -4,25 +4,10 @@
//! Animation implementations for various SVG-related types.
use super::{Animate, Procedure, ToAnimatedZero};
use super::{Animate, Procedure};
use crate::properties::animated_properties::ListAnimation;
use crate::values::animated::color::Color as AnimatedColor;
use crate::values::computed::url::ComputedUrl;
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
use crate::values::generics::svg::{SVGPaint, SVGStrokeDashArray};
/// Animated SVGPaint.
pub type IntermediateSVGPaint = SVGPaint<AnimatedColor, ComputedUrl>;
impl ToAnimatedZero for IntermediateSVGPaint {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(IntermediateSVGPaint {
kind: self.kind.to_animated_zero()?,
fallback: self.fallback.and_then(|v| v.to_animated_zero().ok()),
})
}
}
use crate::values::generics::svg::SVGStrokeDashArray;
/// <https://www.w3.org/TR/SVG11/painting.html#StrokeDasharrayProperty>
impl<L> Animate for SVGStrokeDashArray<L>

View file

@ -8,7 +8,7 @@ use crate::values::computed::color::Color;
use crate::values::computed::length::{Length, NonNegativeLength};
#[cfg(feature = "gecko")]
use crate::values::computed::url::ComputedUrl;
use crate::values::computed::{Angle, NonNegativeNumber};
use crate::values::computed::{Angle, NonNegativeNumber, ZeroToOneNumber};
use crate::values::generics::effects::BoxShadow as GenericBoxShadow;
use crate::values::generics::effects::Filter as GenericFilter;
use crate::values::generics::effects::SimpleShadow as GenericSimpleShadow;
@ -20,13 +20,25 @@ pub type BoxShadow = GenericBoxShadow<Color, Length, NonNegativeLength, Length>;
/// A computed value for a single `filter`.
#[cfg(feature = "gecko")]
pub type Filter =
GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, SimpleShadow, ComputedUrl>;
pub type Filter = GenericFilter<
Angle,
NonNegativeNumber,
ZeroToOneNumber,
NonNegativeLength,
SimpleShadow,
ComputedUrl,
>;
/// A computed value for a single `filter`.
#[cfg(feature = "servo")]
pub type Filter =
GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, Impossible, Impossible>;
pub type Filter = GenericFilter<
Angle,
NonNegativeNumber,
ZeroToOneNumber,
NonNegativeLength,
Impossible,
Impossible,
>;
/// A computed value for the `drop-shadow()` filter.
pub type SimpleShadow = GenericSimpleShadow<Color, Length, NonNegativeLength>;

View file

@ -7,10 +7,10 @@
use self::transform::DirectionVector;
use super::animated::ToAnimatedValue;
use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent;
use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as GenericTrackBreadth};
use super::generics::grid::{TrackList as GenericTrackList, TrackSize as GenericTrackSize};
use super::generics::grid::{GenericGridLine, GenericTrackBreadth};
use super::generics::grid::{GenericTrackSize, TrackList as GenericTrackList};
use super::generics::transform::IsParallelTo;
use super::generics::{self, GreaterThanOrEqualToOne, NonNegative};
use super::generics::{self, GreaterThanOrEqualToOne, NonNegative, ZeroToOne};
use super::specified;
use super::{CSSFloat, CSSInteger};
use crate::context::QuirksMode;
@ -75,6 +75,7 @@ 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::TextDecorationSkipInk;
pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight};
pub use self::text::{OverflowWrap, TextOverflow, WordBreak, WordSpacing};
pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle};
@ -519,6 +520,30 @@ impl From<NonNegativeNumber> for CSSFloat {
}
}
/// A wrapper of Number, but the value between 0 and 1
pub type ZeroToOneNumber = ZeroToOne<CSSFloat>;
impl ToAnimatedValue for ZeroToOneNumber {
type AnimatedValue = CSSFloat;
#[inline]
fn to_animated_value(self) -> Self::AnimatedValue {
self.0
}
#[inline]
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
Self(animated.max(0.).min(1.))
}
}
impl From<CSSFloat> for ZeroToOneNumber {
#[inline]
fn from(number: CSSFloat) -> Self {
Self(number)
}
}
/// A wrapper of Number, but the value >= 1.
pub type GreaterThanOrEqualToOneNumber = GreaterThanOrEqualToOne<CSSFloat>;

View file

@ -11,23 +11,13 @@ use crate::values::generics::svg as generic;
use crate::values::RGBA;
use crate::Zero;
pub use crate::values::specified::SVGPaintOrder;
pub use crate::values::specified::MozContextProperties;
pub use crate::values::specified::{MozContextProperties, SVGPaintOrder};
/// Computed SVG Paint value
pub type SVGPaint = generic::SVGPaint<Color, ComputedUrl>;
/// Computed SVG Paint Kind value
pub type SVGPaintKind = generic::SVGPaintKind<Color, ComputedUrl>;
pub type SVGPaint = generic::GenericSVGPaint<Color, ComputedUrl>;
impl Default for SVGPaint {
fn default() -> Self {
SVGPaint {
kind: generic::SVGPaintKind::None,
fallback: None,
}
}
}
/// Computed SVG Paint Kind value
pub type SVGPaintKind = generic::GenericSVGPaintKind<Color, ComputedUrl>;
impl SVGPaint {
/// Opaque black color
@ -35,7 +25,7 @@ impl SVGPaint {
let rgba = RGBA::from_floats(0., 0., 0., 1.).into();
SVGPaint {
kind: generic::SVGPaintKind::Color(rgba),
fallback: None,
fallback: generic::SVGPaintFallback::Unset,
}
}
}
@ -62,16 +52,16 @@ impl SVGWidth {
}
/// [ <length> | <percentage> | <number> ]# | context-value
pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeLengthPercentage>;
pub type SVGStrokeDashArray = generic::GenericSVGStrokeDashArray<NonNegativeLengthPercentage>;
impl Default for SVGStrokeDashArray {
fn default() -> Self {
generic::SVGStrokeDashArray::Values(vec![])
generic::SVGStrokeDashArray::Values(Default::default())
}
}
/// <opacity-value> | context-fill-opacity | context-stroke-opacity
pub type SVGOpacity = generic::SVGOpacity<Opacity>;
pub type SVGOpacity = generic::GenericSVGOpacity<Opacity>;
impl Default for SVGOpacity {
fn default() -> Self {

View file

@ -19,9 +19,9 @@ use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
pub use crate::values::specified::TextAlignKeyword as TextAlign;
pub use crate::values::specified::TextTransform;
pub use crate::values::specified::{LineBreak, OverflowWrap, WordBreak};
pub use crate::values::specified::{TextDecorationLine, TextEmphasisPosition};
pub use crate::values::specified::{TextDecorationSkipInk, TextTransform};
/// A computed value for the `initial-letter` property.
pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;

View file

@ -70,7 +70,7 @@ pub enum TimingKeyword {
#[cfg(feature = "gecko")]
fn step_position_jump_enabled(_context: &ParserContext) -> bool {
use crate::gecko_bindings::structs;
unsafe { structs::StaticPrefs_sVarCache_layout_css_step_position_jump_enabled }
unsafe { structs::StaticPrefs::sVarCache_layout_css_step_position_jump_enabled }
}
#[cfg(feature = "servo")]

View file

@ -52,34 +52,34 @@ pub use self::GenericBoxShadow as BoxShadow;
ToShmem,
)]
#[repr(C, u8)]
pub enum GenericFilter<Angle, Factor, Length, Shadow, U> {
pub enum GenericFilter<Angle, NonNegativeFactor, ZeroToOneFactor, Length, Shadow, U> {
/// `blur(<length>)`
#[css(function)]
Blur(Length),
/// `brightness(<factor>)`
#[css(function)]
Brightness(Factor),
Brightness(NonNegativeFactor),
/// `contrast(<factor>)`
#[css(function)]
Contrast(Factor),
Contrast(NonNegativeFactor),
/// `grayscale(<factor>)`
#[css(function)]
Grayscale(Factor),
Grayscale(ZeroToOneFactor),
/// `hue-rotate(<angle>)`
#[css(function)]
HueRotate(Angle),
/// `invert(<factor>)`
#[css(function)]
Invert(Factor),
Invert(ZeroToOneFactor),
/// `opacity(<factor>)`
#[css(function)]
Opacity(Factor),
Opacity(ZeroToOneFactor),
/// `saturate(<factor>)`
#[css(function)]
Saturate(Factor),
Saturate(NonNegativeFactor),
/// `sepia(<factor>)`
#[css(function)]
Sepia(Factor),
Sepia(ZeroToOneFactor),
/// `drop-shadow(...)`
#[css(function)]
DropShadow(Shadow),

View file

@ -6,15 +6,22 @@
//! [grids](https://drafts.csswg.org/css-grid/).
use crate::parser::{Parse, ParserContext};
use crate::values::computed::{Context, ToComputedValue};
use crate::values::specified;
use crate::values::specified::grid::parse_line_names;
use crate::values::{CSSFloat, CustomIdent};
use crate::{Atom, Zero};
use cssparser::Parser;
use std::fmt::{self, Write};
use std::{mem, usize};
use std::{cmp, mem, usize};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
/// These are the limits that we choose to clamp grid line numbers to.
/// http://drafts.csswg.org/css-grid/#overlarge-grids
/// line_num is clamped to this range at parse time.
pub const MIN_GRID_LINE: i32 = -10000;
/// See above.
pub const MAX_GRID_LINE: i32 = 10000;
/// A `<grid-line>` type.
///
/// <https://drafts.csswg.org/css-grid/#typedef-grid-row-start-grid-line>
@ -29,36 +36,48 @@ use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
ToResolvedValue,
ToShmem,
)]
pub struct GridLine<Integer> {
/// Flag to check whether it's a `span` keyword.
pub is_span: bool,
/// A custom identifier for named lines.
#[repr(C)]
pub struct GenericGridLine<Integer> {
/// A custom identifier for named lines, or the empty atom otherwise.
///
/// <https://drafts.csswg.org/css-grid/#grid-placement-slot>
pub ident: Option<CustomIdent>,
pub ident: Atom,
/// Denotes the nth grid line from grid item's placement.
pub line_num: Option<Integer>,
///
/// This is clamped by MIN_GRID_LINE and MAX_GRID_LINE.
///
/// NOTE(emilio): If we ever allow animating these we need to either do
/// something more complicated for the clamping, or do this clamping at
/// used-value time.
pub line_num: Integer,
/// Flag to check whether it's a `span` keyword.
pub is_span: bool,
}
impl<Integer> GridLine<Integer> {
pub use self::GenericGridLine as GridLine;
impl<Integer> GridLine<Integer>
where
Integer: Zero,
{
/// The `auto` value.
pub fn auto() -> Self {
Self {
is_span: false,
line_num: None,
ident: None,
line_num: Zero::zero(),
ident: atom!(""),
}
}
/// Check whether this `<grid-line>` represents an `auto` value.
pub fn is_auto(&self) -> bool {
self.ident.is_none() && self.line_num.is_none() && !self.is_span
self.ident == atom!("") && self.line_num.is_zero() && !self.is_span
}
}
impl<Integer> ToCss for GridLine<Integer>
where
Integer: ToCss,
Integer: ToCss + Zero,
{
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
@ -72,18 +91,18 @@ where
dest.write_str("span")?;
}
if let Some(ref i) = self.line_num {
if !self.line_num.is_zero() {
if self.is_span {
dest.write_str(" ")?;
}
i.to_css(dest)?;
self.line_num.to_css(dest)?;
}
if let Some(ref s) = self.ident {
if self.is_span || self.line_num.is_some() {
if self.ident != atom!("") {
if self.is_span || !self.line_num.is_zero() {
dest.write_str(" ")?;
}
s.to_css(dest)?;
CustomIdent(self.ident.clone()).to_css(dest)?;
}
Ok(())
@ -114,25 +133,29 @@ impl Parse for GridLine<specified::Integer> {
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
if grid_line.line_num.is_some() || grid_line.ident.is_some() {
if !grid_line.line_num.is_zero() || grid_line.ident != atom!("") {
val_before_span = true;
}
grid_line.is_span = true;
} else if let Ok(i) = input.try(|i| specified::Integer::parse(context, i)) {
// FIXME(emilio): Probably shouldn't reject if it's calc()...
if i.value() == 0 || val_before_span || grid_line.line_num.is_some() {
let value = i.value();
if value == 0 || val_before_span || !grid_line.line_num.is_zero() {
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
grid_line.line_num = Some(i);
grid_line.line_num = specified::Integer::new(cmp::max(
MIN_GRID_LINE,
cmp::min(value, MAX_GRID_LINE),
));
} else if let Ok(name) = input.try(|i| i.expect_ident_cloned()) {
if val_before_span || grid_line.ident.is_some() {
if val_before_span || grid_line.ident != atom!("") {
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
// NOTE(emilio): `span` is consumed above, so we only need to
// reject `auto`.
grid_line.ident = Some(CustomIdent::from_ident(location, &name, &["auto"])?);
grid_line.ident = CustomIdent::from_ident(location, &name, &["auto"])?.0;
} else {
break;
}
@ -143,12 +166,12 @@ impl Parse for GridLine<specified::Integer> {
}
if grid_line.is_span {
if let Some(i) = grid_line.line_num {
if i.value() <= 0 {
if !grid_line.line_num.is_zero() {
if grid_line.line_num.value() <= 0 {
// disallow negative integers for grid spans
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
} else if grid_line.ident.is_none() {
} else if grid_line.ident == atom!("") {
// integer could be omitted
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
@ -158,33 +181,12 @@ impl Parse for GridLine<specified::Integer> {
}
}
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(
Animate,
Clone,
Copy,
Debug,
Eq,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
pub enum TrackKeyword {
Auto,
MaxContent,
MinContent,
}
/// A track breadth for explicit grid track sizing. It's generic solely to
/// avoid re-implementing it for the computed type.
///
/// <https://drafts.csswg.org/css-grid/#typedef-track-breadth>
///
/// cbindgen:derive-tagged-enum-copy-constructor=true
#[derive(
Animate,
Clone,
@ -197,16 +199,23 @@ pub enum TrackKeyword {
ToResolvedValue,
ToShmem,
)]
pub enum TrackBreadth<L> {
#[repr(C, u8)]
pub enum GenericTrackBreadth<L> {
/// The generic type is almost always a non-negative `<length-percentage>`
Breadth(L),
/// A flex fraction specified in `fr` units.
#[css(dimension)]
Fr(CSSFloat),
/// One of the track-sizing keywords (`auto`, `min-content`, `max-content`)
Keyword(TrackKeyword),
/// `auto`
Auto,
/// `min-content`
MinContent,
/// `max-content`
MaxContent,
}
pub use self::GenericTrackBreadth as TrackBreadth;
impl<L> TrackBreadth<L> {
/// Check whether this is a `<fixed-breadth>` (i.e., it only has `<length-percentage>`)
///
@ -221,23 +230,40 @@ impl<L> TrackBreadth<L> {
/// generic only to avoid code bloat. It only takes `<length-percentage>`
///
/// <https://drafts.csswg.org/css-grid/#typedef-track-size>
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToResolvedValue, ToShmem)]
pub enum TrackSize<L> {
///
/// cbindgen:derive-tagged-enum-copy-constructor=true
#[derive(
Clone,
Debug,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToResolvedValue,
ToShmem,
)]
#[repr(C, u8)]
pub enum GenericTrackSize<L> {
/// A flexible `<track-breadth>`
Breadth(TrackBreadth<L>),
Breadth(GenericTrackBreadth<L>),
/// A `minmax` function for a range over an inflexible `<track-breadth>`
/// and a flexible `<track-breadth>`
///
/// <https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-minmax>
#[css(function)]
Minmax(TrackBreadth<L>, TrackBreadth<L>),
Minmax(GenericTrackBreadth<L>, GenericTrackBreadth<L>),
/// A `fit-content` function.
///
/// This stores a TrackBreadth<L> for convenience, but it can only be a
/// LengthPercentage.
///
/// <https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-fit-content>
#[css(function)]
FitContent(L),
FitContent(GenericTrackBreadth<L>),
}
pub use self::GenericTrackSize as TrackSize;
impl<L> TrackSize<L> {
/// Check whether this is a `<fixed-size>`
///
@ -266,7 +292,7 @@ impl<L> TrackSize<L> {
impl<L> Default for TrackSize<L> {
fn default() -> Self {
TrackSize::Breadth(TrackBreadth::Keyword(TrackKeyword::Auto))
TrackSize::Breadth(TrackBreadth::Auto)
}
}
@ -287,7 +313,7 @@ impl<L: ToCss> ToCss for TrackSize<L> {
TrackSize::Minmax(ref min, ref max) => {
// According to gecko minmax(auto, <flex>) is equivalent to <flex>,
// and both are serialized as <flex>.
if let TrackBreadth::Keyword(TrackKeyword::Auto) = *min {
if let TrackBreadth::Auto = *min {
if let TrackBreadth::Fr(_) = *max {
return max.to_css(dest);
}
@ -308,48 +334,6 @@ impl<L: ToCss> ToCss for TrackSize<L> {
}
}
impl<L: ToComputedValue> ToComputedValue for TrackSize<L> {
type ComputedValue = TrackSize<L::ComputedValue>;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
match *self {
TrackSize::Breadth(TrackBreadth::Fr(ref f)) => {
// <flex> outside `minmax()` expands to `mimmax(auto, <flex>)`
// https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-flex
// FIXME(nox): This sounds false, the spec just says that <flex>
// implies `minmax(auto, <flex>)`, not that it should be changed
// into `minmax` at computed value time.
TrackSize::Minmax(
TrackBreadth::Keyword(TrackKeyword::Auto),
TrackBreadth::Fr(f.to_computed_value(context)),
)
},
TrackSize::Breadth(ref b) => TrackSize::Breadth(b.to_computed_value(context)),
TrackSize::Minmax(ref b1, ref b2) => {
TrackSize::Minmax(b1.to_computed_value(context), b2.to_computed_value(context))
},
TrackSize::FitContent(ref lp) => TrackSize::FitContent(lp.to_computed_value(context)),
}
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
match *computed {
TrackSize::Breadth(ref b) => {
TrackSize::Breadth(ToComputedValue::from_computed_value(b))
},
TrackSize::Minmax(ref b1, ref b2) => TrackSize::Minmax(
ToComputedValue::from_computed_value(b1),
ToComputedValue::from_computed_value(b2),
),
TrackSize::FitContent(ref lp) => {
TrackSize::FitContent(ToComputedValue::from_computed_value(lp))
},
}
}
}
/// Helper function for serializing identifiers with a prefix and suffix, used
/// for serializing <line-names> (in grid).
pub fn concat_serialize_idents<W>(

View file

@ -103,7 +103,12 @@ pub enum CounterStyleOrNone {
Name(CustomIdent),
/// `symbols()`
#[css(function)]
Symbols(SymbolsType, Symbols),
Symbols(#[css(skip_if = "is_symbolic")] SymbolsType, Symbols),
}
#[inline]
fn is_symbolic(symbols_type: &SymbolsType) -> bool {
*symbols_type == SymbolsType::Symbolic
}
impl CounterStyleOrNone {
@ -227,6 +232,28 @@ impl<T: Zero> Zero for NonNegative<T> {
)]
pub struct GreaterThanOrEqualToOne<T>(pub T);
/// A wrapper of values between zero and one.
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
Hash,
MallocSizeOf,
PartialEq,
PartialOrd,
SpecifiedValueInfo,
ToAnimatedZero,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
#[repr(transparent)]
pub struct ZeroToOne<T>(pub T);
/// A clip rect for clip and image-region
#[allow(missing_docs)]
#[derive(

View file

@ -5,14 +5,11 @@
//! Generic types for CSS values in SVG
use crate::parser::{Parse, ParserContext};
use crate::values::{Either, None_};
use cssparser::Parser;
use style_traits::{ParseError, StyleParseErrorKind};
use style_traits::ParseError;
/// An SVG paint value
///
/// <https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint>
#[animation(no_bound(UrlPaintServer))]
/// The fallback of an SVG paint server value.
/// cbindgen:derive-tagged-enum-copy-constructor=true
#[derive(
Animate,
Clone,
@ -20,26 +17,35 @@ use style_traits::{ParseError, StyleParseErrorKind};
Debug,
MallocSizeOf,
PartialEq,
Parse,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
pub struct SVGPaint<ColorType, UrlPaintServer> {
/// The paint source
pub kind: SVGPaintKind<ColorType, UrlPaintServer>,
/// The fallback color. It would be empty, the `none` keyword or <color>.
pub fallback: Option<Either<ColorType, None_>>,
#[repr(C, u8)]
pub enum GenericSVGPaintFallback<C> {
/// The `none` keyword.
None,
/// A magic value that represents no fallback specified and serializes to
/// the empty string.
#[css(skip)]
Unset,
/// A color.
Color(C),
}
/// An SVG paint value without the fallback
pub use self::GenericSVGPaintFallback as SVGPaintFallback;
/// An SVG paint value
///
/// Whereas the spec only allows PaintServer
/// to have a fallback, Gecko lets the context
/// properties have a fallback as well.
#[animation(no_bound(UrlPaintServer))]
/// <https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint>
///
/// cbindgen:derive-tagged-enum-copy-constructor=true
#[animation(no_bound(Url))]
#[derive(
Animate,
Clone,
@ -55,80 +61,82 @@ pub struct SVGPaint<ColorType, UrlPaintServer> {
ToResolvedValue,
ToShmem,
)]
pub enum SVGPaintKind<ColorType, UrlPaintServer> {
#[repr(C)]
pub struct GenericSVGPaint<Color, Url> {
/// The paint source.
pub kind: GenericSVGPaintKind<Color, Url>,
/// The fallback color.
pub fallback: GenericSVGPaintFallback<Color>,
}
pub use self::GenericSVGPaint as SVGPaint;
impl<C, U> Default for SVGPaint<C, U> {
fn default() -> Self {
Self {
kind: SVGPaintKind::None,
fallback: SVGPaintFallback::Unset,
}
}
}
/// An SVG paint value without the fallback.
///
/// Whereas the spec only allows PaintServer to have a fallback, Gecko lets the
/// context properties have a fallback as well.
///
/// cbindgen:derive-tagged-enum-copy-constructor=true
#[animation(no_bound(U))]
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Debug,
MallocSizeOf,
PartialEq,
Parse,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
#[repr(C, u8)]
pub enum GenericSVGPaintKind<C, U> {
/// `none`
#[animation(error)]
None,
/// `<color>`
Color(ColorType),
Color(C),
/// `url(...)`
#[animation(error)]
PaintServer(UrlPaintServer),
PaintServer(U),
/// `context-fill`
ContextFill,
/// `context-stroke`
ContextStroke,
}
impl<ColorType, UrlPaintServer> SVGPaintKind<ColorType, UrlPaintServer> {
/// Parse a keyword value only
fn parse_ident<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
try_match_ident_ignore_ascii_case! { input,
"none" => Ok(SVGPaintKind::None),
"context-fill" => Ok(SVGPaintKind::ContextFill),
"context-stroke" => Ok(SVGPaintKind::ContextStroke),
}
}
}
pub use self::GenericSVGPaintKind as SVGPaintKind;
/// Parse SVGPaint's fallback.
/// fallback is keyword(none), Color or empty.
/// <https://svgwg.org/svg2-draft/painting.html#SpecifyingPaint>
fn parse_fallback<'i, 't, ColorType: Parse>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Option<Either<ColorType, None_>> {
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
Some(Either::Second(None_))
} else {
if let Ok(color) = input.try(|i| ColorType::parse(context, i)) {
Some(Either::First(color))
} else {
None
}
}
}
impl<ColorType: Parse, UrlPaintServer: Parse> Parse for SVGPaint<ColorType, UrlPaintServer> {
impl<C: Parse, U: Parse> Parse for SVGPaint<C, U> {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if let Ok(url) = input.try(|i| UrlPaintServer::parse(context, i)) {
Ok(SVGPaint {
kind: SVGPaintKind::PaintServer(url),
fallback: parse_fallback(context, input),
})
} else if let Ok(kind) = input.try(SVGPaintKind::parse_ident) {
if let SVGPaintKind::None = kind {
Ok(SVGPaint {
kind: kind,
fallback: None,
})
} else {
Ok(SVGPaint {
kind: kind,
fallback: parse_fallback(context, input),
})
}
} else if let Ok(color) = input.try(|i| ColorType::parse(context, i)) {
Ok(SVGPaint {
kind: SVGPaintKind::Color(color),
fallback: None,
})
} else {
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
let kind = SVGPaintKind::parse(context, input)?;
if matches!(kind, SVGPaintKind::None | SVGPaintKind::Color(..)) {
return Ok(SVGPaint {
kind,
fallback: SVGPaintFallback::Unset,
});
}
let fallback = input
.try(|i| SVGPaintFallback::parse(context, i))
.unwrap_or(SVGPaintFallback::Unset);
Ok(SVGPaint { kind, fallback })
}
}
@ -171,14 +179,17 @@ pub enum SVGLength<L> {
ToResolvedValue,
ToShmem,
)]
pub enum SVGStrokeDashArray<L> {
#[repr(C, u8)]
pub enum GenericSVGStrokeDashArray<L> {
/// `[ <length> | <percentage> | <number> ]#`
#[css(comma)]
Values(#[css(if_empty = "none", iterable)] Vec<L>),
Values(#[css(if_empty = "none", iterable)] crate::OwnedSlice<L>),
/// `context-value`
ContextValue,
}
pub use self::GenericSVGStrokeDashArray as SVGStrokeDashArray;
/// An SVG opacity value accepts `context-{fill,stroke}-opacity` in
/// addition to opacity value.
#[derive(
@ -197,7 +208,8 @@ pub enum SVGStrokeDashArray<L> {
ToResolvedValue,
ToShmem,
)]
pub enum SVGOpacity<OpacityType> {
#[repr(C, u8)]
pub enum GenericSVGOpacity<OpacityType> {
/// `<opacity-value>`
Opacity(OpacityType),
/// `context-fill-opacity`
@ -207,3 +219,5 @@ pub enum SVGOpacity<OpacityType> {
#[animation(error)]
ContextStrokeOpacity,
}
pub use self::GenericSVGOpacity as SVGOpacity;

View file

@ -75,7 +75,7 @@ fn line_height_moz_block_height_enabled(context: &ParserContext) -> bool {
use crate::gecko_bindings::structs;
context.in_ua_sheet() ||
unsafe {
structs::StaticPrefs_sVarCache_layout_css_line_height_moz_block_height_content_enabled
structs::StaticPrefs::sVarCache_layout_css_line_height_moz_block_height_content_enabled
}
}

View file

@ -542,11 +542,7 @@ impl<T: ToMatrix> Transform<T> {
)
};
let (m, is_3d) = match self.to_transform_3d_matrix_f64(reference_box) {
Ok(result) => result,
Err(err) => return Err(err),
};
let (m, is_3d) = self.to_transform_3d_matrix_f64(reference_box)?;
Ok((cast_3d_transform(m), is_3d))
}

View file

@ -60,7 +60,7 @@ pub type Polygon = generic::GenericPolygon<LengthPercentage>;
fn is_clip_path_path_enabled(context: &ParserContext) -> bool {
use crate::gecko_bindings::structs::mozilla;
context.chrome_rules_enabled() ||
unsafe { mozilla::StaticPrefs_sVarCache_layout_css_clip_path_path_enabled }
unsafe { mozilla::StaticPrefs::sVarCache_layout_css_clip_path_path_enabled }
}
#[cfg(feature = "servo")]
fn is_clip_path_path_enabled(_: &ParserContext) -> bool {

View file

@ -242,7 +242,7 @@ impl Parse for BorderSpacing {
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Size2D::parse_with(context, input, |context, input| {
NonNegativeLength::parse_quirky(context, input, AllowQuirks::Yes).map(From::from)
NonNegativeLength::parse_quirky(context, input, AllowQuirks::Yes)
})
.map(GenericBorderSpacing)
}

View file

@ -25,7 +25,7 @@ use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
fn moz_display_values_enabled(context: &ParserContext) -> bool {
use crate::gecko_bindings::structs;
context.in_ua_or_chrome_sheet() ||
unsafe { structs::StaticPrefs_sVarCache_layout_css_xul_display_values_content_enabled }
unsafe { structs::StaticPrefs::sVarCache_layout_css_xul_display_values_content_enabled }
}
#[cfg(feature = "gecko")]
@ -33,7 +33,7 @@ fn moz_box_display_values_enabled(context: &ParserContext) -> bool {
use crate::gecko_bindings::structs;
context.in_ua_or_chrome_sheet() ||
unsafe {
structs::StaticPrefs_sVarCache_layout_css_xul_box_display_values_content_enabled
structs::StaticPrefs::sVarCache_layout_css_xul_box_display_values_content_enabled
}
}

View file

@ -8,6 +8,7 @@ use crate::parser::{Parse, ParserContext};
use crate::values::computed::effects::BoxShadow as ComputedBoxShadow;
use crate::values::computed::effects::SimpleShadow as ComputedSimpleShadow;
use crate::values::computed::NonNegativeNumber as ComputedNonNegativeNumber;
use crate::values::computed::ZeroToOneNumber as ComputedZeroToOneNumber;
use crate::values::computed::{Context, ToComputedValue};
use crate::values::generics::effects::BoxShadow as GenericBoxShadow;
use crate::values::generics::effects::Filter as GenericFilter;
@ -30,59 +31,57 @@ pub type BoxShadow =
/// A specified value for a single `filter`.
#[cfg(feature = "gecko")]
pub type SpecifiedFilter =
GenericFilter<Angle, Factor, NonNegativeLength, SimpleShadow, SpecifiedUrl>;
pub type SpecifiedFilter = GenericFilter<
Angle,
NonNegativeFactor,
ZeroToOneFactor,
NonNegativeLength,
SimpleShadow,
SpecifiedUrl,
>;
/// A specified value for a single `filter`.
#[cfg(feature = "servo")]
pub type SpecifiedFilter = GenericFilter<Angle, Factor, NonNegativeLength, Impossible, Impossible>;
pub type SpecifiedFilter = GenericFilter<
Angle,
NonNegativeFactor,
ZeroToOneFactor,
NonNegativeLength,
Impossible,
Impossible,
>;
pub use self::SpecifiedFilter as Filter;
/// A value for the `<factor>` parts in `Filter`.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
pub struct Factor(NumberOrPercentage);
pub struct NonNegativeFactor(NumberOrPercentage);
impl Factor {
/// Parse this factor but clamp to one if the value is over 100%.
#[inline]
pub fn parse_with_clamping_to_one<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Factor::parse(context, input).map(|v| v.clamp_to_one())
}
/// A value for the `<factor>` parts in `Filter` which clamps to one.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
pub struct ZeroToOneFactor(NumberOrPercentage);
/// Clamp the value to 1 if the value is over 100%.
#[inline]
fn clamp_to_one(self) -> Self {
match self.0 {
/// Clamp the value to 1 if the value is over 100%.
#[inline]
fn clamp_to_one(number: NumberOrPercentage) -> NumberOrPercentage {
match number {
NumberOrPercentage::Percentage(percent) => {
Factor(NumberOrPercentage::Percentage(percent.clamp_to_hundred()))
},
NumberOrPercentage::Number(number) => {
Factor(NumberOrPercentage::Number(number.clamp_to_one()))
NumberOrPercentage::Percentage(percent.clamp_to_hundred())
},
NumberOrPercentage::Number(number) => NumberOrPercentage::Number(number.clamp_to_one()),
}
}
}
macro_rules! factor_impl_common {
($ty:ty, $computed_ty:ty) => {
impl $ty {
fn one() -> Self {
Factor(NumberOrPercentage::Number(Number::new(1.0)))
Self(NumberOrPercentage::Number(Number::new(1.)))
}
}
impl Parse for Factor {
#[inline]
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
NumberOrPercentage::parse_non_negative(context, input).map(Factor)
}
}
impl ToComputedValue for Factor {
type ComputedValue = ComputedNonNegativeNumber;
impl ToComputedValue for $ty {
type ComputedValue = $computed_ty;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
@ -95,10 +94,36 @@ impl ToComputedValue for Factor {
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
Factor(NumberOrPercentage::Number(
Self(NumberOrPercentage::Number(
ToComputedValue::from_computed_value(&computed.0),
))
}
}
};
}
factor_impl_common!(NonNegativeFactor, ComputedNonNegativeNumber);
factor_impl_common!(ZeroToOneFactor, ComputedZeroToOneNumber);
impl Parse for NonNegativeFactor {
#[inline]
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
NumberOrPercentage::parse_non_negative(context, input).map(Self)
}
}
impl Parse for ZeroToOneFactor {
#[inline]
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
NumberOrPercentage::parse_non_negative(context, input)
.map(clamp_to_one)
.map(Self)
}
}
/// A specified value for the `drop-shadow()` filter.
@ -221,19 +246,19 @@ impl Parse for Filter {
.unwrap_or(Zero::zero()),
)),
"brightness" => Ok(GenericFilter::Brightness(
i.try(|i| Factor::parse(context, i))
.unwrap_or(Factor::one()),
i.try(|i| NonNegativeFactor::parse(context, i))
.unwrap_or(NonNegativeFactor::one()),
)),
"contrast" => Ok(GenericFilter::Contrast(
i.try(|i| Factor::parse(context, i))
.unwrap_or(Factor::one()),
i.try(|i| NonNegativeFactor::parse(context, i))
.unwrap_or(NonNegativeFactor::one()),
)),
"grayscale" => {
// Values of amount over 100% are allowed but UAs must clamp the values to 1.
// https://drafts.fxtf.org/filter-effects/#funcdef-filter-grayscale
Ok(GenericFilter::Grayscale(
i.try(|i| Factor::parse_with_clamping_to_one(context, i))
.unwrap_or(Factor::one()),
i.try(|i| ZeroToOneFactor::parse(context, i))
.unwrap_or(ZeroToOneFactor::one()),
))
},
"hue-rotate" => {
@ -248,28 +273,28 @@ impl Parse for Filter {
// Values of amount over 100% are allowed but UAs must clamp the values to 1.
// https://drafts.fxtf.org/filter-effects/#funcdef-filter-invert
Ok(GenericFilter::Invert(
i.try(|i| Factor::parse_with_clamping_to_one(context, i))
.unwrap_or(Factor::one()),
i.try(|i| ZeroToOneFactor::parse(context, i))
.unwrap_or(ZeroToOneFactor::one()),
))
},
"opacity" => {
// Values of amount over 100% are allowed but UAs must clamp the values to 1.
// https://drafts.fxtf.org/filter-effects/#funcdef-filter-opacity
Ok(GenericFilter::Opacity(
i.try(|i| Factor::parse_with_clamping_to_one(context, i))
.unwrap_or(Factor::one()),
i.try(|i| ZeroToOneFactor::parse(context, i))
.unwrap_or(ZeroToOneFactor::one()),
))
},
"saturate" => Ok(GenericFilter::Saturate(
i.try(|i| Factor::parse(context, i))
.unwrap_or(Factor::one()),
i.try(|i| NonNegativeFactor::parse(context, i))
.unwrap_or(NonNegativeFactor::one()),
)),
"sepia" => {
// Values of amount over 100% are allowed but UAs must clamp the values to 1.
// https://drafts.fxtf.org/filter-effects/#funcdef-filter-sepia
Ok(GenericFilter::Sepia(
i.try(|i| Factor::parse_with_clamping_to_one(context, i))
.unwrap_or(Factor::one()),
i.try(|i| ZeroToOneFactor::parse(context, i))
.unwrap_or(ZeroToOneFactor::one()),
))
},
"drop-shadow" => Ok(GenericFilter::DropShadow(Parse::parse(context, i)?)),

View file

@ -8,7 +8,7 @@
use crate::parser::{Parse, ParserContext};
use crate::values::computed::{self, Context, ToComputedValue};
use crate::values::generics::grid::{GridTemplateComponent, RepeatCount, TrackBreadth};
use crate::values::generics::grid::{LineNameList, TrackKeyword, TrackRepeat, TrackSize};
use crate::values::generics::grid::{LineNameList, TrackRepeat, TrackSize};
use crate::values::generics::grid::{TrackList, TrackListType, TrackListValue};
use crate::values::specified::{Integer, LengthPercentage};
use crate::values::{CSSFloat, CustomIdent};
@ -27,11 +27,32 @@ pub fn parse_flex<'i, 't>(input: &mut Parser<'i, 't>) -> Result<CSSFloat, ParseE
}
}
impl<L> TrackBreadth<L> {
fn parse_keyword<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
#[derive(Parse)]
enum TrackKeyword {
Auto,
MaxContent,
MinContent,
}
Ok(match TrackKeyword::parse(input)? {
TrackKeyword::Auto => TrackBreadth::Auto,
TrackKeyword::MaxContent => TrackBreadth::MaxContent,
TrackKeyword::MinContent => TrackBreadth::MinContent,
})
}
}
impl Parse for TrackBreadth<LengthPercentage> {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
// FIXME: This and other callers in this file should use
// NonNegativeLengthPercentage instead.
//
// Though it seems these cannot be animated so it's ~ok.
if let Ok(lp) = input.try(|i| LengthPercentage::parse_non_negative(context, i)) {
return Ok(TrackBreadth::Breadth(lp));
}
@ -40,7 +61,7 @@ impl Parse for TrackBreadth<LengthPercentage> {
return Ok(TrackBreadth::Fr(f));
}
TrackKeyword::parse(input).map(TrackBreadth::Keyword)
Self::parse_keyword(input)
}
}
@ -58,10 +79,7 @@ impl Parse for TrackSize<LengthPercentage> {
let inflexible_breadth =
match input.try(|i| LengthPercentage::parse_non_negative(context, i)) {
Ok(lp) => TrackBreadth::Breadth(lp),
Err(..) => {
let keyword = TrackKeyword::parse(input)?;
TrackBreadth::Keyword(keyword)
},
Err(..) => TrackBreadth::parse_keyword(input)?,
};
input.expect_comma()?;
@ -74,7 +92,7 @@ impl Parse for TrackSize<LengthPercentage> {
input.expect_function_matching("fit-content")?;
let lp = input.parse_nested_block(|i| LengthPercentage::parse_non_negative(context, i))?;
Ok(TrackSize::FitContent(lp))
Ok(TrackSize::FitContent(TrackBreadth::Breadth(lp)))
}
}
@ -381,7 +399,7 @@ impl ToComputedValue for TrackList<LengthPercentage, Integer> {
#[inline]
fn allow_grid_template_subgrids() -> bool {
use crate::gecko_bindings::structs::mozilla;
unsafe { mozilla::StaticPrefs_sVarCache_layout_css_grid_template_subgrid_value_enabled }
unsafe { mozilla::StaticPrefs::sVarCache_layout_css_grid_template_subgrid_value_enabled }
}
#[cfg(feature = "servo")]

View file

@ -17,9 +17,9 @@ use crate::context::QuirksMode;
use crate::parser::{Parse, ParserContext};
use crate::values::serialize_atom_identifier;
use crate::values::specified::calc::CalcNode;
use crate::{Atom, Namespace, Prefix};
use crate::{Atom, Namespace, Prefix, Zero};
use cssparser::{Parser, Token};
use num_traits::{One, Zero};
use num_traits::One;
use std::f32;
use std::fmt::{self, Write};
use std::ops::Add;
@ -74,14 +74,14 @@ pub use self::position::{PositionComponent, ZIndex};
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::{SVGLength, SVGOpacity, SVGPaint};
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
pub use self::svg_path::SVGPathData;
pub use self::table::XSpan;
pub use self::text::TextTransform;
pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight, TextAlign};
pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle, WordBreak};
pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing};
pub use self::text::{TextDecorationSkipInk, TextTransform};
pub use self::time::Time;
pub use self::transform::{Rotate, Scale, Transform};
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
@ -342,8 +342,6 @@ impl Parse for GreaterThanOrEqualToOneNumber {
/// <number> | <percentage>
///
/// Accepts only non-negative numbers.
///
/// FIXME(emilio): Should probably use Either.
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
pub enum NumberOrPercentage {
@ -449,6 +447,18 @@ pub struct Integer {
was_calc: bool,
}
impl Zero for Integer {
#[inline]
fn zero() -> Self {
Self::new(0)
}
#[inline]
fn is_zero(&self) -> bool {
self.value() == 0
}
}
impl One for Integer {
#[inline]
fn one() -> Self {

View file

@ -18,10 +18,7 @@ use style_traits::{CommaWithSpace, CssWriter, ParseError, Separator};
use style_traits::{StyleParseErrorKind, ToCss};
/// Specified SVG Paint value
pub type SVGPaint = generic::SVGPaint<Color, SpecifiedUrl>;
/// Specified SVG Paint Kind value
pub type SVGPaintKind = generic::SVGPaintKind<Color, SpecifiedUrl>;
pub type SVGPaint = generic::GenericSVGPaint<Color, SpecifiedUrl>;
/// <length> | <percentage> | <number> | context-value
pub type SVGLength = generic::SVGLength<LengthPercentage>;
@ -36,7 +33,7 @@ pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeLengthPerce
#[cfg(feature = "gecko")]
pub fn is_context_value_enabled() -> bool {
use crate::gecko_bindings::structs::mozilla;
unsafe { mozilla::StaticPrefs_sVarCache_gfx_font_rendering_opentype_svg_enabled }
unsafe { mozilla::StaticPrefs::sVarCache_gfx_font_rendering_opentype_svg_enabled }
}
/// Whether the `context-value` value is enabled.
@ -80,14 +77,14 @@ impl Parse for SVGStrokeDashArray {
NonNegativeLengthPercentage::parse_quirky(context, i, AllowQuirks::Always)
})
}) {
return Ok(generic::SVGStrokeDashArray::Values(values));
return Ok(generic::SVGStrokeDashArray::Values(values.into()));
}
try_match_ident_ignore_ascii_case! { input,
"context-value" if is_context_value_enabled() => {
Ok(generic::SVGStrokeDashArray::ContextValue)
},
"none" => Ok(generic::SVGStrokeDashArray::Values(vec![])),
"none" => Ok(generic::SVGStrokeDashArray::Values(Default::default())),
}
}
}
@ -200,7 +197,7 @@ impl Parse for SVGPaintOrder {
// fill in rest
for i in pos..PAINT_ORDER_COUNT {
for paint in 0..PAINT_ORDER_COUNT {
for paint in 1..(PAINT_ORDER_COUNT + 1) {
// if not seen, set bit at position, mark as seen
if (seen & (1 << paint)) == 0 {
seen |= 1 << paint;

View file

@ -1054,3 +1054,28 @@ pub enum OverflowWrap {
BreakWord,
Anywhere,
}
/// Implements text-decoration-skip-ink which takes the keywords auto | none
///
/// https://drafts.csswg.org/css-text-decor-4/#text-decoration-skip-ink-property
#[repr(u8)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(
Clone,
Copy,
Debug,
Eq,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
#[allow(missing_docs)]
pub enum TextDecorationSkipInk {
Auto,
None,
}