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

style: Sync changes from mozilla central.

See individual commits for details.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23194)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2019-04-12 09:22:28 -04:00 committed by GitHub
commit a74f5222db
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
174 changed files with 3687 additions and 2228 deletions

45
Cargo.lock generated
View file

@ -942,6 +942,17 @@ dependencies = [
"deny_public_fields 0.0.1", "deny_public_fields 0.0.1",
] ]
[[package]]
name = "derive_common"
version = "0.0.1"
dependencies = [
"darling 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "derive_more" name = "derive_more"
version = "0.13.0" version = "0.13.0"
@ -3646,6 +3657,8 @@ dependencies = [
"servo_arc 0.1.1", "servo_arc 0.1.1",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"to_shmem 0.0.1",
"to_shmem_derive 0.0.1",
] ]
[[package]] [[package]]
@ -3992,6 +4005,8 @@ dependencies = [
"malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_rand 0.0.1", "servo_rand 0.0.1",
"to_shmem 0.0.1",
"to_shmem_derive 0.0.1",
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -4240,6 +4255,8 @@ dependencies = [
"style_traits 0.0.1", "style_traits 0.0.1",
"thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
"to_shmem 0.0.1",
"to_shmem_derive 0.0.1",
"toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"uluru 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "uluru 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -4253,6 +4270,7 @@ name = "style_derive"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"darling 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "darling 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"derive_common 0.0.1",
"proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
@ -4297,6 +4315,8 @@ dependencies = [
"servo_arc 0.1.1", "servo_arc 0.1.1",
"servo_atoms 0.0.1", "servo_atoms 0.0.1",
"servo_url 0.0.1", "servo_url 0.0.1",
"to_shmem 0.0.1",
"to_shmem_derive 0.0.1",
"webrender_api 0.60.0 (git+https://github.com/servo/webrender)", "webrender_api 0.60.0 (git+https://github.com/servo/webrender)",
] ]
@ -4435,6 +4455,31 @@ dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "to_shmem"
version = "0.0.1"
dependencies = [
"cssparser 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_arc 0.1.1",
"smallbitvec 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "to_shmem_derive"
version = "0.0.1"
dependencies = [
"darling 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"derive_common 0.0.1",
"proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "0.1.8" version = "0.1.8"

View file

@ -0,0 +1,16 @@
[package]
name = "derive_common"
version = "0.0.1"
authors = ["The Servo Project Developers"]
license = "MPL-2.0"
publish = false
[lib]
path = "lib.rs"
[dependencies]
darling = "0.8"
proc-macro2 = "0.4"
quote = "0.6"
syn = { version = "0.15", features = ["visit"] }
synstructure = "0.10"

View file

@ -32,8 +32,8 @@ use synstructure::{self, BindStyle, BindingInfo, VariantAst, VariantInfo};
pub fn propagate_clauses_to_output_type( pub fn propagate_clauses_to_output_type(
where_clause: &mut Option<syn::WhereClause>, where_clause: &mut Option<syn::WhereClause>,
generics: &syn::Generics, generics: &syn::Generics,
trait_path: Path, trait_path: &Path,
trait_output: Ident, trait_output: &Ident,
) { ) {
let where_clause = match *where_clause { let where_clause = match *where_clause {
Some(ref mut clause) => clause, Some(ref mut clause) => clause,
@ -104,7 +104,7 @@ where
}) })
} }
pub fn fmap_trait_output(input: &DeriveInput, trait_path: &Path, trait_output: Ident) -> Path { pub fn fmap_trait_output(input: &DeriveInput, trait_path: &Path, trait_output: &Ident) -> Path {
let segment = PathSegment { let segment = PathSegment {
ident: input.ident.clone(), ident: input.ident.clone(),
arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments { arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {

View file

@ -0,0 +1,13 @@
/* 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/. */
extern crate darling;
extern crate proc_macro2;
#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;
extern crate synstructure;
pub mod cg;

View file

@ -26,7 +26,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc; use std::sync::Arc;
use style::computed_values::{font_stretch, font_style, font_variant_caps, font_weight}; use style::computed_values::{font_stretch, font_style, font_variant_caps, font_weight};
use style::properties::style_structs::Font as FontStyleStruct; use style::properties::style_structs::Font as FontStyleStruct;
use style::values::computed::font::SingleFontFamily; use style::values::computed::font::{GenericFontFamily, SingleFontFamily};
use unicode_script::Script; use unicode_script::Script;
macro_rules! ot_tag { macro_rules! ot_tag {
@ -564,9 +564,14 @@ impl<'a> From<&'a SingleFontFamily> for FontFamilyName {
FontFamilyName::Specific(family_name.name.clone()) FontFamilyName::Specific(family_name.name.clone())
}, },
SingleFontFamily::Generic(ref generic_name) => { SingleFontFamily::Generic(generic) => FontFamilyName::Generic(match generic {
FontFamilyName::Generic(generic_name.clone()) GenericFontFamily::None => panic!("Shouldn't appear in style"),
}, GenericFontFamily::Serif => atom!("serif"),
GenericFontFamily::SansSerif => atom!("sans-serif"),
GenericFontFamily::Monospace => atom!("monospace"),
GenericFontFamily::Cursive => atom!("cursive"),
GenericFontFamily::Fantasy => atom!("fantasy"),
}),
} }
} }
} }

View file

@ -20,7 +20,7 @@ use std::rc::Rc;
use style::properties::longhands::font_variant_caps::computed_value::T as FontVariantCaps; use style::properties::longhands::font_variant_caps::computed_value::T as FontVariantCaps;
use style::properties::style_structs::Font as FontStyleStruct; use style::properties::style_structs::Font as FontStyleStruct;
use style::values::computed::font::{ use style::values::computed::font::{
FamilyName, FamilyNameSyntax, FontFamily, FontFamilyList, FontSize, FamilyName, FontFamily, FontFamilyList, FontFamilyNameSyntax, FontSize,
}; };
use style::values::computed::font::{FontStretch, FontWeight, SingleFontFamily}; use style::values::computed::font::{FontStretch, FontWeight, SingleFontFamily};
use style::values::generics::font::FontStyle; use style::values::generics::font::FontStyle;
@ -114,7 +114,7 @@ fn font_family(names: Vec<&str>) -> FontFamily {
.map(|name| { .map(|name| {
SingleFontFamily::FamilyName(FamilyName { SingleFontFamily::FamilyName(FamilyName {
name: Atom::from(name), name: Atom::from(name),
syntax: FamilyNameSyntax::Quoted, syntax: FontFamilyNameSyntax::Quoted,
}) })
}) })
.collect(); .collect();

View file

@ -19,9 +19,10 @@ use std::fmt;
use std::sync::Arc; use std::sync::Arc;
use style::logical_geometry::LogicalSize; use style::logical_geometry::LogicalSize;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::values::computed::length::{MaxSize, NonNegativeLengthOrAuto, Size}; use style::values::computed::length::{
MaxSize, NonNegativeLengthOrAuto, NonNegativeLengthPercentageOrNormal, Size,
};
use style::values::generics::column::ColumnCount; use style::values::generics::column::ColumnCount;
use style::values::Either;
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe impl crate::flow::HasBaseFlow for MulticolFlow {} unsafe impl crate::flow::HasBaseFlow for MulticolFlow {}
@ -106,8 +107,10 @@ impl Flow for MulticolFlow {
{ {
let style = &self.block_flow.fragment.style; let style = &self.block_flow.fragment.style;
let column_gap = match style.get_position().column_gap { let column_gap = match style.get_position().column_gap {
Either::First(len) => len.0.to_pixel_length(content_inline_size).into(), NonNegativeLengthPercentageOrNormal::LengthPercentage(len) => {
Either::Second(_normal) => { len.0.to_pixel_length(content_inline_size).into()
},
NonNegativeLengthPercentageOrNormal::Normal => {
self.block_flow.fragment.style.get_font().font_size.size() self.block_flow.fragment.style.get_font().font_size.size()
}, },
}; };

View file

@ -643,6 +643,7 @@ impl LayoutElementHelpers for LayoutDom<Element> {
}; };
if let Some(font_family) = font_family { if let Some(font_family) = font_family {
// FIXME(emilio): This in Gecko parses a whole family list.
hints.push(from_declaration( hints.push(from_declaration(
shared_lock, shared_lock,
PropertyDeclaration::FontFamily(font_family::SpecifiedValue::Values( PropertyDeclaration::FontFamily(font_family::SpecifiedValue::Values(

View file

@ -31,6 +31,8 @@ precomputed-hash = "0.1"
servo_arc = { version = "0.1", path = "../servo_arc" } servo_arc = { version = "0.1", path = "../servo_arc" }
smallvec = "0.6" smallvec = "0.6"
thin-slice = "0.1.0" thin-slice = "0.1.0"
to_shmem = { path = "../to_shmem" }
to_shmem_derive = { path = "../to_shmem_derive" }
[build-dependencies] [build-dependencies]
phf_codegen = "0.7.18" phf_codegen = "0.7.18"

View file

@ -6,11 +6,15 @@ use crate::parser::SelectorImpl;
use cssparser::ToCss; use cssparser::ToCss;
use std::fmt; use std::fmt;
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq, ToShmem)]
#[shmem(no_bounds)]
pub struct AttrSelectorWithOptionalNamespace<Impl: SelectorImpl> { pub struct AttrSelectorWithOptionalNamespace<Impl: SelectorImpl> {
#[shmem(field_bound)]
pub namespace: Option<NamespaceConstraint<(Impl::NamespacePrefix, Impl::NamespaceUrl)>>, pub namespace: Option<NamespaceConstraint<(Impl::NamespacePrefix, Impl::NamespaceUrl)>>,
#[shmem(field_bound)]
pub local_name: Impl::LocalName, pub local_name: Impl::LocalName,
pub local_name_lower: Impl::LocalName, pub local_name_lower: Impl::LocalName,
#[shmem(field_bound)]
pub operation: ParsedAttrSelectorOperation<Impl::AttrValue>, pub operation: ParsedAttrSelectorOperation<Impl::AttrValue>,
pub never_matches: bool, pub never_matches: bool,
} }
@ -24,7 +28,7 @@ impl<Impl: SelectorImpl> AttrSelectorWithOptionalNamespace<Impl> {
} }
} }
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq, ToShmem)]
pub enum NamespaceConstraint<NamespaceUrl> { pub enum NamespaceConstraint<NamespaceUrl> {
Any, Any,
@ -32,7 +36,7 @@ pub enum NamespaceConstraint<NamespaceUrl> {
Specific(NamespaceUrl), Specific(NamespaceUrl),
} }
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq, ToShmem)]
pub enum ParsedAttrSelectorOperation<AttrValue> { pub enum ParsedAttrSelectorOperation<AttrValue> {
Exists, Exists,
WithValue { WithValue {
@ -72,7 +76,7 @@ impl<AttrValue> AttrSelectorOperation<AttrValue> {
} }
} }
#[derive(Clone, Copy, Eq, PartialEq)] #[derive(Clone, Copy, Eq, PartialEq, ToShmem)]
pub enum AttrSelectorOperator { pub enum AttrSelectorOperator {
Equal, Equal,
Includes, Includes,
@ -132,7 +136,7 @@ impl AttrSelectorOperator {
/// The definition of whitespace per CSS Selectors Level 3 § 4. /// The definition of whitespace per CSS Selectors Level 3 § 4.
pub static SELECTOR_WHITESPACE: &'static [char] = &[' ', '\t', '\n', '\r', '\x0C']; pub static SELECTOR_WHITESPACE: &'static [char] = &[' ', '\t', '\n', '\r', '\x0C'];
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq, ToShmem)]
pub enum ParsedCaseSensitivity { pub enum ParsedCaseSensitivity {
// 's' was specified. // 's' was specified.
ExplicitCaseSensitive, ExplicitCaseSensitive,

View file

@ -199,7 +199,7 @@ pub const HAS_SLOTTED_BIT: u32 = 1 << 31;
/// We use ten bits for each specificity kind (id, class, element), and the two /// We use ten bits for each specificity kind (id, class, element), and the two
/// high bits for the pseudo and slotted flags. /// high bits for the pseudo and slotted flags.
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq, ToShmem)]
pub struct SpecificityAndFlags(pub u32); pub struct SpecificityAndFlags(pub u32);
impl SpecificityAndFlags { impl SpecificityAndFlags {

View file

@ -21,6 +21,9 @@ extern crate precomputed_hash;
extern crate servo_arc; extern crate servo_arc;
extern crate smallvec; extern crate smallvec;
extern crate thin_slice; extern crate thin_slice;
extern crate to_shmem;
#[macro_use]
extern crate to_shmem_derive;
pub mod attr; pub mod attr;
pub mod bloom; pub mod bloom;

View file

@ -221,8 +221,11 @@ pub trait Parser<'i> {
} }
} }
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq, ToShmem)]
pub struct SelectorList<Impl: SelectorImpl>(pub SmallVec<[Selector<Impl>; 1]>); #[shmem(no_bounds)]
pub struct SelectorList<Impl: SelectorImpl>(
#[shmem(field_bound)] pub SmallVec<[Selector<Impl>; 1]>,
);
impl<Impl: SelectorImpl> SelectorList<Impl> { impl<Impl: SelectorImpl> SelectorList<Impl> {
/// Parse a comma-separated list of Selectors. /// Parse a comma-separated list of Selectors.
@ -507,8 +510,11 @@ pub fn namespace_empty_string<Impl: SelectorImpl>() -> Impl::NamespaceUrl {
/// ///
/// This reordering doesn't change the semantics of selector matching, and we /// This reordering doesn't change the semantics of selector matching, and we
/// handle it in to_css to make it invisible to serialization. /// handle it in to_css to make it invisible to serialization.
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq, ToShmem)]
pub struct Selector<Impl: SelectorImpl>(ThinArc<SpecificityAndFlags, Component<Impl>>); #[shmem(no_bounds)]
pub struct Selector<Impl: SelectorImpl>(
#[shmem(field_bound)] ThinArc<SpecificityAndFlags, Component<Impl>>,
);
impl<Impl: SelectorImpl> Selector<Impl> { impl<Impl: SelectorImpl> Selector<Impl> {
#[inline] #[inline]
@ -776,7 +782,7 @@ impl<'a, Impl: SelectorImpl> Iterator for AncestorIter<'a, Impl> {
} }
} }
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq, ToShmem)]
pub enum Combinator { pub enum Combinator {
Child, // > Child, // >
Descendant, // space Descendant, // space
@ -824,22 +830,27 @@ impl Combinator {
/// optimal packing and cache performance, see [1]. /// optimal packing and cache performance, see [1].
/// ///
/// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1357973 /// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1357973
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq, ToShmem)]
#[shmem(no_bounds)]
pub enum Component<Impl: SelectorImpl> { pub enum Component<Impl: SelectorImpl> {
Combinator(Combinator), Combinator(Combinator),
ExplicitAnyNamespace, ExplicitAnyNamespace,
ExplicitNoNamespace, ExplicitNoNamespace,
DefaultNamespace(Impl::NamespaceUrl), DefaultNamespace(#[shmem(field_bound)] Impl::NamespaceUrl),
Namespace(Impl::NamespacePrefix, Impl::NamespaceUrl), Namespace(
#[shmem(field_bound)] Impl::NamespacePrefix,
#[shmem(field_bound)] Impl::NamespaceUrl,
),
ExplicitUniversalType, ExplicitUniversalType,
LocalName(LocalName<Impl>), LocalName(LocalName<Impl>),
ID(Impl::Identifier), ID(#[shmem(field_bound)] Impl::Identifier),
Class(Impl::ClassName), Class(#[shmem(field_bound)] Impl::ClassName),
AttributeInNoNamespaceExists { AttributeInNoNamespaceExists {
#[shmem(field_bound)]
local_name: Impl::LocalName, local_name: Impl::LocalName,
local_name_lower: Impl::LocalName, local_name_lower: Impl::LocalName,
}, },
@ -847,6 +858,7 @@ pub enum Component<Impl: SelectorImpl> {
AttributeInNoNamespace { AttributeInNoNamespace {
local_name: Impl::LocalName, local_name: Impl::LocalName,
operator: AttrSelectorOperator, operator: AttrSelectorOperator,
#[shmem(field_bound)]
value: Impl::AttrValue, value: Impl::AttrValue,
case_sensitivity: ParsedCaseSensitivity, case_sensitivity: ParsedCaseSensitivity,
never_matches: bool, never_matches: bool,
@ -878,7 +890,7 @@ pub enum Component<Impl: SelectorImpl> {
FirstOfType, FirstOfType,
LastOfType, LastOfType,
OnlyOfType, OnlyOfType,
NonTSPseudoClass(Impl::NonTSPseudoClass), NonTSPseudoClass(#[shmem(field_bound)] Impl::NonTSPseudoClass),
/// The ::slotted() pseudo-element (which isn't actually a pseudo-element, /// The ::slotted() pseudo-element (which isn't actually a pseudo-element,
/// and probably should be a pseudo-class): /// and probably should be a pseudo-class):
/// ///
@ -902,7 +914,7 @@ pub enum Component<Impl: SelectorImpl> {
/// ///
/// See https://github.com/w3c/csswg-drafts/issues/2158 /// See https://github.com/w3c/csswg-drafts/issues/2158
Host(Option<Selector<Impl>>), Host(Option<Selector<Impl>>),
PseudoElement(Impl::PseudoElement), PseudoElement(#[shmem(field_bound)] Impl::PseudoElement),
} }
impl<Impl: SelectorImpl> Component<Impl> { impl<Impl: SelectorImpl> Component<Impl> {
@ -957,8 +969,10 @@ impl<Impl: SelectorImpl> Component<Impl> {
} }
} }
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq, ToShmem)]
#[shmem(no_bounds)]
pub struct LocalName<Impl: SelectorImpl> { pub struct LocalName<Impl: SelectorImpl> {
#[shmem(field_bound)]
pub name: Impl::LocalName, pub name: Impl::LocalName,
pub lower_name: Impl::LocalName, pub lower_name: Impl::LocalName,
} }

View file

@ -16,6 +16,8 @@
//! * We can add methods to support our custom use cases [1]. //! * We can add methods to support our custom use cases [1].
//! * We have support for dynamically-sized types (see from_header_and_iter). //! * We have support for dynamically-sized types (see from_header_and_iter).
//! * We have support for thin arcs to unsized types (see ThinArc). //! * We have support for thin arcs to unsized types (see ThinArc).
//! * We have support for references to static data, which don't do any
//! refcounting.
//! //!
//! [1]: https://bugzilla.mozilla.org/show_bug.cgi?id=1360883 //! [1]: https://bugzilla.mozilla.org/show_bug.cgi?id=1360883
@ -32,6 +34,7 @@ use nodrop::NoDrop;
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use stable_deref_trait::{CloneStableDeref, StableDeref}; use stable_deref_trait::{CloneStableDeref, StableDeref};
use std::alloc::Layout;
use std::borrow; use std::borrow;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::convert::From; use std::convert::From;
@ -74,6 +77,10 @@ macro_rules! offset_of {
/// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. /// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references.
const MAX_REFCOUNT: usize = (isize::MAX) as usize; const MAX_REFCOUNT: usize = (isize::MAX) as usize;
/// Special refcount value that means the data is not reference counted,
/// and that the `Arc` is really acting as a read-only static reference.
const STATIC_REFCOUNT: usize = usize::MAX;
/// An atomically reference counted shared pointer /// An atomically reference counted shared pointer
/// ///
/// See the documentation for [`Arc`] in the standard library. Unlike the /// See the documentation for [`Arc`] in the standard library. Unlike the
@ -194,6 +201,32 @@ impl<T> Arc<T> {
} }
} }
/// Create a new static Arc<T> (one that won't reference count the object)
/// and place it in the allocation provided by the specified `alloc`
/// function.
///
/// `alloc` must return a pointer into a static allocation suitable for
/// storing data with the `Layout` passed into it. The pointer returned by
/// `alloc` will not be freed.
#[inline]
pub unsafe fn new_static<F>(alloc: F, data: T) -> Arc<T>
where
F: FnOnce(Layout) -> *mut u8,
{
let ptr = alloc(Layout::new::<ArcInner<T>>()) as *mut ArcInner<T>;
let x = ArcInner {
count: atomic::AtomicUsize::new(STATIC_REFCOUNT),
data,
};
ptr::write(ptr, x);
Arc {
p: ptr::NonNull::new_unchecked(ptr),
}
}
/// Produce a pointer to the data that can be converted back /// Produce a pointer to the data that can be converted back
/// to an Arc. This is basically an `&Arc<T>`, without the extra indirection. /// to an Arc. This is basically an `&Arc<T>`, without the extra indirection.
/// It has the benefits of an `&T` but also knows about the underlying refcount /// It has the benefits of an `&T` but also knows about the underlying refcount
@ -225,8 +258,14 @@ impl<T> Arc<T> {
/// Returns the address on the heap of the Arc itself -- not the T within it -- for memory /// Returns the address on the heap of the Arc itself -- not the T within it -- for memory
/// reporting. /// reporting.
///
/// If this is a static reference, this returns null.
pub fn heap_ptr(&self) -> *const c_void { pub fn heap_ptr(&self) -> *const c_void {
self.p.as_ptr() as *const ArcInner<T> as *const c_void if self.inner().count.load(Relaxed) == STATIC_REFCOUNT {
ptr::null()
} else {
self.p.as_ptr() as *const ArcInner<T> as *const c_void
}
} }
} }
@ -262,30 +301,34 @@ impl<T: ?Sized> Arc<T> {
impl<T: ?Sized> Clone for Arc<T> { impl<T: ?Sized> Clone for Arc<T> {
#[inline] #[inline]
fn clone(&self) -> Self { fn clone(&self) -> Self {
// Using a relaxed ordering is alright here, as knowledge of the // Using a relaxed ordering to check for STATIC_REFCOUNT is safe, since
// original reference prevents other threads from erroneously deleting // `count` never changes between STATIC_REFCOUNT and other values.
// the object. if self.inner().count.load(Relaxed) != STATIC_REFCOUNT {
// // Using a relaxed ordering is alright here, as knowledge of the
// As explained in the [Boost documentation][1], Increasing the // original reference prevents other threads from erroneously deleting
// reference counter can always be done with memory_order_relaxed: New // the object.
// references to an object can only be formed from an existing //
// reference, and passing an existing reference from one thread to // As explained in the [Boost documentation][1], Increasing the
// another must already provide any required synchronization. // reference counter can always be done with memory_order_relaxed: New
// // references to an object can only be formed from an existing
// [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) // reference, and passing an existing reference from one thread to
let old_size = self.inner().count.fetch_add(1, Relaxed); // another must already provide any required synchronization.
//
// [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
let old_size = self.inner().count.fetch_add(1, Relaxed);
// However we need to guard against massive refcounts in case someone // However we need to guard against massive refcounts in case someone
// is `mem::forget`ing Arcs. If we don't do this the count can overflow // is `mem::forget`ing Arcs. If we don't do this the count can overflow
// and users will use-after free. We racily saturate to `isize::MAX` on // and users will use-after free. We racily saturate to `isize::MAX` on
// the assumption that there aren't ~2 billion threads incrementing // the assumption that there aren't ~2 billion threads incrementing
// the reference count at once. This branch will never be taken in // the reference count at once. This branch will never be taken in
// any realistic program. // any realistic program.
// //
// We abort because such a program is incredibly degenerate, and we // We abort because such a program is incredibly degenerate, and we
// don't care to support it. // don't care to support it.
if old_size > MAX_REFCOUNT { if old_size > MAX_REFCOUNT {
process::abort(); process::abort();
}
} }
unsafe { unsafe {
@ -351,7 +394,8 @@ impl<T: ?Sized> Arc<T> {
} }
} }
/// Whether or not the `Arc` is uniquely owned (is the refcount 1?) /// Whether or not the `Arc` is uniquely owned (is the refcount 1?) and not
/// a static reference.
#[inline] #[inline]
pub fn is_unique(&self) -> bool { pub fn is_unique(&self) -> bool {
// See the extensive discussion in [1] for why this needs to be Acquire. // See the extensive discussion in [1] for why this needs to be Acquire.
@ -364,6 +408,12 @@ impl<T: ?Sized> Arc<T> {
impl<T: ?Sized> Drop for Arc<T> { impl<T: ?Sized> Drop for Arc<T> {
#[inline] #[inline]
fn drop(&mut self) { fn drop(&mut self) {
// Using a relaxed ordering to check for STATIC_REFCOUNT is safe, since
// `count` never changes between STATIC_REFCOUNT and other values.
if self.inner().count.load(Relaxed) == STATIC_REFCOUNT {
return;
}
// Because `fetch_sub` is already atomic, we do not need to synchronize // Because `fetch_sub` is already atomic, we do not need to synchronize
// with other threads unless we are going to delete the object. // with other threads unless we are going to delete the object.
if self.inner().count.fetch_sub(1, Release) != 1 { if self.inner().count.fetch_sub(1, Release) != 1 {
@ -528,10 +578,20 @@ fn divide_rounding_up(dividend: usize, divisor: usize) -> usize {
impl<H, T> Arc<HeaderSlice<H, [T]>> { impl<H, T> Arc<HeaderSlice<H, [T]>> {
/// Creates an Arc for a HeaderSlice using the given header struct and /// Creates an Arc for a HeaderSlice using the given header struct and
/// iterator to generate the slice. The resulting Arc will be fat. /// iterator to generate the slice.
///
/// `is_static` indicates whether to create a static Arc.
///
/// `alloc` is used to get a pointer to the memory into which the
/// dynamically sized ArcInner<HeaderSlice<H, T>> value will be
/// written. If `is_static` is true, then `alloc` must return a
/// pointer into some static memory allocation. If it is false,
/// then `alloc` must return an allocation that can be dellocated
/// by calling Box::from_raw::<ArcInner<HeaderSlice<H, T>>> on it.
#[inline] #[inline]
pub fn from_header_and_iter<I>(header: H, mut items: I) -> Self fn from_header_and_iter_alloc<F, I>(alloc: F, header: H, mut items: I, is_static: bool) -> Self
where where
F: FnOnce(Layout) -> *mut u8,
I: Iterator<Item = T> + ExactSizeIterator, I: Iterator<Item = T> + ExactSizeIterator,
{ {
use std::mem::size_of; use std::mem::size_of;
@ -565,22 +625,20 @@ impl<H, T> Arc<HeaderSlice<H, [T]>> {
let ptr: *mut ArcInner<HeaderSlice<H, [T]>>; let ptr: *mut ArcInner<HeaderSlice<H, [T]>>;
unsafe { unsafe {
// Allocate the buffer. We use Vec because the underlying allocation // Allocate the buffer.
// machinery isn't available in stable Rust. let layout = if mem::align_of::<T>() <= mem::align_of::<usize>() {
// Layout::from_size_align_unchecked(size, mem::align_of::<usize>())
// To avoid alignment issues, we allocate words rather than bytes,
// rounding up to the nearest word size.
let buffer = if mem::align_of::<T>() <= mem::align_of::<usize>() {
Self::allocate_buffer::<usize>(size)
} else if mem::align_of::<T>() <= mem::align_of::<u64>() { } else if mem::align_of::<T>() <= mem::align_of::<u64>() {
// On 32-bit platforms <T> may have 8 byte alignment while usize has 4 byte aligment. // On 32-bit platforms <T> may have 8 byte alignment while usize has 4 byte aligment.
// Use u64 to avoid over-alignment. // Use u64 to avoid over-alignment.
// This branch will compile away in optimized builds. // This branch will compile away in optimized builds.
Self::allocate_buffer::<u64>(size) Layout::from_size_align_unchecked(size, mem::align_of::<u64>())
} else { } else {
panic!("Over-aligned type not handled"); panic!("Over-aligned type not handled");
}; };
let buffer = alloc(layout);
// Synthesize the fat pointer. We do this by claiming we have a direct // Synthesize the fat pointer. We do this by claiming we have a direct
// pointer to a [T], and then changing the type of the borrow. The key // pointer to a [T], and then changing the type of the borrow. The key
// point here is that the length portion of the fat pointer applies // point here is that the length portion of the fat pointer applies
@ -594,7 +652,12 @@ impl<H, T> Arc<HeaderSlice<H, [T]>> {
// //
// Note that any panics here (i.e. from the iterator) are safe, since // Note that any panics here (i.e. from the iterator) are safe, since
// we'll just leak the uninitialized memory. // we'll just leak the uninitialized memory.
ptr::write(&mut ((*ptr).count), atomic::AtomicUsize::new(1)); let count = if is_static {
atomic::AtomicUsize::new(STATIC_REFCOUNT)
} else {
atomic::AtomicUsize::new(1)
};
ptr::write(&mut ((*ptr).count), count);
ptr::write(&mut ((*ptr).data.header), header); ptr::write(&mut ((*ptr).data.header), header);
let mut current: *mut T = &mut (*ptr).data.slice[0]; let mut current: *mut T = &mut (*ptr).data.slice[0];
for _ in 0..num_items { for _ in 0..num_items {
@ -628,8 +691,37 @@ impl<H, T> Arc<HeaderSlice<H, [T]>> {
} }
} }
/// Creates an Arc for a HeaderSlice using the given header struct and
/// iterator to generate the slice. The resulting Arc will be fat.
#[inline]
pub fn from_header_and_iter<I>(header: H, items: I) -> Self
where
I: Iterator<Item = T> + ExactSizeIterator,
{
Arc::from_header_and_iter_alloc(
|layout| {
// align will only ever be align_of::<usize>() or align_of::<u64>()
let align = layout.align();
unsafe {
if align == mem::align_of::<usize>() {
Self::allocate_buffer::<usize>(layout.size())
} else {
assert_eq!(align, mem::align_of::<u64>());
Self::allocate_buffer::<u64>(layout.size())
}
}
},
header,
items,
/* is_static = */ false,
)
}
#[inline] #[inline]
unsafe fn allocate_buffer<W>(size: usize) -> *mut u8 { unsafe fn allocate_buffer<W>(size: usize) -> *mut u8 {
// We use Vec because the underlying allocation machinery isn't
// available in stable Rust. To avoid alignment issues, we allocate
// words rather than bytes, rounding up to the nearest word size.
let words_to_allocate = divide_rounding_up(size, mem::size_of::<W>()); let words_to_allocate = divide_rounding_up(size, mem::size_of::<W>());
let mut vec = Vec::<W>::with_capacity(words_to_allocate); let mut vec = Vec::<W>::with_capacity(words_to_allocate);
vec.set_len(words_to_allocate); vec.set_len(words_to_allocate);
@ -730,11 +822,37 @@ impl<H, T> ThinArc<H, T> {
Arc::into_thin(Arc::from_header_and_iter(header, items)) Arc::into_thin(Arc::from_header_and_iter(header, items))
} }
/// Create a static `ThinArc` for a HeaderSlice using the given header
/// struct and iterator to generate the slice, placing it in the allocation
/// provided by the specified `alloc` function.
///
/// `alloc` must return a pointer into a static allocation suitable for
/// storing data with the `Layout` passed into it. The pointer returned by
/// `alloc` will not be freed.
pub unsafe fn static_from_header_and_iter<F, I>(alloc: F, header: H, items: I) -> Self
where
F: FnOnce(Layout) -> *mut u8,
I: Iterator<Item = T> + ExactSizeIterator,
{
let header = HeaderWithLength::new(header, items.len());
Arc::into_thin(Arc::from_header_and_iter_alloc(
alloc, header, items, /* is_static = */ true,
))
}
/// Returns the address on the heap of the ThinArc itself -- not the T /// Returns the address on the heap of the ThinArc itself -- not the T
/// within it -- for memory reporting. /// within it -- for memory reporting.
///
/// If this is a static ThinArc, this returns null.
#[inline] #[inline]
pub fn heap_ptr(&self) -> *const c_void { pub fn heap_ptr(&self) -> *const c_void {
self.ptr as *const ArcInner<T> as *const c_void let is_static =
ThinArc::with_arc(self, |a| a.inner().count.load(Relaxed) == STATIC_REFCOUNT);
if is_static {
ptr::null()
} else {
self.ptr as *const ArcInner<T> as *const c_void
}
} }
} }

View file

@ -20,7 +20,7 @@ gecko = ["style_traits/gecko", "fallible/known_system_malloc"]
use_bindgen = ["bindgen", "regex", "toml"] use_bindgen = ["bindgen", "regex", "toml"]
servo = ["serde", "style_traits/servo", "servo_atoms", "servo_config", "html5ever", servo = ["serde", "style_traits/servo", "servo_atoms", "servo_config", "html5ever",
"cssparser/serde", "encoding_rs", "malloc_size_of/servo", "arrayvec/use_union", "cssparser/serde", "encoding_rs", "malloc_size_of/servo", "arrayvec/use_union",
"servo_url", "string_cache", "crossbeam-channel"] "servo_url", "string_cache", "crossbeam-channel", "to_shmem/servo", "servo_arc/servo"]
gecko_debug = [] gecko_debug = []
[dependencies] [dependencies]
@ -68,6 +68,8 @@ style_derive = {path = "../style_derive"}
style_traits = {path = "../style_traits"} style_traits = {path = "../style_traits"}
servo_url = {path = "../url", optional = true} servo_url = {path = "../url", optional = true}
thin-slice = "0.1.0" thin-slice = "0.1.0"
to_shmem = {path = "../to_shmem"}
to_shmem_derive = {path = "../to_shmem_derive"}
time = "0.1" time = "0.1"
uluru = "0.3" uluru = "0.3"
unicode-bidi = "0.3" unicode-bidi = "0.3"

View file

@ -339,8 +339,6 @@ mod bindings {
} }
fn setup_logging() -> bool { fn setup_logging() -> bool {
use log;
struct BuildLogger { struct BuildLogger {
file: Option<Mutex<fs::File>>, file: Option<Mutex<fs::File>>,
filter: String, filter: String,

View file

@ -1,239 +0,0 @@
header = """/* 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/. */"""
autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen.
* To generate this file:
* 1. Get the latest cbindgen using `cargo install --force cbindgen`
* a. Alternatively, you can clone `https://github.com/eqrion/cbindgen` and use a tagged release
* 2. Run `rustup run nightly cbindgen toolkit/library/rust/ --lockfile Cargo.lock --crate style -o layout/style/ServoStyleConsts.h`
*/
#include "nsCoord.h"
#include "Units.h"
#include "mozilla/gfx/Types.h"
class nsAtom;
namespace mozilla {
class WritingMode;
enum HalfCorner : uint8_t;
enum LogicalSide : uint8_t;
namespace css {
struct URLValue;
}
// Work-around weird cbindgen renaming.
typedef css::URLValue StyleURLValue;
typedef nsAtom StylensAtom;
}
"""
include_guard = "mozilla_ServoStyleConsts_h"
include_version = true
braces = "SameLine"
line_length = 80
tab_width = 2
language = "C++"
namespaces = ["mozilla"]
[parse]
parse_deps = true
include = ["cssparser", "style_traits"]
[struct]
derive_eq = true
derive_neq = true
[macro_expansion]
bitflags = true
[enum]
derive_helper_methods = true
derive_const_casts = true
cast_assert_name = "MOZ_ASSERT"
[export]
prefix = "Style"
include = [
"Appearance",
"BreakBetween",
"BreakWithin",
"BorderStyle",
"OutlineStyle",
"ComputedFontStretchRange",
"ComputedFontStyleDescriptor",
"ComputedFontWeightRange",
"ComputedTimingFunction",
"CursorKind",
"Display",
"DisplayMode",
"PrefersColorScheme",
"ExtremumLength",
"FillRule",
"FontDisplay",
"FontFaceSourceListComponent",
"FontLanguageOverride",
"OverflowWrap",
"TimingFunction",
"PathCommand",
"UnicodeRange",
"UserSelect",
"Float",
"OverscrollBehavior",
"ScrollSnapAlign",
"ScrollSnapType",
"OverflowAnchor",
"OverflowClipBox",
"Resize",
"Overflow",
"LengthPercentage",
"LetterSpacing",
"NonNegativeLengthPercentage",
"LengthPercentageOrAuto",
"LineHeight",
"NonNegativeLengthPercentageOrAuto",
"Rect",
"IntersectionObserverRootMargin",
"Size",
"MaxSize",
"FlexBasis",
"Position",
"BackgroundSize",
"BorderImageSlice",
"BorderSpacing",
"BorderRadius",
"NonNegativeLengthOrNumberRect",
"Perspective",
"ZIndex",
"TransformOrigin",
"WordBreak",
"Contain",
"RestyleHint",
"TouchAction",
"WillChangeBits",
"TextDecorationLine",
"MozListReversed",
"Owned",
"OwnedOrNull",
"Strong",
]
item_types = ["enums", "structs", "typedefs"]
[export.body]
"CSSPixelLength" = """
inline nscoord ToAppUnits() const;
inline bool IsZero() const;
"""
"LengthPercentage" = """
// Defined in nsStyleCoord.h
static constexpr inline StyleLengthPercentage Zero();
static inline StyleLengthPercentage FromAppUnits(nscoord);
static inline StyleLengthPercentage FromPixels(CSSCoord);
static inline StyleLengthPercentage FromPercentage(float);
inline CSSCoord LengthInCSSPixels() const;
inline float Percentage() const;
inline bool HasPercent() const;
inline bool ConvertsToLength() const;
inline nscoord ToLength() const;
inline bool ConvertsToPercentage() const;
inline bool HasLengthAndPercentage() const;
inline float ToPercentage() const;
inline bool IsDefinitelyZero() const;
inline CSSCoord ResolveToCSSPixels(CSSCoord aPercentageBasisInCSSPixels) const;
template<typename T> inline CSSCoord ResolveToCSSPixelsWith(T aPercentageGetter) const;
template<typename T, typename U>
inline nscoord Resolve(T aPercentageGetter, U aPercentRoundingFunction) const;
template<typename T>
inline nscoord Resolve(nscoord aPercentageBasis, T aPercentRoundingFunction) const;
template<typename T> inline nscoord Resolve(T aPercentageGetter) const;
inline nscoord Resolve(nscoord aPercentageBasis) const;
"""
"GenericLengthPercentageOrAuto" = """
inline bool ConvertsToLength() const;
inline nscoord ToLength() const;
inline bool ConvertsToPercentage() const;
inline float ToPercentage() const;
inline bool HasPercent() const;
inline bool HasLengthAndPercentage() const;
"""
"GenericSize" = """
inline bool ConvertsToLength() const;
inline nscoord ToLength() const;
inline bool ConvertsToPercentage() const;
inline float ToPercentage() const;
inline bool HasPercent() const;
inline bool HasLengthAndPercentage() const;
inline bool BehavesLikeInitialValueOnBlockAxis() const;
"""
"GenericFlexBasis" = """
inline bool IsAuto() const;
"""
"GenericMaxSize" = """
inline bool ConvertsToLength() const;
inline nscoord ToLength() const;
inline bool ConvertsToPercentage() const;
inline float ToPercentage() const;
inline bool HasPercent() const;
inline bool HasLengthAndPercentage() const;
inline bool BehavesLikeInitialValueOnBlockAxis() const;
"""
"GenericPosition" = """
inline bool DependsOnPositioningAreaSize() const;
static inline StyleGenericPosition FromPercentage(float);
"""
"GenericBackgroundSize" = """
bool IsInitialValue() const;
"""
"Rect" = """
// Defined in nsStyleCoord.h
template<typename Predicate> inline bool All(Predicate) const;
template<typename Predicate> inline bool Any(Predicate) const;
// Defined in WritingModes.h
inline const T& Get(mozilla::Side) const;
inline const T& Get(mozilla::WritingMode, mozilla::LogicalSide) const;
inline const T& GetIStart(mozilla::WritingMode) const;
inline const T& GetBStart(mozilla::WritingMode) const;
inline const T& GetIEnd(mozilla::WritingMode) const;
inline const T& GetBEnd(mozilla::WritingMode) const;
"""
"GenericBorderRadius" = """
inline const StyleLengthPercentage& Get(mozilla::HalfCorner) const;
"""
"RestyleHint" = """
static inline StyleRestyleHint RestyleSubtree();
static inline StyleRestyleHint RecascadeSubtree();
static inline StyleRestyleHint ForAnimations();
"""
# TODO(emilio): Add hooks to cbindgen to be able to generate MOZ_MUST_USE_TYPE
# or MOZ_MUST_USE on the functions.
"Owned" = """
UniquePtr<GeckoType> Consume() {
UniquePtr<GeckoType> ret(ptr);
ptr = nullptr;
return ret;
}
"""
"OwnedOrNull" = """
UniquePtr<GeckoType> Consume() {
UniquePtr<GeckoType> ret(ptr);
ptr = nullptr;
return ret;
}
"""
"Strong" = """
already_AddRefed<GeckoType> Consume() {
already_AddRefed<GeckoType> ret(const_cast<GeckoType*>(ptr));
ptr = nullptr;
return ret;
}
"""

View file

@ -164,7 +164,7 @@ macro_rules! counter_style_descriptors {
$( #[$doc: meta] $name: tt $ident: ident / $setter: ident [$checker: tt]: $ty: ty, )+ $( #[$doc: meta] $name: tt $ident: ident / $setter: ident [$checker: tt]: $ty: ty, )+
) => { ) => {
/// An @counter-style rule /// An @counter-style rule
#[derive(Clone, Debug)] #[derive(Clone, Debug, ToShmem)]
pub struct CounterStyleRuleData { pub struct CounterStyleRuleData {
name: CustomIdent, name: CustomIdent,
generation: Wrapping<u32>, generation: Wrapping<u32>,
@ -337,7 +337,7 @@ impl CounterStyleRuleData {
} }
/// <https://drafts.csswg.org/css-counter-styles/#counter-style-system> /// <https://drafts.csswg.org/css-counter-styles/#counter-style-system>
#[derive(Clone, Debug)] #[derive(Clone, Debug, ToShmem)]
pub enum System { pub enum System {
/// 'cyclic' /// 'cyclic'
Cyclic, Cyclic,
@ -410,7 +410,7 @@ impl ToCss for System {
/// <https://drafts.csswg.org/css-counter-styles/#typedef-symbol> /// <https://drafts.csswg.org/css-counter-styles/#typedef-symbol>
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss)] #[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToShmem)]
pub enum Symbol { pub enum Symbol {
/// <string> /// <string>
String(String), String(String),
@ -447,7 +447,7 @@ impl Symbol {
} }
/// <https://drafts.csswg.org/css-counter-styles/#counter-style-negative> /// <https://drafts.csswg.org/css-counter-styles/#counter-style-negative>
#[derive(Clone, Debug, ToCss)] #[derive(Clone, Debug, ToCss, ToShmem)]
pub struct Negative(pub Symbol, pub Option<Symbol>); pub struct Negative(pub Symbol, pub Option<Symbol>);
impl Parse for Negative { impl Parse for Negative {
@ -465,11 +465,11 @@ impl Parse for Negative {
/// <https://drafts.csswg.org/css-counter-styles/#counter-style-range> /// <https://drafts.csswg.org/css-counter-styles/#counter-style-range>
/// ///
/// Empty Vec represents 'auto' /// Empty Vec represents 'auto'
#[derive(Clone, Debug)] #[derive(Clone, Debug, ToShmem)]
pub struct Ranges(pub Vec<Range<CounterBound>>); pub struct Ranges(pub Vec<Range<CounterBound>>);
/// A bound found in `Ranges`. /// A bound found in `Ranges`.
#[derive(Clone, Copy, Debug, ToCss)] #[derive(Clone, Copy, Debug, ToCss, ToShmem)]
pub enum CounterBound { pub enum CounterBound {
/// An integer bound. /// An integer bound.
Integer(Integer), Integer(Integer),
@ -548,7 +548,7 @@ where
} }
/// <https://drafts.csswg.org/css-counter-styles/#counter-style-pad> /// <https://drafts.csswg.org/css-counter-styles/#counter-style-pad>
#[derive(Clone, Debug, ToCss)] #[derive(Clone, Debug, ToCss, ToShmem)]
pub struct Pad(pub Integer, pub Symbol); pub struct Pad(pub Integer, pub Symbol);
impl Parse for Pad { impl Parse for Pad {
@ -564,7 +564,7 @@ impl Parse for Pad {
} }
/// <https://drafts.csswg.org/css-counter-styles/#counter-style-fallback> /// <https://drafts.csswg.org/css-counter-styles/#counter-style-fallback>
#[derive(Clone, Debug, ToCss)] #[derive(Clone, Debug, ToCss, ToShmem)]
pub struct Fallback(pub CustomIdent); pub struct Fallback(pub CustomIdent);
impl Parse for Fallback { impl Parse for Fallback {
@ -578,7 +578,7 @@ impl Parse for Fallback {
/// <https://drafts.csswg.org/css-counter-styles/#descdef-counter-style-symbols> /// <https://drafts.csswg.org/css-counter-styles/#descdef-counter-style-symbols>
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss)] #[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToShmem)]
pub struct Symbols(#[css(iterable)] pub Vec<Symbol>); pub struct Symbols(#[css(iterable)] pub Vec<Symbol>);
impl Parse for Symbols { impl Parse for Symbols {
@ -602,7 +602,7 @@ impl Parse for Symbols {
} }
/// <https://drafts.csswg.org/css-counter-styles/#descdef-counter-style-additive-symbols> /// <https://drafts.csswg.org/css-counter-styles/#descdef-counter-style-additive-symbols>
#[derive(Clone, Debug, ToCss)] #[derive(Clone, Debug, ToCss, ToShmem)]
pub struct AdditiveSymbols(pub Vec<AdditiveTuple>); pub struct AdditiveSymbols(pub Vec<AdditiveTuple>);
impl Parse for AdditiveSymbols { impl Parse for AdditiveSymbols {
@ -623,7 +623,7 @@ impl Parse for AdditiveSymbols {
} }
/// <integer> && <symbol> /// <integer> && <symbol>
#[derive(Clone, Debug, ToCss)] #[derive(Clone, Debug, ToCss, ToShmem)]
pub struct AdditiveTuple { pub struct AdditiveTuple {
/// <integer> /// <integer>
pub weight: Integer, pub weight: Integer,
@ -651,7 +651,7 @@ impl Parse for AdditiveTuple {
} }
/// <https://drafts.csswg.org/css-counter-styles/#counter-style-speak-as> /// <https://drafts.csswg.org/css-counter-styles/#counter-style-speak-as>
#[derive(Clone, Debug, ToCss)] #[derive(Clone, Debug, ToCss, ToShmem)]
pub enum SpeakAs { pub enum SpeakAs {
/// auto /// auto
Auto, Auto,

View file

@ -96,7 +96,7 @@ pub fn parse_name(s: &str) -> Result<&str, ()> {
/// ///
/// We preserve the original CSS for serialization, and also the variable /// We preserve the original CSS for serialization, and also the variable
/// references to other custom property names. /// references to other custom property names.
#[derive(Clone, Debug, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
pub struct VariableValue { pub struct VariableValue {
css: String, css: String,

View file

@ -642,15 +642,6 @@ pub trait TElement:
self.unset_dirty_descendants(); self.unset_dirty_descendants();
} }
/// Clear all element flags related to dirtiness.
///
/// In Gecko, this corresponds to the regular dirty descendants bit, the
/// animation-only dirty descendants bit, the lazy frame construction bit,
/// and the lazy frame construction descendants bit.
unsafe fn clear_dirty_bits(&self) {
self.unset_dirty_descendants();
}
/// Returns true if this element is a visited link. /// Returns true if this element is a visited link.
/// ///
/// Servo doesn't support visited styles yet. /// Servo doesn't support visited styles yet.
@ -825,11 +816,15 @@ pub trait TElement:
Self: 'a, Self: 'a,
F: FnMut(&'a CascadeData, QuirksMode, Option<Self>), F: FnMut(&'a CascadeData, QuirksMode, Option<Self>),
{ {
use rule_collector::containing_shadow_ignoring_svg_use;
let mut doc_rules_apply = !self.each_xbl_cascade_data(|data, quirks_mode| { let mut doc_rules_apply = !self.each_xbl_cascade_data(|data, quirks_mode| {
f(data, quirks_mode, None); f(data, quirks_mode, None);
}); });
if let Some(shadow) = self.containing_shadow() { // Use the same rules to look for the containing host as we do for rule
// collection.
if let Some(shadow) = containing_shadow_ignoring_svg_use(*self) {
doc_rules_apply = false; doc_rules_apply = false;
if let Some(data) = shadow.style_data() { if let Some(data) = shadow.style_data() {
f( f(

View file

@ -6,8 +6,10 @@
#![deny(missing_docs)] #![deny(missing_docs)]
use crate::selector_parser::SelectorImpl;
use crate::stylesheets::UrlExtraData; use crate::stylesheets::UrlExtraData;
use cssparser::{BasicParseErrorKind, ParseErrorKind, SourceLocation, Token}; use cssparser::{BasicParseErrorKind, ParseErrorKind, SourceLocation, Token};
use selectors::SelectorList;
use std::fmt; use std::fmt;
use style_traits::ParseError; use style_traits::ParseError;
@ -15,7 +17,11 @@ use style_traits::ParseError;
#[derive(Debug)] #[derive(Debug)]
pub enum ContextualParseError<'a> { pub enum ContextualParseError<'a> {
/// A property declaration was not recognized. /// A property declaration was not recognized.
UnsupportedPropertyDeclaration(&'a str, ParseError<'a>), UnsupportedPropertyDeclaration(
&'a str,
ParseError<'a>,
Option<&'a SelectorList<SelectorImpl>>,
),
/// A font face descriptor was not recognized. /// A font face descriptor was not recognized.
UnsupportedFontFaceDescriptor(&'a str, ParseError<'a>), UnsupportedFontFaceDescriptor(&'a str, ParseError<'a>),
/// A font feature values descriptor was not recognized. /// A font feature values descriptor was not recognized.
@ -121,7 +127,7 @@ impl<'a> fmt::Display for ContextualParseError<'a> {
} }
match *self { match *self {
ContextualParseError::UnsupportedPropertyDeclaration(decl, ref err) => { ContextualParseError::UnsupportedPropertyDeclaration(decl, ref err, _selectors) => {
write!(f, "Unsupported property declaration: '{}', ", decl)?; write!(f, "Unsupported property declaration: '{}', ", decl)?;
parse_error_to_str(err, f) parse_error_to_str(err, f)
}, },

View file

@ -34,7 +34,7 @@ use style_traits::{StyleParseErrorKind, ToCss};
/// A source for a font-face rule. /// A source for a font-face rule.
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, ToCss)] #[derive(Clone, Debug, Eq, PartialEq, ToCss, ToShmem)]
pub enum Source { pub enum Source {
/// A `url()` source. /// A `url()` source.
Url(UrlSource), Url(UrlSource),
@ -68,7 +68,7 @@ pub enum FontFaceSourceListComponent {
/// ///
/// <https://drafts.csswg.org/css-fonts/#src-desc> /// <https://drafts.csswg.org/css-fonts/#src-desc>
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq, ToShmem)]
pub struct UrlSource { pub struct UrlSource {
/// The specified url. /// The specified url.
pub url: SpecifiedUrl, pub url: SpecifiedUrl,
@ -101,7 +101,9 @@ impl ToCss for UrlSource {
/// on whether and when it is downloaded and ready to use. /// on whether and when it is downloaded and ready to use.
#[allow(missing_docs)] #[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)] #[derive(
Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss, ToShmem,
)]
#[repr(u8)] #[repr(u8)]
pub enum FontDisplay { pub enum FontDisplay {
Auto, Auto,
@ -144,7 +146,7 @@ macro_rules! impl_range {
/// The font-weight descriptor: /// The font-weight descriptor:
/// ///
/// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-weight /// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-weight
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq, ToShmem)]
pub struct FontWeightRange(pub AbsoluteFontWeight, pub AbsoluteFontWeight); pub struct FontWeightRange(pub AbsoluteFontWeight, pub AbsoluteFontWeight);
impl_range!(FontWeightRange, AbsoluteFontWeight); impl_range!(FontWeightRange, AbsoluteFontWeight);
@ -176,7 +178,7 @@ impl FontWeightRange {
/// The font-stretch descriptor: /// The font-stretch descriptor:
/// ///
/// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-stretch /// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-stretch
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq, ToShmem)]
pub struct FontStretchRange(pub FontStretch, pub FontStretch); pub struct FontStretchRange(pub FontStretch, pub FontStretch);
impl_range!(FontStretchRange, FontStretch); impl_range!(FontStretchRange, FontStretch);
@ -205,7 +207,7 @@ impl FontStretchRange {
/// The font-style descriptor: /// The font-style descriptor:
/// ///
/// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-style /// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-style
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq, ToShmem)]
#[allow(missing_docs)] #[allow(missing_docs)]
pub enum FontStyle { pub enum FontStyle {
Normal, Normal,
@ -435,7 +437,7 @@ macro_rules! font_face_descriptors_common {
/// Data inside a `@font-face` rule. /// Data inside a `@font-face` rule.
/// ///
/// <https://drafts.csswg.org/css-fonts/#font-face-rule> /// <https://drafts.csswg.org/css-fonts/#font-face-rule>
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq, ToShmem)]
pub struct FontFaceRuleData { pub struct FontFaceRuleData {
$( $(
#[$doc] #[$doc]

View file

@ -43,7 +43,11 @@ pub trait FontMetricsProvider {
} }
/// Get default size of a given language and generic family. /// Get default size of a given language and generic family.
fn get_size(&self, font_name: &Atom, font_family: u8) -> Au; fn get_size(
&self,
font_name: &Atom,
font_family: crate::values::computed::font::GenericFontFamily,
) -> Au;
/// Construct from a shared style context /// Construct from a shared style context
fn create_from(context: &SharedStyleContext) -> Self fn create_from(context: &SharedStyleContext) -> Self
@ -66,7 +70,7 @@ impl FontMetricsProvider for ServoMetricsProvider {
ServoMetricsProvider ServoMetricsProvider
} }
fn get_size(&self, _font_name: &Atom, _font_family: u8) -> Au { fn get_size(&self, _: &Atom, _: crate::values::computed::font::GenericFontFamily) -> Au {
unreachable!("Dummy provider should never be used to compute font size") unreachable!("Dummy provider should never be used to compute font size")
} }
} }

View file

@ -0,0 +1,21 @@
/* 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 http://mozilla.org/MPL/2.0/. */
//! FFI implementations for types listed in ServoBoxedTypeList.h.
use crate::gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
use to_shmem::SharedMemoryBuilder;
// TODO(heycam): The FFI impls for most of the types in ServoBoxedTypeList.h are spread across
// various files at the moment, but should probably all move here, and use macros to define
// them more succinctly, like we do in arc_types.rs.
#[cfg(feature = "gecko")]
unsafe impl HasFFI for SharedMemoryBuilder {
type FFIType = crate::gecko_bindings::bindings::RawServoSharedMemoryBuilder;
}
#[cfg(feature = "gecko")]
unsafe impl HasSimpleFFI for SharedMemoryBuilder {}
#[cfg(feature = "gecko")]
unsafe impl HasBoxFFI for SharedMemoryBuilder {}

View file

@ -123,14 +123,11 @@ impl nsStyleImage {
match image { match image {
GenericImage::Gradient(boxed_gradient) => self.set_gradient(*boxed_gradient), GenericImage::Gradient(boxed_gradient) => self.set_gradient(*boxed_gradient),
GenericImage::Url(ref url) => unsafe { GenericImage::Url(ref url) => unsafe {
bindings::Gecko_SetLayerImageImageValue(self, (url.0).0.url_value.get()); bindings::Gecko_SetLayerImageImageValue(self, url.url_value_ptr())
}, },
GenericImage::Rect(ref image_rect) => { GenericImage::Rect(ref image_rect) => {
unsafe { unsafe {
bindings::Gecko_SetLayerImageImageValue( bindings::Gecko_SetLayerImageImageValue(self, image_rect.url.url_value_ptr());
self,
(image_rect.url.0).0.url_value.get(),
);
bindings::Gecko_InitializeImageCropRect(self); bindings::Gecko_InitializeImageCropRect(self);
// Set CropRect // Set CropRect
@ -421,10 +418,8 @@ impl nsStyleImage {
use self::structs::NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE as CLOSEST_SIDE; use self::structs::NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE as CLOSEST_SIDE;
use self::structs::NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER as FARTHEST_CORNER; use self::structs::NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER as FARTHEST_CORNER;
use self::structs::NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE as FARTHEST_SIDE; use self::structs::NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE as FARTHEST_SIDE;
use crate::values::computed::image::LineDirection;
use crate::values::computed::position::Position; use crate::values::computed::position::Position;
use crate::values::computed::Length; use crate::values::generics::image::{Circle, ColorStop, Ellipse};
use crate::values::generics::image::{Circle, ColorStop, CompatMode, Ellipse};
use crate::values::generics::image::{EndingShape, GradientKind, ShapeExtent}; use crate::values::generics::image::{EndingShape, GradientKind, ShapeExtent};
let gecko_gradient = bindings::Gecko_GetGradientImageValue(self) let gecko_gradient = bindings::Gecko_GetGradientImageValue(self)
@ -837,8 +832,7 @@ impl TrackSize<LengthPercentage> {
/// Return TrackSize from given two nsStyleCoord /// Return TrackSize from given two nsStyleCoord
pub fn from_gecko_style_coords<T: CoordData>(gecko_min: &T, gecko_max: &T) -> Self { pub fn from_gecko_style_coords<T: CoordData>(gecko_min: &T, gecko_max: &T) -> Self {
use crate::gecko_bindings::structs::root::nsStyleUnit; use crate::gecko_bindings::structs::root::nsStyleUnit;
use crate::values::computed::length::LengthPercentage; use crate::values::generics::grid::TrackBreadth;
use crate::values::generics::grid::{TrackBreadth, TrackSize};
if gecko_min.unit() == nsStyleUnit::eStyleUnit_None { if gecko_min.unit() == nsStyleUnit::eStyleUnit_None {
debug_assert!( debug_assert!(
@ -865,8 +859,6 @@ impl TrackSize<LengthPercentage> {
/// Save TrackSize to given gecko fields. /// Save TrackSize to given gecko fields.
pub fn to_gecko_style_coords<T: CoordDataMut>(&self, gecko_min: &mut T, gecko_max: &mut T) { pub fn to_gecko_style_coords<T: CoordDataMut>(&self, gecko_min: &mut T, gecko_max: &mut T) {
use crate::values::generics::grid::TrackSize;
match *self { match *self {
TrackSize::FitContent(ref lop) => { TrackSize::FitContent(ref lop) => {
// Gecko sets min value to None and max value to the actual value in fit-content // Gecko sets min value to None and max value to the actual value in fit-content
@ -896,8 +888,6 @@ impl TrackListValue<LengthPercentage, Integer> {
/// Save TrackSize to given gecko fields. /// Save TrackSize to given gecko fields.
pub fn to_gecko_style_coords<T: CoordDataMut>(&self, gecko_min: &mut T, gecko_max: &mut T) { pub fn to_gecko_style_coords<T: CoordDataMut>(&self, gecko_min: &mut T, gecko_max: &mut T) {
use crate::values::generics::grid::TrackListValue;
match *self { match *self {
TrackListValue::TrackSize(ref size) => size.to_gecko_style_coords(gecko_min, gecko_max), TrackListValue::TrackSize(ref size) => size.to_gecko_style_coords(gecko_min, gecko_max),
_ => unreachable!("Should only transform from track-size computed values"), _ => unreachable!("Should only transform from track-size computed values"),
@ -921,8 +911,6 @@ where
pub fn from_gecko_rect( pub fn from_gecko_rect(
sides: &crate::gecko_bindings::structs::nsStyleSides, sides: &crate::gecko_bindings::structs::nsStyleSides,
) -> Option<crate::values::generics::rect::Rect<T>> { ) -> Option<crate::values::generics::rect::Rect<T>> {
use crate::values::generics::rect::Rect;
Some(Rect::new( 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(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(1)).expect("coord[1] cound not convert"),

View file

@ -127,10 +127,6 @@ fn eval_device_aspect_ratio(
} }
/// https://compat.spec.whatwg.org/#css-media-queries-webkit-device-pixel-ratio /// https://compat.spec.whatwg.org/#css-media-queries-webkit-device-pixel-ratio
///
/// FIXME(emilio): This should be an alias of `resolution`, according to the
/// spec, and also according to the code in Chromium. Unify with
/// `eval_resolution`.
fn eval_device_pixel_ratio( fn eval_device_pixel_ratio(
device: &Device, device: &Device,
query_value: Option<f32>, query_value: Option<f32>,

View file

@ -169,6 +169,7 @@ impl Device {
self.document() self.document()
.mPresShell .mPresShell
.as_ref()? .as_ref()?
._base
.mPresContext .mPresContext
.mRawPtr .mRawPtr
.as_ref() .as_ref()

View file

@ -8,6 +8,7 @@
mod non_ts_pseudo_class_list; mod non_ts_pseudo_class_list;
pub mod arc_types; pub mod arc_types;
pub mod boxed_types;
pub mod conversions; pub mod conversions;
pub mod data; pub mod data;
pub mod media_features; pub mod media_features;

View file

@ -3,7 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/// Gecko's pseudo-element definition. /// Gecko's pseudo-element definition.
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
pub enum PseudoElement { pub enum PseudoElement {
% for pseudo in PSEUDOS: % for pseudo in PSEUDOS:
/// ${pseudo.value} /// ${pseudo.value}

View file

@ -44,7 +44,7 @@ pub type Lang = Atom;
macro_rules! pseudo_class_name { macro_rules! pseudo_class_name {
([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => { ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => {
/// Our representation of a non tree-structural pseudo-class. /// Our representation of a non tree-structural pseudo-class.
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
pub enum NonTSPseudoClass { pub enum NonTSPseudoClass {
$( $(
#[doc = $css] #[doc = $css]

View file

@ -17,16 +17,20 @@ use cssparser::Parser;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use nsstring::nsCString; use nsstring::nsCString;
use servo_arc::Arc; use servo_arc::Arc;
use std::collections::HashMap;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use std::mem::ManuallyDrop;
use std::sync::RwLock;
use style_traits::{CssWriter, ParseError, ToCss}; use style_traits::{CssWriter, ParseError, ToCss};
use to_shmem::{SharedMemoryBuilder, ToShmem};
/// A CSS url() value for gecko. /// A CSS url() value for gecko.
#[css(function = "url")] #[css(function = "url")]
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)] #[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
pub struct CssUrl(pub Arc<CssUrlData>); pub struct CssUrl(pub Arc<CssUrlData>);
/// Data shared between CssUrls. /// Data shared between CssUrls.
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)] #[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
pub struct CssUrlData { pub struct CssUrlData {
/// The URL in unresolved string form. /// The URL in unresolved string form.
serialization: String, serialization: String,
@ -81,6 +85,20 @@ impl CssUrlData {
} }
} }
#[cfg(debug_assertions)]
impl Drop for CssUrlData {
fn drop(&mut self) {
assert!(
!URL_VALUE_TABLE
.read()
.unwrap()
.contains_key(&CssUrlDataKey(self as *mut _ as *const _)),
"All CssUrlData objects used as keys in URL_VALUE_TABLE should be \
from shared memory style sheets, and so should never be dropped",
);
}
}
impl Parse for CssUrl { impl Parse for CssUrl {
fn parse<'i, 't>( fn parse<'i, 't>(
context: &ParserContext, context: &ParserContext,
@ -104,15 +122,54 @@ impl MallocSizeOf for CssUrl {
} }
} }
/// A key type for URL_VALUE_TABLE.
#[derive(Eq, Hash, PartialEq)]
struct CssUrlDataKey(*const CssUrlData);
unsafe impl Sync for CssUrlDataKey {}
unsafe impl Send for CssUrlDataKey {}
/// The source of a Gecko URLValue object for a SpecifiedUrl.
#[derive(Clone, Debug)]
pub enum URLValueSource {
/// A strong reference to a Gecko URLValue object.
URLValue(RefPtr<URLValue>),
/// A CORSMode value used to lazily construct a Gecko URLValue object.
///
/// The lazily created object will be stored in URL_VALUE_TABLE.
CORSMode(CORSMode),
}
impl ToShmem for URLValueSource {
fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> ManuallyDrop<Self> {
ManuallyDrop::new(match self {
URLValueSource::URLValue(r) => URLValueSource::CORSMode(r.mCORSMode),
URLValueSource::CORSMode(c) => URLValueSource::CORSMode(*c),
})
}
}
/// A specified non-image `url()` value. /// A specified non-image `url()` value.
#[derive(Clone, Debug, SpecifiedValueInfo, ToCss)] #[derive(Clone, Debug, SpecifiedValueInfo, ToCss, ToShmem)]
pub struct SpecifiedUrl { pub struct SpecifiedUrl {
/// The specified url value. /// The specified url value.
pub url: CssUrl, pub url: CssUrl,
/// Gecko's URLValue so that we can reuse it while rematching a /// Gecko's URLValue so that we can reuse it while rematching a
/// property with this specified value. /// property with this specified value.
///
/// Box this to avoid SpecifiedUrl getting bigger than two words,
/// and increasing the size of PropertyDeclaration.
#[css(skip)] #[css(skip)]
pub url_value: RefPtr<URLValue>, url_value: Box<URLValueSource>,
}
fn make_url_value(url: &CssUrl, cors_mode: CORSMode) -> RefPtr<URLValue> {
unsafe {
let ptr = bindings::Gecko_URLValue_Create(url.0.clone().into_strong(), cors_mode);
// We do not expect Gecko_URLValue_Create returns null.
debug_assert!(!ptr.is_null());
RefPtr::from_addrefed(ptr)
}
} }
impl SpecifiedUrl { impl SpecifiedUrl {
@ -122,12 +179,7 @@ impl SpecifiedUrl {
} }
fn from_css_url_with_cors(url: CssUrl, cors: CORSMode) -> Self { fn from_css_url_with_cors(url: CssUrl, cors: CORSMode) -> Self {
let url_value = unsafe { let url_value = Box::new(URLValueSource::URLValue(make_url_value(&url, cors)));
let ptr = bindings::Gecko_URLValue_Create(url.0.clone().into_strong(), cors);
// We do not expect Gecko_URLValue_Create returns null.
debug_assert!(!ptr.is_null());
RefPtr::from_addrefed(ptr)
};
Self { url, url_value } Self { url, url_value }
} }
@ -140,6 +192,45 @@ impl SpecifiedUrl {
use crate::gecko_bindings::structs::root::mozilla::CORSMode_CORS_ANONYMOUS; use crate::gecko_bindings::structs::root::mozilla::CORSMode_CORS_ANONYMOUS;
Self::from_css_url_with_cors(url, CORSMode_CORS_ANONYMOUS) Self::from_css_url_with_cors(url, CORSMode_CORS_ANONYMOUS)
} }
fn with_url_value<F, T>(&self, f: F) -> T
where
F: FnOnce(&RefPtr<URLValue>) -> T,
{
match *self.url_value {
URLValueSource::URLValue(ref r) => f(r),
URLValueSource::CORSMode(cors_mode) => {
{
let guard = URL_VALUE_TABLE.read().unwrap();
if let Some(r) = guard.get(&(CssUrlDataKey(&*self.url.0 as *const _))) {
return f(r);
}
}
let mut guard = URL_VALUE_TABLE.write().unwrap();
let r = guard
.entry(CssUrlDataKey(&*self.url.0 as *const _))
.or_insert_with(|| make_url_value(&self.url, cors_mode));
f(r)
},
}
}
/// Clone a new, strong reference to the Gecko URLValue.
pub fn clone_url_value(&self) -> RefPtr<URLValue> {
self.with_url_value(RefPtr::clone)
}
/// Get a raw pointer to the URLValue held by this SpecifiedUrl, for FFI.
pub fn url_value_ptr(&self) -> *mut URLValue {
self.with_url_value(RefPtr::get)
}
}
/// Clears URL_VALUE_TABLE. Entries in this table, which are for specified URL
/// values that come from shared memory style sheets, would otherwise persist
/// until the end of the process and be reported as leaks.
pub fn shutdown() {
URL_VALUE_TABLE.write().unwrap().clear();
} }
impl Parse for SpecifiedUrl { impl Parse for SpecifiedUrl {
@ -165,7 +256,7 @@ impl MallocSizeOf for SpecifiedUrl {
// Although this is a RefPtr, this is the primary reference because // Although this is a RefPtr, this is the primary reference because
// SpecifiedUrl is responsible for creating the url_value. So we // SpecifiedUrl is responsible for creating the url_value. So we
// measure unconditionally here. // measure unconditionally here.
n += unsafe { bindings::Gecko_URLValue_SizeOfIncludingThis(self.url_value.get()) }; n += unsafe { bindings::Gecko_URLValue_SizeOfIncludingThis(self.url_value_ptr()) };
n n
} }
} }
@ -185,7 +276,7 @@ impl ToComputedValue for SpecifiedUrl {
} }
/// A specified image `url()` value. /// A specified image `url()` value.
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)] #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
pub struct SpecifiedImageUrl(pub SpecifiedUrl); pub struct SpecifiedImageUrl(pub SpecifiedUrl);
impl SpecifiedImageUrl { impl SpecifiedImageUrl {
@ -258,7 +349,8 @@ impl ToCss for ComputedUrl {
where where
W: Write, W: Write,
{ {
serialize_computed_url(&self.0.url_value, dest, bindings::Gecko_GetComputedURLSpec) self.0
.with_url_value(|r| serialize_computed_url(r, dest, bindings::Gecko_GetComputedURLSpec))
} }
} }
@ -267,12 +359,20 @@ impl ComputedUrl {
pub unsafe fn from_url_value(url_value: RefPtr<URLValue>) -> Self { pub unsafe fn from_url_value(url_value: RefPtr<URLValue>) -> Self {
let css_url = &*url_value.mCssUrl.mRawPtr; let css_url = &*url_value.mCssUrl.mRawPtr;
let url = CssUrl(CssUrlData::as_arc(&css_url).clone_arc()); let url = CssUrl(CssUrlData::as_arc(&css_url).clone_arc());
ComputedUrl(SpecifiedUrl { url, url_value }) ComputedUrl(SpecifiedUrl {
url,
url_value: Box::new(URLValueSource::URLValue(url_value)),
})
}
/// Clone a new, strong reference to the Gecko URLValue.
pub fn clone_url_value(&self) -> RefPtr<URLValue> {
self.0.clone_url_value()
} }
/// Get a raw pointer to the URLValue held by this ComputedUrl, for FFI. /// Get a raw pointer to the URLValue held by this ComputedUrl, for FFI.
pub fn url_value_ptr(&self) -> *mut URLValue { pub fn url_value_ptr(&self) -> *mut URLValue {
self.0.url_value.get() self.0.url_value_ptr()
} }
} }
@ -285,11 +385,9 @@ impl ToCss for ComputedImageUrl {
where where
W: Write, W: Write,
{ {
serialize_computed_url( (self.0).0.with_url_value(|r| {
&(self.0).0.url_value, serialize_computed_url(r, dest, bindings::Gecko_GetComputedImageURLSpec)
dest, })
bindings::Gecko_GetComputedImageURLSpec,
)
} }
} }
@ -299,11 +397,27 @@ impl ComputedImageUrl {
let url_value = image_request.mImageValue.to_safe(); let url_value = image_request.mImageValue.to_safe();
let css_url = &*url_value.mCssUrl.mRawPtr; let css_url = &*url_value.mCssUrl.mRawPtr;
let url = CssUrl(CssUrlData::as_arc(&css_url).clone_arc()); let url = CssUrl(CssUrlData::as_arc(&css_url).clone_arc());
ComputedImageUrl(SpecifiedImageUrl(SpecifiedUrl { url, url_value })) ComputedImageUrl(SpecifiedImageUrl(SpecifiedUrl {
url,
url_value: Box::new(URLValueSource::URLValue(url_value)),
}))
}
/// Clone a new, strong reference to the Gecko URLValue.
pub fn clone_url_value(&self) -> RefPtr<URLValue> {
(self.0).0.clone_url_value()
} }
/// Get a raw pointer to the URLValue held by this ComputedImageUrl, for FFI. /// Get a raw pointer to the URLValue held by this ComputedImageUrl, for FFI.
pub fn url_value_ptr(&self) -> *mut URLValue { pub fn url_value_ptr(&self) -> *mut URLValue {
(self.0).0.url_value.get() (self.0).0.url_value_ptr()
} }
} }
lazy_static! {
/// A table mapping CssUrlData objects to their lazily created Gecko
/// URLValue objects.
static ref URL_VALUE_TABLE: RwLock<HashMap<CssUrlDataKey, RefPtr<URLValue>>> = {
Default::default()
};
}

View file

@ -18,7 +18,7 @@ use crate::values::generics::gecko::ScrollSnapPoint;
use crate::values::generics::grid::{TrackBreadth, TrackKeyword}; use crate::values::generics::grid::{TrackBreadth, TrackKeyword};
use crate::values::generics::length::LengthPercentageOrAuto; use crate::values::generics::length::LengthPercentageOrAuto;
use crate::values::generics::{CounterStyleOrNone, NonNegative}; use crate::values::generics::{CounterStyleOrNone, NonNegative};
use crate::values::{Auto, Either, None_, Normal}; use crate::values::Either;
use crate::{Atom, Zero}; use crate::{Atom, Zero};
use app_units::Au; use app_units::Au;
use cssparser::RGBA; use cssparser::RGBA;
@ -44,23 +44,6 @@ impl nsStyleCoord {
} }
} }
impl<A: GeckoStyleCoordConvertible, B: GeckoStyleCoordConvertible> GeckoStyleCoordConvertible
for Either<A, B>
{
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
Either::First(ref v) => v.to_gecko_style_coord(coord),
Either::Second(ref v) => v.to_gecko_style_coord(coord),
}
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
A::from_gecko_style_coord(coord)
.map(Either::First)
.or_else(|| B::from_gecko_style_coord(coord).map(Either::Second))
}
}
impl<Inner> GeckoStyleCoordConvertible for NonNegative<Inner> impl<Inner> GeckoStyleCoordConvertible for NonNegative<Inner>
where where
Inner: GeckoStyleCoordConvertible, Inner: GeckoStyleCoordConvertible,
@ -265,48 +248,6 @@ impl GeckoStyleCoordConvertible for Angle {
} }
} }
impl GeckoStyleCoordConvertible for Auto {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
coord.set_value(CoordDataValue::Auto)
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
if let CoordDataValue::Auto = coord.as_value() {
Some(Auto)
} else {
None
}
}
}
impl GeckoStyleCoordConvertible for None_ {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
coord.set_value(CoordDataValue::None)
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
if let CoordDataValue::None = coord.as_value() {
Some(None_)
} else {
None
}
}
}
impl GeckoStyleCoordConvertible for Normal {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
coord.set_value(CoordDataValue::Normal)
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
if let CoordDataValue::Normal = coord.as_value() {
Some(Normal)
} else {
None
}
}
}
impl GeckoStyleCoordConvertible for ScrollSnapPoint<LengthPercentage> { impl GeckoStyleCoordConvertible for ScrollSnapPoint<LengthPercentage> {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match self.repeated() { match self.repeated() {
@ -317,7 +258,6 @@ impl GeckoStyleCoordConvertible for ScrollSnapPoint<LengthPercentage> {
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> { fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
use crate::gecko_bindings::structs::root::nsStyleUnit; use crate::gecko_bindings::structs::root::nsStyleUnit;
use crate::values::generics::gecko::ScrollSnapPoint;
Some(match coord.unit() { Some(match coord.unit() {
nsStyleUnit::eStyleUnit_None => ScrollSnapPoint::None, nsStyleUnit::eStyleUnit_None => ScrollSnapPoint::None,

View file

@ -69,6 +69,7 @@ use crate::selector_parser::{AttrValue, HorizontalDirection, Lang};
use crate::shared_lock::Locked; use crate::shared_lock::Locked;
use crate::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace}; use crate::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
use crate::stylist::CascadeData; use crate::stylist::CascadeData;
use crate::values::computed::font::GenericFontFamily;
use crate::values::specified::length::FontBaseSize; use crate::values::specified::length::FontBaseSize;
use crate::CaseSensitivityExt; use crate::CaseSensitivityExt;
use app_units::Au; use app_units::Au;
@ -985,7 +986,6 @@ fn get_animation_rule(
element: &GeckoElement, element: &GeckoElement,
cascade_level: CascadeLevel, cascade_level: CascadeLevel,
) -> Option<Arc<Locked<PropertyDeclarationBlock>>> { ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
use crate::gecko_bindings::sugar::ownership::HasSimpleFFI;
use crate::properties::longhands::ANIMATABLE_PROPERTY_COUNT; use crate::properties::longhands::ANIMATABLE_PROPERTY_COUNT;
// There's a very rough correlation between the number of effects // There's a very rough correlation between the number of effects
@ -1041,7 +1041,7 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
GeckoFontMetricsProvider::new() GeckoFontMetricsProvider::new()
} }
fn get_size(&self, font_name: &Atom, font_family: u8) -> Au { fn get_size(&self, font_name: &Atom, font_family: GenericFontFamily) -> Au {
let mut cache = self.font_size_cache.borrow_mut(); let mut cache = self.font_size_cache.borrow_mut();
if let Some(sizes) = cache.iter().find(|el| el.0 == *font_name) { if let Some(sizes) = cache.iter().find(|el| el.0 == *font_name) {
return sizes.1.size_for_generic(font_family); return sizes.1.size_for_generic(font_family);
@ -1100,16 +1100,17 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
} }
impl structs::FontSizePrefs { impl structs::FontSizePrefs {
fn size_for_generic(&self, font_family: u8) -> Au { fn size_for_generic(&self, font_family: GenericFontFamily) -> Au {
Au(match font_family { Au(match font_family {
structs::kPresContext_DefaultVariableFont_ID => self.mDefaultVariableSize, GenericFontFamily::None => self.mDefaultVariableSize,
structs::kPresContext_DefaultFixedFont_ID => self.mDefaultFixedSize, GenericFontFamily::Serif => self.mDefaultSerifSize,
structs::kGenericFont_serif => self.mDefaultSerifSize, GenericFontFamily::SansSerif => self.mDefaultSansSerifSize,
structs::kGenericFont_sans_serif => self.mDefaultSansSerifSize, GenericFontFamily::Monospace => self.mDefaultMonospaceSize,
structs::kGenericFont_monospace => self.mDefaultMonospaceSize, GenericFontFamily::Cursive => self.mDefaultCursiveSize,
structs::kGenericFont_cursive => self.mDefaultCursiveSize, GenericFontFamily::Fantasy => self.mDefaultFantasySize,
structs::kGenericFont_fantasy => self.mDefaultFantasySize, GenericFontFamily::MozEmoji => unreachable!(
_ => unreachable!("Unknown generic ID"), "Should never get here, since this doesn't (yet) appear on font family"
),
}) })
} }
} }
@ -1422,16 +1423,6 @@ impl<'le> TElement for GeckoElement<'le> {
) )
} }
#[inline]
unsafe fn clear_dirty_bits(&self) {
self.unset_flags(
ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32 |
ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO as u32 |
NODE_DESCENDANTS_NEED_FRAMES as u32 |
NODE_NEEDS_FRAME as u32,
)
}
fn is_visited_link(&self) -> bool { fn is_visited_link(&self) -> bool {
self.state().intersects(ElementState::IN_VISITED_STATE) self.state().intersects(ElementState::IN_VISITED_STATE)
} }

View file

@ -15,4 +15,3 @@ mod ns_t_array;
pub mod origin_flags; pub mod origin_flags;
pub mod ownership; pub mod ownership;
pub mod refptr; pub mod refptr;
mod style_complex_color;

View file

@ -65,6 +65,14 @@ pub unsafe trait HasBoxFFI: HasSimpleFFI {
fn into_ffi(self: Box<Self>) -> Owned<Self::FFIType> { fn into_ffi(self: Box<Self>) -> Owned<Self::FFIType> {
unsafe { transmute(self) } unsafe { transmute(self) }
} }
/// Drops an owned FFI pointer. This conceptually takes the
/// Owned<Self::FFIType>, except it's a bit of a paint to do that without
/// much benefit.
#[inline]
unsafe fn drop_ffi(ptr: *mut Self::FFIType) {
let _ = Box::from_raw(ptr as *mut Self);
}
} }
/// Helper trait for conversions between FFI Strong/Borrowed types and Arcs /// Helper trait for conversions between FFI Strong/Borrowed types and Arcs
@ -268,14 +276,6 @@ pub struct Owned<GeckoType> {
} }
impl<GeckoType> Owned<GeckoType> { impl<GeckoType> Owned<GeckoType> {
/// Gets this `Owned` type as a `Box<ServoType>`.
pub fn into_box<ServoType>(self) -> Box<ServoType>
where
ServoType: HasBoxFFI<FFIType = GeckoType>,
{
unsafe { transmute(self) }
}
/// Converts this instance to a (non-null) instance of `OwnedOrNull`. /// Converts this instance to a (non-null) instance of `OwnedOrNull`.
pub fn maybe(self) -> OwnedOrNull<GeckoType> { pub fn maybe(self) -> OwnedOrNull<GeckoType> {
unsafe { transmute(self) } unsafe { transmute(self) }

View file

@ -1,111 +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 to interact with Gecko's StyleComplexColor.
use crate::gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
use crate::gecko_bindings::structs::StyleComplexColor;
use crate::gecko_bindings::structs::StyleComplexColor_Tag as Tag;
use crate::values::computed::{Color as ComputedColor, ColorOrAuto, RGBAColor as ComputedRGBA};
use crate::values::generics::color::{
Color as GenericColor, ColorOrAuto as GenericColorOrAuto, ComplexColorRatios,
};
impl StyleComplexColor {
/// Create a `StyleComplexColor` value that represents `currentColor`.
pub fn current_color() -> Self {
StyleComplexColor {
mColor: 0,
mBgRatio: 0.,
mFgRatio: 1.,
mTag: Tag::eForeground,
}
}
/// Create a `StyleComplexColor` value that represents `auto`.
pub fn auto() -> Self {
StyleComplexColor {
mColor: 0,
mBgRatio: 0.,
mFgRatio: 1.,
mTag: Tag::eAuto,
}
}
}
impl From<ComputedRGBA> for StyleComplexColor {
fn from(other: ComputedRGBA) -> Self {
StyleComplexColor {
mColor: convert_rgba_to_nscolor(&other),
mBgRatio: 1.,
mFgRatio: 0.,
mTag: Tag::eNumeric,
}
}
}
impl From<ComputedColor> for StyleComplexColor {
fn from(other: ComputedColor) -> Self {
match other {
GenericColor::Numeric(color) => color.into(),
GenericColor::Foreground => Self::current_color(),
GenericColor::Complex(color, ratios) => {
debug_assert!(ratios != ComplexColorRatios::NUMERIC);
debug_assert!(ratios != ComplexColorRatios::FOREGROUND);
StyleComplexColor {
mColor: convert_rgba_to_nscolor(&color).into(),
mBgRatio: ratios.bg,
mFgRatio: ratios.fg,
mTag: Tag::eComplex,
}
},
}
}
}
impl From<StyleComplexColor> for ComputedColor {
fn from(other: StyleComplexColor) -> Self {
match other.mTag {
Tag::eNumeric => {
debug_assert!(other.mBgRatio == 1. && other.mFgRatio == 0.);
GenericColor::Numeric(convert_nscolor_to_rgba(other.mColor))
},
Tag::eForeground => {
debug_assert!(other.mBgRatio == 0. && other.mFgRatio == 1.);
GenericColor::Foreground
},
Tag::eComplex => {
debug_assert!(other.mBgRatio != 1. || other.mFgRatio != 0.);
debug_assert!(other.mBgRatio != 0. || other.mFgRatio != 1.);
GenericColor::Complex(
convert_nscolor_to_rgba(other.mColor),
ComplexColorRatios {
bg: other.mBgRatio,
fg: other.mFgRatio,
},
)
},
Tag::eAuto => unreachable!("Unsupport StyleComplexColor with tag eAuto"),
}
}
}
impl From<ColorOrAuto> for StyleComplexColor {
fn from(other: ColorOrAuto) -> Self {
match other {
GenericColorOrAuto::Color(color) => color.into(),
GenericColorOrAuto::Auto => StyleComplexColor::auto(),
}
}
}
impl From<StyleComplexColor> for ColorOrAuto {
fn from(other: StyleComplexColor) -> Self {
if other.mTag != Tag::eAuto {
GenericColorOrAuto::Color(other.into())
} else {
GenericColorOrAuto::Auto
}
}
}

View file

@ -25,9 +25,11 @@ use std::char::{self, DecodeUtf16};
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::iter::Cloned; use std::iter::Cloned;
use std::mem::{self, ManuallyDrop};
use std::ops::Deref; use std::ops::Deref;
use std::{mem, slice, str}; use std::{slice, str};
use style_traits::SpecifiedValueInfo; use style_traits::SpecifiedValueInfo;
use to_shmem::{SharedMemoryBuilder, ToShmem};
#[macro_use] #[macro_use]
#[allow(improper_ctypes, non_camel_case_types, missing_docs)] #[allow(improper_ctypes, non_camel_case_types, missing_docs)]
@ -122,6 +124,18 @@ impl Borrow<WeakAtom> for Atom {
} }
} }
impl ToShmem for Atom {
fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> ManuallyDrop<Self> {
assert!(
self.is_static(),
"ToShmem failed for Atom: must be a static atom: {}",
self
);
ManuallyDrop::new(Atom(self.0))
}
}
impl Eq for WeakAtom {} impl Eq for WeakAtom {}
impl PartialEq for WeakAtom { impl PartialEq for WeakAtom {
#[inline] #[inline]

View file

@ -24,7 +24,7 @@ macro_rules! ns {
} }
/// A Gecko namespace is just a wrapped atom. /// A Gecko namespace is just a wrapped atom.
#[derive(Clone, Debug, Default, Eq, Hash, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, Default, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
pub struct Namespace(pub Atom); pub struct Namespace(pub Atom);
impl PrecomputedHash for Namespace { impl PrecomputedHash for Namespace {

View file

@ -750,8 +750,19 @@ where
// //
// Note that we'll also restyle the pseudo-element because // Note that we'll also restyle the pseudo-element because
// it would match this invalidation. // it would match this invalidation.
if self.processor.invalidates_on_eager_pseudo_element() && pseudo.is_eager() { if self.processor.invalidates_on_eager_pseudo_element() {
invalidated_self = true; if pseudo.is_eager() {
invalidated_self = true;
}
// If we start or stop matching some marker rules, and
// don't have a marker, then we need to restyle the
// element to potentially create one.
//
// Same caveats as for other eager pseudos apply, this
// could be more fine-grained.
if pseudo.is_marker() && self.element.marker_pseudo_element().is_none() {
invalidated_self = true;
}
} }
} }

View file

@ -99,6 +99,9 @@ extern crate style_traits;
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
extern crate thin_slice; extern crate thin_slice;
extern crate time; extern crate time;
extern crate to_shmem;
#[macro_use]
extern crate to_shmem_derive;
extern crate uluru; extern crate uluru;
extern crate unicode_bidi; extern crate unicode_bidi;
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]

View file

@ -80,6 +80,8 @@ macro_rules! define_keyword_type {
ToAnimatedZero, ToAnimatedZero,
ToComputedValue, ToComputedValue,
ToCss, ToCss,
ToResolvedValue,
ToShmem,
)] )]
pub struct $name; pub struct $name;

View file

@ -471,7 +471,7 @@ trait PrivateMatchMethods: TElement {
debug!("accumulate_damage_for: {:?}", self); debug!("accumulate_damage_for: {:?}", self);
debug_assert!(!shared_context debug_assert!(!shared_context
.traversal_flags .traversal_flags
.contains(TraversalFlags::Forgetful)); .contains(TraversalFlags::FinalAnimationTraversal));
let difference = self.compute_style_difference(old_values, new_values, pseudo); let difference = self.compute_style_difference(old_values, new_values, pseudo);
@ -723,11 +723,11 @@ pub trait MatchMethods: TElement {
} }
} }
// Don't accumulate damage if we're in a forgetful traversal. // Don't accumulate damage if we're in the final animation traversal.
if context if context
.shared .shared
.traversal_flags .traversal_flags
.contains(TraversalFlags::Forgetful) .contains(TraversalFlags::FinalAnimationTraversal)
{ {
return ChildCascadeRequirement::MustCascadeChildren; return ChildCascadeRequirement::MustCascadeChildren;
} }

View file

@ -14,7 +14,7 @@ use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
/// A binary `and` or `or` operator. /// A binary `and` or `or` operator.
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)] #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss, ToShmem)]
#[allow(missing_docs)] #[allow(missing_docs)]
pub enum Operator { pub enum Operator {
And, And,
@ -29,7 +29,7 @@ enum AllowOr {
} }
/// Represents a media condition. /// Represents a media condition.
#[derive(Clone, Debug, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
pub enum MediaCondition { pub enum MediaCondition {
/// A simple media feature expression, implicitly parenthesized. /// A simple media feature expression, implicitly parenthesized.
Feature(MediaFeatureExpression), Feature(MediaFeatureExpression),

View file

@ -17,7 +17,6 @@ use crate::parser::{Parse, ParserContext};
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
use crate::servo::media_queries::MEDIA_FEATURES; use crate::servo::media_queries::MEDIA_FEATURES;
use crate::str::{starts_with_ignore_ascii_case, string_as_ascii_lowercase}; use crate::str::{starts_with_ignore_ascii_case, string_as_ascii_lowercase};
use crate::stylesheets::Origin;
use crate::values::computed::{self, ToComputedValue}; use crate::values::computed::{self, ToComputedValue};
use crate::values::specified::{Integer, Length, Number, Resolution}; use crate::values::specified::{Integer, Length, Number, Resolution};
use crate::values::{serialize_atom_identifier, CSSFloat}; use crate::values::{serialize_atom_identifier, CSSFloat};
@ -28,7 +27,7 @@ use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
/// An aspect ratio, with a numerator and denominator. /// An aspect ratio, with a numerator and denominator.
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)] #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
pub struct AspectRatio(pub u32, pub u32); pub struct AspectRatio(pub u32, pub u32);
impl ToCss for AspectRatio { impl ToCss for AspectRatio {
@ -52,7 +51,7 @@ impl PartialOrd for AspectRatio {
} }
/// The kind of matching that should be performed on a media feature value. /// The kind of matching that should be performed on a media feature value.
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)] #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
pub enum Range { pub enum Range {
/// At least the specified value. /// At least the specified value.
Min, Min,
@ -61,7 +60,7 @@ pub enum Range {
} }
/// The operator that was specified in this media feature. /// The operator that was specified in this media feature.
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)] #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
pub enum Operator { pub enum Operator {
/// = /// =
Equal, Equal,
@ -94,7 +93,7 @@ impl ToCss for Operator {
/// ///
/// Ranged media features are not allowed with operations (that'd make no /// Ranged media features are not allowed with operations (that'd make no
/// sense). /// sense).
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)] #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
pub enum RangeOrOperator { pub enum RangeOrOperator {
/// A `Range`. /// A `Range`.
Range(Range), Range(Range),
@ -152,7 +151,7 @@ impl RangeOrOperator {
/// A feature expression contains a reference to the media feature, the value /// A feature expression contains a reference to the media feature, the value
/// the media query contained, and the range to evaluate. /// the media query contained, and the range to evaluate.
#[derive(Clone, Debug, MallocSizeOf)] #[derive(Clone, Debug, MallocSizeOf, ToShmem)]
pub struct MediaFeatureExpression { pub struct MediaFeatureExpression {
feature_index: usize, feature_index: usize,
value: Option<MediaExpressionValue>, value: Option<MediaExpressionValue>,
@ -290,7 +289,7 @@ impl MediaFeatureExpression {
let mut requirements = ParsingRequirements::empty(); let mut requirements = ParsingRequirements::empty();
if context.chrome_rules_enabled() || context.stylesheet_origin == Origin::UserAgent { if context.in_ua_or_chrome_sheet() {
requirements.insert(ParsingRequirements::CHROME_AND_UA_ONLY); requirements.insert(ParsingRequirements::CHROME_AND_UA_ONLY);
} }
@ -468,7 +467,7 @@ impl MediaFeatureExpression {
/// If the first, this would need to store the relevant values. /// If the first, this would need to store the relevant values.
/// ///
/// See: https://github.com/w3c/csswg-drafts/issues/1968 /// See: https://github.com/w3c/csswg-drafts/issues/1968
#[derive(Clone, Debug, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
pub enum MediaExpressionValue { pub enum MediaExpressionValue {
/// A length. /// A length.
Length(Length), Length(Length),

View file

@ -15,7 +15,7 @@ use cssparser::{ParserInput, Token};
/// A type that encapsulates a media query list. /// A type that encapsulates a media query list.
#[css(comma, derive_debug)] #[css(comma, derive_debug)]
#[derive(Clone, MallocSizeOf, ToCss)] #[derive(Clone, MallocSizeOf, ToCss, ToShmem)]
pub struct MediaList { pub struct MediaList {
/// The list of media queries. /// The list of media queries.
#[css(iterable)] #[css(iterable)]

View file

@ -16,7 +16,7 @@ use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, ToCss}; use style_traits::{CssWriter, ParseError, ToCss};
/// <https://drafts.csswg.org/mediaqueries/#mq-prefix> /// <https://drafts.csswg.org/mediaqueries/#mq-prefix>
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)] #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss, ToShmem)]
pub enum Qualifier { pub enum Qualifier {
/// Hide a media query from legacy UAs: /// Hide a media query from legacy UAs:
/// <https://drafts.csswg.org/mediaqueries/#mq-only> /// <https://drafts.csswg.org/mediaqueries/#mq-only>
@ -27,7 +27,7 @@ pub enum Qualifier {
} }
/// <https://drafts.csswg.org/mediaqueries/#media-types> /// <https://drafts.csswg.org/mediaqueries/#media-types>
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
pub struct MediaType(pub CustomIdent); pub struct MediaType(pub CustomIdent);
impl MediaType { impl MediaType {
@ -58,7 +58,7 @@ impl MediaType {
/// A [media query][mq]. /// A [media query][mq].
/// ///
/// [mq]: https://drafts.csswg.org/mediaqueries/ /// [mq]: https://drafts.csswg.org/mediaqueries/
#[derive(Clone, Debug, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
pub struct MediaQuery { pub struct MediaQuery {
/// The qualifier for this query. /// The qualifier for this query.
pub qualifier: Option<Qualifier>, pub qualifier: Option<Qualifier>,
@ -151,7 +151,7 @@ impl MediaQuery {
} }
/// <http://dev.w3.org/csswg/mediaqueries-3/#media0> /// <http://dev.w3.org/csswg/mediaqueries-3/#media0>
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
pub enum MediaQueryType { pub enum MediaQueryType {
/// A media type that matches every device. /// A media type that matches every device.
All, All,

View file

@ -146,10 +146,23 @@ impl<'a> ParserContext<'a> {
error_reporter.report_error(self.url_data, location, error) error_reporter.report_error(self.url_data, location, error)
} }
/// Whether we're in a user-agent stylesheet.
#[inline]
pub fn in_ua_sheet(&self) -> bool {
self.stylesheet_origin == Origin::UserAgent
}
/// Returns whether chrome-only rules should be parsed. /// Returns whether chrome-only rules should be parsed.
#[inline]
pub fn chrome_rules_enabled(&self) -> bool { pub fn chrome_rules_enabled(&self) -> bool {
self.url_data.is_chrome() || self.stylesheet_origin == Origin::User self.url_data.is_chrome() || self.stylesheet_origin == Origin::User
} }
/// Whether we're in a user-agent stylesheet or chrome rules are enabled.
#[inline]
pub fn in_ua_or_chrome_sheet(&self) -> bool {
self.in_ua_sheet() || self.chrome_rules_enabled()
}
} }
/// A trait to abstract parsing of a specified value given a `ParserContext` and /// A trait to abstract parsing of a specified value given a `ParserContext` and

View file

@ -683,6 +683,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
fn recompute_default_font_family_type_if_needed(&mut self) { fn recompute_default_font_family_type_if_needed(&mut self) {
use crate::gecko_bindings::{bindings, structs}; use crate::gecko_bindings::{bindings, structs};
use crate::values::computed::font::GenericFontFamily;
if !self.seen.contains(LonghandId::XLang) && if !self.seen.contains(LonghandId::XLang) &&
!self.seen.contains(LonghandId::FontFamily) { !self.seen.contains(LonghandId::FontFamily) {
@ -697,7 +698,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
// System fonts are all right, and should have the default font type // System fonts are all right, and should have the default font type
// set to none already, so bail out early. // set to none already, so bail out early.
if font.mFont.systemFont { if font.mFont.systemFont {
debug_assert_eq!(font.mFont.fontlist.mDefaultFontType, structs::FontFamilyType::eFamily_none); debug_assert_eq!(font.mFont.fontlist.mDefaultFontType, GenericFontFamily::None);
return; return;
} }
@ -717,11 +718,11 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
!use_document_fonts && !use_document_fonts &&
matches!( matches!(
font.mGenericID, font.mGenericID,
structs::kGenericFont_NONE | GenericFontFamily::None |
structs::kGenericFont_fantasy | GenericFontFamily::Fantasy |
structs::kGenericFont_cursive GenericFontFamily::Cursive
) && ) &&
default_font_type != structs::FontFamilyType::eFamily_none; default_font_type != GenericFontFamily::None;
if !prioritize_user_fonts && default_font_type == font.mFont.fontlist.mDefaultFontType { if !prioritize_user_fonts && default_font_type == font.mFont.fontlist.mDefaultFontType {
// Nothing to do. // Nothing to do.

View file

@ -341,6 +341,8 @@ class Longhand(object):
"SVGOpacity", "SVGOpacity",
"SVGPaintOrder", "SVGPaintOrder",
"ScrollSnapAlign", "ScrollSnapAlign",
"ScrollSnapAxis",
"ScrollSnapStrictness",
"ScrollSnapType", "ScrollSnapType",
"TextAlign", "TextAlign",
"TextDecorationLine", "TextDecorationLine",

View file

@ -25,6 +25,8 @@ use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCs
use crate::stylesheets::{CssRuleType, Origin, UrlExtraData}; use crate::stylesheets::{CssRuleType, Origin, UrlExtraData};
use super::*; use super::*;
use crate::values::computed::Context; use crate::values::computed::Context;
use crate::selector_parser::SelectorImpl;
use selectors::SelectorList;
/// The animation rules. /// The animation rules.
/// ///
@ -88,7 +90,7 @@ impl Importance {
/// Overridden declarations are skipped. /// Overridden declarations are skipped.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone)] #[derive(Clone, ToShmem)]
pub struct PropertyDeclarationBlock { pub struct PropertyDeclarationBlock {
/// The group of declarations, along with their importance. /// The group of declarations, along with their importance.
/// ///
@ -1211,7 +1213,7 @@ pub fn parse_style_attribute(
); );
let mut input = ParserInput::new(input); let mut input = ParserInput::new(input);
parse_property_declaration_list(&context, &mut Parser::new(&mut input)) parse_property_declaration_list(&context, &mut Parser::new(&mut input), None)
} }
/// Parse a given property declaration. Can result in multiple /// Parse a given property declaration. Can result in multiple
@ -1248,6 +1250,7 @@ pub fn parse_one_declaration_into(
let error = ContextualParseError::UnsupportedPropertyDeclaration( let error = ContextualParseError::UnsupportedPropertyDeclaration(
parser.slice_from(start_position), parser.slice_from(start_position),
err, err,
None
); );
context.log_css_error(location, error); context.log_css_error(location, error);
}) })
@ -1312,6 +1315,7 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> {
pub fn parse_property_declaration_list( pub fn parse_property_declaration_list(
context: &ParserContext, context: &ParserContext,
input: &mut Parser, input: &mut Parser,
selectors: Option<&SelectorList<SelectorImpl>>
) -> PropertyDeclarationBlock { ) -> PropertyDeclarationBlock {
let mut declarations = SourcePropertyDeclaration::new(); let mut declarations = SourcePropertyDeclaration::new();
let mut block = PropertyDeclarationBlock::new(); let mut block = PropertyDeclarationBlock::new();
@ -1338,7 +1342,7 @@ pub fn parse_property_declaration_list(
} }
let location = error.location; let location = error.location;
let error = ContextualParseError::UnsupportedPropertyDeclaration(slice, error); let error = ContextualParseError::UnsupportedPropertyDeclaration(slice, error, selectors);
context.log_css_error(location, error); context.log_css_error(location, error);
} }
} }

View file

@ -40,8 +40,6 @@ use crate::gecko_bindings::structs::nsCSSPropertyID;
use crate::gecko_bindings::structs::mozilla::PseudoStyleType; use crate::gecko_bindings::structs::mozilla::PseudoStyleType;
use crate::gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut}; use crate::gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
use crate::gecko_bindings::sugar::refptr::RefPtr; use crate::gecko_bindings::sugar::refptr::RefPtr;
use crate::gecko::values::convert_nscolor_to_rgba;
use crate::gecko::values::convert_rgba_to_nscolor;
use crate::gecko::values::GeckoStyleCoordConvertible; use crate::gecko::values::GeckoStyleCoordConvertible;
use crate::gecko::values::round_border_to_device_pixels; use crate::gecko::values::round_border_to_device_pixels;
use crate::logical_geometry::WritingMode; use crate::logical_geometry::WritingMode;
@ -397,34 +395,6 @@ def set_gecko_property(ffi_name, expr):
} }
</%def> </%def>
<%def name="impl_color_setter(ident, gecko_ffi_name)">
#[allow(unreachable_code)]
#[allow(non_snake_case)]
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
${set_gecko_property(gecko_ffi_name, "v.into()")}
}
</%def>
<%def name="impl_color_copy(ident, gecko_ffi_name)">
#[allow(non_snake_case)]
pub fn copy_${ident}_from(&mut self, other: &Self) {
let color = ${get_gecko_property(gecko_ffi_name, self_param = "other")};
${set_gecko_property(gecko_ffi_name, "color")};
}
#[allow(non_snake_case)]
pub fn reset_${ident}(&mut self, other: &Self) {
self.copy_${ident}_from(other)
}
</%def>
<%def name="impl_color_clone(ident, gecko_ffi_name)">
#[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
${get_gecko_property(gecko_ffi_name)}.into()
}
</%def>
<%def name="impl_keyword(ident, gecko_ffi_name, keyword, cast_type='u8', **kwargs)"> <%def name="impl_keyword(ident, gecko_ffi_name, keyword, cast_type='u8', **kwargs)">
<%call expr="impl_keyword_setter(ident, gecko_ffi_name, keyword, cast_type, **kwargs)"></%call> <%call expr="impl_keyword_setter(ident, gecko_ffi_name, keyword, cast_type, **kwargs)"></%call>
<%call expr="impl_simple_copy(ident, gecko_ffi_name, **kwargs)"></%call> <%call expr="impl_simple_copy(ident, gecko_ffi_name, **kwargs)"></%call>
@ -449,24 +419,6 @@ def set_gecko_property(ffi_name, expr):
} }
</%def> </%def>
<%def name="impl_color(ident, gecko_ffi_name)">
<%call expr="impl_color_setter(ident, gecko_ffi_name)"></%call>
<%call expr="impl_color_copy(ident, gecko_ffi_name)"></%call>
<%call expr="impl_color_clone(ident, gecko_ffi_name)"></%call>
</%def>
<%def name="impl_rgba_color(ident, gecko_ffi_name)">
#[allow(non_snake_case)]
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
${set_gecko_property(gecko_ffi_name, "convert_rgba_to_nscolor(&v)")}
}
<%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call>
#[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
convert_nscolor_to_rgba(${get_gecko_property(gecko_ffi_name)})
}
</%def>
<%def name="impl_svg_length(ident, gecko_ffi_name)"> <%def name="impl_svg_length(ident, gecko_ffi_name)">
// When context-value is used on an SVG length, the corresponding flag is // When context-value is used on an SVG length, the corresponding flag is
// set on mContextFlags, and the length field is set to the initial value. // set on mContextFlags, and the length field is set to the initial value.
@ -826,7 +778,7 @@ def set_gecko_property(ffi_name, expr):
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
match v { match v {
UrlOrNone::Url(ref url) => { UrlOrNone::Url(ref url) => {
self.gecko.${gecko_ffi_name}.set_move(url.0.url_value.clone()) self.gecko.${gecko_ffi_name}.set_move(url.clone_url_value())
} }
UrlOrNone::None => { UrlOrNone::None => {
unsafe { unsafe {
@ -1238,18 +1190,7 @@ impl Clone for ${style_struct.gecko_struct_name} {
# Types used with predefined_type()-defined properties that we can auto-generate. # Types used with predefined_type()-defined properties that we can auto-generate.
predefined_types = { predefined_types = {
"Color": impl_color,
"ColorOrAuto": impl_color,
"length::LengthOrAuto": impl_style_coord,
"length::LengthOrNormal": impl_style_coord,
"length::NonNegativeLengthOrAuto": impl_style_coord,
"length::NonNegativeLengthPercentageOrNormal": impl_style_coord,
"Length": impl_absolute_length,
"LengthOrNormal": impl_style_coord,
"LengthPercentageOrAuto": impl_style_coord,
"MozListReversed": impl_simple,
"MozScriptMinSize": impl_absolute_length, "MozScriptMinSize": impl_absolute_length,
"RGBAColor": impl_rgba_color,
"SVGLength": impl_svg_length, "SVGLength": impl_svg_length,
"SVGOpacity": impl_svg_opacity, "SVGOpacity": impl_svg_opacity,
"SVGPaint": impl_svg_paint, "SVGPaint": impl_svg_paint,
@ -1379,7 +1320,7 @@ fn static_assert() {
self.gecko.mBorderStyle[${side.index}] self.gecko.mBorderStyle[${side.index}]
} }
<% impl_color("border_%s_color" % side.ident, "mBorder%sColor" % side.name) %> <% impl_simple("border_%s_color" % side.ident, "mBorder%sColor" % side.name) %>
<% impl_non_negative_length("border_%s_width" % side.ident, <% impl_non_negative_length("border_%s_width" % side.ident,
"mComputedBorder.%s" % side.ident, "mComputedBorder.%s" % side.ident,
@ -1984,18 +1925,20 @@ fn static_assert() {
<% impl_font_settings("font_variation_settings", "gfxFontVariation", "VariationValue", "f32", "f32") %> <% impl_font_settings("font_variation_settings", "gfxFontVariation", "VariationValue", "f32", "f32") %>
pub fn set_font_family(&mut self, v: longhands::font_family::computed_value::T) { pub fn set_font_family(&mut self, v: longhands::font_family::computed_value::T) {
use crate::gecko_bindings::structs::FontFamilyType; use crate::values::computed::font::GenericFontFamily;
let is_system_font = v.is_system_font; let is_system_font = v.is_system_font;
self.gecko.mFont.systemFont = is_system_font; self.gecko.mFont.systemFont = is_system_font;
self.gecko.mGenericID = if is_system_font { self.gecko.mGenericID = if is_system_font {
structs::kGenericFont_NONE GenericFontFamily::None
} else { } else {
v.families.single_generic().unwrap_or(structs::kGenericFont_NONE) v.families.single_generic().unwrap_or(GenericFontFamily::None)
}; };
self.gecko.mFont.fontlist.mFontlist.mBasePtr.set_move(v.families.0.clone()); self.gecko.mFont.fontlist.mFontlist.mBasePtr.set_move(
v.families.shared_font_list().clone()
);
// Fixed-up if needed in Cascade::fixup_font_stuff. // Fixed-up if needed in Cascade::fixup_font_stuff.
self.gecko.mFont.fontlist.mDefaultFontType = FontFamilyType::eFamily_none; self.gecko.mFont.fontlist.mDefaultFontType = GenericFontFamily::None;
} }
pub fn copy_font_family_from(&mut self, other: &Self) { pub fn copy_font_family_from(&mut self, other: &Self) {
@ -2009,36 +1952,16 @@ fn static_assert() {
} }
pub fn clone_font_family(&self) -> longhands::font_family::computed_value::T { pub fn clone_font_family(&self) -> longhands::font_family::computed_value::T {
use crate::gecko_bindings::structs::FontFamilyType;
use crate::values::computed::font::{FontFamily, SingleFontFamily, FontFamilyList}; use crate::values::computed::font::{FontFamily, SingleFontFamily, FontFamilyList};
let fontlist = &self.gecko.mFont.fontlist; let fontlist = &self.gecko.mFont.fontlist;
let shared_fontlist = unsafe { fontlist.mFontlist.mBasePtr.to_safe() }; let shared_fontlist = unsafe { fontlist.mFontlist.mBasePtr.to_safe() };
let families = if shared_fontlist.mNames.is_empty() { let families = if shared_fontlist.mNames.is_empty() {
let default = fontlist.mDefaultFontType; let default = SingleFontFamily::Generic(fontlist.mDefaultFontType);
let default = match default {
FontFamilyType::eFamily_serif => {
SingleFontFamily::Generic(atom!("serif"))
}
_ => {
// This can break with some combinations of user prefs, see
// bug 1442195 for example. It doesn't really matter in this
// case...
//
// FIXME(emilio): Probably should be storing the whole
// default font name instead though.
debug_assert_eq!(
default,
FontFamilyType::eFamily_sans_serif,
"Default generic should be serif or sans-serif"
);
SingleFontFamily::Generic(atom!("sans-serif"))
}
};
FontFamilyList::new(Box::new([default])) FontFamilyList::new(Box::new([default]))
} else { } else {
FontFamilyList(shared_fontlist) FontFamilyList::SharedFontList(shared_fontlist)
}; };
FontFamily { FontFamily {
@ -3781,7 +3704,7 @@ fn static_assert() {
}, },
Url(ref url) => { Url(ref url) => {
unsafe { unsafe {
bindings::Gecko_nsStyleFilter_SetURLValue(gecko_filter, url.0.url_value.get()); bindings::Gecko_nsStyleFilter_SetURLValue(gecko_filter, url.url_value_ptr());
} }
}, },
} }
@ -4162,7 +4085,7 @@ fn set_style_svg_path(
% if ident == "clip_path": % if ident == "clip_path":
ShapeSource::ImageOrUrl(ref url) => { ShapeSource::ImageOrUrl(ref url) => {
unsafe { unsafe {
bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.0.url_value.get()) bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.url_value_ptr())
} }
} }
% elif ident == "shape_outside": % elif ident == "shape_outside":
@ -4404,23 +4327,10 @@ clip-path
} }
</%self:impl_trait> </%self:impl_trait>
<%self:impl_trait style_struct_name="Color" <%self:impl_trait style_struct_name="Color">
skip_longhands="*">
pub fn set_color(&mut self, v: longhands::color::computed_value::T) {
let result = convert_rgba_to_nscolor(&v);
${set_gecko_property("mColor", "result")}
}
<%call expr="impl_simple_copy('color', 'mColor')"></%call>
pub fn clone_color(&self) -> longhands::color::computed_value::T {
let color = ${get_gecko_property("mColor")} as u32;
convert_nscolor_to_rgba(color)
}
</%self:impl_trait> </%self:impl_trait>
<%self:impl_trait style_struct_name="InheritedUI" <%self:impl_trait style_struct_name="InheritedUI" skip_longhands="cursor">
skip_longhands="cursor scrollbar-color">
pub fn set_cursor(&mut self, v: longhands::cursor::computed_value::T) { pub fn set_cursor(&mut self, v: longhands::cursor::computed_value::T) {
self.gecko.mCursor = v.keyword; self.gecko.mCursor = v.keyword;
unsafe { unsafe {
@ -4482,48 +4392,6 @@ clip-path
longhands::cursor::computed_value::T { images, keyword } longhands::cursor::computed_value::T { images, keyword }
} }
pub fn set_scrollbar_color(&mut self, v: longhands::scrollbar_color::computed_value::T) {
use crate::gecko_bindings::structs::StyleComplexColor;
use crate::values::generics::ui::ScrollbarColor;
match v {
ScrollbarColor::Auto => {
self.gecko.mScrollbarFaceColor = StyleComplexColor::auto();
self.gecko.mScrollbarTrackColor = StyleComplexColor::auto();
}
ScrollbarColor::Colors { thumb, track } => {
self.gecko.mScrollbarFaceColor = thumb.into();
self.gecko.mScrollbarTrackColor = track.into();
}
}
}
pub fn copy_scrollbar_color_from(&mut self, other: &Self) {
self.gecko.mScrollbarFaceColor = other.gecko.mScrollbarFaceColor;
self.gecko.mScrollbarTrackColor = other.gecko.mScrollbarTrackColor;
}
pub fn reset_scrollbar_color(&mut self, other: &Self) {
self.copy_scrollbar_color_from(other);
}
pub fn clone_scrollbar_color(&self) -> longhands::scrollbar_color::computed_value::T {
use crate::gecko_bindings::structs::StyleComplexColor_Tag as Tag;
use crate::values::generics::ui::ScrollbarColor;
debug_assert!(
(self.gecko.mScrollbarFaceColor.mTag == Tag::eAuto) ==
(self.gecko.mScrollbarTrackColor.mTag == Tag::eAuto),
"Whether the two colors are `auto` should match",
);
if self.gecko.mScrollbarFaceColor.mTag == Tag::eAuto {
ScrollbarColor::Auto
} else {
ScrollbarColor::Colors {
thumb: self.gecko.mScrollbarFaceColor.into(),
track: self.gecko.mScrollbarTrackColor.into(),
}
}
}
</%self:impl_trait> </%self:impl_trait>
<%self:impl_trait style_struct_name="Column" <%self:impl_trait style_struct_name="Column"

View file

@ -105,7 +105,7 @@
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::values::{computed, specified}; use crate::values::{computed, specified};
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::values::{Auto, Either, None_, Normal}; use crate::values::{Auto, Either, None_};
${caller.body()} ${caller.body()}
} }
@ -128,8 +128,15 @@
% if separator == "Comma": % if separator == "Comma":
#[css(comma)] #[css(comma)]
% endif % endif
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToAnimatedValue, #[derive(
ToCss)] Clone,
Debug,
MallocSizeOf,
PartialEq,
ToAnimatedValue,
ToResolvedValue,
ToCss,
)]
pub struct List<T>( pub struct List<T>(
% if not allow_empty: % if not allow_empty:
#[css(iterable)] #[css(iterable)]
@ -205,7 +212,7 @@
% if separator == "Comma": % if separator == "Comma":
#[css(comma)] #[css(comma)]
% endif % endif
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
pub struct SpecifiedValue( pub struct SpecifiedValue(
% if not allow_empty: % if not allow_empty:
#[css(iterable)] #[css(iterable)]
@ -285,7 +292,7 @@
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::properties::{UnparsedValue, ShorthandId}; use crate::properties::{UnparsedValue, ShorthandId};
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::values::{Auto, Either, None_, Normal}; use crate::values::{Auto, Either, None_};
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::error_reporting::ParseErrorReporter; use crate::error_reporting::ParseErrorReporter;
#[allow(unused_imports)] #[allow(unused_imports)]
@ -425,8 +432,20 @@
pub mod computed_value { pub mod computed_value {
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, #[derive(
PartialEq, SpecifiedValueInfo, ToCss)] Clone,
Copy,
Debug,
Eq,
Hash,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToCss,
ToResolvedValue,
ToShmem,
)]
pub enum T { pub enum T {
% for value in keyword.values_for(product): % for value in keyword.values_for(product):
${to_camel_case(value)}, ${to_camel_case(value)},
@ -437,7 +456,7 @@
} }
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Copy, Debug, Eq, PartialEq, SpecifiedValueInfo, ToCss)] #[derive(Clone, Copy, Debug, Eq, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
pub enum SpecifiedValue { pub enum SpecifiedValue {
Keyword(computed_value::T), Keyword(computed_value::T),
#[css(skip)] #[css(skip)]
@ -588,8 +607,18 @@
</%def> </%def>
% if extra_specified: % if extra_specified:
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, #[derive(
SpecifiedValueInfo, ToCss)] Clone,
Copy,
Debug,
Eq,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToCss,
ToShmem,
)]
pub enum SpecifiedValue { pub enum SpecifiedValue {
${variants(keyword.values_for(product) + extra_specified.split(), bool(extra_specified))} ${variants(keyword.values_for(product) + extra_specified.split(), bool(extra_specified))}
} }
@ -598,9 +627,9 @@
% endif % endif
pub mod computed_value { pub mod computed_value {
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss)] #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)]
% if not extra_specified: % if not extra_specified:
#[derive(Parse, SpecifiedValueInfo, ToComputedValue)] #[derive(Parse, SpecifiedValueInfo, ToComputedValue, ToShmem)]
% endif % endif
pub enum T { pub enum T {
${variants(data.longhands_by_name[name].keyword.values_for(product), not extra_specified)} ${variants(data.longhands_by_name[name].keyword.values_for(product), not extra_specified)}

View file

@ -9,7 +9,7 @@
${helpers.predefined_type( ${helpers.predefined_type(
"background-color", "background-color",
"Color", "Color",
"computed_value::T::transparent()", "computed::Color::transparent()",
initial_specified_value="SpecifiedValue::transparent()", initial_specified_value="SpecifiedValue::transparent()",
spec="https://drafts.csswg.org/css-backgrounds/#background-color", spec="https://drafts.csswg.org/css-backgrounds/#background-color",
animation_value_type="AnimatedColor", animation_value_type="AnimatedColor",

View file

@ -427,18 +427,14 @@ ${helpers.predefined_type(
animation_value_type="discrete", animation_value_type="discrete",
)} )}
% for axis in ["x", "y"]: ${helpers.predefined_type(
${helpers.predefined_type( "scroll-snap-type",
"scroll-snap-type-" + axis, "ScrollSnapType",
"ScrollSnapType", "computed::ScrollSnapType::none()",
"computed::ScrollSnapType::None", products="gecko",
products="gecko", spec="https://drafts.csswg.org/css-scroll-snap-1/#scroll-snap-type",
needs_context=False, animation_value_type="discrete",
gecko_pref="layout.css.scroll-snap.enabled", )}
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-type-x)",
animation_value_type="discrete",
)}
% endfor
% for axis in ["x", "y"]: % for axis in ["x", "y"]:
${helpers.predefined_type( ${helpers.predefined_type(

View file

@ -67,6 +67,7 @@ pub mod system_colors {
use crate::gecko_bindings::structs::root::mozilla::LookAndFeel_ColorID; use crate::gecko_bindings::structs::root::mozilla::LookAndFeel_ColorID;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss}; use style_traits::{CssWriter, ToCss};
use to_shmem::impl_trivial_to_shmem;
use crate::values::computed::{Context, ToComputedValue}; use crate::values::computed::{Context, ToComputedValue};
pub type SystemColor = LookAndFeel_ColorID; pub type SystemColor = LookAndFeel_ColorID;
@ -75,6 +76,8 @@ pub mod system_colors {
// is a bindgen type. So we implement it on the typedef instead. // is a bindgen type. So we implement it on the typedef instead.
malloc_size_of_is_0!(SystemColor); malloc_size_of_is_0!(SystemColor);
impl_trivial_to_shmem!(SystemColor);
impl ToCss for SystemColor { impl ToCss for SystemColor {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where where

View file

@ -326,7 +326,7 @@ ${helpers.predefined_type(
use app_units::Au; use app_units::Au;
use cssparser::{Parser, ToCss}; use cssparser::{Parser, ToCss};
use crate::gecko_bindings::structs::FontFamilyType; use crate::values::computed::font::GenericFontFamily;
use crate::properties::longhands; use crate::properties::longhands;
use std::fmt; use std::fmt;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
@ -346,7 +346,7 @@ ${helpers.predefined_type(
font_optical_sizing""".split() font_optical_sizing""".split()
%> %>
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToCss)] SpecifiedValueInfo, ToCss, ToShmem)]
pub enum SystemFont { pub enum SystemFont {
% for font in system_fonts: % for font in system_fonts:
${to_camel_case(font)}, ${to_camel_case(font)},
@ -406,9 +406,9 @@ ${helpers.predefined_type(
let font_style = FontStyle::from_gecko(system.style); let font_style = FontStyle::from_gecko(system.style);
let ret = ComputedSystemFont { let ret = ComputedSystemFont {
font_family: FontFamily { font_family: FontFamily {
families: FontFamilyList(unsafe { families: FontFamilyList::SharedFontList(
system.fontlist.mFontlist.mBasePtr.to_safe() unsafe { system.fontlist.mFontlist.mBasePtr.to_safe() }
}), ),
is_system_font: true, is_system_font: true,
}, },
font_size: FontSize { font_size: FontSize {
@ -466,7 +466,7 @@ ${helpers.predefined_type(
pub ${name}: longhands::${name}::computed_value::T, pub ${name}: longhands::${name}::computed_value::T,
% endfor % endfor
pub system_font: SystemFont, pub system_font: SystemFont,
pub default_font_type: FontFamilyType, pub default_font_type: GenericFontFamily,
} }
impl SystemFont { impl SystemFont {
@ -495,8 +495,7 @@ ${helpers.predefined_type(
// a lot of code with `if product == gecko` conditionals, we have a // a lot of code with `if product == gecko` conditionals, we have a
// dummy system font module that does nothing // dummy system font module that does nothing
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, SpecifiedValueInfo, ToCss)] #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
/// void enum for system font, can never exist /// void enum for system font, can never exist
pub enum SystemFont {} pub enum SystemFont {}
impl SystemFont { impl SystemFont {
@ -521,9 +520,9 @@ ${helpers.single_keyword(
${helpers.predefined_type( ${helpers.predefined_type(
"-moz-font-smoothing-background-color", "-moz-font-smoothing-background-color",
"RGBAColor", "color::MozFontSmoothingBackgroundColor",
"RGBA::transparent()", "computed::color::MozFontSmoothingBackgroundColor::transparent()",
animation_value_type="AnimatedRGBA", animation_value_type="none",
products="gecko", products="gecko",
gecko_ffi_name="mFont.fontSmoothingBackgroundColor", gecko_ffi_name="mFont.fontSmoothingBackgroundColor",
enabled_in="chrome", enabled_in="chrome",

View file

@ -63,6 +63,7 @@ ${helpers.predefined_type(
"generics::color::ColorOrAuto::Auto", "generics::color::ColorOrAuto::Auto",
spec="https://drafts.csswg.org/css-ui/#caret-color", spec="https://drafts.csswg.org/css-ui/#caret-color",
animation_value_type="AnimatedCaretColor", animation_value_type="AnimatedCaretColor",
boxed=True,
ignored_when_colors_disabled=True, ignored_when_colors_disabled=True,
products="gecko", products="gecko",
)} )}

View file

@ -372,7 +372,7 @@ ${helpers.predefined_type(
${helpers.predefined_type( ${helpers.predefined_type(
"column-gap", "column-gap",
"length::NonNegativeLengthPercentageOrNormal", "length::NonNegativeLengthPercentageOrNormal",
"Either::Second(Normal)", "computed::length::NonNegativeLengthPercentageOrNormal::normal()",
alias="grid-column-gap" if product == "gecko" else "", alias="grid-column-gap" if product == "gecko" else "",
extra_prefixes="moz", extra_prefixes="moz",
servo_pref="layout.columns.enabled", servo_pref="layout.columns.enabled",
@ -385,7 +385,7 @@ ${helpers.predefined_type(
${helpers.predefined_type( ${helpers.predefined_type(
"row-gap", "row-gap",
"length::NonNegativeLengthPercentageOrNormal", "length::NonNegativeLengthPercentageOrNormal",
"Either::Second(Normal)", "computed::length::NonNegativeLengthPercentageOrNormal::normal()",
alias="grid-row-gap", alias="grid-row-gap",
products="gecko", products="gecko",
spec="https://drafts.csswg.org/css-align-3/#propdef-row-gap", spec="https://drafts.csswg.org/css-align-3/#propdef-row-gap",

View file

@ -36,9 +36,10 @@ use selectors::parser::SelectorParseErrorKind;
#[cfg(feature = "servo")] use servo_config::prefs; #[cfg(feature = "servo")] use servo_config::prefs;
use style_traits::{CssWriter, KeywordsCollectFn, ParseError, ParsingMode}; use style_traits::{CssWriter, KeywordsCollectFn, ParseError, ParsingMode};
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss}; use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
use to_shmem::impl_trivial_to_shmem;
use crate::stylesheets::{CssRuleType, Origin, UrlExtraData}; use crate::stylesheets::{CssRuleType, Origin, UrlExtraData};
use crate::values::generics::text::LineHeight; use crate::values::generics::text::LineHeight;
use crate::values::computed; use crate::values::{computed, resolved};
use crate::values::computed::NonNegativeLength; use crate::values::computed::NonNegativeLength;
use crate::values::serialize_atom_name; use crate::values::serialize_atom_name;
use crate::rule_tree::StrongRuleNode; use crate::rule_tree::StrongRuleNode;
@ -256,6 +257,7 @@ pub mod shorthands {
%> %>
/// Servo's representation for a property declaration. /// Servo's representation for a property declaration.
#[derive(ToShmem)]
#[repr(u16)] #[repr(u16)]
pub enum PropertyDeclaration { pub enum PropertyDeclaration {
% for variant in variants: % for variant in variants:
@ -741,11 +743,13 @@ static ${name}: LonghandIdSet = LonghandIdSet {
</%def> </%def>
/// A set of longhand properties /// A set of longhand properties
#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq)] #[derive(Clone, Copy, Debug, Default, MallocSizeOf, PartialEq)]
pub struct LonghandIdSet { pub struct LonghandIdSet {
storage: [u32; (${len(data.longhands)} - 1 + 32) / 32] storage: [u32; (${len(data.longhands)} - 1 + 32) / 32]
} }
impl_trivial_to_shmem!(LonghandIdSet);
/// An iterator over a set of longhand ids. /// An iterator over a set of longhand ids.
pub struct LonghandIdSetIterator<'a> { pub struct LonghandIdSetIterator<'a> {
longhands: &'a LonghandIdSet, longhands: &'a LonghandIdSet,
@ -893,7 +897,7 @@ impl LonghandIdSet {
/// An enum to represent a CSS Wide keyword. /// An enum to represent a CSS Wide keyword.
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToCss)] ToCss, ToShmem)]
pub enum CSSWideKeyword { pub enum CSSWideKeyword {
/// The `initial` keyword. /// The `initial` keyword.
Initial, Initial,
@ -993,7 +997,7 @@ pub enum LogicalGroup {
} }
/// An identifier for a given longhand property. /// An identifier for a given longhand property.
#[derive(Clone, Copy, Eq, Hash, MallocSizeOf, PartialEq)] #[derive(Clone, Copy, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
#[repr(u16)] #[repr(u16)]
pub enum LonghandId { pub enum LonghandId {
% for i, property in enumerate(data.longhands): % for i, property in enumerate(data.longhands):
@ -1266,49 +1270,12 @@ impl LonghandId {
LonghandId::FontStyle | LonghandId::FontStyle |
LonghandId::FontFamily | LonghandId::FontFamily |
// Needed to resolve currentcolor at computed value time properly.
//
// FIXME(emilio): All the properties should be moved to currentcolor
// as a computed-value (and thus resolving it at used-value time).
//
// This would allow this property to go away from this list.
LonghandId::Color |
// FIXME(emilio): There's no reason for this afaict, nuke it.
LonghandId::TextDecorationLine |
// Needed to properly compute the writing mode, to resolve logical // Needed to properly compute the writing mode, to resolve logical
// properties, and similar stuff. // properties, and similar stuff.
LonghandId::WritingMode | LonghandId::WritingMode |
LonghandId::Direction LonghandId::Direction
) )
} }
/// Whether computed values of this property lossily convert any complex
/// colors into RGBA colors.
///
/// In Gecko, there are some properties still that compute currentcolor
/// down to an RGBA color at computed value time, instead of as
/// `StyleComplexColor`s. For these properties, we must return `false`,
/// so that we correctly avoid caching style data in the rule tree.
pub fn stores_complex_colors_lossily(&self) -> bool {
% if product == "gecko":
matches!(*self,
% for property in data.longhands:
% if property.predefined_type == "RGBAColor":
LonghandId::${property.camel_case} |
% endif
% endfor
LonghandId::BackgroundImage |
LonghandId::BorderImageSource |
LonghandId::BoxShadow |
LonghandId::MaskImage |
LonghandId::TextShadow
)
% else:
false
% endif
}
} }
/// An iterator over all the property ids that are enabled for a given /// An iterator over all the property ids that are enabled for a given
@ -1335,7 +1302,7 @@ where
} }
/// An identifier for a given shorthand property. /// An identifier for a given shorthand property.
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
#[repr(u16)] #[repr(u16)]
pub enum ShorthandId { pub enum ShorthandId {
% for i, property in enumerate(data.shorthands): % for i, property in enumerate(data.shorthands):
@ -1533,7 +1500,7 @@ impl ShorthandId {
} }
/// An unparsed property value that contains `var()` functions. /// An unparsed property value that contains `var()` functions.
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq, ToShmem)]
pub struct UnparsedValue { pub struct UnparsedValue {
/// The css serialization for this value. /// The css serialization for this value.
css: String, css: String,
@ -1954,7 +1921,7 @@ impl PropertyId {
/// A declaration using a CSS-wide keyword. /// A declaration using a CSS-wide keyword.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, PartialEq, ToCss)] #[derive(Clone, PartialEq, ToCss, ToShmem)]
pub struct WideKeywordDeclaration { pub struct WideKeywordDeclaration {
#[css(skip)] #[css(skip)]
id: LonghandId, id: LonghandId,
@ -1963,7 +1930,7 @@ pub struct WideKeywordDeclaration {
/// An unparsed declaration that contains `var()` functions. /// An unparsed declaration that contains `var()` functions.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, PartialEq, ToCss)] #[derive(Clone, PartialEq, ToCss, ToShmem)]
pub struct VariableDeclaration { pub struct VariableDeclaration {
#[css(skip)] #[css(skip)]
id: LonghandId, id: LonghandId,
@ -1973,7 +1940,7 @@ pub struct VariableDeclaration {
/// A custom property declaration value is either an unparsed value or a CSS /// A custom property declaration value is either an unparsed value or a CSS
/// wide-keyword. /// wide-keyword.
#[derive(Clone, PartialEq, ToCss)] #[derive(Clone, PartialEq, ToCss, ToShmem)]
pub enum CustomDeclarationValue { pub enum CustomDeclarationValue {
/// A value. /// A value.
Value(Arc<crate::custom_properties::SpecifiedValue>), Value(Arc<crate::custom_properties::SpecifiedValue>),
@ -1983,7 +1950,7 @@ pub enum CustomDeclarationValue {
/// A custom property declaration with the property name and the declared value. /// A custom property declaration with the property name and the declared value.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, PartialEq, ToCss)] #[derive(Clone, PartialEq, ToCss, ToShmem)]
pub struct CustomDeclaration { pub struct CustomDeclaration {
/// The name of the custom property. /// The name of the custom property.
#[css(skip)] #[css(skip)]
@ -2845,19 +2812,19 @@ impl ComputedValues {
where where
W: Write, W: Write,
{ {
use crate::values::resolved::ToResolvedValue;
let context = resolved::Context {
style: self,
};
// TODO(emilio): Is it worth to merge branches here just like // TODO(emilio): Is it worth to merge branches here just like
// PropertyDeclaration::to_css does? // PropertyDeclaration::to_css does?
//
// We'd need to get a concept of ~resolved value, which may not be worth
// it.
match property_id { match property_id {
% for prop in data.longhands: % for prop in data.longhands:
LonghandId::${prop.camel_case} => { LonghandId::${prop.camel_case} => {
let value = self.clone_${prop.ident}(); let value = self.clone_${prop.ident}();
% if prop.predefined_type == "Color": value.to_resolved_value(&context).to_css(dest)
let value = self.resolve_color(value);
% endif
value.to_css(dest)
} }
% endfor % endfor
} }

View file

@ -303,36 +303,6 @@ macro_rules! try_parse_one {
} }
</%helpers:shorthand> </%helpers:shorthand>
<%helpers:shorthand name="scroll-snap-type" products="gecko"
gecko_pref="layout.css.scroll-snap.enabled"
sub_properties="scroll-snap-type-x scroll-snap-type-y"
spec="https://drafts.csswg.org/css-scroll-snap/#propdef-scroll-snap-type">
use crate::properties::longhands::scroll_snap_type_x;
pub fn parse_value<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Longhands, ParseError<'i>> {
let result = scroll_snap_type_x::parse(context, input)?;
Ok(expanded! {
scroll_snap_type_x: result,
scroll_snap_type_y: result,
})
}
impl<'a> ToCss for LonghandsToSerialize<'a> {
// Serializes into the single keyword value if both scroll-snap-type-x and scroll-snap-type-y are same.
// Otherwise into an empty string. This is done to match Gecko's behaviour.
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
if self.scroll_snap_type_x == self.scroll_snap_type_y {
self.scroll_snap_type_x.to_css(dest)
} else {
Ok(())
}
}
}
</%helpers:shorthand>
${helpers.two_properties_shorthand( ${helpers.two_properties_shorthand(
"overscroll-behavior", "overscroll-behavior",
"overscroll-behavior-x", "overscroll-behavior-x",

View file

@ -75,8 +75,15 @@ impl Drop for RuleTree {
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
impl MallocSizeOf for RuleTree { impl MallocSizeOf for RuleTree {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = unsafe { ops.malloc_size_of(self.root.ptr()) }; let mut n = 0;
n += self.root.get().size_of(ops); let mut stack = SmallVec::<[_; 32]>::new();
stack.push(self.root.downgrade());
while let Some(node) = stack.pop() {
n += unsafe { ops.malloc_size_of(node.ptr()) };
stack.extend(unsafe { (*node.ptr()).iter_children() });
}
n n
} }
} }
@ -947,18 +954,6 @@ impl RuleNode {
} }
} }
#[cfg(feature = "gecko")]
impl MallocSizeOf for RuleNode {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = 0;
for child in self.iter_children() {
n += unsafe { ops.malloc_size_of(child.ptr()) };
n += unsafe { (*child.ptr()).size_of(ops) };
}
n
}
}
#[derive(Clone)] #[derive(Clone)]
struct WeakRuleNode { struct WeakRuleNode {
p: ptr::NonNull<RuleNode>, p: ptr::NonNull<RuleNode>,
@ -1239,7 +1234,7 @@ impl StrongRuleNode {
use crate::gecko_bindings::structs::NS_AUTHOR_SPECIFIED_BACKGROUND; use crate::gecko_bindings::structs::NS_AUTHOR_SPECIFIED_BACKGROUND;
use crate::gecko_bindings::structs::NS_AUTHOR_SPECIFIED_BORDER; use crate::gecko_bindings::structs::NS_AUTHOR_SPECIFIED_BORDER;
use crate::gecko_bindings::structs::NS_AUTHOR_SPECIFIED_PADDING; use crate::gecko_bindings::structs::NS_AUTHOR_SPECIFIED_PADDING;
use crate::properties::{CSSWideKeyword, LonghandId, LonghandIdSet}; use crate::properties::{CSSWideKeyword, LonghandId};
use crate::properties::{PropertyDeclaration, PropertyDeclarationId}; use crate::properties::{PropertyDeclaration, PropertyDeclarationId};
use crate::values::specified::Color; use crate::values::specified::Color;
use std::borrow::Cow; use std::borrow::Cow;

View file

@ -177,7 +177,7 @@ impl<T> PerPseudoElementMap<T> {
/// Values for the :dir() pseudo class /// Values for the :dir() pseudo class
/// ///
/// "ltr" and "rtl" values are normalized to lowercase. /// "ltr" and "rtl" values are normalized to lowercase.
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
pub struct Direction(pub Atom); pub struct Direction(pub Atom);
/// Horizontal values for the :dir() pseudo class /// Horizontal values for the :dir() pseudo class

View file

@ -29,8 +29,7 @@ use style_traits::{ParseError, StyleParseErrorKind};
/// A pseudo-element, both public and private. /// A pseudo-element, both public and private.
/// ///
/// NB: If you add to this list, be sure to update `each_simple_pseudo_element` too. /// NB: If you add to this list, be sure to update `each_simple_pseudo_element` too.
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[allow(missing_docs)] #[allow(missing_docs)]
#[repr(usize)] #[repr(usize)]
pub enum PseudoElement { pub enum PseudoElement {
@ -265,8 +264,7 @@ pub type Lang = Box<str>;
/// A non tree-structural pseudo-class. /// A non tree-structural pseudo-class.
/// See https://drafts.csswg.org/selectors-4/#structural-pseudos /// See https://drafts.csswg.org/selectors-4/#structural-pseudos
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[allow(missing_docs)] #[allow(missing_docs)]
pub enum NonTSPseudoClass { pub enum NonTSPseudoClass {
Active, Active,

View file

@ -12,7 +12,7 @@ use std::fmt::{self, Write};
// nonzero optimization is important in keeping the size of SpecifiedUrl below // nonzero optimization is important in keeping the size of SpecifiedUrl below
// the threshold. // the threshold.
use crate::values::computed::{Context, ToComputedValue}; use crate::values::computed::{Context, ToComputedValue};
use std::sync::Arc; use servo_arc::Arc;
use style_traits::{CssWriter, ParseError, ToCss}; use style_traits::{CssWriter, ParseError, ToCss};
/// A CSS url() value for servo. /// A CSS url() value for servo.
@ -26,7 +26,7 @@ use style_traits::{CssWriter, ParseError, ToCss};
/// ///
/// TODO(emilio): This should be shrunk by making CssUrl a wrapper type of an /// TODO(emilio): This should be shrunk by making CssUrl a wrapper type of an
/// arc, and keep the serialization in that Arc. See gecko/url.rs for example. /// arc, and keep the serialization in that Arc. See gecko/url.rs for example.
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize, SpecifiedValueInfo)] #[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize, SpecifiedValueInfo, ToShmem)]
pub struct CssUrl { pub struct CssUrl {
/// The original URI. This might be optional since we may insert computed /// The original URI. This might be optional since we may insert computed
/// values of images into the cascade directly, and we don't bother to /// values of images into the cascade directly, and we don't bother to

View file

@ -15,8 +15,10 @@ use std::cell::UnsafeCell;
use std::fmt; use std::fmt;
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
use std::mem; use std::mem;
use std::mem::ManuallyDrop;
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
use std::ptr; use std::ptr;
use to_shmem::{SharedMemoryBuilder, ToShmem};
/// A shared read/write lock that can protect multiple objects. /// A shared read/write lock that can protect multiple objects.
/// ///
@ -28,6 +30,10 @@ use std::ptr;
/// Servo needs the blocking behavior for its unsynchronized animation setup, /// Servo needs the blocking behavior for its unsynchronized animation setup,
/// but that may not be web-compatible and may need to be changed (at which /// but that may not be web-compatible and may need to be changed (at which
/// point Servo could use AtomicRefCell too). /// point Servo could use AtomicRefCell too).
///
/// Gecko also needs the ability to have "read only" SharedRwLocks, which are
/// used for objects stored in (read only) shared memory. Attempting to acquire
/// write access to objects protected by a read only SharedRwLock will panic.
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))] #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
pub struct SharedRwLock { pub struct SharedRwLock {
@ -36,7 +42,7 @@ pub struct SharedRwLock {
arc: Arc<RwLock<()>>, arc: Arc<RwLock<()>>,
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
cell: Arc<AtomicRefCell<SomethingZeroSizedButTyped>>, cell: Option<Arc<AtomicRefCell<SomethingZeroSizedButTyped>>>,
} }
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
@ -61,10 +67,16 @@ impl SharedRwLock {
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub fn new() -> Self { pub fn new() -> Self {
SharedRwLock { SharedRwLock {
cell: Arc::new(AtomicRefCell::new(SomethingZeroSizedButTyped)), cell: Some(Arc::new(AtomicRefCell::new(SomethingZeroSizedButTyped))),
} }
} }
/// Create a new read-only shared lock (gecko).
#[cfg(feature = "gecko")]
pub fn read_only() -> Self {
SharedRwLock { cell: None }
}
/// Wrap the given data to make its access protected by this lock. /// Wrap the given data to make its access protected by this lock.
pub fn wrap<T>(&self, data: T) -> Locked<T> { pub fn wrap<T>(&self, data: T) -> Locked<T> {
Locked { Locked {
@ -83,7 +95,7 @@ impl SharedRwLock {
/// Obtain the lock for reading (gecko). /// Obtain the lock for reading (gecko).
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub fn read(&self) -> SharedRwLockReadGuard { pub fn read(&self) -> SharedRwLockReadGuard {
SharedRwLockReadGuard(self.cell.borrow()) SharedRwLockReadGuard(self.cell.as_ref().map(|cell| cell.borrow()))
} }
/// Obtain the lock for writing (servo). /// Obtain the lock for writing (servo).
@ -96,16 +108,16 @@ impl SharedRwLock {
/// Obtain the lock for writing (gecko). /// Obtain the lock for writing (gecko).
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub fn write(&self) -> SharedRwLockWriteGuard { pub fn write(&self) -> SharedRwLockWriteGuard {
SharedRwLockWriteGuard(self.cell.borrow_mut()) SharedRwLockWriteGuard(self.cell.as_ref().unwrap().borrow_mut())
} }
} }
/// Proof that a shared lock was obtained for reading (servo). /// Proof that a shared lock was obtained for reading (servo).
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
pub struct SharedRwLockReadGuard<'a>(&'a SharedRwLock); pub struct SharedRwLockReadGuard<'a>(&'a SharedRwLock);
/// Proof that a shared lock was obtained for writing (gecko). /// Proof that a shared lock was obtained for reading (gecko).
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub struct SharedRwLockReadGuard<'a>(AtomicRef<'a, SomethingZeroSizedButTyped>); pub struct SharedRwLockReadGuard<'a>(Option<AtomicRef<'a, SomethingZeroSizedButTyped>>);
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
impl<'a> Drop for SharedRwLockReadGuard<'a> { impl<'a> Drop for SharedRwLockReadGuard<'a> {
fn drop(&mut self) { fn drop(&mut self) {
@ -149,22 +161,41 @@ impl<T: fmt::Debug> fmt::Debug for Locked<T> {
} }
impl<T> Locked<T> { impl<T> Locked<T> {
#[cfg(feature = "gecko")]
#[inline]
fn is_read_only_lock(&self) -> bool {
self.shared_lock.cell.is_none()
}
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
fn same_lock_as(&self, lock: &SharedRwLock) -> bool { fn same_lock_as(&self, lock: &SharedRwLock) -> bool {
Arc::ptr_eq(&self.shared_lock.arc, &lock.arc) Arc::ptr_eq(&self.shared_lock.arc, &lock.arc)
} }
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
fn same_lock_as(&self, derefed_guard: &SomethingZeroSizedButTyped) -> bool { fn same_lock_as(&self, derefed_guard: Option<&SomethingZeroSizedButTyped>) -> bool {
ptr::eq(self.shared_lock.cell.as_ptr(), derefed_guard) ptr::eq(
self.shared_lock
.cell
.as_ref()
.map(|cell| cell.as_ptr())
.unwrap_or(ptr::null_mut()),
derefed_guard
.map(|guard| guard as *const _ as *mut _)
.unwrap_or(ptr::null_mut()),
)
} }
/// Access the data for reading. /// Access the data for reading.
pub fn read_with<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> &'a T { pub fn read_with<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> &'a T {
#[cfg(feature = "gecko")]
assert!( assert!(
self.same_lock_as(&guard.0), self.is_read_only_lock() || self.same_lock_as(guard.0.as_ref().map(|r| &**r)),
"Locked::read_with called with a guard from an unrelated SharedRwLock" "Locked::read_with called with a guard from an unrelated SharedRwLock"
); );
#[cfg(not(feature = "gecko"))]
assert!(self.same_lock_as(&guard.0));
let ptr = self.data.get(); let ptr = self.data.get();
// Unsafe: // Unsafe:
@ -185,10 +216,14 @@ impl<T> Locked<T> {
/// Access the data for writing. /// Access the data for writing.
pub fn write_with<'a>(&'a self, guard: &'a mut SharedRwLockWriteGuard) -> &'a mut T { pub fn write_with<'a>(&'a self, guard: &'a mut SharedRwLockWriteGuard) -> &'a mut T {
#[cfg(feature = "gecko")]
assert!( assert!(
self.same_lock_as(&guard.0), !self.is_read_only_lock() && self.same_lock_as(Some(&guard.0)),
"Locked::write_with called with a guard from an unrelated SharedRwLock" "Locked::write_with called with a guard from a read only or unrelated SharedRwLock"
); );
#[cfg(not(feature = "gecko"))]
assert!(self.same_lock_as(&guard.0));
let ptr = self.data.get(); let ptr = self.data.get();
// Unsafe: // Unsafe:
@ -203,6 +238,26 @@ impl<T> Locked<T> {
} }
} }
#[cfg(feature = "gecko")]
impl<T: ToShmem> ToShmem for Locked<T> {
fn to_shmem(&self, builder: &mut SharedMemoryBuilder) -> ManuallyDrop<Self> {
let guard = self.shared_lock.read();
ManuallyDrop::new(Locked {
shared_lock: SharedRwLock::read_only(),
data: UnsafeCell::new(ManuallyDrop::into_inner(
self.read_with(&guard).to_shmem(builder),
)),
})
}
}
#[cfg(feature = "servo")]
impl<T: ToShmem> ToShmem for Locked<T> {
fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> ManuallyDrop<Self> {
panic!("ToShmem not supported in Servo currently")
}
}
#[allow(dead_code)] #[allow(dead_code)]
mod compile_time_assert { mod compile_time_assert {
use super::{SharedRwLockReadGuard, SharedRwLockWriteGuard}; use super::{SharedRwLockReadGuard, SharedRwLockWriteGuard};

View file

@ -723,52 +723,6 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
} }
} }
/// For HTML elements with 'display:list-item' we add a default 'counter-increment:list-item'
/// unless 'counter-increment' already has a value for 'list-item'.
///
/// https://drafts.csswg.org/css-lists-3/#declaring-a-list-item
#[cfg(feature = "gecko")]
fn adjust_for_list_item<E>(&mut self, element: Option<E>)
where
E: TElement,
{
use crate::properties::longhands::counter_increment::computed_value::T as ComputedIncrement;
use crate::values::generics::counters::CounterPair;
use crate::values::specified::list::MozListReversed;
use crate::values::CustomIdent;
if self.style.get_box().clone_display() != Display::ListItem {
return;
}
if self.style.pseudo.is_some() {
return;
}
if !element.map_or(false, |e| e.is_html_element()) {
return;
}
// Note that we map <li value=INTEGER> to 'counter-set: list-item INTEGER;
// counter-increment: list-item 0;' so we'll return here unless the author
// explicitly specified something else.
let increments = self.style.get_counters().clone_counter_increment();
if increments.iter().any(|i| i.name.0 == atom!("list-item")) {
return;
}
let reversed = self.style.get_list().clone__moz_list_reversed() == MozListReversed::True;
let increment = if reversed { -1 } else { 1 };
let list_increment = CounterPair {
name: CustomIdent(atom!("list-item")),
value: increment,
};
let increments = increments
.iter()
.cloned()
.chain(std::iter::once(list_increment));
self.style
.mutate_counters()
.set_counter_increment(ComputedIncrement::new(increments.collect()));
}
/// Adjusts the style to account for various fixups that don't fit naturally /// Adjusts the style to account for various fixups that don't fit naturally
/// into the cascade. /// into the cascade.
/// ///
@ -833,7 +787,6 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
{ {
self.adjust_for_appearance(element); self.adjust_for_appearance(element);
self.adjust_for_list_item(element);
} }
self.set_bits(); self.set_bits();
} }

View file

@ -211,8 +211,6 @@ where
type Item = (&'a S, SheetRebuildKind); type Item = (&'a S, SheetRebuildKind);
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
use std::mem;
loop { loop {
let potential_sheet = self.iter.next()?; let potential_sheet = self.iter.next()?;

View file

@ -20,7 +20,7 @@ use servo_arc::Arc;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
#[derive(Debug)] #[derive(Debug, ToShmem)]
/// A @-moz-document rule /// A @-moz-document rule
pub struct DocumentRule { pub struct DocumentRule {
/// The parsed condition /// The parsed condition
@ -72,7 +72,7 @@ impl DeepCloneWithLock for DocumentRule {
} }
/// The kind of media document that the rule will match. /// The kind of media document that the rule will match.
#[derive(Clone, Copy, Debug, Parse, PartialEq, ToCss)] #[derive(Clone, Copy, Debug, Parse, PartialEq, ToCss, ToShmem)]
#[allow(missing_docs)] #[allow(missing_docs)]
pub enum MediaDocumentKind { pub enum MediaDocumentKind {
All, All,
@ -82,7 +82,7 @@ pub enum MediaDocumentKind {
} }
/// A matching function for a `@document` rule's condition. /// A matching function for a `@document` rule's condition.
#[derive(Clone, Debug, ToCss)] #[derive(Clone, Debug, ToCss, ToShmem)]
pub enum DocumentMatchingFunction { pub enum DocumentMatchingFunction {
/// Exact URL matching function. It evaluates to true whenever the /// Exact URL matching function. It evaluates to true whenever the
/// URL of the document being styled is exactly the URL given. /// URL of the document being styled is exactly the URL given.
@ -216,7 +216,7 @@ impl DocumentMatchingFunction {
/// URL matching functions, and the condition evaluates to true whenever any /// URL matching functions, and the condition evaluates to true whenever any
/// one of those functions evaluates to true. /// one of those functions evaluates to true.
#[css(comma)] #[css(comma)]
#[derive(Clone, Debug, ToCss)] #[derive(Clone, Debug, ToCss, ToShmem)]
pub struct DocumentCondition(#[css(iterable)] Vec<DocumentMatchingFunction>); pub struct DocumentCondition(#[css(iterable)] Vec<DocumentMatchingFunction>);
impl DocumentCondition { impl DocumentCondition {

View file

@ -30,7 +30,7 @@ use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
/// - `SingleValue` is to keep just one unsigned integer value. /// - `SingleValue` is to keep just one unsigned integer value.
/// - `PairValues` is to keep one or two unsigned integer values. /// - `PairValues` is to keep one or two unsigned integer values.
/// - `VectorValues` is to keep a list of unsigned integer values. /// - `VectorValues` is to keep a list of unsigned integer values.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq, ToShmem)]
pub struct FFVDeclaration<T> { pub struct FFVDeclaration<T> {
/// An `<ident>` for declaration name. /// An `<ident>` for declaration name.
pub name: Atom, pub name: Atom,
@ -58,7 +58,7 @@ pub trait ToGeckoFontFeatureValues {
} }
/// A @font-feature-values block declaration value that keeps one value. /// A @font-feature-values block declaration value that keeps one value.
#[derive(Clone, Debug, PartialEq, ToCss)] #[derive(Clone, Debug, PartialEq, ToCss, ToShmem)]
pub struct SingleValue(pub u32); pub struct SingleValue(pub u32);
impl Parse for SingleValue { impl Parse for SingleValue {
@ -87,7 +87,7 @@ impl ToGeckoFontFeatureValues for SingleValue {
} }
/// A @font-feature-values block declaration value that keeps one or two values. /// A @font-feature-values block declaration value that keeps one or two values.
#[derive(Clone, Debug, PartialEq, ToCss)] #[derive(Clone, Debug, PartialEq, ToCss, ToShmem)]
pub struct PairValues(pub u32, pub Option<u32>); pub struct PairValues(pub u32, pub Option<u32>);
impl Parse for PairValues { impl Parse for PairValues {
@ -131,7 +131,7 @@ impl ToGeckoFontFeatureValues for PairValues {
} }
/// A @font-feature-values block declaration value that keeps a list of values. /// A @font-feature-values block declaration value that keeps a list of values.
#[derive(Clone, Debug, PartialEq, ToCss)] #[derive(Clone, Debug, PartialEq, ToCss, ToShmem)]
pub struct VectorValues(#[css(iterable)] pub Vec<u32>); pub struct VectorValues(#[css(iterable)] pub Vec<u32>);
impl Parse for VectorValues { impl Parse for VectorValues {
@ -225,7 +225,7 @@ macro_rules! font_feature_values_blocks {
/// The [`@font-feature-values`][font-feature-values] at-rule. /// The [`@font-feature-values`][font-feature-values] at-rule.
/// ///
/// [font-feature-values]: https://drafts.csswg.org/css-fonts-3/#at-font-feature-values-rule /// [font-feature-values]: https://drafts.csswg.org/css-fonts-3/#at-font-feature-values-rule
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq, ToShmem)]
pub struct FontFeatureValuesRule { pub struct FontFeatureValuesRule {
/// Font family list for @font-feature-values rule. /// Font family list for @font-feature-values rule.
/// Family names cannot contain generic families. FamilyName /// Family names cannot contain generic families. FamilyName

View file

@ -15,7 +15,9 @@ use crate::stylesheets::{CssRule, Origin, StylesheetInDocument};
use crate::values::CssUrl; use crate::values::CssUrl;
use cssparser::SourceLocation; use cssparser::SourceLocation;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use std::mem::ManuallyDrop;
use style_traits::{CssWriter, ToCss}; use style_traits::{CssWriter, ToCss};
use to_shmem::{SharedMemoryBuilder, ToShmem};
/// With asynchronous stylesheet parsing, we can't synchronously create a /// With asynchronous stylesheet parsing, we can't synchronously create a
/// GeckoStyleSheet. So we use this placeholder instead. /// GeckoStyleSheet. So we use this placeholder instead.
@ -180,6 +182,12 @@ pub struct ImportRule {
pub source_location: SourceLocation, pub source_location: SourceLocation,
} }
impl ToShmem for ImportRule {
fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> ManuallyDrop<Self> {
panic!("ToShmem failed for ImportRule: cannot handle imported style sheets")
}
}
impl DeepCloneWithLock for ImportRule { impl DeepCloneWithLock for ImportRule {
fn deep_clone_with_lock( fn deep_clone_with_lock(
&self, &self,

View file

@ -26,7 +26,7 @@ use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCs
/// A [`@keyframes`][keyframes] rule. /// A [`@keyframes`][keyframes] rule.
/// ///
/// [keyframes]: https://drafts.csswg.org/css-animations/#keyframes /// [keyframes]: https://drafts.csswg.org/css-animations/#keyframes
#[derive(Debug)] #[derive(Debug, ToShmem)]
pub struct KeyframesRule { pub struct KeyframesRule {
/// The name of the current animation. /// The name of the current animation.
pub name: KeyframesName, pub name: KeyframesName,
@ -99,7 +99,7 @@ impl DeepCloneWithLock for KeyframesRule {
/// A number from 0 to 1, indicating the percentage of the animation when this /// A number from 0 to 1, indicating the percentage of the animation when this
/// keyframe should run. /// keyframe should run.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToShmem)]
pub struct KeyframePercentage(pub f32); pub struct KeyframePercentage(pub f32);
impl ::std::cmp::Ord for KeyframePercentage { impl ::std::cmp::Ord for KeyframePercentage {
@ -150,7 +150,7 @@ impl KeyframePercentage {
/// A keyframes selector is a list of percentages or from/to symbols, which are /// A keyframes selector is a list of percentages or from/to symbols, which are
/// converted at parse time to percentages. /// converted at parse time to percentages.
#[css(comma)] #[css(comma)]
#[derive(Clone, Debug, Eq, PartialEq, ToCss)] #[derive(Clone, Debug, Eq, PartialEq, ToCss, ToShmem)]
pub struct KeyframeSelector(#[css(iterable)] Vec<KeyframePercentage>); pub struct KeyframeSelector(#[css(iterable)] Vec<KeyframePercentage>);
impl KeyframeSelector { impl KeyframeSelector {
@ -174,7 +174,7 @@ impl KeyframeSelector {
} }
/// A keyframe. /// A keyframe.
#[derive(Debug)] #[derive(Debug, ToShmem)]
pub struct Keyframe { pub struct Keyframe {
/// The selector this keyframe was specified from. /// The selector this keyframe was specified from.
pub selector: KeyframeSelector, pub selector: KeyframeSelector,

View file

@ -21,7 +21,7 @@ use style_traits::{CssWriter, ToCss};
/// An [`@media`][media] urle. /// An [`@media`][media] urle.
/// ///
/// [media]: https://drafts.csswg.org/css-conditional/#at-ruledef-media /// [media]: https://drafts.csswg.org/css-conditional/#at-ruledef-media
#[derive(Debug)] #[derive(Debug, ToShmem)]
pub struct MediaRule { pub struct MediaRule {
/// The list of media queries used by this media rule. /// The list of media queries used by this media rule.
pub media_queries: Arc<Locked<MediaList>>, pub media_queries: Arc<Locked<MediaList>>,

View file

@ -23,6 +23,10 @@ mod stylesheet;
pub mod supports_rule; pub mod supports_rule;
pub mod viewport_rule; pub mod viewport_rule;
#[cfg(feature = "gecko")]
use crate::gecko_bindings::sugar::refptr::RefCounted;
#[cfg(feature = "gecko")]
use crate::gecko_bindings::{bindings, structs};
use crate::parser::ParserContext; use crate::parser::ParserContext;
use crate::shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked}; use crate::shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked};
use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard}; use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
@ -32,7 +36,11 @@ use cssparser::{parse_one_rule, Parser, ParserInput};
use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf}; use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
use servo_arc::Arc; use servo_arc::Arc;
use std::fmt; use std::fmt;
#[cfg(feature = "gecko")]
use std::mem::{self, ManuallyDrop};
use style_traits::ParsingMode; use style_traits::ParsingMode;
#[cfg(feature = "gecko")]
use to_shmem::{SharedMemoryBuilder, ToShmem};
pub use self::counter_style_rule::CounterStyleRule; pub use self::counter_style_rule::CounterStyleRule;
pub use self::document_rule::DocumentRule; pub use self::document_rule::DocumentRule;
@ -60,18 +68,76 @@ pub use self::viewport_rule::ViewportRule;
pub type UrlExtraData = ::servo_url::ServoUrl; pub type UrlExtraData = ::servo_url::ServoUrl;
/// Extra data that the backend may need to resolve url values. /// Extra data that the backend may need to resolve url values.
///
/// If the usize's lowest bit is 0, then this is a strong reference to a
/// structs::URLExtraData object.
///
/// Otherwise, shifting the usize's bits the right by one gives the
/// UserAgentStyleSheetID value corresponding to the style sheet whose
/// URLExtraData this is, which is stored in URLExtraData_sShared. We don't
/// hold a strong reference to that object from here, but we rely on that
/// array's objects being held alive until shutdown.
///
/// We use this packed representation rather than an enum so that
/// `from_ptr_ref` can work.
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
#[derive(Clone, PartialEq)] #[derive(PartialEq)]
pub struct UrlExtraData( pub struct UrlExtraData(usize);
pub crate::gecko_bindings::sugar::refptr::RefPtr<crate::gecko_bindings::structs::URLExtraData>,
); #[cfg(feature = "gecko")]
impl Clone for UrlExtraData {
fn clone(&self) -> UrlExtraData {
UrlExtraData::new(self.ptr())
}
}
#[cfg(feature = "gecko")]
impl Drop for UrlExtraData {
fn drop(&mut self) {
// No need to release when we have an index into URLExtraData_sShared.
if self.0 & 1 == 0 {
unsafe {
self.as_ref().release();
}
}
}
}
#[cfg(feature = "gecko")]
impl ToShmem for UrlExtraData {
fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> ManuallyDrop<Self> {
if self.0 & 1 == 0 {
let shared_extra_datas = unsafe { &structs::URLExtraData_sShared };
let self_ptr = self.as_ref() as *const _ as *mut _;
let sheet_id = shared_extra_datas
.iter()
.position(|r| r.mRawPtr == self_ptr)
.expect(
"ToShmem failed for UrlExtraData: expected sheet's URLExtraData to be in \
URLExtraData::sShared",
);
ManuallyDrop::new(UrlExtraData((sheet_id << 1) | 1))
} else {
ManuallyDrop::new(UrlExtraData(self.0))
}
}
}
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
impl UrlExtraData { impl UrlExtraData {
/// Create a new UrlExtraData wrapping a pointer to the specified Gecko
/// URLExtraData object.
pub fn new(ptr: *mut structs::URLExtraData) -> UrlExtraData {
unsafe {
(*ptr).addref();
}
UrlExtraData(ptr as usize)
}
/// True if this URL scheme is chrome. /// True if this URL scheme is chrome.
#[inline] #[inline]
pub fn is_chrome(&self) -> bool { pub fn is_chrome(&self) -> bool {
self.0.mIsChrome self.as_ref().mIsChrome
} }
/// Create a reference to this `UrlExtraData` from a reference to pointer. /// Create a reference to this `UrlExtraData` from a reference to pointer.
@ -80,16 +146,30 @@ impl UrlExtraData {
/// ///
/// This method doesn't touch refcount. /// This method doesn't touch refcount.
#[inline] #[inline]
pub unsafe fn from_ptr_ref(ptr: &*mut crate::gecko_bindings::structs::URLExtraData) -> &Self { pub unsafe fn from_ptr_ref(ptr: &*mut structs::URLExtraData) -> &Self {
::std::mem::transmute(ptr) mem::transmute(ptr)
}
/// Returns a pointer to the Gecko URLExtraData object.
pub fn ptr(&self) -> *mut structs::URLExtraData {
if self.0 & 1 == 0 {
self.0 as *mut structs::URLExtraData
} else {
unsafe {
let sheet_id = self.0 >> 1;
structs::URLExtraData_sShared[sheet_id].mRawPtr
}
}
}
fn as_ref(&self) -> &structs::URLExtraData {
unsafe { &*(self.ptr() as *const structs::URLExtraData) }
} }
} }
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
impl fmt::Debug for UrlExtraData { impl fmt::Debug for UrlExtraData {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
use crate::gecko_bindings::{bindings, structs};
struct DebugURI(*mut structs::nsIURI); struct DebugURI(*mut structs::nsIURI);
impl fmt::Debug for DebugURI { impl fmt::Debug for DebugURI {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
@ -105,10 +185,13 @@ impl fmt::Debug for UrlExtraData {
formatter formatter
.debug_struct("URLExtraData") .debug_struct("URLExtraData")
.field("is_chrome", &self.is_chrome()) .field("is_chrome", &self.is_chrome())
.field("base", &DebugURI(self.0.mBaseURI.raw::<structs::nsIURI>())) .field(
"base",
&DebugURI(self.as_ref().mBaseURI.raw::<structs::nsIURI>()),
)
.field( .field(
"referrer", "referrer",
&DebugURI(self.0.mReferrer.raw::<structs::nsIURI>()), &DebugURI(self.as_ref().mReferrer.raw::<structs::nsIURI>()),
) )
.finish() .finish()
} }
@ -122,7 +205,7 @@ impl Eq for UrlExtraData {}
/// A CSS rule. /// A CSS rule.
/// ///
/// TODO(emilio): Lots of spec links should be around. /// TODO(emilio): Lots of spec links should be around.
#[derive(Clone, Debug)] #[derive(Clone, Debug, ToShmem)]
#[allow(missing_docs)] #[allow(missing_docs)]
pub enum CssRule { pub enum CssRule {
// No Charset here, CSSCharsetRule has been removed from CSSOM // No Charset here, CSSCharsetRule has been removed from CSSOM

View file

@ -11,7 +11,7 @@ use cssparser::SourceLocation;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
/// A `@namespace` rule. /// A `@namespace` rule.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq, ToShmem)]
#[allow(missing_docs)] #[allow(missing_docs)]
pub struct NamespaceRule { pub struct NamespaceRule {
/// The namespace prefix, and `None` if it's the default Namespace /// The namespace prefix, and `None` if it's the default Namespace

View file

@ -10,7 +10,7 @@ use std::ops::BitOrAssign;
/// Each style rule has an origin, which determines where it enters the cascade. /// Each style rule has an origin, which determines where it enters the cascade.
/// ///
/// <https://drafts.csswg.org/css-cascade/#cascading-origins> /// <https://drafts.csswg.org/css-cascade/#cascading-origins>
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq, ToShmem)]
#[repr(u8)] #[repr(u8)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))] #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
pub enum Origin { pub enum Origin {

View file

@ -25,7 +25,7 @@ use std::fmt::{self, Write};
/// ///
/// [page]: https://drafts.csswg.org/css2/page.html#page-box /// [page]: https://drafts.csswg.org/css2/page.html#page-box
/// [page-selectors]: https://drafts.csswg.org/css2/page.html#page-selectors /// [page-selectors]: https://drafts.csswg.org/css2/page.html#page-selectors
#[derive(Debug)] #[derive(Debug, ToShmem)]
pub struct PageRule { pub struct PageRule {
/// The declaration block this page rule contains. /// The declaration block this page rule contains.
pub block: Arc<Locked<PropertyDeclarationBlock>>, pub block: Arc<Locked<PropertyDeclarationBlock>>,

View file

@ -17,7 +17,7 @@ use servo_arc::{Arc, RawOffsetArc};
use std::fmt::{self, Write}; use std::fmt::{self, Write};
/// A list of CSS rules. /// A list of CSS rules.
#[derive(Debug)] #[derive(Debug, ToShmem)]
pub struct CssRules(pub Vec<CssRule>); pub struct CssRules(pub Vec<CssRule>);
impl CssRules { impl CssRules {

View file

@ -133,7 +133,7 @@ pub enum State {
Body = 4, Body = 4,
} }
#[derive(Clone, Debug, MallocSizeOf)] #[derive(Clone, Debug, MallocSizeOf, ToShmem)]
/// Vendor prefix. /// Vendor prefix.
pub enum VendorPrefix { pub enum VendorPrefix {
/// -moz prefix. /// -moz prefix.
@ -548,7 +548,7 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> {
self.namespaces, self.namespaces,
); );
let declarations = parse_property_declaration_list(&context, input); let declarations = parse_property_declaration_list(&context, input, None);
Ok(CssRule::Page(Arc::new(self.shared_lock.wrap(PageRule { Ok(CssRule::Page(Arc::new(self.shared_lock.wrap(PageRule {
block: Arc::new(self.shared_lock.wrap(declarations)), block: Arc::new(self.shared_lock.wrap(declarations)),
source_location, source_location,
@ -596,7 +596,7 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> {
let context = let context =
ParserContext::new_with_rule_type(self.context, CssRuleType::Style, self.namespaces); ParserContext::new_with_rule_type(self.context, CssRuleType::Style, self.namespaces);
let declarations = parse_property_declaration_list(&context, input); let declarations = parse_property_declaration_list(&context, input, Some(&selectors));
let block = Arc::new(self.shared_lock.wrap(declarations)); let block = Arc::new(self.shared_lock.wrap(declarations));
Ok(CssRule::Style(Arc::new(self.shared_lock.wrap(StyleRule { Ok(CssRule::Style(Arc::new(self.shared_lock.wrap(StyleRule {
selectors, selectors,

View file

@ -19,7 +19,7 @@ use servo_arc::Arc;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
/// A style rule, with selectors and declarations. /// A style rule, with selectors and declarations.
#[derive(Debug)] #[derive(Debug, ToShmem)]
pub struct StyleRule { pub struct StyleRule {
/// The list of selectors in this rule. /// The list of selectors in this rule.
pub selectors: SelectorList<SelectorImpl>, pub selectors: SelectorList<SelectorImpl>,

View file

@ -107,6 +107,34 @@ impl StylesheetContents {
} }
} }
/// Creates a new StylesheetContents with the specified pre-parsed rules,
/// origin, URL data, and quirks mode.
///
/// Since the rules have already been parsed, and the intention is that
/// this function is used for read only User Agent style sheets, an empty
/// namespace map is used, and the source map and source URLs are set to
/// None.
///
/// An empty namespace map should be fine, as it is only used for parsing,
/// not serialization of existing selectors. Since UA sheets are read only,
/// we should never need the namespace map.
pub fn from_shared_data(
rules: Arc<Locked<CssRules>>,
origin: Origin,
url_data: UrlExtraData,
quirks_mode: QuirksMode,
) -> Self {
Self {
rules,
origin,
url_data: RwLock::new(url_data),
namespaces: RwLock::new(Namespaces::default()),
quirks_mode,
source_map_url: RwLock::new(None),
source_url: RwLock::new(None),
}
}
/// Returns a reference to the list of rules. /// Returns a reference to the list of rules.
#[inline] #[inline]
pub fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] { pub fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {

View file

@ -26,7 +26,7 @@ use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
/// An [`@supports`][supports] rule. /// An [`@supports`][supports] rule.
/// ///
/// [supports]: https://drafts.csswg.org/css-conditional-3/#at-supports /// [supports]: https://drafts.csswg.org/css-conditional-3/#at-supports
#[derive(Debug)] #[derive(Debug, ToShmem)]
pub struct SupportsRule { pub struct SupportsRule {
/// The parsed condition /// The parsed condition
pub condition: SupportsCondition, pub condition: SupportsCondition,
@ -76,7 +76,7 @@ impl DeepCloneWithLock for SupportsRule {
/// An @supports condition /// An @supports condition
/// ///
/// <https://drafts.csswg.org/css-conditional-3/#at-supports> /// <https://drafts.csswg.org/css-conditional-3/#at-supports>
#[derive(Clone, Debug)] #[derive(Clone, Debug, ToShmem)]
pub enum SupportsCondition { pub enum SupportsCondition {
/// `not (condition)` /// `not (condition)`
Not(Box<SupportsCondition>), Not(Box<SupportsCondition>),
@ -223,8 +223,7 @@ impl SupportsCondition {
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
fn eval_moz_bool_pref(name: &CStr, cx: &ParserContext) -> bool { fn eval_moz_bool_pref(name: &CStr, cx: &ParserContext) -> bool {
use crate::gecko_bindings::bindings; use crate::gecko_bindings::bindings;
use crate::stylesheets::Origin; if !cx.in_ua_or_chrome_sheet() {
if cx.stylesheet_origin != Origin::UserAgent && !cx.chrome_rules_enabled() {
return false; return false;
} }
unsafe { bindings::Gecko_GetBoolPrefValue(name.as_ptr()) } unsafe { bindings::Gecko_GetBoolPrefValue(name.as_ptr()) }
@ -306,7 +305,7 @@ impl ToCss for SupportsCondition {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, ToShmem)]
/// A possibly-invalid CSS selector. /// A possibly-invalid CSS selector.
pub struct RawSelector(pub String); pub struct RawSelector(pub String);
@ -368,7 +367,7 @@ impl RawSelector {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, ToShmem)]
/// A possibly-invalid property declaration /// A possibly-invalid property declaration
pub struct Declaration(pub String); pub struct Declaration(pub String);

View file

@ -80,7 +80,7 @@ macro_rules! declare_viewport_descriptor_inner {
[ ] [ ]
$number_of_variants: expr $number_of_variants: expr
) => { ) => {
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq, ToShmem)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))] #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[allow(missing_docs)] #[allow(missing_docs)]
pub enum ViewportDescriptor { pub enum ViewportDescriptor {
@ -147,7 +147,7 @@ trait FromMeta: Sized {
/// * http://dev.w3.org/csswg/css-device-adapt/#extend-to-zoom /// * http://dev.w3.org/csswg/css-device-adapt/#extend-to-zoom
#[allow(missing_docs)] #[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))] #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[derive(Clone, Debug, PartialEq, ToCss)] #[derive(Clone, Debug, PartialEq, ToCss, ToShmem)]
pub enum ViewportLength { pub enum ViewportLength {
Specified(NonNegativeLengthPercentageOrAuto), Specified(NonNegativeLengthPercentageOrAuto),
ExtendToZoom, ExtendToZoom,
@ -225,7 +225,7 @@ struct ViewportRuleParser<'a, 'b: 'a> {
context: &'a ParserContext<'b>, context: &'a ParserContext<'b>,
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq, ToShmem)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))] #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[allow(missing_docs)] #[allow(missing_docs)]
pub struct ViewportDescriptorDeclaration { pub struct ViewportDescriptorDeclaration {
@ -335,7 +335,7 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for ViewportRuleParser<'a, 'b> {
} }
/// A `@viewport` rule. /// A `@viewport` rule.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq, ToShmem)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))] #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
pub struct ViewportRule { pub struct ViewportRule {
/// The declarations contained in this @viewport rule. /// The declarations contained in this @viewport rule.

View file

@ -129,6 +129,9 @@ impl UserAgentCascadeDataCache {
} }
fn expire_unused(&mut self) { fn expire_unused(&mut self) {
// is_unique() returns false for static references, but we never have
// static references to UserAgentCascadeDatas. If we did, it may not
// make sense to put them in the cache in the first place.
self.entries.retain(|e| !e.is_unique()) self.entries.retain(|e| !e.is_unique())
} }

View file

@ -307,8 +307,6 @@ pub fn resolve_style<E>(
where where
E: TElement, E: TElement,
{ {
use crate::style_resolver::StyleResolverForElement;
debug_assert!( debug_assert!(
rule_inclusion == RuleInclusion::DefaultOnly || rule_inclusion == RuleInclusion::DefaultOnly ||
pseudo.map_or(false, |p| p.is_before_or_after()) || pseudo.map_or(false, |p| p.is_before_or_after()) ||
@ -406,7 +404,6 @@ pub fn recalc_style_at<E, D, F>(
D: DomTraversal<E>, D: DomTraversal<E>,
F: FnMut(E::ConcreteNode), F: FnMut(E::ConcreteNode),
{ {
use crate::traversal_flags::TraversalFlags;
use std::cmp; use std::cmp;
let flags = context.shared.traversal_flags; let flags = context.shared.traversal_flags;
@ -538,12 +535,6 @@ pub fn recalc_style_at<E, D, F>(
debug_assert!(!element.has_animation_only_dirty_descendants()); debug_assert!(!element.has_animation_only_dirty_descendants());
} }
debug_assert!(
flags.for_animation_only() ||
!flags.contains(TraversalFlags::ClearDirtyBits) ||
!element.has_animation_only_dirty_descendants(),
"Should have cleared animation bits already"
);
clear_state_after_traversing(element, data, flags); clear_state_after_traversing(element, data, flags);
} }
@ -551,27 +542,11 @@ fn clear_state_after_traversing<E>(element: E, data: &mut ElementData, flags: Tr
where where
E: TElement, E: TElement,
{ {
// If we are in a forgetful traversal, drop the existing restyle if flags.intersects(TraversalFlags::FinalAnimationTraversal) {
// data here, since we won't need to perform a post-traversal to pick up debug_assert!(flags.for_animation_only());
// any change hints.
if flags.contains(TraversalFlags::Forgetful) {
data.clear_restyle_flags_and_damage(); data.clear_restyle_flags_and_damage();
}
// Clear dirty bits as appropriate.
if flags.for_animation_only() {
if flags.intersects(
TraversalFlags::ClearDirtyBits | TraversalFlags::ClearAnimationOnlyDirtyDescendants,
) {
unsafe {
element.unset_animation_only_dirty_descendants();
}
}
} else if flags.contains(TraversalFlags::ClearDirtyBits) {
// The animation traversal happens first, so we don't need to guard against
// clearing the animation bit on the regular traversal.
unsafe { unsafe {
element.clear_dirty_bits(); element.unset_animation_only_dirty_descendants();
} }
} }
} }

View file

@ -16,15 +16,9 @@ bitflags! {
/// Traverse and update all elements with CSS animations since /// Traverse and update all elements with CSS animations since
/// @keyframes rules may have changed. Triggered by CSS rule changes. /// @keyframes rules may have changed. Triggered by CSS rule changes.
const ForCSSRuleChanges = 1 << 1; const ForCSSRuleChanges = 1 << 1;
/// A forgetful traversal ignores the previous state of the frame tree, and /// The final animation-only traversal, which shouldn't really care about other
/// thus does not compute damage or maintain other state describing the styles /// style changes anymore.
/// pre-traversal. A forgetful traversal is usually the right thing if you const FinalAnimationTraversal = 1 << 2;
/// aren't going to do a post-traversal.
const Forgetful = 1 << 3;
/// Clears all the dirty bits on the elements traversed.
const ClearDirtyBits = 1 << 5;
/// Clears the animation-only dirty descendants bit in the subtree.
const ClearAnimationOnlyDirtyDescendants = 1 << 6;
/// Allows the traversal to run in parallel if there are sufficient cores on /// Allows the traversal to run in parallel if there are sufficient cores on
/// the machine. /// the machine.
const ParallelTraversal = 1 << 7; const ParallelTraversal = 1 << 7;
@ -58,10 +52,7 @@ pub fn assert_traversal_flags_match() {
check_traversal_flags! { check_traversal_flags! {
ServoTraversalFlags_AnimationOnly => TraversalFlags::AnimationOnly, ServoTraversalFlags_AnimationOnly => TraversalFlags::AnimationOnly,
ServoTraversalFlags_ForCSSRuleChanges => TraversalFlags::ForCSSRuleChanges, ServoTraversalFlags_ForCSSRuleChanges => TraversalFlags::ForCSSRuleChanges,
ServoTraversalFlags_Forgetful => TraversalFlags::Forgetful, ServoTraversalFlags_FinalAnimationTraversal => TraversalFlags::FinalAnimationTraversal,
ServoTraversalFlags_ClearDirtyBits => TraversalFlags::ClearDirtyBits,
ServoTraversalFlags_ClearAnimationOnlyDirtyDescendants =>
TraversalFlags::ClearAnimationOnlyDirtyDescendants,
ServoTraversalFlags_ParallelTraversal => TraversalFlags::ParallelTraversal, ServoTraversalFlags_ParallelTraversal => TraversalFlags::ParallelTraversal,
ServoTraversalFlags_FlushThrottledAnimations => TraversalFlags::FlushThrottledAnimations, ServoTraversalFlags_FlushThrottledAnimations => TraversalFlags::FlushThrottledAnimations,
} }

View file

@ -100,8 +100,8 @@ impl Color {
fn effective_intermediate_rgba(&self) -> RGBA { fn effective_intermediate_rgba(&self) -> RGBA {
match *self { match *self {
GenericColor::Numeric(color) => color, GenericColor::Numeric(color) => color,
GenericColor::Foreground => RGBA::transparent(), GenericColor::CurrentColor => RGBA::transparent(),
GenericColor::Complex(color, ratios) => RGBA { GenericColor::Complex { color, ratios } => RGBA {
alpha: color.alpha * ratios.bg, alpha: color.alpha * ratios.bg,
..color.clone() ..color.clone()
}, },
@ -111,8 +111,8 @@ impl Color {
fn effective_ratios(&self) -> ComplexColorRatios { fn effective_ratios(&self) -> ComplexColorRatios {
match *self { match *self {
GenericColor::Numeric(..) => ComplexColorRatios::NUMERIC, GenericColor::Numeric(..) => ComplexColorRatios::NUMERIC,
GenericColor::Foreground => ComplexColorRatios::FOREGROUND, GenericColor::CurrentColor => ComplexColorRatios::CURRENT_COLOR,
GenericColor::Complex(.., ratios) => ratios, GenericColor::Complex { ratios, .. } => ratios,
} }
} }
} }
@ -128,18 +128,18 @@ impl Animate for Color {
Ok(match (*self, *other, procedure) { Ok(match (*self, *other, procedure) {
// Any interpolation of currentcolor with currentcolor returns currentcolor. // Any interpolation of currentcolor with currentcolor returns currentcolor.
(Foreground, Foreground, Procedure::Interpolate { .. }) => Foreground, (CurrentColor, CurrentColor, Procedure::Interpolate { .. }) => CurrentColor,
// Animating two numeric colors. // Animating two numeric colors.
(Numeric(c1), Numeric(c2), _) => Numeric(c1.animate(&c2, procedure)?), (Numeric(c1), Numeric(c2), _) => Numeric(c1.animate(&c2, procedure)?),
// Combinations of numeric color and currentcolor // Combinations of numeric color and currentcolor
(Foreground, Numeric(color), _) => Self::with_ratios( (CurrentColor, Numeric(color), _) => Self::with_ratios(
color, color,
ComplexColorRatios { ComplexColorRatios {
bg: other_weight as f32, bg: other_weight as f32,
fg: this_weight as f32, fg: this_weight as f32,
}, },
), ),
(Numeric(color), Foreground, _) => Self::with_ratios( (Numeric(color), CurrentColor, _) => Self::with_ratios(
color, color,
ComplexColorRatios { ComplexColorRatios {
bg: this_weight as f32, bg: this_weight as f32,
@ -148,7 +148,7 @@ impl Animate for Color {
), ),
// Any other animation of currentcolor with currentcolor. // Any other animation of currentcolor with currentcolor.
(Foreground, Foreground, _) => Self::with_ratios( (CurrentColor, CurrentColor, _) => Self::with_ratios(
RGBA::transparent(), RGBA::transparent(),
ComplexColorRatios { ComplexColorRatios {
bg: 0., bg: 0.,
@ -162,8 +162,8 @@ impl Animate for Color {
fn scaled_rgba(color: &Color) -> RGBA { fn scaled_rgba(color: &Color) -> RGBA {
match *color { match *color {
GenericColor::Numeric(color) => color, GenericColor::Numeric(color) => color,
GenericColor::Foreground => RGBA::transparent(), GenericColor::CurrentColor => RGBA::transparent(),
GenericColor::Complex(color, ratios) => RGBA { GenericColor::Complex { color, ratios } => RGBA {
red: color.red * ratios.bg, red: color.red * ratios.bg,
green: color.green * ratios.bg, green: color.green * ratios.bg,
blue: color.blue * ratios.bg, blue: color.blue * ratios.bg,
@ -236,9 +236,9 @@ impl ComputeSquaredDistance for Color {
// All comments from the Animate impl also applies here. // All comments from the Animate impl also applies here.
Ok(match (*self, *other) { Ok(match (*self, *other) {
(Foreground, Foreground) => SquaredDistance::from_sqrt(0.), (CurrentColor, CurrentColor) => SquaredDistance::from_sqrt(0.),
(Numeric(c1), Numeric(c2)) => c1.compute_squared_distance(&c2)?, (Numeric(c1), Numeric(c2)) => c1.compute_squared_distance(&c2)?,
(Foreground, Numeric(color)) | (Numeric(color), Foreground) => { (CurrentColor, Numeric(color)) | (Numeric(color), CurrentColor) => {
// `computed_squared_distance` is symmetric. // `computed_squared_distance` is symmetric.
color.compute_squared_distance(&RGBA::transparent())? + color.compute_squared_distance(&RGBA::transparent())? +
SquaredDistance::from_sqrt(1.) SquaredDistance::from_sqrt(1.)

View file

@ -33,7 +33,7 @@ pub use super::specified::{AlignSelf, JustifySelf};
/// sucks :(. /// sucks :(.
/// ///
/// See the discussion in https://bugzil.la/1384542. /// See the discussion in https://bugzil.la/1384542.
#[derive(Clone, Copy, Debug, Eq, PartialEq, ToCss)] #[derive(Clone, Copy, Debug, Eq, PartialEq, ToCss, ToResolvedValue)]
pub struct JustifyItems { pub struct JustifyItems {
/// The specified value for the property. Can contain the bare `legacy` /// The specified value for the property. Can contain the bare `legacy`
/// keyword. /// keyword.

View file

@ -14,7 +14,18 @@ use style_traits::{CssWriter, ToCss};
/// A computed angle in degrees. /// A computed angle in degrees.
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Add, Animate, Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToAnimatedZero)] #[derive(
Add,
Animate,
Clone,
Copy,
Debug,
MallocSizeOf,
PartialEq,
PartialOrd,
ToAnimatedZero,
ToResolvedValue,
)]
pub struct Angle(CSSFloat); pub struct Angle(CSSFloat);
impl ToCss for Angle { impl ToCss for Angle {

View file

@ -14,8 +14,10 @@ use crate::values::specified::box_ as specified;
pub use crate::values::specified::box_::{AnimationName, Appearance, BreakBetween, BreakWithin}; pub use crate::values::specified::box_::{AnimationName, Appearance, BreakBetween, BreakWithin};
pub use crate::values::specified::box_::{Clear as SpecifiedClear, Float as SpecifiedFloat}; pub use crate::values::specified::box_::{Clear as SpecifiedClear, Float as SpecifiedFloat};
pub use crate::values::specified::box_::{Contain, Display, Overflow}; pub use crate::values::specified::box_::{Contain, Display, Overflow};
pub use crate::values::specified::box_::{OverflowAnchor, OverflowClipBox}; pub use crate::values::specified::box_::{OverflowAnchor, OverflowClipBox, OverscrollBehavior};
pub use crate::values::specified::box_::{OverscrollBehavior, ScrollSnapAlign, ScrollSnapType}; pub use crate::values::specified::box_::{
ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStrictness, ScrollSnapType,
};
pub use crate::values::specified::box_::{TouchAction, TransitionProperty, WillChange}; pub use crate::values::specified::box_::{TouchAction, TransitionProperty, WillChange};
/// A computed value for the `vertical-align` property. /// A computed value for the `vertical-align` property.
@ -49,6 +51,7 @@ pub type Perspective = GenericPerspective<NonNegativeLength>;
PartialEq, PartialEq,
SpecifiedValueInfo, SpecifiedValueInfo,
ToCss, ToCss,
ToResolvedValue,
)] )]
#[repr(u8)] #[repr(u8)]
/// A computed value for the `float` property. /// A computed value for the `float` property.
@ -118,6 +121,7 @@ impl ToComputedValue for SpecifiedFloat {
PartialEq, PartialEq,
SpecifiedValueInfo, SpecifiedValueInfo,
ToCss, ToCss,
ToResolvedValue,
)] )]
/// A computed value for the `clear` property. /// A computed value for the `clear` property.
pub enum Clear { pub enum Clear {
@ -178,7 +182,7 @@ impl ToComputedValue for SpecifiedClear {
/// A computed value for the `resize` property. /// A computed value for the `resize` property.
#[allow(missing_docs)] #[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToCss)] #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToCss, ToResolvedValue)]
#[repr(u8)] #[repr(u8)]
pub enum Resize { pub enum Resize {
None, None,

View file

@ -11,14 +11,14 @@ use cssparser::{Color as CSSParserColor, RGBA};
use std::fmt; use std::fmt;
use style_traits::{CssWriter, ToCss}; use style_traits::{CssWriter, ToCss};
/// Computed value type for the specified RGBAColor.
pub type RGBAColor = RGBA;
/// The computed value of the `color` property. /// The computed value of the `color` property.
pub type ColorPropertyValue = RGBA; pub type ColorPropertyValue = RGBA;
/// The computed value of `-moz-font-smoothing-background-color`.
pub type MozFontSmoothingBackgroundColor = RGBA;
/// A computed value for `<color>`. /// A computed value for `<color>`.
pub type Color = GenericColor<RGBAColor>; pub type Color = GenericColor<RGBA>;
impl Color { impl Color {
/// Returns a complex color value representing transparent. /// Returns a complex color value representing transparent.
@ -33,8 +33,8 @@ impl Color {
// Common cases that the complex color is either pure numeric // Common cases that the complex color is either pure numeric
// color or pure currentcolor. // color or pure currentcolor.
GenericColor::Numeric(color) => return color, GenericColor::Numeric(color) => return color,
GenericColor::Foreground => return fg_color, GenericColor::CurrentColor => return fg_color,
GenericColor::Complex(color, ratios) => (color, ratios), GenericColor::Complex { color, ratios } => (color, ratios),
}; };
// For the more complicated case that the alpha value differs, // For the more complicated case that the alpha value differs,
@ -76,7 +76,7 @@ impl ToCss for Color {
{ {
match *self { match *self {
GenericColor::Numeric(color) => color.to_css(dest), GenericColor::Numeric(color) => color.to_css(dest),
GenericColor::Foreground => CSSParserColor::CurrentColor.to_css(dest), GenericColor::CurrentColor => CSSParserColor::CurrentColor.to_css(dest),
_ => Ok(()), _ => Ok(()),
} }
} }

View file

@ -24,9 +24,13 @@ use cssparser::{serialize_identifier, CssStringWriter, Parser};
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
#[cfg(feature = "gecko")]
use std::mem::{self, ManuallyDrop};
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
use std::slice; use std::slice;
use style_traits::{CssWriter, ParseError, ToCss}; use style_traits::{CssWriter, ParseError, ToCss};
#[cfg(feature = "gecko")]
use to_shmem::{SharedMemoryBuilder, ToShmem};
pub use crate::values::computed::Length as MozScriptMinSize; pub use crate::values::computed::Length as MozScriptMinSize;
pub use crate::values::specified::font::{FontSynthesis, MozScriptSizeMultiplier}; pub use crate::values::specified::font::{FontSynthesis, MozScriptSizeMultiplier};
@ -37,7 +41,9 @@ pub use crate::values::specified::font::{XLang, XTextZoom};
/// https://drafts.csswg.org/css-fonts-4/#propdef-font-weight /// https://drafts.csswg.org/css-fonts-4/#propdef-font-weight
/// ///
/// This is effectively just a `Number`. /// This is effectively just a `Number`.
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] #[derive(
Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue,
)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
pub struct FontWeight(pub Number); pub struct FontWeight(pub Number);
@ -71,6 +77,7 @@ impl ToAnimatedValue for FontWeight {
PartialEq, PartialEq,
ToAnimatedZero, ToAnimatedZero,
ToCss, ToCss,
ToResolvedValue,
)] )]
/// The computed value of font-size /// The computed value of font-size
pub struct FontSize { pub struct FontSize {
@ -154,10 +161,6 @@ impl FontSize {
} }
} }
/// XXXManishearth it might be better to
/// animate this as computed, however this complicates
/// clamping and might not be the right thing to do.
/// We should figure it out.
impl ToAnimatedValue for FontSize { impl ToAnimatedValue for FontSize {
type AnimatedValue = NonNegativeLength; type AnimatedValue = NonNegativeLength;
@ -175,8 +178,8 @@ impl ToAnimatedValue for FontSize {
} }
} }
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq, ToResolvedValue)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))] #[cfg_attr(feature = "servo", derive(Hash, MallocSizeOf))]
/// Specifies a prioritized list of font family names or generic family names. /// Specifies a prioritized list of font family names or generic family names.
pub struct FontFamily { pub struct FontFamily {
/// The actual list of family names. /// The actual list of family names.
@ -190,7 +193,9 @@ impl FontFamily {
/// Get default font family as `serif` which is a generic font-family /// Get default font family as `serif` which is a generic font-family
pub fn serif() -> Self { pub fn serif() -> Self {
FontFamily { FontFamily {
families: FontFamilyList::new(Box::new([SingleFontFamily::Generic(atom!("serif"))])), families: FontFamilyList::new(Box::new([SingleFontFamily::Generic(
GenericFontFamily::Serif,
)])),
is_system_font: false, is_system_font: false,
} }
} }
@ -202,9 +207,8 @@ impl MallocSizeOf for FontFamily {
// SharedFontList objects are generally shared from the pointer // SharedFontList objects are generally shared from the pointer
// stored in the specified value. So only count this if the // stored in the specified value. So only count this if the
// SharedFontList is unshared. // SharedFontList is unshared.
unsafe { let shared_font_list = self.families.shared_font_list().get();
bindings::Gecko_SharedFontList_SizeOfIncludingThisIfUnshared(self.families.0.get()) unsafe { bindings::Gecko_SharedFontList_SizeOfIncludingThisIfUnshared(shared_font_list) }
}
} }
} }
@ -223,14 +227,14 @@ impl ToCss for FontFamily {
} }
} }
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToResolvedValue, ToShmem)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
/// The name of a font family of choice /// The name of a font family of choice
pub struct FamilyName { pub struct FamilyName {
/// Name of the font family /// Name of the font family
pub name: Atom, pub name: Atom,
/// Syntax of the font family /// Syntax of the font family
pub syntax: FamilyNameSyntax, pub syntax: FontFamilyNameSyntax,
} }
impl ToCss for FamilyName { impl ToCss for FamilyName {
@ -239,12 +243,12 @@ impl ToCss for FamilyName {
W: fmt::Write, W: fmt::Write,
{ {
match self.syntax { match self.syntax {
FamilyNameSyntax::Quoted => { FontFamilyNameSyntax::Quoted => {
dest.write_char('"')?; dest.write_char('"')?;
write!(CssStringWriter::new(dest), "{}", self.name)?; write!(CssStringWriter::new(dest), "{}", self.name)?;
dest.write_char('"') dest.write_char('"')
}, },
FamilyNameSyntax::Identifiers => { FontFamilyNameSyntax::Identifiers => {
let mut first = true; let mut first = true;
for ident in self.name.to_string().split(' ') { for ident in self.name.to_string().split(' ') {
if first { if first {
@ -266,11 +270,12 @@ impl ToCss for FamilyName {
} }
} }
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToResolvedValue, ToShmem)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
/// Font family names must either be given quoted as strings, /// Font family names must either be given quoted as strings,
/// or unquoted as a sequence of one or more identifiers. /// or unquoted as a sequence of one or more identifiers.
pub enum FamilyNameSyntax { #[repr(u8)]
pub enum FontFamilyNameSyntax {
/// The family name was specified in a quoted form, e.g. "Font Name" /// The family name was specified in a quoted form, e.g. "Font Name"
/// or 'Font Name'. /// or 'Font Name'.
Quoted, Quoted,
@ -280,85 +285,59 @@ pub enum FamilyNameSyntax {
Identifiers, Identifiers,
} }
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss, ToResolvedValue, ToShmem)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize, Hash))]
/// A set of faces that vary in weight, width or slope. /// A set of faces that vary in weight, width or slope.
pub enum SingleFontFamily { pub enum SingleFontFamily {
/// The name of a font family of choice. /// The name of a font family of choice.
FamilyName(FamilyName), FamilyName(FamilyName),
/// Generic family name. /// Generic family name.
Generic(Atom), Generic(GenericFontFamily),
}
/// A generic font-family name.
///
/// The order here is important, if you change it make sure that
/// `gfxPlatformFontList.h`s ranged array and `gfxFontFamilyList`'s
/// sSingleGenerics are updated as well.
#[derive(
Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, Parse, ToCss, ToResolvedValue, ToShmem,
)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[repr(u8)]
#[allow(missing_docs)]
pub enum GenericFontFamily {
/// No generic family specified, only for internal usage.
#[css(skip)]
None,
Serif,
SansSerif,
#[parse(aliases = "-moz-fixed")]
Monospace,
Cursive,
Fantasy,
/// An internal value for emoji font selection.
#[css(skip)]
#[cfg(feature = "gecko")]
MozEmoji,
} }
impl SingleFontFamily { impl SingleFontFamily {
#[inline] /// Parse a font-family value.
/// Get font family name as Atom
pub fn atom(&self) -> &Atom {
match *self {
SingleFontFamily::FamilyName(ref family_name) => &family_name.name,
SingleFontFamily::Generic(ref name) => name,
}
}
#[inline]
#[cfg(not(feature = "gecko"))] // Gecko can't borrow atoms as UTF-8.
/// Get font family name
pub fn name(&self) -> &str {
self.atom()
}
#[cfg(not(feature = "gecko"))] // Gecko can't borrow atoms as UTF-8.
/// Get the corresponding font-family with Atom
pub fn from_atom(input: Atom) -> SingleFontFamily {
match input {
atom!("serif") |
atom!("sans-serif") |
atom!("cursive") |
atom!("fantasy") |
atom!("monospace") => return SingleFontFamily::Generic(input),
_ => {},
}
match_ignore_ascii_case! { &input,
"serif" => return SingleFontFamily::Generic(atom!("serif")),
"sans-serif" => return SingleFontFamily::Generic(atom!("sans-serif")),
"cursive" => return SingleFontFamily::Generic(atom!("cursive")),
"fantasy" => return SingleFontFamily::Generic(atom!("fantasy")),
"monospace" => return SingleFontFamily::Generic(atom!("monospace")),
_ => {}
}
// We don't know if it's quoted or not. So we set it to
// quoted by default.
SingleFontFamily::FamilyName(FamilyName {
name: input,
syntax: FamilyNameSyntax::Quoted,
})
}
/// Parse a font-family value
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if let Ok(value) = input.try(|i| i.expect_string_cloned()) { if let Ok(value) = input.try(|i| i.expect_string_cloned()) {
return Ok(SingleFontFamily::FamilyName(FamilyName { return Ok(SingleFontFamily::FamilyName(FamilyName {
name: Atom::from(&*value), name: Atom::from(&*value),
syntax: FamilyNameSyntax::Quoted, syntax: FontFamilyNameSyntax::Quoted,
})); }));
} }
let first_ident = input.expect_ident()?.clone();
// FIXME(bholley): The fast thing to do here would be to look up the let first_ident = input.expect_ident_cloned()?;
// string (as lowercase) in the static atoms table. We don't have an if let Ok(generic) = GenericFontFamily::from_ident(&first_ident) {
// API to do that yet though, so we do the simple thing for now. return Ok(SingleFontFamily::Generic(generic));
let mut css_wide_keyword = false; }
match_ignore_ascii_case! { &first_ident,
"serif" => return Ok(SingleFontFamily::Generic(atom!("serif"))),
"sans-serif" => return Ok(SingleFontFamily::Generic(atom!("sans-serif"))),
"cursive" => return Ok(SingleFontFamily::Generic(atom!("cursive"))),
"fantasy" => return Ok(SingleFontFamily::Generic(atom!("fantasy"))),
"monospace" => return Ok(SingleFontFamily::Generic(atom!("monospace"))),
#[cfg(feature = "gecko")]
"-moz-fixed" => return Ok(SingleFontFamily::Generic(atom!("-moz-fixed"))),
let reserved = match_ignore_ascii_case! { &first_ident,
// https://drafts.csswg.org/css-fonts/#propdef-font-family // https://drafts.csswg.org/css-fonts/#propdef-font-family
// "Font family names that happen to be the same as a keyword value // "Font family names that happen to be the same as a keyword value
// (`inherit`, `serif`, `sans-serif`, `monospace`, `fantasy`, and `cursive`) // (`inherit`, `serif`, `sans-serif`, `monospace`, `fantasy`, and `cursive`)
@ -366,18 +345,15 @@ impl SingleFontFamily {
// The keywords initial and default are reserved for future use // The keywords initial and default are reserved for future use
// and must also be quoted when used as font names. // and must also be quoted when used as font names.
// UAs must not consider these keywords as matching the <family-name> type." // UAs must not consider these keywords as matching the <family-name> type."
"inherit" => css_wide_keyword = true, "inherit" | "initial" | "unset" | "revert" | "default" => true,
"initial" => css_wide_keyword = true, _ => false,
"unset" => css_wide_keyword = true, };
"default" => css_wide_keyword = true,
_ => {}
}
let mut value = first_ident.as_ref().to_owned(); let mut value = first_ident.as_ref().to_owned();
// These keywords are not allowed by themselves. // These keywords are not allowed by themselves.
// The only way this value can be valid with with another keyword. // The only way this value can be valid with with another keyword.
if css_wide_keyword { if reserved {
let ident = input.expect_ident()?; let ident = input.expect_ident()?;
value.push(' '); value.push(' ');
value.push_str(&ident); value.push_str(&ident);
@ -391,9 +367,9 @@ impl SingleFontFamily {
// `font-family: \ a\ \ b\ \ c\ ;`, it is tricky to serialize them // `font-family: \ a\ \ b\ \ c\ ;`, it is tricky to serialize them
// as identifiers correctly. Just mark them quoted so we don't need // as identifiers correctly. Just mark them quoted so we don't need
// to worry about them in serialization code. // to worry about them in serialization code.
FamilyNameSyntax::Quoted FontFamilyNameSyntax::Quoted
} else { } else {
FamilyNameSyntax::Identifiers FontFamilyNameSyntax::Identifiers
}; };
Ok(SingleFontFamily::FamilyName(FamilyName { Ok(SingleFontFamily::FamilyName(FamilyName {
name: Atom::from(value), name: Atom::from(value),
@ -401,134 +377,97 @@ impl SingleFontFamily {
})) }))
} }
#[cfg(feature = "gecko")] #[cfg(feature = "servo")]
/// Return the generic ID for a given generic font name /// Get the corresponding font-family with Atom
pub fn generic(name: &Atom) -> (structs::FontFamilyType, u8) { pub fn from_atom(input: Atom) -> SingleFontFamily {
use crate::gecko_bindings::structs::FontFamilyType; match input {
if *name == atom!("serif") { atom!("serif") => return SingleFontFamily::Generic(GenericFontFamily::Serif),
(FontFamilyType::eFamily_serif, structs::kGenericFont_serif) atom!("sans-serif") => return SingleFontFamily::Generic(GenericFontFamily::SansSerif),
} else if *name == atom!("sans-serif") { atom!("cursive") => return SingleFontFamily::Generic(GenericFontFamily::Cursive),
( atom!("fantasy") => return SingleFontFamily::Generic(GenericFontFamily::Fantasy),
FontFamilyType::eFamily_sans_serif, atom!("monospace") => return SingleFontFamily::Generic(GenericFontFamily::Monospace),
structs::kGenericFont_sans_serif, _ => {},
)
} else if *name == atom!("cursive") {
(
FontFamilyType::eFamily_cursive,
structs::kGenericFont_cursive,
)
} else if *name == atom!("fantasy") {
(
FontFamilyType::eFamily_fantasy,
structs::kGenericFont_fantasy,
)
} else if *name == atom!("monospace") {
(
FontFamilyType::eFamily_monospace,
structs::kGenericFont_monospace,
)
} else if *name == atom!("-moz-fixed") {
(
FontFamilyType::eFamily_moz_fixed,
structs::kGenericFont_moz_fixed,
)
} else {
panic!("Unknown generic {}", name);
} }
match_ignore_ascii_case! { &input,
"serif" => return SingleFontFamily::Generic(GenericFontFamily::Serif),
"sans-serif" => return SingleFontFamily::Generic(GenericFontFamily::SansSerif),
"cursive" => return SingleFontFamily::Generic(GenericFontFamily::Cursive),
"fantasy" => return SingleFontFamily::Generic(GenericFontFamily::Fantasy),
"monospace" => return SingleFontFamily::Generic(GenericFontFamily::Monospace),
_ => {}
}
// We don't know if it's quoted or not. So we set it to
// quoted by default.
SingleFontFamily::FamilyName(FamilyName {
name: input,
syntax: FontFamilyNameSyntax::Quoted,
})
} }
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
/// Get the corresponding font-family with family name /// Get the corresponding font-family with family name
fn from_font_family_name(family: &structs::FontFamilyName) -> SingleFontFamily { fn from_font_family_name(family: &structs::FontFamilyName) -> SingleFontFamily {
use crate::gecko_bindings::structs::FontFamilyType; if family.mName.mRawPtr.is_null() {
debug_assert_ne!(family.mGeneric, GenericFontFamily::None);
match family.mType { return SingleFontFamily::Generic(family.mGeneric);
FontFamilyType::eFamily_sans_serif => SingleFontFamily::Generic(atom!("sans-serif")),
FontFamilyType::eFamily_serif => SingleFontFamily::Generic(atom!("serif")),
FontFamilyType::eFamily_monospace => SingleFontFamily::Generic(atom!("monospace")),
FontFamilyType::eFamily_cursive => SingleFontFamily::Generic(atom!("cursive")),
FontFamilyType::eFamily_fantasy => SingleFontFamily::Generic(atom!("fantasy")),
FontFamilyType::eFamily_moz_fixed => SingleFontFamily::Generic(atom!("-moz-fixed")),
FontFamilyType::eFamily_named => {
let name = unsafe { Atom::from_raw(family.mName.mRawPtr) };
SingleFontFamily::FamilyName(FamilyName {
name,
syntax: FamilyNameSyntax::Identifiers,
})
},
FontFamilyType::eFamily_named_quoted => {
let name = unsafe { Atom::from_raw(family.mName.mRawPtr) };
SingleFontFamily::FamilyName(FamilyName {
name,
syntax: FamilyNameSyntax::Quoted,
})
},
_ => panic!("Found unexpected font FontFamilyType"),
}
}
}
impl ToCss for SingleFontFamily {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: fmt::Write,
{
match *self {
SingleFontFamily::FamilyName(ref name) => name.to_css(dest),
// All generic values accepted by the parser are known to not require escaping.
SingleFontFamily::Generic(ref name) => {
#[cfg(feature = "gecko")]
{
// We should treat -moz-fixed as monospace
if name == &atom!("-moz-fixed") {
return dest.write_str("monospace");
}
}
write!(dest, "{}", name)
},
} }
let name = unsafe { Atom::from_raw(family.mName.mRawPtr) };
SingleFontFamily::FamilyName(FamilyName {
name,
syntax: family.mSyntax,
})
} }
} }
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToResolvedValue, ToShmem)]
/// A list of SingleFontFamily /// A list of SingleFontFamily
pub struct FontFamilyList(Box<[SingleFontFamily]>); pub struct FontFamilyList(Box<[SingleFontFamily]>);
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
/// A list of SingleFontFamily /// A list of SingleFontFamily
pub struct FontFamilyList(pub RefPtr<structs::SharedFontList>); pub enum FontFamilyList {
/// A strong reference to a Gecko SharedFontList object.
SharedFontList(RefPtr<structs::SharedFontList>),
/// A font-family generic ID.
Generic(GenericFontFamily),
}
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
impl Hash for FontFamilyList { impl ToShmem for FontFamilyList {
fn hash<H>(&self, state: &mut H) fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> ManuallyDrop<Self> {
where // In practice, the only SharedFontList objects we create from shared
H: Hasher, // style sheets are ones with a single generic entry.
{ ManuallyDrop::new(match *self {
use crate::string_cache::WeakAtom; FontFamilyList::SharedFontList(ref r) => {
assert!(
for name in self.0.mNames.iter() { r.mNames.len() == 1 && r.mNames[0].mName.mRawPtr.is_null(),
name.mType.hash(state); "ToShmem failed for FontFamilyList: cannot handle non-generic families",
if !name.mName.mRawPtr.is_null() { );
unsafe { FontFamilyList::Generic(r.mNames[0].mGeneric)
WeakAtom::new(name.mName.mRawPtr).hash(state); },
} FontFamilyList::Generic(t) => FontFamilyList::Generic(t),
} })
}
} }
} }
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
impl PartialEq for FontFamilyList { impl PartialEq for FontFamilyList {
fn eq(&self, other: &FontFamilyList) -> bool { fn eq(&self, other: &FontFamilyList) -> bool {
if self.0.mNames.len() != other.0.mNames.len() { let self_list = self.shared_font_list();
let other_list = other.shared_font_list();
if self_list.mNames.len() != other_list.mNames.len() {
return false; return false;
} }
for (a, b) in self.0.mNames.iter().zip(other.0.mNames.iter()) { for (a, b) in self_list.mNames.iter().zip(other_list.mNames.iter()) {
if a.mType != b.mType || a.mName.mRawPtr != b.mName.mRawPtr { if a.mSyntax != b.mSyntax ||
a.mName.mRawPtr != b.mName.mRawPtr ||
a.mGeneric != b.mGeneric
{
return false; return false;
} }
} }
@ -540,14 +479,14 @@ impl PartialEq for FontFamilyList {
impl Eq for FontFamilyList {} impl Eq for FontFamilyList {}
impl FontFamilyList { impl FontFamilyList {
#[cfg(feature = "servo")]
/// Return FontFamilyList with a vector of SingleFontFamily /// Return FontFamilyList with a vector of SingleFontFamily
#[cfg(feature = "servo")]
pub fn new(families: Box<[SingleFontFamily]>) -> FontFamilyList { pub fn new(families: Box<[SingleFontFamily]>) -> FontFamilyList {
FontFamilyList(families) FontFamilyList(families)
} }
#[cfg(feature = "gecko")]
/// Return FontFamilyList with a vector of SingleFontFamily /// Return FontFamilyList with a vector of SingleFontFamily
#[cfg(feature = "gecko")]
pub fn new(families: Box<[SingleFontFamily]>) -> FontFamilyList { pub fn new(families: Box<[SingleFontFamily]>) -> FontFamilyList {
let fontlist; let fontlist;
let names; let names;
@ -559,58 +498,69 @@ impl FontFamilyList {
for family in families.iter() { for family in families.iter() {
match *family { match *family {
SingleFontFamily::FamilyName(ref f) => { SingleFontFamily::FamilyName(ref f) => unsafe {
let quoted = matches!(f.syntax, FamilyNameSyntax::Quoted); bindings::Gecko_nsTArray_FontFamilyName_AppendNamed(
unsafe { names,
bindings::Gecko_nsTArray_FontFamilyName_AppendNamed( f.name.as_ptr(),
names, f.syntax,
f.name.as_ptr(), );
quoted,
);
}
}, },
SingleFontFamily::Generic(ref name) => { SingleFontFamily::Generic(family) => unsafe {
let (family_type, _generic) = SingleFontFamily::generic(name); bindings::Gecko_nsTArray_FontFamilyName_AppendGeneric(names, family);
unsafe {
bindings::Gecko_nsTArray_FontFamilyName_AppendGeneric(names, family_type);
}
}, },
} }
} }
FontFamilyList(unsafe { RefPtr::from_addrefed(fontlist) }) FontFamilyList::SharedFontList(unsafe { RefPtr::from_addrefed(fontlist) })
} }
#[cfg(feature = "servo")]
/// Return iterator of SingleFontFamily /// Return iterator of SingleFontFamily
#[cfg(feature = "servo")]
pub fn iter(&self) -> slice::Iter<SingleFontFamily> { pub fn iter(&self) -> slice::Iter<SingleFontFamily> {
self.0.iter() self.0.iter()
} }
#[cfg(feature = "gecko")]
/// Return iterator of SingleFontFamily /// Return iterator of SingleFontFamily
#[cfg(feature = "gecko")]
pub fn iter(&self) -> FontFamilyNameIter { pub fn iter(&self) -> FontFamilyNameIter {
FontFamilyNameIter { FontFamilyNameIter {
names: &self.0.mNames, names: &self.shared_font_list().mNames,
cur: 0, cur: 0,
} }
} }
#[cfg(feature = "gecko")]
/// Return the generic ID if it is a single generic font /// Return the generic ID if it is a single generic font
pub fn single_generic(&self) -> Option<u8> { pub fn single_generic(&self) -> Option<GenericFontFamily> {
let mut iter = self.iter(); let mut iter = self.iter();
if let Some(SingleFontFamily::Generic(ref name)) = iter.next() { if let Some(SingleFontFamily::Generic(f)) = iter.next() {
if iter.next().is_none() { if iter.next().is_none() {
return Some(SingleFontFamily::generic(name).1); return Some(f.clone());
} }
} }
None None
} }
/// Return a reference to the Gecko SharedFontList.
#[cfg(feature = "gecko")]
pub fn shared_font_list(&self) -> &RefPtr<structs::SharedFontList> {
match *self {
FontFamilyList::SharedFontList(ref r) => r,
FontFamilyList::Generic(t) => {
unsafe {
// TODO(heycam): Should really add StaticRefPtr sugar.
let index = t as usize;
mem::transmute::<
&structs::StaticRefPtr<structs::SharedFontList>,
&RefPtr<structs::SharedFontList>,
>(&structs::SharedFontList_sSingleGenerics[index])
}
},
}
}
} }
#[cfg(feature = "gecko")]
/// Iterator of FontFamily /// Iterator of FontFamily
#[cfg(feature = "gecko")]
pub struct FontFamilyNameIter<'a> { pub struct FontFamilyNameIter<'a> {
names: &'a structs::nsTArray<structs::FontFamilyName>, names: &'a structs::nsTArray<structs::FontFamilyName>,
cur: usize, cur: usize,
@ -631,8 +581,18 @@ impl<'a> Iterator for FontFamilyNameIter<'a> {
} }
} }
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
/// Preserve the readability of text when font fallback occurs /// Preserve the readability of text when font fallback occurs
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
PartialEq,
ToCss,
ToResolvedValue,
)]
pub enum FontSizeAdjust { pub enum FontSizeAdjust {
#[animation(error)] #[animation(error)]
/// None variant /// None variant
@ -713,7 +673,7 @@ pub type FontVariationSettings = FontSettings<VariationValue<Number>>;
/// OpenType "language system" tag, so we should be able to compute /// OpenType "language system" tag, so we should be able to compute
/// it and store it as a 32-bit integer /// it and store it as a 32-bit integer
/// (see http://www.microsoft.com/typography/otspec/languagetags.htm). /// (see http://www.microsoft.com/typography/otspec/languagetags.htm).
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)] #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToResolvedValue)]
#[repr(C)] #[repr(C)]
pub struct FontLanguageOverride(pub u32); pub struct FontLanguageOverride(pub u32);
@ -819,7 +779,7 @@ impl ToComputedValue for specified::MozScriptLevel {
/// A wrapper over an `Angle`, that handles clamping to the appropriate range /// A wrapper over an `Angle`, that handles clamping to the appropriate range
/// for `font-style` animation. /// for `font-style` animation.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
pub struct FontStyleAngle(pub Angle); pub struct FontStyleAngle(pub Angle);
@ -916,7 +876,9 @@ impl ToCss for FontStyle {
/// A value for the font-stretch property per: /// A value for the font-stretch property per:
/// ///
/// https://drafts.csswg.org/css-fonts-4/#propdef-font-stretch /// https://drafts.csswg.org/css-fonts-4/#propdef-font-stretch
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] #[derive(
Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue,
)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
pub struct FontStretch(pub NonNegativePercentage); pub struct FontStretch(pub NonNegativePercentage);

View file

@ -36,7 +36,7 @@ pub type GradientKind =
generic::GradientKind<LineDirection, Length, LengthPercentage, Position, Angle>; generic::GradientKind<LineDirection, Length, LengthPercentage, Position, Angle>;
/// A computed gradient line direction. /// A computed gradient line direction.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)] #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToResolvedValue)]
pub enum LineDirection { pub enum LineDirection {
/// An angle. /// An angle.
Angle(Angle), Angle(Angle),

View file

@ -10,12 +10,12 @@ use crate::values::computed::NonNegativeNumber;
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance}; use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
use crate::values::generics::length as generics; use crate::values::generics::length as generics;
use crate::values::generics::length::{ use crate::values::generics::length::{
GenericLengthOrNumber, MaxSize as GenericMaxSize, Size as GenericSize, GenericLengthOrNumber, GenericLengthPercentageOrNormal, GenericMaxSize, GenericSize,
}; };
use crate::values::generics::NonNegative; use crate::values::generics::NonNegative;
use crate::values::specified::length::ViewportPercentageLength; use crate::values::specified::length::ViewportPercentageLength;
use crate::values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength}; use crate::values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength};
use crate::values::{specified, CSSFloat, Either, Normal}; use crate::values::{specified, CSSFloat};
use crate::Zero; use crate::Zero;
use app_units::Au; use app_units::Au;
use ordered_float::NotNan; use ordered_float::NotNan;
@ -75,7 +75,7 @@ impl ToComputedValue for specified::Length {
/// ///
/// https://drafts.csswg.org/css-values-4/#typedef-length-percentage /// https://drafts.csswg.org/css-values-4/#typedef-length-percentage
#[allow(missing_docs)] #[allow(missing_docs)]
#[derive(Clone, Copy, Debug, MallocSizeOf, ToAnimatedZero)] #[derive(Clone, Copy, Debug, MallocSizeOf, ToAnimatedZero, ToResolvedValue)]
#[repr(C)] #[repr(C)]
pub struct LengthPercentage { pub struct LengthPercentage {
length: Length, length: Length,
@ -608,6 +608,8 @@ impl Size {
PartialOrd, PartialOrd,
ToAnimatedValue, ToAnimatedValue,
ToAnimatedZero, ToAnimatedZero,
ToResolvedValue,
ToShmem,
)] )]
#[repr(C)] #[repr(C)]
pub struct CSSPixelLength(CSSFloat); pub struct CSSPixelLength(CSSFloat);
@ -709,9 +711,6 @@ pub type NonNegativeLengthOrAuto = generics::GenericLengthPercentageOrAuto<NonNe
/// Either a computed `<length>` or a `<number>` value. /// Either a computed `<length>` or a `<number>` value.
pub type LengthOrNumber = GenericLengthOrNumber<Length, Number>; pub type LengthOrNumber = GenericLengthOrNumber<Length, Number>;
/// Either a computed `<length>` or the `normal` keyword.
pub type LengthOrNormal = Either<Length, Normal>;
/// A wrapper of Length, whose value must be >= 0. /// A wrapper of Length, whose value must be >= 0.
pub type NonNegativeLength = NonNegative<Length>; pub type NonNegativeLength = NonNegative<Length>;
@ -782,11 +781,9 @@ impl From<NonNegativeLength> for Au {
} }
} }
/// Either a computed NonNegativeLength or the `normal` keyword.
pub type NonNegativeLengthOrNormal = Either<NonNegativeLength, Normal>;
/// Either a computed NonNegativeLengthPercentage or the `normal` keyword. /// Either a computed NonNegativeLengthPercentage or the `normal` keyword.
pub type NonNegativeLengthPercentageOrNormal = Either<NonNegativeLengthPercentage, Normal>; pub type NonNegativeLengthPercentageOrNormal =
GenericLengthPercentageOrNormal<NonNegativeLengthPercentage>;
/// Either a non-negative `<length>` or a `<number>`. /// Either a non-negative `<length>` or a `<number>`.
pub type NonNegativeLengthOrNumber = GenericLengthOrNumber<NonNegativeLength, NonNegativeNumber>; pub type NonNegativeLengthOrNumber = GenericLengthOrNumber<NonNegativeLength, NonNegativeNumber>;
@ -809,6 +806,8 @@ pub type NonNegativeLengthOrNumber = GenericLengthOrNumber<NonNegativeLength, No
ToAnimatedZero, ToAnimatedZero,
ToComputedValue, ToComputedValue,
ToCss, ToCss,
ToResolvedValue,
ToShmem,
)] )]
#[repr(u8)] #[repr(u8)]
pub enum ExtremumLength { pub enum ExtremumLength {

View file

@ -42,8 +42,9 @@ pub use self::box_::{AnimationIterationCount, AnimationName, Contain};
pub use self::box_::{Appearance, BreakBetween, BreakWithin, Clear, Float}; pub use self::box_::{Appearance, BreakBetween, BreakWithin, Clear, Float};
pub use self::box_::{Display, Overflow, OverflowAnchor, TransitionProperty}; pub use self::box_::{Display, Overflow, OverflowAnchor, TransitionProperty};
pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize}; pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize};
pub use self::box_::{ScrollSnapAlign, ScrollSnapType, TouchAction, VerticalAlign, WillChange}; pub use self::box_::{ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStrictness, ScrollSnapType};
pub use self::color::{Color, ColorOrAuto, ColorPropertyValue, RGBAColor}; pub use self::box_::{TouchAction, VerticalAlign, WillChange};
pub use self::color::{Color, ColorOrAuto, ColorPropertyValue};
pub use self::column::ColumnCount; pub use self::column::ColumnCount;
pub use self::counters::{Content, ContentItem, CounterIncrement, CounterSetOrReset}; pub use self::counters::{Content, ContentItem, CounterIncrement, CounterSetOrReset};
pub use self::easing::TimingFunction; pub use self::easing::TimingFunction;
@ -534,7 +535,9 @@ impl From<GreaterThanOrEqualToOneNumber> for CSSFloat {
} }
#[allow(missing_docs)] #[allow(missing_docs)]
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] #[derive(
Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue,
)]
#[repr(C, u8)] #[repr(C, u8)]
pub enum NumberOrPercentage { pub enum NumberOrPercentage {
Percentage(Percentage), Percentage(Percentage),

View file

@ -27,6 +27,8 @@ use style_traits::{CssWriter, ToCss};
ToAnimatedValue, ToAnimatedValue,
ToAnimatedZero, ToAnimatedZero,
ToComputedValue, ToComputedValue,
ToResolvedValue,
ToShmem,
)] )]
#[repr(C)] #[repr(C)]
pub struct Percentage(pub CSSFloat); pub struct Percentage(pub CSSFloat);

View file

@ -37,6 +37,7 @@ pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;
PartialEq, PartialEq,
ToAnimatedValue, ToAnimatedValue,
ToAnimatedZero, ToAnimatedZero,
ToResolvedValue,
)] )]
pub struct LetterSpacing(pub Length); pub struct LetterSpacing(pub Length);
@ -102,7 +103,7 @@ impl ToComputedValue for specified::WordSpacing {
/// A computed value for the `line-height` property. /// A computed value for the `line-height` property.
pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeLength>; pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeLength>;
#[derive(Clone, Debug, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToResolvedValue)]
/// text-overflow. /// text-overflow.
/// When the specified value only has one side, that's the "second" /// When the specified value only has one side, that's the "second"
/// side, and the sides are logical, so "second" means "end". The /// side, and the sides are logical, so "second" means "end". The
@ -155,7 +156,7 @@ impl ToCss for TextOverflow {
/// and similar stuff when we implement it. /// and similar stuff when we implement it.
/// ///
/// FIXME(emilio): Also, should be just a bitfield instead of three bytes. /// FIXME(emilio): Also, should be just a bitfield instead of three bytes.
#[derive(Clone, Copy, Debug, Default, MallocSizeOf, PartialEq)] #[derive(Clone, Copy, Debug, Default, MallocSizeOf, PartialEq, ToResolvedValue)]
pub struct TextDecorationsInEffect { pub struct TextDecorationsInEffect {
/// Whether an underline is in effect. /// Whether an underline is in effect.
pub underline: bool, pub underline: bool,
@ -193,7 +194,7 @@ impl TextDecorationsInEffect {
} }
/// computed value for the text-emphasis-style property /// computed value for the text-emphasis-style property
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)]
pub enum TextEmphasisStyle { pub enum TextEmphasisStyle {
/// Keyword value for the text-emphasis-style property (`filled` `open`) /// Keyword value for the text-emphasis-style property (`filled` `open`)
Keyword(TextEmphasisKeywordValue), Keyword(TextEmphasisKeywordValue),
@ -204,7 +205,7 @@ pub enum TextEmphasisStyle {
} }
/// Keyword value for the text-emphasis-style property /// Keyword value for the text-emphasis-style property
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)]
pub struct TextEmphasisKeywordValue { pub struct TextEmphasisKeywordValue {
/// fill for the text-emphasis-style property /// fill for the text-emphasis-style property
pub fill: TextEmphasisFillMode, pub fill: TextEmphasisFillMode,

View file

@ -9,7 +9,7 @@ use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss}; use style_traits::{CssWriter, ToCss};
/// A computed `<time>` value. /// A computed `<time>` value.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToResolvedValue)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
pub struct Time { pub struct Time {
seconds: CSSFloat, seconds: CSSFloat,

View file

@ -19,4 +19,4 @@ pub type Cursor = generics::Cursor<CursorImage>;
pub type CursorImage = generics::CursorImage<ComputedImageUrl, Number>; pub type CursorImage = generics::CursorImage<ComputedImageUrl, Number>;
/// A computed value for `scrollbar-color` property. /// A computed value for `scrollbar-color` property.
pub type ScrollbarColor = generics::ScrollbarColor<Color>; pub type ScrollbarColor = generics::GenericScrollbarColor<Color>;

View file

@ -27,6 +27,8 @@ fn width_and_height_are_auto<L>(
ToAnimatedZero, ToAnimatedZero,
ToComputedValue, ToComputedValue,
ToCss, ToCss,
ToResolvedValue,
ToShmem,
)] )]
#[repr(C, u8)] #[repr(C, u8)]
pub enum GenericBackgroundSize<LengthPercent> { pub enum GenericBackgroundSize<LengthPercent> {

View file

@ -31,6 +31,8 @@ pub type ClippingShape<BasicShape, Url> = ShapeSource<BasicShape, GeometryBox, U
ToAnimatedValue, ToAnimatedValue,
ToComputedValue, ToComputedValue,
ToCss, ToCss,
ToResolvedValue,
ToShmem,
)] )]
pub enum GeometryBox { pub enum GeometryBox {
FillBox, FillBox,
@ -58,6 +60,8 @@ pub type FloatAreaShape<BasicShape, Image> = ShapeSource<BasicShape, ShapeBox, I
ToAnimatedValue, ToAnimatedValue,
ToComputedValue, ToComputedValue,
ToCss, ToCss,
ToResolvedValue,
ToShmem,
)] )]
pub enum ShapeBox { pub enum ShapeBox {
MarginBox, MarginBox,
@ -79,6 +83,8 @@ pub enum ShapeBox {
ToAnimatedValue, ToAnimatedValue,
ToComputedValue, ToComputedValue,
ToCss, ToCss,
ToResolvedValue,
ToShmem,
)] )]
pub enum ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> { pub enum ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> {
#[animation(error)] #[animation(error)]
@ -104,11 +110,25 @@ pub enum ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> {
ToAnimatedValue, ToAnimatedValue,
ToComputedValue, ToComputedValue,
ToCss, ToCss,
ToResolvedValue,
ToShmem,
)] )]
pub enum BasicShape<H, V, LengthPercentage, NonNegativeLengthPercentage> { pub enum BasicShape<H, V, LengthPercentage, NonNegativeLengthPercentage> {
Inset(#[css(field_bound)] InsetRect<LengthPercentage, NonNegativeLengthPercentage>), Inset(
Circle(#[css(field_bound)] Circle<H, V, NonNegativeLengthPercentage>), #[css(field_bound)]
Ellipse(#[css(field_bound)] Ellipse<H, V, NonNegativeLengthPercentage>), #[shmem(field_bound)]
InsetRect<LengthPercentage, NonNegativeLengthPercentage>,
),
Circle(
#[css(field_bound)]
#[shmem(field_bound)]
Circle<H, V, NonNegativeLengthPercentage>,
),
Ellipse(
#[css(field_bound)]
#[shmem(field_bound)]
Ellipse<H, V, NonNegativeLengthPercentage>,
),
Polygon(Polygon<LengthPercentage>), Polygon(Polygon<LengthPercentage>),
} }
@ -125,9 +145,12 @@ pub enum BasicShape<H, V, LengthPercentage, NonNegativeLengthPercentage> {
SpecifiedValueInfo, SpecifiedValueInfo,
ToAnimatedValue, ToAnimatedValue,
ToComputedValue, ToComputedValue,
ToResolvedValue,
ToShmem,
)] )]
pub struct InsetRect<LengthPercentage, NonNegativeLengthPercentage> { pub struct InsetRect<LengthPercentage, NonNegativeLengthPercentage> {
pub rect: Rect<LengthPercentage>, pub rect: Rect<LengthPercentage>,
#[shmem(field_bound)]
pub round: BorderRadius<NonNegativeLengthPercentage>, pub round: BorderRadius<NonNegativeLengthPercentage>,
} }
@ -145,6 +168,8 @@ pub struct InsetRect<LengthPercentage, NonNegativeLengthPercentage> {
SpecifiedValueInfo, SpecifiedValueInfo,
ToAnimatedValue, ToAnimatedValue,
ToComputedValue, ToComputedValue,
ToResolvedValue,
ToShmem,
)] )]
pub struct Circle<H, V, NonNegativeLengthPercentage> { pub struct Circle<H, V, NonNegativeLengthPercentage> {
pub position: Position<H, V>, pub position: Position<H, V>,
@ -165,6 +190,8 @@ pub struct Circle<H, V, NonNegativeLengthPercentage> {
SpecifiedValueInfo, SpecifiedValueInfo,
ToAnimatedValue, ToAnimatedValue,
ToComputedValue, ToComputedValue,
ToResolvedValue,
ToShmem,
)] )]
pub struct Ellipse<H, V, NonNegativeLengthPercentage> { pub struct Ellipse<H, V, NonNegativeLengthPercentage> {
pub position: Position<H, V>, pub position: Position<H, V>,
@ -186,6 +213,8 @@ pub struct Ellipse<H, V, NonNegativeLengthPercentage> {
ToAnimatedValue, ToAnimatedValue,
ToComputedValue, ToComputedValue,
ToCss, ToCss,
ToResolvedValue,
ToShmem,
)] )]
pub enum ShapeRadius<NonNegativeLengthPercentage> { pub enum ShapeRadius<NonNegativeLengthPercentage> {
Length(NonNegativeLengthPercentage), Length(NonNegativeLengthPercentage),
@ -208,6 +237,8 @@ pub enum ShapeRadius<NonNegativeLengthPercentage> {
ToAnimatedValue, ToAnimatedValue,
ToComputedValue, ToComputedValue,
ToCss, ToCss,
ToResolvedValue,
ToShmem,
)] )]
pub struct Polygon<LengthPercentage> { pub struct Polygon<LengthPercentage> {
/// The filling rule for a polygon. /// The filling rule for a polygon.
@ -228,6 +259,8 @@ pub struct Polygon<LengthPercentage> {
ToAnimatedValue, ToAnimatedValue,
ToComputedValue, ToComputedValue,
ToCss, ToCss,
ToResolvedValue,
ToShmem,
)] )]
pub struct PolygonCoord<LengthPercentage>(pub LengthPercentage, pub LengthPercentage); pub struct PolygonCoord<LengthPercentage>(pub LengthPercentage, pub LengthPercentage);
@ -249,6 +282,8 @@ pub struct PolygonCoord<LengthPercentage>(pub LengthPercentage, pub LengthPercen
ToAnimatedValue, ToAnimatedValue,
ToComputedValue, ToComputedValue,
ToCss, ToCss,
ToResolvedValue,
ToShmem,
)] )]
#[repr(u8)] #[repr(u8)]
pub enum FillRule { pub enum FillRule {
@ -270,6 +305,8 @@ pub enum FillRule {
ToAnimatedValue, ToAnimatedValue,
ToComputedValue, ToComputedValue,
ToCss, ToCss,
ToResolvedValue,
ToShmem,
)] )]
pub struct Path { pub struct Path {
/// The filling rule for the svg path. /// The filling rule for the svg path.

Some files were not shown because too many files have changed in this diff Show more