Skip to main content

style/
lib.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Calculate [specified][specified] and [computed values][computed] from a
6//! tree of DOM nodes and a set of stylesheets.
7//!
8//! [computed]: https://drafts.csswg.org/css-cascade/#computed
9//! [specified]: https://drafts.csswg.org/css-cascade/#specified
10//!
11//! In particular, this crate contains the definitions of supported properties,
12//! the code to parse them into specified values and calculate the computed
13//! values based on the specified values, as well as the code to serialize both
14//! specified and computed values.
15//!
16//! The main entry point is [`recalc_style_at`][recalc_style_at].
17//!
18//! [recalc_style_at]: traversal/fn.recalc_style_at.html
19//!
20//! A list of supported style properties can be found as [docs::supported_properties]
21//!
22//! Major dependencies are the [cssparser][cssparser] and [selectors][selectors]
23//! crates.
24//!
25//! [cssparser]: ../cssparser/index.html
26//! [selectors]: ../selectors/index.html
27
28#![deny(missing_docs)]
29
30pub(crate) use cssparser;
31
32#[macro_use]
33extern crate bitflags;
34#[macro_use]
35#[cfg(feature = "gecko")]
36extern crate gecko_profiler;
37#[cfg(feature = "gecko")]
38#[macro_use]
39pub mod gecko_string_cache;
40#[macro_use]
41extern crate log;
42#[macro_use]
43extern crate serde;
44pub use servo_arc;
45#[cfg(feature = "servo")]
46#[macro_use]
47extern crate stylo_atoms;
48#[macro_use]
49extern crate static_assertions;
50
51#[macro_use]
52mod macros;
53
54mod derives {
55    pub(crate) use derive_more::{Add, AddAssign, Deref, DerefMut, From};
56    pub(crate) use malloc_size_of_derive::MallocSizeOf;
57    pub(crate) use num_derive::FromPrimitive;
58    pub(crate) use style_derive::{
59        Animate, ComputeSquaredDistance, Parse, SpecifiedValueInfo, ToAnimatedValue,
60        ToAnimatedZero, ToComputedValue, ToCss, ToResolvedValue, ToTyped,
61    };
62    pub(crate) use to_shmem_derive::ToShmem;
63}
64
65pub mod applicable_declarations;
66pub mod author_styles;
67pub mod bezier;
68pub mod bloom;
69pub mod color;
70#[path = "properties/computed_value_flags.rs"]
71pub mod computed_value_flags;
72pub mod context;
73pub mod counter_style;
74pub mod custom_properties;
75pub mod custom_properties_map;
76pub mod data;
77pub mod device;
78pub mod dom;
79pub mod dom_apis;
80pub mod driver;
81pub mod error_reporting;
82pub mod font_face;
83pub mod font_metrics;
84#[cfg(feature = "gecko")]
85#[allow(unsafe_code)]
86pub mod gecko_bindings;
87pub mod global_style_data;
88pub mod invalidation;
89#[allow(missing_docs)] // TODO.
90pub mod logical_geometry;
91pub mod matching;
92pub mod media_queries;
93pub mod parallel;
94pub mod parser;
95pub mod piecewise_linear;
96pub mod properties_and_values;
97#[macro_use]
98pub mod queries;
99pub mod rule_cache;
100pub mod rule_collector;
101pub mod rule_tree;
102pub mod scoped_tls;
103pub mod selector_map;
104pub mod selector_parser;
105pub mod shared_lock;
106pub mod sharing;
107mod simple_buckets_map;
108pub mod str;
109pub mod style_adjuster;
110pub mod style_resolver;
111pub mod stylesheet_set;
112pub mod stylesheets;
113pub mod stylist;
114pub mod thread_state;
115pub mod traversal;
116pub mod traversal_flags;
117pub mod typed_om;
118pub mod url;
119pub mod use_counters;
120
121#[macro_use]
122#[allow(non_camel_case_types)]
123pub mod values;
124
125#[cfg(all(doc, feature = "servo"))]
126/// Documentation
127pub mod docs {
128    /// The CSS properties supported by the style system.
129    /// Generated from the `properties.mako.rs` template by `build.rs`
130    pub mod supported_properties {
131        #![doc = include_str!(concat!(env!("OUT_DIR"), "/css-properties.html"))]
132    }
133}
134
135#[cfg(feature = "gecko")]
136pub use crate::gecko_string_cache as string_cache;
137#[cfg(feature = "gecko")]
138pub use crate::gecko_string_cache::Atom;
139/// The namespace prefix type for Gecko, which is just an atom.
140#[cfg(feature = "gecko")]
141pub type Prefix = crate::values::AtomIdent;
142/// The local name of an element for Gecko, which is just an atom.
143#[cfg(feature = "gecko")]
144pub type LocalName = crate::values::AtomIdent;
145#[cfg(feature = "gecko")]
146pub use crate::gecko_string_cache::Namespace;
147
148#[cfg(feature = "servo")]
149pub use stylo_atoms::Atom;
150
151#[cfg(feature = "servo")]
152#[allow(missing_docs)]
153pub type LocalName = crate::values::GenericAtomIdent<web_atoms::LocalNameStaticSet>;
154#[cfg(feature = "servo")]
155#[allow(missing_docs)]
156pub type Namespace = crate::values::GenericAtomIdent<web_atoms::NamespaceStaticSet>;
157#[cfg(feature = "servo")]
158#[allow(missing_docs)]
159pub type Prefix = crate::values::GenericAtomIdent<web_atoms::PrefixStaticSet>;
160
161pub use style_traits::arc_slice::ArcSlice;
162pub use style_traits::owned_slice::OwnedSlice;
163pub use style_traits::owned_str::OwnedStr;
164
165use std::hash::{BuildHasher, Hash};
166
167#[cfg_attr(feature = "servo", macro_use)]
168pub mod properties;
169
170#[cfg(feature = "gecko")]
171#[allow(unsafe_code)]
172pub mod gecko;
173
174// uses a macro from properties
175#[cfg(feature = "servo")]
176#[allow(unsafe_code)]
177pub mod servo;
178#[cfg(feature = "servo")]
179pub use servo::{animation, attr};
180
181macro_rules! reexport_computed_values {
182    ( $( { $name: ident } )+ ) => {
183        /// Types for [computed values][computed].
184        ///
185        /// [computed]: https://drafts.csswg.org/css-cascade/#computed
186        pub mod computed_values {
187            $(
188                pub use crate::properties::longhands::$name::computed_value as $name;
189            )+
190            // Don't use a side-specific name needlessly:
191            pub use crate::properties::longhands::border_top_style::computed_value as border_style;
192        }
193    }
194}
195longhand_properties_idents!(reexport_computed_values);
196#[cfg(feature = "gecko")]
197use crate::gecko_string_cache::WeakAtom;
198#[cfg(feature = "servo")]
199use stylo_atoms::Atom as WeakAtom;
200
201/// Extension methods for selectors::attr::CaseSensitivity
202pub trait CaseSensitivityExt {
203    /// Return whether two atoms compare equal according to this case sensitivity.
204    fn eq_atom(self, a: &WeakAtom, b: &WeakAtom) -> bool;
205}
206
207impl CaseSensitivityExt for selectors::attr::CaseSensitivity {
208    #[inline]
209    fn eq_atom(self, a: &WeakAtom, b: &WeakAtom) -> bool {
210        match self {
211            selectors::attr::CaseSensitivity::CaseSensitive => a == b,
212            selectors::attr::CaseSensitivity::AsciiCaseInsensitive => a.eq_ignore_ascii_case(b),
213        }
214    }
215}
216
217/// A trait pretty much similar to num_traits::Zero, but without the need of
218/// implementing `Add`.
219pub trait Zero {
220    /// Returns the zero value.
221    fn zero() -> Self;
222
223    /// Returns whether this value is zero.
224    fn is_zero(&self) -> bool;
225}
226
227impl<T> Zero for T
228where
229    T: num_traits::Zero,
230{
231    fn zero() -> Self {
232        <Self as num_traits::Zero>::zero()
233    }
234
235    fn is_zero(&self) -> bool {
236        <Self as num_traits::Zero>::is_zero(self)
237    }
238}
239
240/// A trait implementing a function to tell if the number is zero without a percent
241pub trait ZeroNoPercent {
242    /// So, `0px` should return `true`, but `0%` or `1px` should return `false`
243    fn is_zero_no_percent(&self) -> bool;
244}
245
246/// A trait pretty much similar to num_traits::One, but without the need of
247/// implementing `Mul`.
248pub trait One {
249    /// Reutrns the one value.
250    fn one() -> Self;
251
252    /// Returns whether this value is one.
253    fn is_one(&self) -> bool;
254}
255
256impl<T> One for T
257where
258    T: num_traits::One + PartialEq,
259{
260    fn one() -> Self {
261        <Self as num_traits::One>::one()
262    }
263
264    fn is_one(&self) -> bool {
265        *self == One::one()
266    }
267}
268
269/// An allocation error.
270///
271/// TODO(emilio): Would be nice to have more information here, or for SmallVec
272/// to return the standard error type (and then we can just return that).
273///
274/// But given we use these mostly to bail out and ignore them, it's not a big
275/// deal.
276#[derive(Debug)]
277pub struct AllocErr;
278
279impl From<smallvec::CollectionAllocErr> for AllocErr {
280    #[inline]
281    fn from(_: smallvec::CollectionAllocErr) -> Self {
282        Self
283    }
284}
285
286impl From<std::collections::TryReserveError> for AllocErr {
287    #[inline]
288    fn from(_: std::collections::TryReserveError) -> Self {
289        Self
290    }
291}
292
293/// Shrink the capacity of the collection if needed.
294pub(crate) trait ShrinkIfNeeded {
295    fn shrink_if_needed(&mut self);
296}
297
298/// We shrink the capacity of a collection if we're wasting more than a 25% of
299/// its capacity, and if the collection is arbitrarily big enough
300/// (>= CAPACITY_THRESHOLD entries).
301#[inline]
302fn should_shrink(len: usize, capacity: usize) -> bool {
303    const CAPACITY_THRESHOLD: usize = 64;
304    capacity >= CAPACITY_THRESHOLD && len + capacity / 4 < capacity
305}
306
307impl<K, V, H> ShrinkIfNeeded for std::collections::HashMap<K, V, H>
308where
309    K: Eq + Hash,
310    H: BuildHasher,
311{
312    fn shrink_if_needed(&mut self) {
313        if should_shrink(self.len(), self.capacity()) {
314            self.shrink_to_fit();
315        }
316    }
317}
318
319impl<T, H> ShrinkIfNeeded for std::collections::HashSet<T, H>
320where
321    T: Eq + Hash,
322    H: BuildHasher,
323{
324    fn shrink_if_needed(&mut self) {
325        if should_shrink(self.len(), self.capacity()) {
326            self.shrink_to_fit();
327        }
328    }
329}
330
331// TODO(emilio): Measure and see if we're wasting a lot of memory on Vec /
332// SmallVec, and if so consider shrinking those as well.