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",
]
[[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]]
name = "derive_more"
version = "0.13.0"
@ -3646,6 +3657,8 @@ dependencies = [
"servo_arc 0.1.1",
"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)",
"to_shmem 0.0.1",
"to_shmem_derive 0.0.1",
]
[[package]]
@ -3992,6 +4005,8 @@ dependencies = [
"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)",
"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_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)",
@ -4240,6 +4255,8 @@ dependencies = [
"style_traits 0.0.1",
"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)",
"to_shmem 0.0.1",
"to_shmem_derive 0.0.1",
"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)",
"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"
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)",
@ -4297,6 +4315,8 @@ dependencies = [
"servo_arc 0.1.1",
"servo_atoms 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)",
]
@ -4435,6 +4455,31 @@ dependencies = [
"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]]
name = "tokio"
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(
where_clause: &mut Option<syn::WhereClause>,
generics: &syn::Generics,
trait_path: Path,
trait_output: Ident,
trait_path: &Path,
trait_output: &Ident,
) {
let where_clause = match *where_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 {
ident: input.ident.clone(),
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 style::computed_values::{font_stretch, font_style, font_variant_caps, font_weight};
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;
macro_rules! ot_tag {
@ -564,9 +564,14 @@ impl<'a> From<&'a SingleFontFamily> for FontFamilyName {
FontFamilyName::Specific(family_name.name.clone())
},
SingleFontFamily::Generic(ref generic_name) => {
FontFamilyName::Generic(generic_name.clone())
},
SingleFontFamily::Generic(generic) => FontFamilyName::Generic(match generic {
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::style_structs::Font as FontStyleStruct;
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::generics::font::FontStyle;
@ -114,7 +114,7 @@ fn font_family(names: Vec<&str>) -> FontFamily {
.map(|name| {
SingleFontFamily::FamilyName(FamilyName {
name: Atom::from(name),
syntax: FamilyNameSyntax::Quoted,
syntax: FontFamilyNameSyntax::Quoted,
})
})
.collect();

View file

@ -19,9 +19,10 @@ use std::fmt;
use std::sync::Arc;
use style::logical_geometry::LogicalSize;
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::Either;
#[allow(unsafe_code)]
unsafe impl crate::flow::HasBaseFlow for MulticolFlow {}
@ -106,8 +107,10 @@ impl Flow for MulticolFlow {
{
let style = &self.block_flow.fragment.style;
let column_gap = match style.get_position().column_gap {
Either::First(len) => len.0.to_pixel_length(content_inline_size).into(),
Either::Second(_normal) => {
NonNegativeLengthPercentageOrNormal::LengthPercentage(len) => {
len.0.to_pixel_length(content_inline_size).into()
},
NonNegativeLengthPercentageOrNormal::Normal => {
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 {
// FIXME(emilio): This in Gecko parses a whole family list.
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::FontFamily(font_family::SpecifiedValue::Values(

View file

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

View file

@ -6,11 +6,15 @@ use crate::parser::SelectorImpl;
use cssparser::ToCss;
use std::fmt;
#[derive(Clone, Eq, PartialEq)]
#[derive(Clone, Eq, PartialEq, ToShmem)]
#[shmem(no_bounds)]
pub struct AttrSelectorWithOptionalNamespace<Impl: SelectorImpl> {
#[shmem(field_bound)]
pub namespace: Option<NamespaceConstraint<(Impl::NamespacePrefix, Impl::NamespaceUrl)>>,
#[shmem(field_bound)]
pub local_name: Impl::LocalName,
pub local_name_lower: Impl::LocalName,
#[shmem(field_bound)]
pub operation: ParsedAttrSelectorOperation<Impl::AttrValue>,
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> {
Any,
@ -32,7 +36,7 @@ pub enum NamespaceConstraint<NamespaceUrl> {
Specific(NamespaceUrl),
}
#[derive(Clone, Eq, PartialEq)]
#[derive(Clone, Eq, PartialEq, ToShmem)]
pub enum ParsedAttrSelectorOperation<AttrValue> {
Exists,
WithValue {
@ -72,7 +76,7 @@ impl<AttrValue> AttrSelectorOperation<AttrValue> {
}
}
#[derive(Clone, Copy, Eq, PartialEq)]
#[derive(Clone, Copy, Eq, PartialEq, ToShmem)]
pub enum AttrSelectorOperator {
Equal,
Includes,
@ -132,7 +136,7 @@ impl AttrSelectorOperator {
/// The definition of whitespace per CSS Selectors Level 3 § 4.
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 {
// 's' was specified.
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
/// 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);
impl SpecificityAndFlags {

View file

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

View file

@ -221,8 +221,11 @@ pub trait Parser<'i> {
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SelectorList<Impl: SelectorImpl>(pub SmallVec<[Selector<Impl>; 1]>);
#[derive(Clone, Debug, Eq, PartialEq, ToShmem)]
#[shmem(no_bounds)]
pub struct SelectorList<Impl: SelectorImpl>(
#[shmem(field_bound)] pub SmallVec<[Selector<Impl>; 1]>,
);
impl<Impl: SelectorImpl> SelectorList<Impl> {
/// 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
/// handle it in to_css to make it invisible to serialization.
#[derive(Clone, Eq, PartialEq)]
pub struct Selector<Impl: SelectorImpl>(ThinArc<SpecificityAndFlags, Component<Impl>>);
#[derive(Clone, Eq, PartialEq, ToShmem)]
#[shmem(no_bounds)]
pub struct Selector<Impl: SelectorImpl>(
#[shmem(field_bound)] ThinArc<SpecificityAndFlags, Component<Impl>>,
);
impl<Impl: SelectorImpl> Selector<Impl> {
#[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 {
Child, // >
Descendant, // space
@ -824,22 +830,27 @@ impl Combinator {
/// optimal packing and cache performance, see [1].
///
/// [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> {
Combinator(Combinator),
ExplicitAnyNamespace,
ExplicitNoNamespace,
DefaultNamespace(Impl::NamespaceUrl),
Namespace(Impl::NamespacePrefix, Impl::NamespaceUrl),
DefaultNamespace(#[shmem(field_bound)] Impl::NamespaceUrl),
Namespace(
#[shmem(field_bound)] Impl::NamespacePrefix,
#[shmem(field_bound)] Impl::NamespaceUrl,
),
ExplicitUniversalType,
LocalName(LocalName<Impl>),
ID(Impl::Identifier),
Class(Impl::ClassName),
ID(#[shmem(field_bound)] Impl::Identifier),
Class(#[shmem(field_bound)] Impl::ClassName),
AttributeInNoNamespaceExists {
#[shmem(field_bound)]
local_name: Impl::LocalName,
local_name_lower: Impl::LocalName,
},
@ -847,6 +858,7 @@ pub enum Component<Impl: SelectorImpl> {
AttributeInNoNamespace {
local_name: Impl::LocalName,
operator: AttrSelectorOperator,
#[shmem(field_bound)]
value: Impl::AttrValue,
case_sensitivity: ParsedCaseSensitivity,
never_matches: bool,
@ -878,7 +890,7 @@ pub enum Component<Impl: SelectorImpl> {
FirstOfType,
LastOfType,
OnlyOfType,
NonTSPseudoClass(Impl::NonTSPseudoClass),
NonTSPseudoClass(#[shmem(field_bound)] Impl::NonTSPseudoClass),
/// The ::slotted() pseudo-element (which isn't actually a pseudo-element,
/// 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
Host(Option<Selector<Impl>>),
PseudoElement(Impl::PseudoElement),
PseudoElement(#[shmem(field_bound)] Impl::PseudoElement),
}
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> {
#[shmem(field_bound)]
pub 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 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 references to static data, which don't do any
//! refcounting.
//!
//! [1]: https://bugzilla.mozilla.org/show_bug.cgi?id=1360883
@ -32,6 +34,7 @@ use nodrop::NoDrop;
#[cfg(feature = "servo")]
use serde::{Deserialize, Serialize};
use stable_deref_trait::{CloneStableDeref, StableDeref};
use std::alloc::Layout;
use std::borrow;
use std::cmp::Ordering;
use std::convert::From;
@ -74,6 +77,10 @@ macro_rules! offset_of {
/// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references.
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
///
/// 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
/// 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
@ -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
/// reporting.
///
/// If this is a static reference, this returns null.
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> {
#[inline]
fn clone(&self) -> Self {
// Using a relaxed ordering is alright here, as knowledge of the
// original reference prevents other threads from erroneously deleting
// the object.
//
// As explained in the [Boost documentation][1], Increasing the
// reference counter can always be done with memory_order_relaxed: New
// references to an object can only be formed from an existing
// reference, and passing an existing reference from one thread to
// 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);
// 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 {
// Using a relaxed ordering is alright here, as knowledge of the
// original reference prevents other threads from erroneously deleting
// the object.
//
// As explained in the [Boost documentation][1], Increasing the
// reference counter can always be done with memory_order_relaxed: New
// references to an object can only be formed from an existing
// reference, and passing an existing reference from one thread to
// 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
// 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
// the assumption that there aren't ~2 billion threads incrementing
// the reference count at once. This branch will never be taken in
// any realistic program.
//
// We abort because such a program is incredibly degenerate, and we
// don't care to support it.
if old_size > MAX_REFCOUNT {
process::abort();
// 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
// and users will use-after free. We racily saturate to `isize::MAX` on
// the assumption that there aren't ~2 billion threads incrementing
// the reference count at once. This branch will never be taken in
// any realistic program.
//
// We abort because such a program is incredibly degenerate, and we
// don't care to support it.
if old_size > MAX_REFCOUNT {
process::abort();
}
}
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]
pub fn is_unique(&self) -> bool {
// 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> {
#[inline]
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
// with other threads unless we are going to delete the object.
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]>> {
/// 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]
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
F: FnOnce(Layout) -> *mut u8,
I: Iterator<Item = T> + ExactSizeIterator,
{
use std::mem::size_of;
@ -565,22 +625,20 @@ impl<H, T> Arc<HeaderSlice<H, [T]>> {
let ptr: *mut ArcInner<HeaderSlice<H, [T]>>;
unsafe {
// Allocate the buffer. 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 buffer = if mem::align_of::<T>() <= mem::align_of::<usize>() {
Self::allocate_buffer::<usize>(size)
// Allocate the buffer.
let layout = if mem::align_of::<T>() <= mem::align_of::<usize>() {
Layout::from_size_align_unchecked(size, mem::align_of::<usize>())
} 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.
// Use u64 to avoid over-alignment.
// This branch will compile away in optimized builds.
Self::allocate_buffer::<u64>(size)
Layout::from_size_align_unchecked(size, mem::align_of::<u64>())
} else {
panic!("Over-aligned type not handled");
};
let buffer = alloc(layout);
// 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
// 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
// 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);
let mut current: *mut T = &mut (*ptr).data.slice[0];
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]
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 mut vec = Vec::<W>::with_capacity(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))
}
/// 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
/// within it -- for memory reporting.
///
/// If this is a static ThinArc, this returns null.
#[inline]
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"]
servo = ["serde", "style_traits/servo", "servo_atoms", "servo_config", "html5ever",
"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 = []
[dependencies]
@ -68,6 +68,8 @@ style_derive = {path = "../style_derive"}
style_traits = {path = "../style_traits"}
servo_url = {path = "../url", optional = true}
thin-slice = "0.1.0"
to_shmem = {path = "../to_shmem"}
to_shmem_derive = {path = "../to_shmem_derive"}
time = "0.1"
uluru = "0.3"
unicode-bidi = "0.3"

View file

@ -339,8 +339,6 @@ mod bindings {
}
fn setup_logging() -> bool {
use log;
struct BuildLogger {
file: Option<Mutex<fs::File>>,
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, )+
) => {
/// An @counter-style rule
#[derive(Clone, Debug)]
#[derive(Clone, Debug, ToShmem)]
pub struct CounterStyleRuleData {
name: CustomIdent,
generation: Wrapping<u32>,
@ -337,7 +337,7 @@ impl CounterStyleRuleData {
}
/// <https://drafts.csswg.org/css-counter-styles/#counter-style-system>
#[derive(Clone, Debug)]
#[derive(Clone, Debug, ToShmem)]
pub enum System {
/// 'cyclic'
Cyclic,
@ -410,7 +410,7 @@ impl ToCss for System {
/// <https://drafts.csswg.org/css-counter-styles/#typedef-symbol>
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss)]
#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToShmem)]
pub enum Symbol {
/// <string>
String(String),
@ -447,7 +447,7 @@ impl Symbol {
}
/// <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>);
impl Parse for Negative {
@ -465,11 +465,11 @@ impl Parse for Negative {
/// <https://drafts.csswg.org/css-counter-styles/#counter-style-range>
///
/// Empty Vec represents 'auto'
#[derive(Clone, Debug)]
#[derive(Clone, Debug, ToShmem)]
pub struct Ranges(pub Vec<Range<CounterBound>>);
/// A bound found in `Ranges`.
#[derive(Clone, Copy, Debug, ToCss)]
#[derive(Clone, Copy, Debug, ToCss, ToShmem)]
pub enum CounterBound {
/// An integer bound.
Integer(Integer),
@ -548,7 +548,7 @@ where
}
/// <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);
impl Parse for Pad {
@ -564,7 +564,7 @@ impl Parse for Pad {
}
/// <https://drafts.csswg.org/css-counter-styles/#counter-style-fallback>
#[derive(Clone, Debug, ToCss)]
#[derive(Clone, Debug, ToCss, ToShmem)]
pub struct Fallback(pub CustomIdent);
impl Parse for Fallback {
@ -578,7 +578,7 @@ impl Parse for Fallback {
/// <https://drafts.csswg.org/css-counter-styles/#descdef-counter-style-symbols>
#[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>);
impl Parse for Symbols {
@ -602,7 +602,7 @@ impl Parse for 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>);
impl Parse for AdditiveSymbols {
@ -623,7 +623,7 @@ impl Parse for AdditiveSymbols {
}
/// <integer> && <symbol>
#[derive(Clone, Debug, ToCss)]
#[derive(Clone, Debug, ToCss, ToShmem)]
pub struct AdditiveTuple {
/// <integer>
pub weight: Integer,
@ -651,7 +651,7 @@ impl Parse for AdditiveTuple {
}
/// <https://drafts.csswg.org/css-counter-styles/#counter-style-speak-as>
#[derive(Clone, Debug, ToCss)]
#[derive(Clone, Debug, ToCss, ToShmem)]
pub enum SpeakAs {
/// 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
/// references to other custom property names.
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
pub struct VariableValue {
css: String,

View file

@ -642,15 +642,6 @@ pub trait TElement:
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.
///
/// Servo doesn't support visited styles yet.
@ -825,11 +816,15 @@ pub trait TElement:
Self: 'a,
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| {
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;
if let Some(data) = shadow.style_data() {
f(

View file

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

View file

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

View file

@ -43,7 +43,11 @@ pub trait FontMetricsProvider {
}
/// 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
fn create_from(context: &SharedStyleContext) -> Self
@ -66,7 +70,7 @@ impl FontMetricsProvider for 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")
}
}

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 {
GenericImage::Gradient(boxed_gradient) => self.set_gradient(*boxed_gradient),
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) => {
unsafe {
bindings::Gecko_SetLayerImageImageValue(
self,
(image_rect.url.0).0.url_value.get(),
);
bindings::Gecko_SetLayerImageImageValue(self, image_rect.url.url_value_ptr());
bindings::Gecko_InitializeImageCropRect(self);
// 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_FARTHEST_CORNER as FARTHEST_CORNER;
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::Length;
use crate::values::generics::image::{Circle, ColorStop, CompatMode, Ellipse};
use crate::values::generics::image::{Circle, ColorStop, Ellipse};
use crate::values::generics::image::{EndingShape, GradientKind, ShapeExtent};
let gecko_gradient = bindings::Gecko_GetGradientImageValue(self)
@ -837,8 +832,7 @@ impl TrackSize<LengthPercentage> {
/// Return TrackSize from given two nsStyleCoord
pub fn from_gecko_style_coords<T: CoordData>(gecko_min: &T, gecko_max: &T) -> Self {
use crate::gecko_bindings::structs::root::nsStyleUnit;
use crate::values::computed::length::LengthPercentage;
use crate::values::generics::grid::{TrackBreadth, TrackSize};
use crate::values::generics::grid::TrackBreadth;
if gecko_min.unit() == nsStyleUnit::eStyleUnit_None {
debug_assert!(
@ -865,8 +859,6 @@ impl TrackSize<LengthPercentage> {
/// Save TrackSize to given gecko fields.
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 {
TrackSize::FitContent(ref lop) => {
// 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.
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 {
TrackListValue::TrackSize(ref size) => size.to_gecko_style_coords(gecko_min, gecko_max),
_ => unreachable!("Should only transform from track-size computed values"),
@ -921,8 +911,6 @@ where
pub fn from_gecko_rect(
sides: &crate::gecko_bindings::structs::nsStyleSides,
) -> Option<crate::values::generics::rect::Rect<T>> {
use crate::values::generics::rect::Rect;
Some(Rect::new(
T::from_gecko_style_coord(&sides.data_at(0)).expect("coord[0] cound not convert"),
T::from_gecko_style_coord(&sides.data_at(1)).expect("coord[1] cound not convert"),

View file

@ -127,10 +127,6 @@ fn eval_device_aspect_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(
device: &Device,
query_value: Option<f32>,

View file

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

View file

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

View file

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

View file

@ -44,7 +44,7 @@ pub type Lang = Atom;
macro_rules! pseudo_class_name {
([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => {
/// 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 {
$(
#[doc = $css]

View file

@ -17,16 +17,20 @@ use cssparser::Parser;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use nsstring::nsCString;
use servo_arc::Arc;
use std::collections::HashMap;
use std::fmt::{self, Write};
use std::mem::ManuallyDrop;
use std::sync::RwLock;
use style_traits::{CssWriter, ParseError, ToCss};
use to_shmem::{SharedMemoryBuilder, ToShmem};
/// A CSS url() value for gecko.
#[css(function = "url")]
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
pub struct CssUrl(pub Arc<CssUrlData>);
/// Data shared between CssUrls.
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
pub struct CssUrlData {
/// The URL in unresolved string form.
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 {
fn parse<'i, 't>(
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.
#[derive(Clone, Debug, SpecifiedValueInfo, ToCss)]
#[derive(Clone, Debug, SpecifiedValueInfo, ToCss, ToShmem)]
pub struct SpecifiedUrl {
/// The specified url value.
pub url: CssUrl,
/// Gecko's URLValue so that we can reuse it while rematching a
/// property with this specified value.
///
/// Box this to avoid SpecifiedUrl getting bigger than two words,
/// and increasing the size of PropertyDeclaration.
#[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 {
@ -122,12 +179,7 @@ impl SpecifiedUrl {
}
fn from_css_url_with_cors(url: CssUrl, cors: CORSMode) -> Self {
let url_value = unsafe {
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)
};
let url_value = Box::new(URLValueSource::URLValue(make_url_value(&url, cors)));
Self { url, url_value }
}
@ -140,6 +192,45 @@ impl SpecifiedUrl {
use crate::gecko_bindings::structs::root::mozilla::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 {
@ -165,7 +256,7 @@ impl MallocSizeOf for SpecifiedUrl {
// Although this is a RefPtr, this is the primary reference because
// SpecifiedUrl is responsible for creating the url_value. So we
// measure unconditionally here.
n += unsafe { bindings::Gecko_URLValue_SizeOfIncludingThis(self.url_value.get()) };
n += unsafe { bindings::Gecko_URLValue_SizeOfIncludingThis(self.url_value_ptr()) };
n
}
}
@ -185,7 +276,7 @@ impl ToComputedValue for SpecifiedUrl {
}
/// 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);
impl SpecifiedImageUrl {
@ -258,7 +349,8 @@ impl ToCss for ComputedUrl {
where
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 {
let css_url = &*url_value.mCssUrl.mRawPtr;
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.
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
W: Write,
{
serialize_computed_url(
&(self.0).0.url_value,
dest,
bindings::Gecko_GetComputedImageURLSpec,
)
(self.0).0.with_url_value(|r| {
serialize_computed_url(r, dest, bindings::Gecko_GetComputedImageURLSpec)
})
}
}
@ -299,11 +397,27 @@ impl ComputedImageUrl {
let url_value = image_request.mImageValue.to_safe();
let css_url = &*url_value.mCssUrl.mRawPtr;
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.
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::length::LengthPercentageOrAuto;
use crate::values::generics::{CounterStyleOrNone, NonNegative};
use crate::values::{Auto, Either, None_, Normal};
use crate::values::Either;
use crate::{Atom, Zero};
use app_units::Au;
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>
where
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> {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match self.repeated() {
@ -317,7 +258,6 @@ impl GeckoStyleCoordConvertible for ScrollSnapPoint<LengthPercentage> {
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
use crate::gecko_bindings::structs::root::nsStyleUnit;
use crate::values::generics::gecko::ScrollSnapPoint;
Some(match coord.unit() {
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::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
use crate::stylist::CascadeData;
use crate::values::computed::font::GenericFontFamily;
use crate::values::specified::length::FontBaseSize;
use crate::CaseSensitivityExt;
use app_units::Au;
@ -985,7 +986,6 @@ fn get_animation_rule(
element: &GeckoElement,
cascade_level: CascadeLevel,
) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
use crate::gecko_bindings::sugar::ownership::HasSimpleFFI;
use crate::properties::longhands::ANIMATABLE_PROPERTY_COUNT;
// There's a very rough correlation between the number of effects
@ -1041,7 +1041,7 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
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();
if let Some(sizes) = cache.iter().find(|el| el.0 == *font_name) {
return sizes.1.size_for_generic(font_family);
@ -1100,16 +1100,17 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
}
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 {
structs::kPresContext_DefaultVariableFont_ID => self.mDefaultVariableSize,
structs::kPresContext_DefaultFixedFont_ID => self.mDefaultFixedSize,
structs::kGenericFont_serif => self.mDefaultSerifSize,
structs::kGenericFont_sans_serif => self.mDefaultSansSerifSize,
structs::kGenericFont_monospace => self.mDefaultMonospaceSize,
structs::kGenericFont_cursive => self.mDefaultCursiveSize,
structs::kGenericFont_fantasy => self.mDefaultFantasySize,
_ => unreachable!("Unknown generic ID"),
GenericFontFamily::None => self.mDefaultVariableSize,
GenericFontFamily::Serif => self.mDefaultSerifSize,
GenericFontFamily::SansSerif => self.mDefaultSansSerifSize,
GenericFontFamily::Monospace => self.mDefaultMonospaceSize,
GenericFontFamily::Cursive => self.mDefaultCursiveSize,
GenericFontFamily::Fantasy => self.mDefaultFantasySize,
GenericFontFamily::MozEmoji => unreachable!(
"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 {
self.state().intersects(ElementState::IN_VISITED_STATE)
}

View file

@ -15,4 +15,3 @@ mod ns_t_array;
pub mod origin_flags;
pub mod ownership;
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> {
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
@ -268,14 +276,6 @@ pub struct 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`.
pub fn maybe(self) -> OwnedOrNull<GeckoType> {
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::hash::{Hash, Hasher};
use std::iter::Cloned;
use std::mem::{self, ManuallyDrop};
use std::ops::Deref;
use std::{mem, slice, str};
use std::{slice, str};
use style_traits::SpecifiedValueInfo;
use to_shmem::{SharedMemoryBuilder, ToShmem};
#[macro_use]
#[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 PartialEq for WeakAtom {
#[inline]

View file

@ -24,7 +24,7 @@ macro_rules! ns {
}
/// 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);
impl PrecomputedHash for Namespace {

View file

@ -750,8 +750,19 @@ where
//
// Note that we'll also restyle the pseudo-element because
// it would match this invalidation.
if self.processor.invalidates_on_eager_pseudo_element() && pseudo.is_eager() {
invalidated_self = true;
if self.processor.invalidates_on_eager_pseudo_element() {
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")]
extern crate thin_slice;
extern crate time;
extern crate to_shmem;
#[macro_use]
extern crate to_shmem_derive;
extern crate uluru;
extern crate unicode_bidi;
#[allow(unused_extern_crates)]

View file

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

View file

@ -471,7 +471,7 @@ trait PrivateMatchMethods: TElement {
debug!("accumulate_damage_for: {:?}", self);
debug_assert!(!shared_context
.traversal_flags
.contains(TraversalFlags::Forgetful));
.contains(TraversalFlags::FinalAnimationTraversal));
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
.shared
.traversal_flags
.contains(TraversalFlags::Forgetful)
.contains(TraversalFlags::FinalAnimationTraversal)
{
return ChildCascadeRequirement::MustCascadeChildren;
}

View file

@ -14,7 +14,7 @@ use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
/// 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)]
pub enum Operator {
And,
@ -29,7 +29,7 @@ enum AllowOr {
}
/// Represents a media condition.
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
pub enum MediaCondition {
/// A simple media feature expression, implicitly parenthesized.
Feature(MediaFeatureExpression),

View file

@ -17,7 +17,6 @@ use crate::parser::{Parse, ParserContext};
#[cfg(feature = "servo")]
use crate::servo::media_queries::MEDIA_FEATURES;
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::specified::{Integer, Length, Number, Resolution};
use crate::values::{serialize_atom_identifier, CSSFloat};
@ -28,7 +27,7 @@ use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
/// 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);
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.
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
pub enum Range {
/// At least the specified value.
Min,
@ -61,7 +60,7 @@ pub enum Range {
}
/// 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 {
/// =
Equal,
@ -94,7 +93,7 @@ impl ToCss for Operator {
///
/// Ranged media features are not allowed with operations (that'd make no
/// sense).
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
pub enum RangeOrOperator {
/// A `Range`.
Range(Range),
@ -152,7 +151,7 @@ impl RangeOrOperator {
/// A feature expression contains a reference to the media feature, the value
/// the media query contained, and the range to evaluate.
#[derive(Clone, Debug, MallocSizeOf)]
#[derive(Clone, Debug, MallocSizeOf, ToShmem)]
pub struct MediaFeatureExpression {
feature_index: usize,
value: Option<MediaExpressionValue>,
@ -290,7 +289,7 @@ impl MediaFeatureExpression {
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);
}
@ -468,7 +467,7 @@ impl MediaFeatureExpression {
/// If the first, this would need to store the relevant values.
///
/// See: https://github.com/w3c/csswg-drafts/issues/1968
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
pub enum MediaExpressionValue {
/// A length.
Length(Length),

View file

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

View file

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

View file

@ -146,10 +146,23 @@ impl<'a> ParserContext<'a> {
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.
#[inline]
pub fn chrome_rules_enabled(&self) -> bool {
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

View file

@ -683,6 +683,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
#[cfg(feature = "gecko")]
fn recompute_default_font_family_type_if_needed(&mut self) {
use crate::gecko_bindings::{bindings, structs};
use crate::values::computed::font::GenericFontFamily;
if !self.seen.contains(LonghandId::XLang) &&
!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
// set to none already, so bail out early.
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;
}
@ -717,11 +718,11 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
!use_document_fonts &&
matches!(
font.mGenericID,
structs::kGenericFont_NONE |
structs::kGenericFont_fantasy |
structs::kGenericFont_cursive
GenericFontFamily::None |
GenericFontFamily::Fantasy |
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 {
// Nothing to do.

View file

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

View file

@ -25,6 +25,8 @@ use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCs
use crate::stylesheets::{CssRuleType, Origin, UrlExtraData};
use super::*;
use crate::values::computed::Context;
use crate::selector_parser::SelectorImpl;
use selectors::SelectorList;
/// The animation rules.
///
@ -88,7 +90,7 @@ impl Importance {
/// Overridden declarations are skipped.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone)]
#[derive(Clone, ToShmem)]
pub struct PropertyDeclarationBlock {
/// The group of declarations, along with their importance.
///
@ -1211,7 +1213,7 @@ pub fn parse_style_attribute(
);
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
@ -1248,6 +1250,7 @@ pub fn parse_one_declaration_into(
let error = ContextualParseError::UnsupportedPropertyDeclaration(
parser.slice_from(start_position),
err,
None
);
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(
context: &ParserContext,
input: &mut Parser,
selectors: Option<&SelectorList<SelectorImpl>>
) -> PropertyDeclarationBlock {
let mut declarations = SourcePropertyDeclaration::new();
let mut block = PropertyDeclarationBlock::new();
@ -1338,7 +1342,7 @@ pub fn parse_property_declaration_list(
}
let location = error.location;
let error = ContextualParseError::UnsupportedPropertyDeclaration(slice, error);
let error = ContextualParseError::UnsupportedPropertyDeclaration(slice, error, selectors);
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::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
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::round_border_to_device_pixels;
use crate::logical_geometry::WritingMode;
@ -397,34 +395,6 @@ def set_gecko_property(ffi_name, expr):
}
</%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)">
<%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>
@ -449,24 +419,6 @@ def set_gecko_property(ffi_name, expr):
}
</%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)">
// 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.
@ -826,7 +778,7 @@ def set_gecko_property(ffi_name, expr):
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
match v {
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 => {
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.
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,
"RGBAColor": impl_rgba_color,
"SVGLength": impl_svg_length,
"SVGOpacity": impl_svg_opacity,
"SVGPaint": impl_svg_paint,
@ -1379,7 +1320,7 @@ fn static_assert() {
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,
"mComputedBorder.%s" % side.ident,
@ -1984,18 +1925,20 @@ fn static_assert() {
<% impl_font_settings("font_variation_settings", "gfxFontVariation", "VariationValue", "f32", "f32") %>
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;
self.gecko.mFont.systemFont = is_system_font;
self.gecko.mGenericID = if is_system_font {
structs::kGenericFont_NONE
GenericFontFamily::None
} 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.
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) {
@ -2009,36 +1952,16 @@ fn static_assert() {
}
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};
let fontlist = &self.gecko.mFont.fontlist;
let shared_fontlist = unsafe { fontlist.mFontlist.mBasePtr.to_safe() };
let families = if shared_fontlist.mNames.is_empty() {
let default = 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"))
}
};
let default = SingleFontFamily::Generic(fontlist.mDefaultFontType);
FontFamilyList::new(Box::new([default]))
} else {
FontFamilyList(shared_fontlist)
FontFamilyList::SharedFontList(shared_fontlist)
};
FontFamily {
@ -3781,7 +3704,7 @@ fn static_assert() {
},
Url(ref url) => {
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":
ShapeSource::ImageOrUrl(ref url) => {
unsafe {
bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.0.url_value.get())
bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.url_value_ptr())
}
}
% elif ident == "shape_outside":
@ -4404,23 +4327,10 @@ clip-path
}
</%self:impl_trait>
<%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 style_struct_name="Color">
</%self:impl_trait>
<%self:impl_trait style_struct_name="InheritedUI"
skip_longhands="cursor scrollbar-color">
<%self:impl_trait style_struct_name="InheritedUI" skip_longhands="cursor">
pub fn set_cursor(&mut self, v: longhands::cursor::computed_value::T) {
self.gecko.mCursor = v.keyword;
unsafe {
@ -4482,48 +4392,6 @@ clip-path
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 style_struct_name="Column"

View file

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

View file

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

View file

@ -427,18 +427,14 @@ ${helpers.predefined_type(
animation_value_type="discrete",
)}
% for axis in ["x", "y"]:
${helpers.predefined_type(
"scroll-snap-type-" + axis,
"ScrollSnapType",
"computed::ScrollSnapType::None",
products="gecko",
needs_context=False,
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
${helpers.predefined_type(
"scroll-snap-type",
"ScrollSnapType",
"computed::ScrollSnapType::none()",
products="gecko",
spec="https://drafts.csswg.org/css-scroll-snap-1/#scroll-snap-type",
animation_value_type="discrete",
)}
% for axis in ["x", "y"]:
${helpers.predefined_type(

View file

@ -67,6 +67,7 @@ pub mod system_colors {
use crate::gecko_bindings::structs::root::mozilla::LookAndFeel_ColorID;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
use to_shmem::impl_trivial_to_shmem;
use crate::values::computed::{Context, ToComputedValue};
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.
malloc_size_of_is_0!(SystemColor);
impl_trivial_to_shmem!(SystemColor);
impl ToCss for SystemColor {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where

View file

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

View file

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

View file

@ -372,7 +372,7 @@ ${helpers.predefined_type(
${helpers.predefined_type(
"column-gap",
"length::NonNegativeLengthPercentageOrNormal",
"Either::Second(Normal)",
"computed::length::NonNegativeLengthPercentageOrNormal::normal()",
alias="grid-column-gap" if product == "gecko" else "",
extra_prefixes="moz",
servo_pref="layout.columns.enabled",
@ -385,7 +385,7 @@ ${helpers.predefined_type(
${helpers.predefined_type(
"row-gap",
"length::NonNegativeLengthPercentageOrNormal",
"Either::Second(Normal)",
"computed::length::NonNegativeLengthPercentageOrNormal::normal()",
alias="grid-row-gap",
products="gecko",
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;
use style_traits::{CssWriter, KeywordsCollectFn, ParseError, ParsingMode};
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
use to_shmem::impl_trivial_to_shmem;
use crate::stylesheets::{CssRuleType, Origin, UrlExtraData};
use crate::values::generics::text::LineHeight;
use crate::values::computed;
use crate::values::{computed, resolved};
use crate::values::computed::NonNegativeLength;
use crate::values::serialize_atom_name;
use crate::rule_tree::StrongRuleNode;
@ -256,6 +257,7 @@ pub mod shorthands {
%>
/// Servo's representation for a property declaration.
#[derive(ToShmem)]
#[repr(u16)]
pub enum PropertyDeclaration {
% for variant in variants:
@ -741,11 +743,13 @@ static ${name}: LonghandIdSet = LonghandIdSet {
</%def>
/// A set of longhand properties
#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq)]
#[derive(Clone, Copy, Debug, Default, MallocSizeOf, PartialEq)]
pub struct LonghandIdSet {
storage: [u32; (${len(data.longhands)} - 1 + 32) / 32]
}
impl_trivial_to_shmem!(LonghandIdSet);
/// An iterator over a set of longhand ids.
pub struct LonghandIdSetIterator<'a> {
longhands: &'a LonghandIdSet,
@ -893,7 +897,7 @@ impl LonghandIdSet {
/// An enum to represent a CSS Wide keyword.
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToCss)]
ToCss, ToShmem)]
pub enum CSSWideKeyword {
/// The `initial` keyword.
Initial,
@ -993,7 +997,7 @@ pub enum LogicalGroup {
}
/// An identifier for a given longhand property.
#[derive(Clone, Copy, Eq, Hash, MallocSizeOf, PartialEq)]
#[derive(Clone, Copy, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
#[repr(u16)]
pub enum LonghandId {
% for i, property in enumerate(data.longhands):
@ -1266,49 +1270,12 @@ impl LonghandId {
LonghandId::FontStyle |
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
// properties, and similar stuff.
LonghandId::WritingMode |
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
@ -1335,7 +1302,7 @@ where
}
/// 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)]
pub enum ShorthandId {
% for i, property in enumerate(data.shorthands):
@ -1533,7 +1500,7 @@ impl ShorthandId {
}
/// An unparsed property value that contains `var()` functions.
#[derive(Debug, Eq, PartialEq)]
#[derive(Debug, Eq, PartialEq, ToShmem)]
pub struct UnparsedValue {
/// The css serialization for this value.
css: String,
@ -1954,7 +1921,7 @@ impl PropertyId {
/// A declaration using a CSS-wide keyword.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, PartialEq, ToCss)]
#[derive(Clone, PartialEq, ToCss, ToShmem)]
pub struct WideKeywordDeclaration {
#[css(skip)]
id: LonghandId,
@ -1963,7 +1930,7 @@ pub struct WideKeywordDeclaration {
/// An unparsed declaration that contains `var()` functions.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, PartialEq, ToCss)]
#[derive(Clone, PartialEq, ToCss, ToShmem)]
pub struct VariableDeclaration {
#[css(skip)]
id: LonghandId,
@ -1973,7 +1940,7 @@ pub struct VariableDeclaration {
/// A custom property declaration value is either an unparsed value or a CSS
/// wide-keyword.
#[derive(Clone, PartialEq, ToCss)]
#[derive(Clone, PartialEq, ToCss, ToShmem)]
pub enum CustomDeclarationValue {
/// A value.
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.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, PartialEq, ToCss)]
#[derive(Clone, PartialEq, ToCss, ToShmem)]
pub struct CustomDeclaration {
/// The name of the custom property.
#[css(skip)]
@ -2845,19 +2812,19 @@ impl ComputedValues {
where
W: Write,
{
use crate::values::resolved::ToResolvedValue;
let context = resolved::Context {
style: self,
};
// TODO(emilio): Is it worth to merge branches here just like
// PropertyDeclaration::to_css does?
//
// We'd need to get a concept of ~resolved value, which may not be worth
// it.
match property_id {
% for prop in data.longhands:
LonghandId::${prop.camel_case} => {
let value = self.clone_${prop.ident}();
% if prop.predefined_type == "Color":
let value = self.resolve_color(value);
% endif
value.to_css(dest)
value.to_resolved_value(&context).to_css(dest)
}
% endfor
}

View file

@ -303,36 +303,6 @@ macro_rules! try_parse_one {
}
</%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(
"overscroll-behavior",
"overscroll-behavior-x",

View file

@ -75,8 +75,15 @@ impl Drop for RuleTree {
#[cfg(feature = "gecko")]
impl MallocSizeOf for RuleTree {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = unsafe { ops.malloc_size_of(self.root.ptr()) };
n += self.root.get().size_of(ops);
let mut n = 0;
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
}
}
@ -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)]
struct WeakRuleNode {
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_BORDER;
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::values::specified::Color;
use std::borrow::Cow;

View file

@ -177,7 +177,7 @@ impl<T> PerPseudoElementMap<T> {
/// Values for the :dir() pseudo class
///
/// "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);
/// 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.
///
/// NB: If you add to this list, be sure to update `each_simple_pseudo_element` too.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
#[allow(missing_docs)]
#[repr(usize)]
pub enum PseudoElement {
@ -265,8 +264,7 @@ pub type Lang = Box<str>;
/// A non tree-structural pseudo-class.
/// See https://drafts.csswg.org/selectors-4/#structural-pseudos
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
#[allow(missing_docs)]
pub enum NonTSPseudoClass {
Active,

View file

@ -12,7 +12,7 @@ use std::fmt::{self, Write};
// nonzero optimization is important in keeping the size of SpecifiedUrl below
// the threshold.
use crate::values::computed::{Context, ToComputedValue};
use std::sync::Arc;
use servo_arc::Arc;
use style_traits::{CssWriter, ParseError, ToCss};
/// 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
/// 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 {
/// 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

View file

@ -15,8 +15,10 @@ use std::cell::UnsafeCell;
use std::fmt;
#[cfg(feature = "servo")]
use std::mem;
use std::mem::ManuallyDrop;
#[cfg(feature = "gecko")]
use std::ptr;
use to_shmem::{SharedMemoryBuilder, ToShmem};
/// 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,
/// but that may not be web-compatible and may need to be changed (at which
/// 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)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
pub struct SharedRwLock {
@ -36,7 +42,7 @@ pub struct SharedRwLock {
arc: Arc<RwLock<()>>,
#[cfg(feature = "gecko")]
cell: Arc<AtomicRefCell<SomethingZeroSizedButTyped>>,
cell: Option<Arc<AtomicRefCell<SomethingZeroSizedButTyped>>>,
}
#[cfg(feature = "gecko")]
@ -61,10 +67,16 @@ impl SharedRwLock {
#[cfg(feature = "gecko")]
pub fn new() -> Self {
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.
pub fn wrap<T>(&self, data: T) -> Locked<T> {
Locked {
@ -83,7 +95,7 @@ impl SharedRwLock {
/// Obtain the lock for reading (gecko).
#[cfg(feature = "gecko")]
pub fn read(&self) -> SharedRwLockReadGuard {
SharedRwLockReadGuard(self.cell.borrow())
SharedRwLockReadGuard(self.cell.as_ref().map(|cell| cell.borrow()))
}
/// Obtain the lock for writing (servo).
@ -96,16 +108,16 @@ impl SharedRwLock {
/// Obtain the lock for writing (gecko).
#[cfg(feature = "gecko")]
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).
#[cfg(feature = "servo")]
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")]
pub struct SharedRwLockReadGuard<'a>(AtomicRef<'a, SomethingZeroSizedButTyped>);
pub struct SharedRwLockReadGuard<'a>(Option<AtomicRef<'a, SomethingZeroSizedButTyped>>);
#[cfg(feature = "servo")]
impl<'a> Drop for SharedRwLockReadGuard<'a> {
fn drop(&mut self) {
@ -149,22 +161,41 @@ impl<T: fmt::Debug> fmt::Debug for 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")]
fn same_lock_as(&self, lock: &SharedRwLock) -> bool {
Arc::ptr_eq(&self.shared_lock.arc, &lock.arc)
}
#[cfg(feature = "gecko")]
fn same_lock_as(&self, derefed_guard: &SomethingZeroSizedButTyped) -> bool {
ptr::eq(self.shared_lock.cell.as_ptr(), derefed_guard)
fn same_lock_as(&self, derefed_guard: Option<&SomethingZeroSizedButTyped>) -> bool {
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.
pub fn read_with<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> &'a T {
#[cfg(feature = "gecko")]
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"
);
#[cfg(not(feature = "gecko"))]
assert!(self.same_lock_as(&guard.0));
let ptr = self.data.get();
// Unsafe:
@ -185,10 +216,14 @@ impl<T> Locked<T> {
/// Access the data for writing.
pub fn write_with<'a>(&'a self, guard: &'a mut SharedRwLockWriteGuard) -> &'a mut T {
#[cfg(feature = "gecko")]
assert!(
self.same_lock_as(&guard.0),
"Locked::write_with called with a guard from an unrelated SharedRwLock"
!self.is_read_only_lock() && self.same_lock_as(Some(&guard.0)),
"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();
// 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)]
mod compile_time_assert {
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
/// into the cascade.
///
@ -833,7 +787,6 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
#[cfg(feature = "gecko")]
{
self.adjust_for_appearance(element);
self.adjust_for_list_item(element);
}
self.set_bits();
}

View file

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

View file

@ -20,7 +20,7 @@ use servo_arc::Arc;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
#[derive(Debug)]
#[derive(Debug, ToShmem)]
/// A @-moz-document rule
pub struct DocumentRule {
/// The parsed condition
@ -72,7 +72,7 @@ impl DeepCloneWithLock for DocumentRule {
}
/// 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)]
pub enum MediaDocumentKind {
All,
@ -82,7 +82,7 @@ pub enum MediaDocumentKind {
}
/// A matching function for a `@document` rule's condition.
#[derive(Clone, Debug, ToCss)]
#[derive(Clone, Debug, ToCss, ToShmem)]
pub enum DocumentMatchingFunction {
/// Exact URL matching function. It evaluates to true whenever the
/// 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
/// one of those functions evaluates to true.
#[css(comma)]
#[derive(Clone, Debug, ToCss)]
#[derive(Clone, Debug, ToCss, ToShmem)]
pub struct DocumentCondition(#[css(iterable)] Vec<DocumentMatchingFunction>);
impl DocumentCondition {

View file

@ -30,7 +30,7 @@ use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
/// - `SingleValue` is to keep just one unsigned integer value.
/// - `PairValues` is to keep one or two 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> {
/// An `<ident>` for declaration name.
pub name: Atom,
@ -58,7 +58,7 @@ pub trait ToGeckoFontFeatureValues {
}
/// 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);
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.
#[derive(Clone, Debug, PartialEq, ToCss)]
#[derive(Clone, Debug, PartialEq, ToCss, ToShmem)]
pub struct PairValues(pub u32, pub Option<u32>);
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.
#[derive(Clone, Debug, PartialEq, ToCss)]
#[derive(Clone, Debug, PartialEq, ToCss, ToShmem)]
pub struct VectorValues(#[css(iterable)] pub Vec<u32>);
impl Parse for VectorValues {
@ -225,7 +225,7 @@ macro_rules! font_feature_values_blocks {
/// The [`@font-feature-values`][font-feature-values] at-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 {
/// Font family list for @font-feature-values rule.
/// Family names cannot contain generic families. FamilyName

View file

@ -15,7 +15,9 @@ use crate::stylesheets::{CssRule, Origin, StylesheetInDocument};
use crate::values::CssUrl;
use cssparser::SourceLocation;
use std::fmt::{self, Write};
use std::mem::ManuallyDrop;
use style_traits::{CssWriter, ToCss};
use to_shmem::{SharedMemoryBuilder, ToShmem};
/// With asynchronous stylesheet parsing, we can't synchronously create a
/// GeckoStyleSheet. So we use this placeholder instead.
@ -180,6 +182,12 @@ pub struct ImportRule {
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 {
fn deep_clone_with_lock(
&self,

View file

@ -26,7 +26,7 @@ use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCs
/// A [`@keyframes`][keyframes] rule.
///
/// [keyframes]: https://drafts.csswg.org/css-animations/#keyframes
#[derive(Debug)]
#[derive(Debug, ToShmem)]
pub struct KeyframesRule {
/// The name of the current animation.
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
/// keyframe should run.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToShmem)]
pub struct KeyframePercentage(pub f32);
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
/// converted at parse time to percentages.
#[css(comma)]
#[derive(Clone, Debug, Eq, PartialEq, ToCss)]
#[derive(Clone, Debug, Eq, PartialEq, ToCss, ToShmem)]
pub struct KeyframeSelector(#[css(iterable)] Vec<KeyframePercentage>);
impl KeyframeSelector {
@ -174,7 +174,7 @@ impl KeyframeSelector {
}
/// A keyframe.
#[derive(Debug)]
#[derive(Debug, ToShmem)]
pub struct Keyframe {
/// The selector this keyframe was specified from.
pub selector: KeyframeSelector,

View file

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

View file

@ -23,6 +23,10 @@ mod stylesheet;
pub mod supports_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::shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked};
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 servo_arc::Arc;
use std::fmt;
#[cfg(feature = "gecko")]
use std::mem::{self, ManuallyDrop};
use style_traits::ParsingMode;
#[cfg(feature = "gecko")]
use to_shmem::{SharedMemoryBuilder, ToShmem};
pub use self::counter_style_rule::CounterStyleRule;
pub use self::document_rule::DocumentRule;
@ -60,18 +68,76 @@ pub use self::viewport_rule::ViewportRule;
pub type UrlExtraData = ::servo_url::ServoUrl;
/// 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")]
#[derive(Clone, PartialEq)]
pub struct UrlExtraData(
pub crate::gecko_bindings::sugar::refptr::RefPtr<crate::gecko_bindings::structs::URLExtraData>,
);
#[derive(PartialEq)]
pub struct UrlExtraData(usize);
#[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")]
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.
#[inline]
pub fn is_chrome(&self) -> bool {
self.0.mIsChrome
self.as_ref().mIsChrome
}
/// Create a reference to this `UrlExtraData` from a reference to pointer.
@ -80,16 +146,30 @@ impl UrlExtraData {
///
/// This method doesn't touch refcount.
#[inline]
pub unsafe fn from_ptr_ref(ptr: &*mut crate::gecko_bindings::structs::URLExtraData) -> &Self {
::std::mem::transmute(ptr)
pub unsafe fn from_ptr_ref(ptr: &*mut structs::URLExtraData) -> &Self {
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")]
impl fmt::Debug for UrlExtraData {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
use crate::gecko_bindings::{bindings, structs};
struct DebugURI(*mut structs::nsIURI);
impl fmt::Debug for DebugURI {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
@ -105,10 +185,13 @@ impl fmt::Debug for UrlExtraData {
formatter
.debug_struct("URLExtraData")
.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(
"referrer",
&DebugURI(self.0.mReferrer.raw::<structs::nsIURI>()),
&DebugURI(self.as_ref().mReferrer.raw::<structs::nsIURI>()),
)
.finish()
}
@ -122,7 +205,7 @@ impl Eq for UrlExtraData {}
/// A CSS rule.
///
/// TODO(emilio): Lots of spec links should be around.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, ToShmem)]
#[allow(missing_docs)]
pub enum CssRule {
// No Charset here, CSSCharsetRule has been removed from CSSOM

View file

@ -11,7 +11,7 @@ use cssparser::SourceLocation;
use std::fmt::{self, Write};
/// A `@namespace` rule.
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, ToShmem)]
#[allow(missing_docs)]
pub struct NamespaceRule {
/// 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.
///
/// <https://drafts.csswg.org/css-cascade/#cascading-origins>
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, ToShmem)]
#[repr(u8)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
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-selectors]: https://drafts.csswg.org/css2/page.html#page-selectors
#[derive(Debug)]
#[derive(Debug, ToShmem)]
pub struct PageRule {
/// The declaration block this page rule contains.
pub block: Arc<Locked<PropertyDeclarationBlock>>,

View file

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

View file

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

View file

@ -19,7 +19,7 @@ use servo_arc::Arc;
use std::fmt::{self, Write};
/// A style rule, with selectors and declarations.
#[derive(Debug)]
#[derive(Debug, ToShmem)]
pub struct StyleRule {
/// The list of selectors in this rule.
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.
#[inline]
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.
///
/// [supports]: https://drafts.csswg.org/css-conditional-3/#at-supports
#[derive(Debug)]
#[derive(Debug, ToShmem)]
pub struct SupportsRule {
/// The parsed condition
pub condition: SupportsCondition,
@ -76,7 +76,7 @@ impl DeepCloneWithLock for SupportsRule {
/// An @supports condition
///
/// <https://drafts.csswg.org/css-conditional-3/#at-supports>
#[derive(Clone, Debug)]
#[derive(Clone, Debug, ToShmem)]
pub enum SupportsCondition {
/// `not (condition)`
Not(Box<SupportsCondition>),
@ -223,8 +223,7 @@ impl SupportsCondition {
#[cfg(feature = "gecko")]
fn eval_moz_bool_pref(name: &CStr, cx: &ParserContext) -> bool {
use crate::gecko_bindings::bindings;
use crate::stylesheets::Origin;
if cx.stylesheet_origin != Origin::UserAgent && !cx.chrome_rules_enabled() {
if !cx.in_ua_or_chrome_sheet() {
return false;
}
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.
pub struct RawSelector(pub String);
@ -368,7 +367,7 @@ impl RawSelector {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, ToShmem)]
/// A possibly-invalid property declaration
pub struct Declaration(pub String);

View file

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

View file

@ -129,6 +129,9 @@ impl UserAgentCascadeDataCache {
}
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())
}

View file

@ -307,8 +307,6 @@ pub fn resolve_style<E>(
where
E: TElement,
{
use crate::style_resolver::StyleResolverForElement;
debug_assert!(
rule_inclusion == RuleInclusion::DefaultOnly ||
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>,
F: FnMut(E::ConcreteNode),
{
use crate::traversal_flags::TraversalFlags;
use std::cmp;
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!(
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);
}
@ -551,27 +542,11 @@ fn clear_state_after_traversing<E>(element: E, data: &mut ElementData, flags: Tr
where
E: TElement,
{
// If we are in a forgetful traversal, drop the existing restyle
// data here, since we won't need to perform a post-traversal to pick up
// any change hints.
if flags.contains(TraversalFlags::Forgetful) {
if flags.intersects(TraversalFlags::FinalAnimationTraversal) {
debug_assert!(flags.for_animation_only());
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 {
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
/// @keyframes rules may have changed. Triggered by CSS rule changes.
const ForCSSRuleChanges = 1 << 1;
/// A forgetful traversal ignores the previous state of the frame tree, and
/// thus does not compute damage or maintain other state describing the styles
/// pre-traversal. A forgetful traversal is usually the right thing if you
/// 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;
/// The final animation-only traversal, which shouldn't really care about other
/// style changes anymore.
const FinalAnimationTraversal = 1 << 2;
/// Allows the traversal to run in parallel if there are sufficient cores on
/// the machine.
const ParallelTraversal = 1 << 7;
@ -58,10 +52,7 @@ pub fn assert_traversal_flags_match() {
check_traversal_flags! {
ServoTraversalFlags_AnimationOnly => TraversalFlags::AnimationOnly,
ServoTraversalFlags_ForCSSRuleChanges => TraversalFlags::ForCSSRuleChanges,
ServoTraversalFlags_Forgetful => TraversalFlags::Forgetful,
ServoTraversalFlags_ClearDirtyBits => TraversalFlags::ClearDirtyBits,
ServoTraversalFlags_ClearAnimationOnlyDirtyDescendants =>
TraversalFlags::ClearAnimationOnlyDirtyDescendants,
ServoTraversalFlags_FinalAnimationTraversal => TraversalFlags::FinalAnimationTraversal,
ServoTraversalFlags_ParallelTraversal => TraversalFlags::ParallelTraversal,
ServoTraversalFlags_FlushThrottledAnimations => TraversalFlags::FlushThrottledAnimations,
}

View file

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

View file

@ -33,7 +33,7 @@ pub use super::specified::{AlignSelf, JustifySelf};
/// sucks :(.
///
/// 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 {
/// The specified value for the property. Can contain the bare `legacy`
/// keyword.

View file

@ -14,7 +14,18 @@ use style_traits::{CssWriter, ToCss};
/// A computed angle in degrees.
#[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);
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_::{Clear as SpecifiedClear, Float as SpecifiedFloat};
pub use crate::values::specified::box_::{Contain, Display, Overflow};
pub use crate::values::specified::box_::{OverflowAnchor, OverflowClipBox};
pub use crate::values::specified::box_::{OverscrollBehavior, ScrollSnapAlign, ScrollSnapType};
pub use crate::values::specified::box_::{OverflowAnchor, OverflowClipBox, OverscrollBehavior};
pub use crate::values::specified::box_::{
ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStrictness, ScrollSnapType,
};
pub use crate::values::specified::box_::{TouchAction, TransitionProperty, WillChange};
/// A computed value for the `vertical-align` property.
@ -49,6 +51,7 @@ pub type Perspective = GenericPerspective<NonNegativeLength>;
PartialEq,
SpecifiedValueInfo,
ToCss,
ToResolvedValue,
)]
#[repr(u8)]
/// A computed value for the `float` property.
@ -118,6 +121,7 @@ impl ToComputedValue for SpecifiedFloat {
PartialEq,
SpecifiedValueInfo,
ToCss,
ToResolvedValue,
)]
/// A computed value for the `clear` property.
pub enum Clear {
@ -178,7 +182,7 @@ impl ToComputedValue for SpecifiedClear {
/// A computed value for the `resize` property.
#[allow(missing_docs)]
#[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)]
pub enum Resize {
None,

View file

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

View file

@ -24,9 +24,13 @@ use cssparser::{serialize_identifier, CssStringWriter, Parser};
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use std::fmt::{self, Write};
use std::hash::{Hash, Hasher};
#[cfg(feature = "gecko")]
use std::mem::{self, ManuallyDrop};
#[cfg(feature = "servo")]
use std::slice;
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::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
///
/// 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))]
pub struct FontWeight(pub Number);
@ -71,6 +77,7 @@ impl ToAnimatedValue for FontWeight {
PartialEq,
ToAnimatedZero,
ToCss,
ToResolvedValue,
)]
/// The computed value of font-size
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 {
type AnimatedValue = NonNegativeLength;
@ -175,8 +178,8 @@ impl ToAnimatedValue for FontSize {
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[derive(Clone, Debug, Eq, PartialEq, ToResolvedValue)]
#[cfg_attr(feature = "servo", derive(Hash, MallocSizeOf))]
/// Specifies a prioritized list of font family names or generic family names.
pub struct FontFamily {
/// The actual list of family names.
@ -190,7 +193,9 @@ impl FontFamily {
/// Get default font family as `serif` which is a generic font-family
pub fn serif() -> Self {
FontFamily {
families: FontFamilyList::new(Box::new([SingleFontFamily::Generic(atom!("serif"))])),
families: FontFamilyList::new(Box::new([SingleFontFamily::Generic(
GenericFontFamily::Serif,
)])),
is_system_font: false,
}
}
@ -202,9 +207,8 @@ impl MallocSizeOf for FontFamily {
// SharedFontList objects are generally shared from the pointer
// stored in the specified value. So only count this if the
// SharedFontList is unshared.
unsafe {
bindings::Gecko_SharedFontList_SizeOfIncludingThisIfUnshared(self.families.0.get())
}
let shared_font_list = self.families.shared_font_list().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))]
/// The name of a font family of choice
pub struct FamilyName {
/// Name of the font family
pub name: Atom,
/// Syntax of the font family
pub syntax: FamilyNameSyntax,
pub syntax: FontFamilyNameSyntax,
}
impl ToCss for FamilyName {
@ -239,12 +243,12 @@ impl ToCss for FamilyName {
W: fmt::Write,
{
match self.syntax {
FamilyNameSyntax::Quoted => {
FontFamilyNameSyntax::Quoted => {
dest.write_char('"')?;
write!(CssStringWriter::new(dest), "{}", self.name)?;
dest.write_char('"')
},
FamilyNameSyntax::Identifiers => {
FontFamilyNameSyntax::Identifiers => {
let mut first = true;
for ident in self.name.to_string().split(' ') {
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))]
/// Font family names must either be given quoted as strings,
/// 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"
/// or 'Font Name'.
Quoted,
@ -280,85 +285,59 @@ pub enum FamilyNameSyntax {
Identifiers,
}
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss, ToResolvedValue, ToShmem)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize, Hash))]
/// A set of faces that vary in weight, width or slope.
pub enum SingleFontFamily {
/// The name of a font family of choice.
FamilyName(FamilyName),
/// 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 {
#[inline]
/// 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
/// Parse a font-family value.
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()) {
return Ok(SingleFontFamily::FamilyName(FamilyName {
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
// string (as lowercase) in the static atoms table. We don't have an
// API to do that yet though, so we do the simple thing for now.
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 first_ident = input.expect_ident_cloned()?;
if let Ok(generic) = GenericFontFamily::from_ident(&first_ident) {
return Ok(SingleFontFamily::Generic(generic));
}
let reserved = match_ignore_ascii_case! { &first_ident,
// https://drafts.csswg.org/css-fonts/#propdef-font-family
// "Font family names that happen to be the same as a keyword value
// (`inherit`, `serif`, `sans-serif`, `monospace`, `fantasy`, and `cursive`)
@ -366,18 +345,15 @@ impl SingleFontFamily {
// The keywords initial and default are reserved for future use
// and must also be quoted when used as font names.
// UAs must not consider these keywords as matching the <family-name> type."
"inherit" => css_wide_keyword = true,
"initial" => css_wide_keyword = true,
"unset" => css_wide_keyword = true,
"default" => css_wide_keyword = true,
_ => {}
}
"inherit" | "initial" | "unset" | "revert" | "default" => true,
_ => false,
};
let mut value = first_ident.as_ref().to_owned();
// These keywords are not allowed by themselves.
// The only way this value can be valid with with another keyword.
if css_wide_keyword {
if reserved {
let ident = input.expect_ident()?;
value.push(' ');
value.push_str(&ident);
@ -391,9 +367,9 @@ impl SingleFontFamily {
// `font-family: \ a\ \ b\ \ c\ ;`, it is tricky to serialize them
// as identifiers correctly. Just mark them quoted so we don't need
// to worry about them in serialization code.
FamilyNameSyntax::Quoted
FontFamilyNameSyntax::Quoted
} else {
FamilyNameSyntax::Identifiers
FontFamilyNameSyntax::Identifiers
};
Ok(SingleFontFamily::FamilyName(FamilyName {
name: Atom::from(value),
@ -401,134 +377,97 @@ impl SingleFontFamily {
}))
}
#[cfg(feature = "gecko")]
/// Return the generic ID for a given generic font name
pub fn generic(name: &Atom) -> (structs::FontFamilyType, u8) {
use crate::gecko_bindings::structs::FontFamilyType;
if *name == atom!("serif") {
(FontFamilyType::eFamily_serif, structs::kGenericFont_serif)
} else if *name == atom!("sans-serif") {
(
FontFamilyType::eFamily_sans_serif,
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);
#[cfg(feature = "servo")]
/// Get the corresponding font-family with Atom
pub fn from_atom(input: Atom) -> SingleFontFamily {
match input {
atom!("serif") => return SingleFontFamily::Generic(GenericFontFamily::Serif),
atom!("sans-serif") => return SingleFontFamily::Generic(GenericFontFamily::SansSerif),
atom!("cursive") => return SingleFontFamily::Generic(GenericFontFamily::Cursive),
atom!("fantasy") => return SingleFontFamily::Generic(GenericFontFamily::Fantasy),
atom!("monospace") => return SingleFontFamily::Generic(GenericFontFamily::Monospace),
_ => {},
}
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")]
/// Get the corresponding font-family with family name
fn from_font_family_name(family: &structs::FontFamilyName) -> SingleFontFamily {
use crate::gecko_bindings::structs::FontFamilyType;
match family.mType {
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)
},
if family.mName.mRawPtr.is_null() {
debug_assert_ne!(family.mGeneric, GenericFontFamily::None);
return SingleFontFamily::Generic(family.mGeneric);
}
let name = unsafe { Atom::from_raw(family.mName.mRawPtr) };
SingleFontFamily::FamilyName(FamilyName {
name,
syntax: family.mSyntax,
})
}
}
#[cfg(feature = "servo")]
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToResolvedValue, ToShmem)]
/// A list of SingleFontFamily
pub struct FontFamilyList(Box<[SingleFontFamily]>);
#[cfg(feature = "gecko")]
#[derive(Clone, Debug)]
/// 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")]
impl Hash for FontFamilyList {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
use crate::string_cache::WeakAtom;
for name in self.0.mNames.iter() {
name.mType.hash(state);
if !name.mName.mRawPtr.is_null() {
unsafe {
WeakAtom::new(name.mName.mRawPtr).hash(state);
}
}
}
impl ToShmem for FontFamilyList {
fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> ManuallyDrop<Self> {
// In practice, the only SharedFontList objects we create from shared
// style sheets are ones with a single generic entry.
ManuallyDrop::new(match *self {
FontFamilyList::SharedFontList(ref r) => {
assert!(
r.mNames.len() == 1 && r.mNames[0].mName.mRawPtr.is_null(),
"ToShmem failed for FontFamilyList: cannot handle non-generic families",
);
FontFamilyList::Generic(r.mNames[0].mGeneric)
},
FontFamilyList::Generic(t) => FontFamilyList::Generic(t),
})
}
}
#[cfg(feature = "gecko")]
impl PartialEq for FontFamilyList {
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;
}
for (a, b) in self.0.mNames.iter().zip(other.0.mNames.iter()) {
if a.mType != b.mType || a.mName.mRawPtr != b.mName.mRawPtr {
for (a, b) in self_list.mNames.iter().zip(other_list.mNames.iter()) {
if a.mSyntax != b.mSyntax ||
a.mName.mRawPtr != b.mName.mRawPtr ||
a.mGeneric != b.mGeneric
{
return false;
}
}
@ -540,14 +479,14 @@ impl PartialEq for FontFamilyList {
impl Eq for FontFamilyList {}
impl FontFamilyList {
#[cfg(feature = "servo")]
/// Return FontFamilyList with a vector of SingleFontFamily
#[cfg(feature = "servo")]
pub fn new(families: Box<[SingleFontFamily]>) -> FontFamilyList {
FontFamilyList(families)
}
#[cfg(feature = "gecko")]
/// Return FontFamilyList with a vector of SingleFontFamily
#[cfg(feature = "gecko")]
pub fn new(families: Box<[SingleFontFamily]>) -> FontFamilyList {
let fontlist;
let names;
@ -559,58 +498,69 @@ impl FontFamilyList {
for family in families.iter() {
match *family {
SingleFontFamily::FamilyName(ref f) => {
let quoted = matches!(f.syntax, FamilyNameSyntax::Quoted);
unsafe {
bindings::Gecko_nsTArray_FontFamilyName_AppendNamed(
names,
f.name.as_ptr(),
quoted,
);
}
SingleFontFamily::FamilyName(ref f) => unsafe {
bindings::Gecko_nsTArray_FontFamilyName_AppendNamed(
names,
f.name.as_ptr(),
f.syntax,
);
},
SingleFontFamily::Generic(ref name) => {
let (family_type, _generic) = SingleFontFamily::generic(name);
unsafe {
bindings::Gecko_nsTArray_FontFamilyName_AppendGeneric(names, family_type);
}
SingleFontFamily::Generic(family) => unsafe {
bindings::Gecko_nsTArray_FontFamilyName_AppendGeneric(names, family);
},
}
}
FontFamilyList(unsafe { RefPtr::from_addrefed(fontlist) })
FontFamilyList::SharedFontList(unsafe { RefPtr::from_addrefed(fontlist) })
}
#[cfg(feature = "servo")]
/// Return iterator of SingleFontFamily
#[cfg(feature = "servo")]
pub fn iter(&self) -> slice::Iter<SingleFontFamily> {
self.0.iter()
}
#[cfg(feature = "gecko")]
/// Return iterator of SingleFontFamily
#[cfg(feature = "gecko")]
pub fn iter(&self) -> FontFamilyNameIter {
FontFamilyNameIter {
names: &self.0.mNames,
names: &self.shared_font_list().mNames,
cur: 0,
}
}
#[cfg(feature = "gecko")]
/// 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();
if let Some(SingleFontFamily::Generic(ref name)) = iter.next() {
if let Some(SingleFontFamily::Generic(f)) = iter.next() {
if iter.next().is_none() {
return Some(SingleFontFamily::generic(name).1);
return Some(f.clone());
}
}
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
#[cfg(feature = "gecko")]
pub struct FontFamilyNameIter<'a> {
names: &'a structs::nsTArray<structs::FontFamilyName>,
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
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
PartialEq,
ToCss,
ToResolvedValue,
)]
pub enum FontSizeAdjust {
#[animation(error)]
/// None variant
@ -713,7 +673,7 @@ pub type FontVariationSettings = FontSettings<VariationValue<Number>>;
/// OpenType "language system" tag, so we should be able to compute
/// it and store it as a 32-bit integer
/// (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)]
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
/// 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))]
pub struct FontStyleAngle(pub Angle);
@ -916,7 +876,9 @@ impl ToCss for FontStyle {
/// A value for the font-stretch property per:
///
/// 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))]
pub struct FontStretch(pub NonNegativePercentage);

View file

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

View file

@ -10,12 +10,12 @@ use crate::values::computed::NonNegativeNumber;
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
use crate::values::generics::length as generics;
use crate::values::generics::length::{
GenericLengthOrNumber, MaxSize as GenericMaxSize, Size as GenericSize,
GenericLengthOrNumber, GenericLengthPercentageOrNormal, GenericMaxSize, GenericSize,
};
use crate::values::generics::NonNegative;
use crate::values::specified::length::ViewportPercentageLength;
use crate::values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength};
use crate::values::{specified, CSSFloat, Either, Normal};
use crate::values::{specified, CSSFloat};
use crate::Zero;
use app_units::Au;
use ordered_float::NotNan;
@ -75,7 +75,7 @@ impl ToComputedValue for specified::Length {
///
/// https://drafts.csswg.org/css-values-4/#typedef-length-percentage
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, MallocSizeOf, ToAnimatedZero)]
#[derive(Clone, Copy, Debug, MallocSizeOf, ToAnimatedZero, ToResolvedValue)]
#[repr(C)]
pub struct LengthPercentage {
length: Length,
@ -608,6 +608,8 @@ impl Size {
PartialOrd,
ToAnimatedValue,
ToAnimatedZero,
ToResolvedValue,
ToShmem,
)]
#[repr(C)]
pub struct CSSPixelLength(CSSFloat);
@ -709,9 +711,6 @@ pub type NonNegativeLengthOrAuto = generics::GenericLengthPercentageOrAuto<NonNe
/// Either a computed `<length>` or a `<number>` value.
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.
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.
pub type NonNegativeLengthPercentageOrNormal = Either<NonNegativeLengthPercentage, Normal>;
pub type NonNegativeLengthPercentageOrNormal =
GenericLengthPercentageOrNormal<NonNegativeLengthPercentage>;
/// Either a non-negative `<length>` or a `<number>`.
pub type NonNegativeLengthOrNumber = GenericLengthOrNumber<NonNegativeLength, NonNegativeNumber>;
@ -809,6 +806,8 @@ pub type NonNegativeLengthOrNumber = GenericLengthOrNumber<NonNegativeLength, No
ToAnimatedZero,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
#[repr(u8)]
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_::{Display, Overflow, OverflowAnchor, TransitionProperty};
pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize};
pub use self::box_::{ScrollSnapAlign, ScrollSnapType, TouchAction, VerticalAlign, WillChange};
pub use self::color::{Color, ColorOrAuto, ColorPropertyValue, RGBAColor};
pub use self::box_::{ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStrictness, ScrollSnapType};
pub use self::box_::{TouchAction, VerticalAlign, WillChange};
pub use self::color::{Color, ColorOrAuto, ColorPropertyValue};
pub use self::column::ColumnCount;
pub use self::counters::{Content, ContentItem, CounterIncrement, CounterSetOrReset};
pub use self::easing::TimingFunction;
@ -534,7 +535,9 @@ impl From<GreaterThanOrEqualToOneNumber> for CSSFloat {
}
#[allow(missing_docs)]
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(
Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue,
)]
#[repr(C, u8)]
pub enum NumberOrPercentage {
Percentage(Percentage),

View file

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

View file

@ -37,6 +37,7 @@ pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;
PartialEq,
ToAnimatedValue,
ToAnimatedZero,
ToResolvedValue,
)]
pub struct LetterSpacing(pub Length);
@ -102,7 +103,7 @@ impl ToComputedValue for specified::WordSpacing {
/// A computed value for the `line-height` property.
pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeLength>;
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToResolvedValue)]
/// text-overflow.
/// When the specified value only has one side, that's the "second"
/// 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.
///
/// 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 {
/// Whether an underline is in effect.
pub underline: bool,
@ -193,7 +194,7 @@ impl TextDecorationsInEffect {
}
/// computed value for the text-emphasis-style property
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)]
pub enum TextEmphasisStyle {
/// Keyword value for the text-emphasis-style property (`filled` `open`)
Keyword(TextEmphasisKeywordValue),
@ -204,7 +205,7 @@ pub enum TextEmphasisStyle {
}
/// Keyword value for the text-emphasis-style property
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)]
pub struct TextEmphasisKeywordValue {
/// fill for the text-emphasis-style property
pub fill: TextEmphasisFillMode,

View file

@ -9,7 +9,7 @@ use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
/// 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))]
pub struct Time {
seconds: CSSFloat,

View file

@ -19,4 +19,4 @@ pub type Cursor = generics::Cursor<CursorImage>;
pub type CursorImage = generics::CursorImage<ComputedImageUrl, Number>;
/// 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,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
#[repr(C, u8)]
pub enum GenericBackgroundSize<LengthPercent> {

View file

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

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