/* 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/. */ //! Calculate [specified][specified] and [computed values][computed] from a //! tree of DOM nodes and a set of stylesheets. //! //! [computed]: https://drafts.csswg.org/css-cascade/#computed //! [specified]: https://drafts.csswg.org/css-cascade/#specified //! //! In particular, this crate contains the definitions of supported properties, //! the code to parse them into specified values and calculate the computed //! values based on the specified values, as well as the code to serialize both //! specified and computed values. //! //! The main entry point is [`recalc_style_at`][recalc_style_at]. //! //! [recalc_style_at]: traversal/fn.recalc_style_at.html //! //! Major dependencies are the [cssparser][cssparser] and [selectors][selectors] //! crates. //! //! [cssparser]: ../cssparser/index.html //! [selectors]: ../selectors/index.html #![deny(missing_docs)] #[macro_use] extern crate bitflags; #[macro_use] extern crate cssparser; #[macro_use] extern crate debug_unreachable; #[macro_use] extern crate derive_more; #[macro_use] extern crate gecko_profiler; #[cfg(feature = "gecko")] #[macro_use] pub mod gecko_string_cache; #[cfg(feature = "servo")] #[macro_use] extern crate html5ever; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; #[macro_use] extern crate malloc_size_of; #[macro_use] extern crate malloc_size_of_derive; #[allow(unused_extern_crates)] #[macro_use] extern crate matches; #[cfg(feature = "gecko")] pub use nsstring; #[cfg(feature = "gecko")] extern crate num_cpus; #[macro_use] extern crate num_derive; #[macro_use] extern crate serde; pub use servo_arc; #[cfg(feature = "servo")] #[macro_use] extern crate servo_atoms; #[macro_use] extern crate static_assertions; #[macro_use] extern crate style_derive; #[macro_use] extern crate to_shmem_derive; #[macro_use] mod macros; pub mod animation; pub mod applicable_declarations; #[allow(missing_docs)] // TODO. #[cfg(feature = "servo")] pub mod attr; pub mod author_styles; pub mod bezier; pub mod bloom; #[path = "properties/computed_value_flags.rs"] pub mod computed_value_flags; pub mod context; pub mod counter_style; pub mod custom_properties; pub mod data; pub mod dom; pub mod dom_apis; pub mod driver; #[cfg(feature = "servo")] mod encoding_support; pub mod error_reporting; pub mod font_face; pub mod font_metrics; #[cfg(feature = "gecko")] #[allow(unsafe_code)] pub mod gecko_bindings; pub mod global_style_data; pub mod invalidation; #[allow(missing_docs)] // TODO. pub mod logical_geometry; pub mod matching; pub mod media_queries; pub mod parallel; pub mod parser; pub mod piecewise_linear; #[macro_use] pub mod queries; pub mod rule_cache; pub mod rule_collector; pub mod rule_tree; pub mod scoped_tls; pub mod selector_map; pub mod selector_parser; pub mod shared_lock; pub mod sharing; pub mod str; pub mod style_adjuster; pub mod style_resolver; pub mod stylesheet_set; pub mod stylesheets; pub mod stylist; pub mod thread_state; pub mod traversal; pub mod traversal_flags; pub mod use_counters; #[macro_use] #[allow(non_camel_case_types)] pub mod values; #[cfg(feature = "gecko")] pub use crate::gecko_string_cache as string_cache; #[cfg(feature = "gecko")] pub use crate::gecko_string_cache::Atom; /// The namespace prefix type for Gecko, which is just an atom. #[cfg(feature = "gecko")] pub type Prefix = crate::values::AtomIdent; /// The local name of an element for Gecko, which is just an atom. #[cfg(feature = "gecko")] pub type LocalName = crate::values::AtomIdent; #[cfg(feature = "gecko")] pub use crate::gecko_string_cache::Namespace; #[cfg(feature = "servo")] pub use servo_atoms::Atom; #[cfg(feature = "servo")] #[allow(missing_docs)] pub type LocalName = crate::values::GenericAtomIdent; #[cfg(feature = "servo")] #[allow(missing_docs)] pub type Namespace = crate::values::GenericAtomIdent; #[cfg(feature = "servo")] #[allow(missing_docs)] pub type Prefix = crate::values::GenericAtomIdent; pub use style_traits::arc_slice::ArcSlice; pub use style_traits::owned_slice::OwnedSlice; pub use style_traits::owned_str::OwnedStr; use std::hash::{BuildHasher, Hash}; /// The CSS properties supported by the style system. /// Generated from the properties.mako.rs template by build.rs #[macro_use] #[allow(unsafe_code)] #[deny(missing_docs)] pub mod properties { include!(concat!(env!("OUT_DIR"), "/properties.rs")); } #[cfg(feature = "gecko")] #[allow(unsafe_code)] pub mod gecko; // uses a macro from properties #[cfg(feature = "servo")] #[allow(unsafe_code)] pub mod servo; #[cfg(feature = "gecko")] #[allow(unsafe_code, missing_docs)] pub mod gecko_properties { include!(concat!(env!("OUT_DIR"), "/gecko_properties.rs")); } macro_rules! reexport_computed_values { ( $( { $name: ident } )+ ) => { /// Types for [computed values][computed]. /// /// [computed]: https://drafts.csswg.org/css-cascade/#computed pub mod computed_values { $( pub use crate::properties::longhands::$name::computed_value as $name; )+ // Don't use a side-specific name needlessly: pub use crate::properties::longhands::border_top_style::computed_value as border_style; } } } longhand_properties_idents!(reexport_computed_values); #[cfg(feature = "gecko")] use crate::gecko_string_cache::WeakAtom; #[cfg(feature = "servo")] use servo_atoms::Atom as WeakAtom; /// Extension methods for selectors::attr::CaseSensitivity pub trait CaseSensitivityExt { /// Return whether two atoms compare equal according to this case sensitivity. fn eq_atom(self, a: &WeakAtom, b: &WeakAtom) -> bool; } impl CaseSensitivityExt for selectors::attr::CaseSensitivity { fn eq_atom(self, a: &WeakAtom, b: &WeakAtom) -> bool { match self { selectors::attr::CaseSensitivity::CaseSensitive => a == b, selectors::attr::CaseSensitivity::AsciiCaseInsensitive => a.eq_ignore_ascii_case(b), } } } /// A trait pretty much similar to num_traits::Zero, but without the need of /// implementing `Add`. pub trait Zero { /// Returns the zero value. fn zero() -> Self; /// Returns whether this value is zero. fn is_zero(&self) -> bool; } impl Zero for T where T: num_traits::Zero, { fn zero() -> Self { ::zero() } fn is_zero(&self) -> bool { ::is_zero(self) } } /// A trait implementing a function to tell if the number is zero without a percent pub trait ZeroNoPercent { /// So, `0px` should return `true`, but `0%` or `1px` should return `false` fn is_zero_no_percent(&self) -> bool; } /// A trait pretty much similar to num_traits::One, but without the need of /// implementing `Mul`. pub trait One { /// Reutrns the one value. fn one() -> Self; /// Returns whether this value is one. fn is_one(&self) -> bool; } impl One for T where T: num_traits::One + PartialEq, { fn one() -> Self { ::one() } fn is_one(&self) -> bool { *self == One::one() } } /// An allocation error. /// /// TODO(emilio): Would be nice to have more information here, or for SmallVec /// to return the standard error type (and then we can just return that). /// /// But given we use these mostly to bail out and ignore them, it's not a big /// deal. #[derive(Debug)] pub struct AllocErr; impl From for AllocErr { #[inline] fn from(_: smallvec::CollectionAllocErr) -> Self { Self } } impl From for AllocErr { #[inline] fn from(_: std::collections::TryReserveError) -> Self { Self } } /// Shrink the capacity of the collection if needed. pub(crate) trait ShrinkIfNeeded { fn shrink_if_needed(&mut self); } /// We shrink the capacity of a collection if we're wasting more than a 25% of /// its capacity, and if the collection is arbitrarily big enough /// (>= CAPACITY_THRESHOLD entries). #[inline] fn should_shrink(len: usize, capacity: usize) -> bool { const CAPACITY_THRESHOLD: usize = 64; capacity >= CAPACITY_THRESHOLD && len + capacity / 4 < capacity } impl ShrinkIfNeeded for std::collections::HashMap where K: Eq + Hash, H: BuildHasher, { fn shrink_if_needed(&mut self) { if should_shrink(self.len(), self.capacity()) { self.shrink_to_fit(); } } } impl ShrinkIfNeeded for std::collections::HashSet where T: Eq + Hash, H: BuildHasher, { fn shrink_if_needed(&mut self) { if should_shrink(self.len(), self.capacity()) { self.shrink_to_fit(); } } } // TODO(emilio): Measure and see if we're wasting a lot of memory on Vec / // SmallVec, and if so consider shrinking those as well.