servo: Merge #14801 - style: Document and force documentation in a big chunk of the style crate (from emilio:no-missing-docs); r=mbrubeck,Manishearth,Wafflespeanut

Style no forced docs for the properties code and similar, but I ran out of time, and I think it's a nice improvement.

I'd appreciate a fast-ish turn-around time because this is pretty much prone to bitrot.

Source-Repo: https://github.com/servo/servo
Source-Revision: bd67163438317daa711b2411ce302aaf5bf4136a
This commit is contained in:
Emilio Cobos Álvarez 2016-12-31 03:19:02 -08:00
Родитель 199f5d426d
Коммит 89013f9ba5
44 изменённых файлов: 1216 добавлений и 462 удалений

Просмотреть файл

@ -88,7 +88,7 @@ pub fn update_animation_state(constellation_chan: &IpcSender<ConstellationMsg>,
if let Animation::Transition(_, unsafe_node, _, ref frame, _) = running_animation {
script_chan.send(ConstellationControlMsg::TransitionEnd(unsafe_node,
frame.property_animation
.property_name(),
.property_name().into(),
frame.duration))
.unwrap();
}

Просмотреть файл

@ -2005,7 +2005,7 @@ impl Fragment {
}
// See CSS 2.1 § 10.8.1.
let font_metrics = text::font_metrics_for_style(&mut layout_context.font_context(),
self.style.get_font_arc());
self.style.clone_font());
let line_height = text::line_height_from_style(&*self.style, &font_metrics);
InlineMetrics::from_font_metrics(&info.run.font_metrics, line_height)
}
@ -2085,7 +2085,7 @@ impl Fragment {
vertical_align::T::middle => {
let font_metrics =
text::font_metrics_for_style(&mut layout_context.font_context(),
style.get_font_arc());
style.clone_font());
offset += (content_inline_metrics.ascent -
content_inline_metrics.space_below_baseline -
font_metrics.x_height).scale_by(0.5)

Просмотреть файл

@ -1089,7 +1089,7 @@ impl InlineFlow {
return LineMetrics::new(Au(0), Au(0))
}
let font_style = style.get_font_arc();
let font_style = style.clone_font();
let font_metrics = text::font_metrics_for_style(font_context, font_style);
let line_height = text::line_height_from_style(style, &font_metrics);
let inline_metrics = InlineMetrics::from_font_metrics(&font_metrics, line_height);
@ -1112,7 +1112,7 @@ impl InlineFlow {
for inline_context in fragments.iter()
.filter_map(|fragment| fragment.inline_context.as_ref()) {
for node in &inline_context.nodes {
let font_style = node.style.get_font_arc();
let font_style = node.style.clone_font();
let font_metrics = text::font_metrics_for_style(font_context, font_style);
let line_height = text::line_height_from_style(&*node.style, &font_metrics);
let inline_metrics = InlineMetrics::from_font_metrics(&font_metrics, line_height);

Просмотреть файл

@ -154,7 +154,7 @@ impl TextRunScanner {
let word_break;
{
let in_fragment = self.clump.front().unwrap();
let font_style = in_fragment.style().get_font_arc();
let font_style = in_fragment.style().clone_font();
let inherited_text_style = in_fragment.style().get_inheritedtext();
fontgroup = font_context.layout_font_group_for_style(font_style);
compression = match in_fragment.white_space() {

Просмотреть файл

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! CSS transitions and animations.
#![deny(missing_docs)]
use Atom;
use bezier::Bezier;
@ -28,8 +29,9 @@ use values::computed::Time;
/// have to keep track the current iteration and the max iteration count.
#[derive(Debug, Clone)]
pub enum KeyframesIterationState {
/// Infinite iterations, so no need to track a state.
Infinite,
// current, max
/// Current and max iterations.
Finite(u32, u32),
}
@ -192,6 +194,7 @@ pub enum Animation {
}
impl Animation {
/// Mark this animation as expired.
#[inline]
pub fn mark_as_expired(&mut self) {
debug_assert!(!self.is_expired());
@ -201,6 +204,7 @@ impl Animation {
}
}
/// Whether this animation is expired.
#[inline]
pub fn is_expired(&self) -> bool {
match *self {
@ -209,6 +213,7 @@ impl Animation {
}
}
/// The opaque node that owns the animation.
#[inline]
pub fn node(&self) -> &OpaqueNode {
match *self {
@ -217,6 +222,7 @@ impl Animation {
}
}
/// Whether this animation is paused. A transition can never be paused.
#[inline]
pub fn is_paused(&self) -> bool {
match *self {
@ -237,6 +243,7 @@ pub struct AnimationFrame {
pub duration: f64,
}
/// Represents an animation for a given property.
#[derive(Debug, Clone)]
pub struct PropertyAnimation {
property: AnimatedProperty,
@ -245,13 +252,15 @@ pub struct PropertyAnimation {
}
impl PropertyAnimation {
pub fn property_name(&self) -> String {
/// Returns the given property name.
pub fn property_name(&self) -> &'static str {
self.property.name()
}
/// Creates a new property animation for the given transition index and old and new styles.
/// Any number of animations may be returned, from zero (if the property did not animate) to
/// one (for a single transition property) to arbitrarily many (for `all`).
/// Creates a new property animation for the given transition index and old
/// and new styles. Any number of animations may be returned, from zero (if
/// the property did not animate) to one (for a single transition property)
/// to arbitrarily many (for `all`).
pub fn from_transition(transition_index: usize,
old_style: &ComputedValues,
new_style: &mut ComputedValues)
@ -312,6 +321,7 @@ impl PropertyAnimation {
}
}
/// Update the given animation at a given point of progress.
pub fn update(&self, style: &mut ComputedValues, time: f64) {
let progress = match self.timing_function {
TransitionTimingFunction::CubicBezier(p1, p2) => {
@ -336,8 +346,9 @@ impl PropertyAnimation {
self.property.does_animate() && self.duration != Time(0.0)
}
/// Whether this animation has the same end value as another one.
#[inline]
pub fn has_the_same_end_value_as(&self, other: &PropertyAnimation) -> bool {
pub fn has_the_same_end_value_as(&self, other: &Self) -> bool {
self.property.has_the_same_end_value_as(&other.property)
}
}
@ -428,6 +439,8 @@ fn compute_style_for_animation_step(context: &SharedStyleContext,
}
}
/// Triggers animations for a given node looking at the animation property
/// values.
pub fn maybe_start_animations(context: &SharedStyleContext,
new_animations_sender: &Sender<Animation>,
node: OpaqueNode,

Просмотреть файл

@ -2,18 +2,22 @@
* 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/. */
//! Two simple cache data structures.
//! A simple LRU cache.
#![deny(missing_docs)]
use std::collections::hash_map::RandomState;
use std::hash::{Hash, Hasher, BuildHasher};
use std::slice::{Iter, IterMut};
/// A LRU cache used to store a set of at most `n` elements at the same time.
///
/// Currently used for the style sharing candidate cache.
pub struct LRUCache<K, V> {
entries: Vec<(K, V)>,
cache_size: usize,
}
impl<K: PartialEq, V: Clone> LRUCache<K, V> {
/// Create a new LRU cache with `size` elements at most.
pub fn new(size: usize) -> LRUCache<K, V> {
LRUCache {
entries: vec![],
@ -22,6 +26,7 @@ impl<K: PartialEq, V: Clone> LRUCache<K, V> {
}
#[inline]
/// Touch a given position, and put it in the last item on the list.
pub fn touch(&mut self, pos: usize) -> &V {
let last_index = self.entries.len() - 1;
if pos != last_index {
@ -31,14 +36,17 @@ impl<K: PartialEq, V: Clone> LRUCache<K, V> {
&self.entries[last_index].1
}
/// Iterate over the contents of this cache.
pub fn iter(&self) -> Iter<(K, V)> {
self.entries.iter()
}
/// Iterate mutably over the contents of this cache.
pub fn iter_mut(&mut self) -> IterMut<(K, V)> {
self.entries.iter_mut()
}
/// Insert a given key and value in the cache.
pub fn insert(&mut self, key: K, val: V) {
if self.entries.len() == self.cache_size {
self.entries.remove(0);
@ -46,6 +54,7 @@ impl<K: PartialEq, V: Clone> LRUCache<K, V> {
self.entries.push((key, val));
}
/// Try to find a key in the cache.
pub fn find(&mut self, key: &K) -> Option<V> {
match self.entries.iter().position(|&(ref k, _)| key == k) {
Some(pos) => Some(self.touch(pos).clone()),
@ -53,7 +62,11 @@ impl<K: PartialEq, V: Clone> LRUCache<K, V> {
}
}
pub fn find_or_create<F>(&mut self, key: K, mut blk: F) -> V where F: FnMut() -> V {
/// Try to find a given key, or create a given item with that key executing
/// `blk`.
pub fn find_or_create<F>(&mut self, key: K, mut blk: F) -> V
where F: FnMut() -> V,
{
match self.entries.iter().position(|&(ref k, _)| *k == key) {
Some(pos) => self.touch(pos).clone(),
None => {
@ -64,61 +77,8 @@ impl<K: PartialEq, V: Clone> LRUCache<K, V> {
}
}
/// Evict all elements from the cache.
pub fn evict_all(&mut self) {
self.entries.clear();
}
}
pub struct SimpleHashCache<K, V> {
entries: Vec<Option<(K, V)>>,
random: RandomState,
}
impl<K: Clone + Eq + Hash, V: Clone> SimpleHashCache<K, V> {
pub fn new(cache_size: usize) -> SimpleHashCache<K, V> {
SimpleHashCache {
entries: vec![None; cache_size],
random: RandomState::new(),
}
}
#[inline]
fn to_bucket(&self, h: usize) -> usize {
h % self.entries.len()
}
#[inline]
fn bucket_for_key<Q: Hash>(&self, key: &Q) -> usize {
let mut hasher = self.random.build_hasher();
key.hash(&mut hasher);
self.to_bucket(hasher.finish() as usize)
}
pub fn insert(&mut self, key: K, value: V) {
let bucket_index = self.bucket_for_key(&key);
self.entries[bucket_index] = Some((key, value));
}
pub fn find<Q>(&self, key: &Q) -> Option<V> where Q: PartialEq<K> + Hash + Eq {
let bucket_index = self.bucket_for_key(key);
match self.entries[bucket_index] {
Some((ref existing_key, ref value)) if key == existing_key => Some((*value).clone()),
_ => None,
}
}
pub fn find_or_create<F>(&mut self, key: K, mut blk: F) -> V where F: FnMut() -> V {
if let Some(value) = self.find(&key) {
return value;
}
let value = blk();
self.insert(key, value.clone());
value
}
pub fn evict_all(&mut self) {
for slot in &mut self.entries {
*slot = None
}
}
}

Просмотреть файл

@ -4,6 +4,8 @@
//! Per-node data used in style calculation.
#![deny(missing_docs)]
use dom::TElement;
use properties::ComputedValues;
use properties::longhands::display::computed_value as display;
@ -19,6 +21,9 @@ use std::sync::Arc;
use stylist::Stylist;
use thread_state;
/// The structure that represents the result of style computation. This is
/// effectively a tuple of rules and computed values, that is, the rule node,
/// and the result of computing that rule node's rules, the `ComputedValues`.
#[derive(Clone)]
pub struct ComputedStyle {
/// The rule node representing the ordered list of rules matched for this
@ -31,6 +36,7 @@ pub struct ComputedStyle {
}
impl ComputedStyle {
/// Trivially construct a new `ComputedStyle`.
pub fn new(rules: StrongRuleNode, values: Arc<ComputedValues>) -> Self {
ComputedStyle {
rules: rules,
@ -49,10 +55,18 @@ impl fmt::Debug for ComputedStyle {
type PseudoStylesInner = HashMap<PseudoElement, ComputedStyle,
BuildHasherDefault<::fnv::FnvHasher>>;
/// A set of styles for a given element's pseudo-elements.
///
/// This is a map from pseudo-element to `ComputedStyle`.
///
/// TODO(emilio): This should probably be a small array by default instead of a
/// full-blown `HashMap`.
#[derive(Clone, Debug)]
pub struct PseudoStyles(PseudoStylesInner);
impl PseudoStyles {
/// Construct an empty set of `PseudoStyles`.
pub fn empty() -> Self {
PseudoStyles(HashMap::with_hasher(Default::default()))
}
@ -71,11 +85,14 @@ impl DerefMut for PseudoStyles {
/// pseudo-elements.
#[derive(Clone, Debug)]
pub struct ElementStyles {
/// The element's style.
pub primary: ComputedStyle,
/// The map of styles for the element's pseudos.
pub pseudos: PseudoStyles,
}
impl ElementStyles {
/// Trivially construct a new `ElementStyles`.
pub fn new(primary: ComputedStyle) -> Self {
ElementStyles {
primary: primary,
@ -83,6 +100,7 @@ impl ElementStyles {
}
}
/// Whether this element `display` value is `none`.
pub fn is_display_none(&self) -> bool {
self.primary.values.get_box().clone_display() == display::T::none
}
@ -127,7 +145,9 @@ impl DescendantRestyleHint {
/// to provide more type safety while propagating restyle hints down the tree.
#[derive(Clone, Debug)]
pub struct StoredRestyleHint {
/// Whether this element should be restyled during the traversal.
pub restyle_self: bool,
/// Whether the descendants of this element need to be restyled.
pub descendants: DescendantRestyleHint,
}
@ -140,6 +160,7 @@ impl StoredRestyleHint {
}
}
/// Creates an empty `StoredRestyleHint`.
pub fn empty() -> Self {
StoredRestyleHint {
restyle_self: false,
@ -147,6 +168,8 @@ impl StoredRestyleHint {
}
}
/// Creates a restyle hint that forces the whole subtree to be restyled,
/// including the element.
pub fn subtree() -> Self {
StoredRestyleHint {
restyle_self: true,
@ -154,10 +177,12 @@ impl StoredRestyleHint {
}
}
/// Whether the restyle hint is empty (nothing requires to be restyled).
pub fn is_empty(&self) -> bool {
!self.restyle_self && self.descendants == DescendantRestyleHint::Empty
}
/// Insert another restyle hint, effectively resulting in the union of both.
pub fn insert(&mut self, other: &Self) {
self.restyle_self = self.restyle_self || other.restyle_self;
self.descendants = self.descendants.union(other.descendants);
@ -185,11 +210,11 @@ impl From<RestyleHint> for StoredRestyleHint {
}
}
// We really want to store an Option<Snapshot> here, but we can't drop Gecko
// Snapshots off-main-thread. So we make a convenient little wrapper to provide
// the semantics of Option<Snapshot>, while deferring the actual drop.
static NO_SNAPSHOT: Option<Snapshot> = None;
/// We really want to store an Option<Snapshot> here, but we can't drop Gecko
/// Snapshots off-main-thread. So we make a convenient little wrapper to provide
/// the semantics of Option<Snapshot>, while deferring the actual drop.
#[derive(Debug)]
pub struct SnapshotOption {
snapshot: Option<Snapshot>,
@ -197,6 +222,7 @@ pub struct SnapshotOption {
}
impl SnapshotOption {
/// An empty snapshot.
pub fn empty() -> Self {
SnapshotOption {
snapshot: None,
@ -204,11 +230,13 @@ impl SnapshotOption {
}
}
/// Destroy this snapshot.
pub fn destroy(&mut self) {
self.destroyed = true;
debug_assert!(self.is_none());
}
/// Ensure a snapshot is available and return a mutable reference to it.
pub fn ensure<F: FnOnce() -> Snapshot>(&mut self, create: F) -> &mut Snapshot {
debug_assert!(thread_state::get().is_layout());
if self.is_none() {
@ -234,7 +262,12 @@ impl Deref for SnapshotOption {
/// Transient data used by the restyle algorithm. This structure is instantiated
/// either before or during restyle traversal, and is cleared at the end of node
/// processing.
///
/// TODO(emilio): Tell bholley to document this more accurately. I can try (and
/// the fields are certainly mostly self-explanatory), but it's better if he
/// does, to avoid any misconception.
#[derive(Debug)]
#[allow(missing_docs)]
pub struct RestyleData {
pub styles: ElementStyles,
pub hint: StoredRestyleHint,
@ -254,8 +287,8 @@ impl RestyleData {
}
}
/// Expands the snapshot (if any) into a restyle hint. Returns true if later siblings
/// must be restyled.
/// Expands the snapshot (if any) into a restyle hint. Returns true if later
/// siblings must be restyled.
pub fn expand_snapshot<E: TElement>(&mut self, element: E, stylist: &Stylist) -> bool {
if self.snapshot.is_none() {
return false;
@ -281,14 +314,17 @@ impl RestyleData {
later_siblings
}
/// Return if the element style's are up to date.
pub fn has_current_styles(&self) -> bool {
!(self.hint.restyle_self || self.recascade || self.snapshot.is_some())
}
/// Returns the element styles.
pub fn styles(&self) -> &ElementStyles {
&self.styles
}
/// Returns a mutable reference to the element styles.
pub fn styles_mut(&mut self) -> &mut ElementStyles {
&mut self.styles
}
@ -317,12 +353,18 @@ impl RestyleData {
/// safety.
#[derive(Debug)]
pub enum ElementData {
/// This is the first styling for this element.
Initial(Option<ElementStyles>),
/// This element has been restyled already, and all the relevant data is
/// inside the `RestyleData`.
Restyle(RestyleData),
/// This element has already been restyled, and only keeps its styles
/// around.
Persistent(ElementStyles),
}
impl ElementData {
/// Trivially construct an ElementData.
pub fn new(existing: Option<ElementStyles>) -> Self {
if let Some(s) = existing {
ElementData::Persistent(s)
@ -331,6 +373,7 @@ impl ElementData {
}
}
/// Return whether this data is from an initial restyle.
pub fn is_initial(&self) -> bool {
match *self {
ElementData::Initial(_) => true,
@ -338,6 +381,7 @@ impl ElementData {
}
}
/// Return whether this data is from an element that hasn't been restyled.
pub fn is_unstyled_initial(&self) -> bool {
match *self {
ElementData::Initial(None) => true,
@ -345,6 +389,8 @@ impl ElementData {
}
}
/// Return whether this data is from an element whose first restyle has just
/// been done.
pub fn is_styled_initial(&self) -> bool {
match *self {
ElementData::Initial(Some(_)) => true,
@ -352,6 +398,8 @@ impl ElementData {
}
}
/// Returns true if this element is being restyled and has been styled
/// before.
pub fn is_restyle(&self) -> bool {
match *self {
ElementData::Restyle(_) => true,
@ -359,6 +407,7 @@ impl ElementData {
}
}
/// Returns the `RestyleData` if it exists.
pub fn as_restyle(&self) -> Option<&RestyleData> {
match *self {
ElementData::Restyle(ref x) => Some(x),
@ -366,6 +415,7 @@ impl ElementData {
}
}
/// Returns a mutable reference to the RestyleData, if it exists.
pub fn as_restyle_mut(&mut self) -> Option<&mut RestyleData> {
match *self {
ElementData::Restyle(ref mut x) => Some(x),
@ -373,6 +423,7 @@ impl ElementData {
}
}
/// Returns whether this element's style is persistent.
pub fn is_persistent(&self) -> bool {
match *self {
ElementData::Persistent(_) => true,
@ -428,6 +479,7 @@ impl ElementData {
*self = ElementData::Persistent(styles);
}
/// Return the restyle damage (if any).
pub fn damage(&self) -> RestyleDamage {
use self::ElementData::*;
match *self {
@ -443,8 +495,8 @@ impl ElementData {
}
}
// A version of the above, with the assertions replaced with warnings to
// be more robust in corner-cases. This will go away soon.
/// A version of the above, with the assertions replaced with warnings to
/// be more robust in corner-cases. This will go away soon.
#[cfg(feature = "gecko")]
pub fn damage_sloppy(&self) -> RestyleDamage {
use self::ElementData::*;
@ -476,6 +528,7 @@ impl ElementData {
}
}
/// Get the element styles, if any.
pub fn get_styles(&self) -> Option<&ElementStyles> {
use self::ElementData::*;
match *self {
@ -485,10 +538,12 @@ impl ElementData {
}
}
/// Get the element styles. Panic if the element has never been styled.
pub fn styles(&self) -> &ElementStyles {
self.get_styles().expect("Calling styles() on unstyled ElementData")
}
/// Get a mutable reference to the element styles, if any.
pub fn get_styles_mut(&mut self) -> Option<&mut ElementStyles> {
use self::ElementData::*;
match *self {
@ -498,10 +553,14 @@ impl ElementData {
}
}
/// Get a mutable reference to the element styles. Panic if the element has
/// never been styled.
pub fn styles_mut(&mut self) -> &mut ElementStyles {
self.get_styles_mut().expect("Calling styles_mut() on unstyled ElementData")
}
/// Finishes the styling of the element, effectively setting the style in
/// the data.
pub fn finish_styling(&mut self, styles: ElementStyles, damage: RestyleDamage) {
use self::ElementData::*;
match *self {

Просмотреть файл

@ -5,6 +5,7 @@
//! Types and traits used to access the DOM from style calculation.
#![allow(unsafe_code)]
#![deny(missing_docs)]
use {Atom, Namespace, LocalName};
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
@ -48,15 +49,24 @@ impl OpaqueNode {
/// We avoid exposing the full type id, since computing it in the general case
/// would be difficult for Gecko nodes.
pub trait NodeInfo {
/// Whether this node is an element.
fn is_element(&self) -> bool;
/// Whether this node is a text node.
fn is_text_node(&self) -> bool;
// Comments, doctypes, etc are ignored by layout algorithms.
/// Whether this node needs layout.
///
/// Comments, doctypes, etc are ignored by layout algorithms.
fn needs_layout(&self) -> bool { self.is_element() || self.is_text_node() }
}
/// A node iterator that only returns node that don't need layout.
pub struct LayoutIterator<T>(pub T);
impl<T, I> Iterator for LayoutIterator<T> where T: Iterator<Item=I>, I: NodeInfo {
impl<T, I> Iterator for LayoutIterator<T>
where T: Iterator<Item=I>,
I: NodeInfo,
{
type Item = I;
fn next(&mut self) -> Option<I> {
loop {
@ -69,11 +79,22 @@ impl<T, I> Iterator for LayoutIterator<T> where T: Iterator<Item=I>, I: NodeInfo
}
}
/// The `TNode` trait. This is the main generic trait over which the style
/// system can be implemented.
pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo {
/// The concrete `TElement` type.
type ConcreteElement: TElement<ConcreteNode = Self>;
/// A concrete children iterator type in order to iterate over the `Node`s.
///
/// TODO(emilio): We should eventually replace this with the `impl Trait`
/// syntax.
type ConcreteChildrenIterator: Iterator<Item = Self>;
/// Convert this node in an `UnsafeNode`.
fn to_unsafe(&self) -> UnsafeNode;
/// Get a node back from an `UnsafeNode`.
unsafe fn from_unsafe(n: &UnsafeNode) -> Self;
/// Returns an iterator over this node's children.
@ -82,24 +103,35 @@ pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo {
/// Converts self into an `OpaqueNode`.
fn opaque(&self) -> OpaqueNode;
/// Get this node's parent element if present.
fn parent_element(&self) -> Option<Self::ConcreteElement> {
self.parent_node().and_then(|n| n.as_element())
}
/// A debug id, only useful, mm... for debugging.
fn debug_id(self) -> usize;
/// Get this node as an element, if it's one.
fn as_element(&self) -> Option<Self::ConcreteElement>;
/// Whether this node needs to be laid out on viewport size change.
fn needs_dirty_on_viewport_size_changed(&self) -> bool;
/// Mark this node as needing layout on viewport size change.
unsafe fn set_dirty_on_viewport_size_changed(&self);
/// Whether this node can be fragmented. This is used for multicol, and only
/// for Servo.
fn can_be_fragmented(&self) -> bool;
/// Set whether this node can be fragmented.
unsafe fn set_can_be_fragmented(&self, value: bool);
/// Get this node's parent node.
fn parent_node(&self) -> Option<Self>;
/// Whether this node is in the document right now needed to clear the
/// restyle data appropriately on some forced restyles.
fn is_in_doc(&self) -> bool;
}
@ -187,14 +219,20 @@ fn fmt_subtree<F, N: TNode>(f: &mut fmt::Formatter, stringify: &F, n: N, indent:
Ok(())
}
/// A trait used to synthesize presentational hints for HTML element attributes.
pub trait PresentationalHintsSynthetizer {
/// Generate the proper applicable declarations due to presentational hints,
/// and insert them into `hints`.
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
where V: Push<ApplicableDeclarationBlock>;
}
/// The element trait, the main abstraction the style crate acts over.
pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + PresentationalHintsSynthetizer {
/// The concrete node type.
type ConcreteNode: TNode<ConcreteElement = Self>;
/// Get this element as a node.
fn as_node(&self) -> Self::ConcreteNode;
/// While doing a reflow, the element at the root has no parent, as far as we're
@ -207,16 +245,25 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre
}
}
/// Get this element's style attribute.
fn style_attribute(&self) -> Option<&Arc<RwLock<PropertyDeclarationBlock>>>;
/// Get this element's state, for non-tree-structural pseudos.
fn get_state(&self) -> ElementState;
/// Whether this element has an attribute with a given namespace.
fn has_attr(&self, namespace: &Namespace, attr: &LocalName) -> bool;
/// Whether an attribute value equals `value`.
fn attr_equals(&self, namespace: &Namespace, attr: &LocalName, value: &Atom) -> bool;
/// XXX: It's a bit unfortunate we need to pass the current computed values
/// as an argument here, but otherwise Servo would crash due to double
/// borrows to return it.
/// Get the pre-existing style to calculate restyle damage (change hints).
///
/// This needs to be generic since it varies between Servo and Gecko.
///
/// XXX(emilio): It's a bit unfortunate we need to pass the current computed
/// values as an argument here, but otherwise Servo would crash due to
/// double borrows to return it.
fn existing_style_for_restyle_damage<'a>(&'a self,
current_computed_values: Option<&'a Arc<ComputedValues>>,
pseudo: Option<&PseudoElement>)
@ -270,11 +317,13 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre
/// about our parallel traversal. However, there are certain situations
/// (including but not limited to the traversal) where we need to send DOM
/// objects to other threads.
///
/// That's the reason why `SendNode` exists.
#[derive(Clone, Debug, PartialEq)]
pub struct SendNode<N: TNode>(N);
unsafe impl<N: TNode> Send for SendNode<N> {}
impl<N: TNode> SendNode<N> {
/// Unsafely construct a SendNode.
pub unsafe fn new(node: N) -> Self {
SendNode(node)
}
@ -286,10 +335,13 @@ impl<N: TNode> Deref for SendNode<N> {
}
}
/// Same reason as for the existence of SendNode, SendElement does the proper
/// things for a given `TElement`.
#[derive(Debug, PartialEq)]
pub struct SendElement<E: TElement>(E);
unsafe impl<E: TElement> Send for SendElement<E> {}
impl<E: TElement> SendElement<E> {
/// Unsafely construct a SendElement.
pub unsafe fn new(el: E) -> Self {
SendElement(el)
}

Просмотреть файл

@ -182,15 +182,24 @@ pub fn arc_ptr_eq<T: 'static>(a: &Arc<T>, b: &Arc<T>) -> bool {
(a as *const T) == (b as *const T)
}
pub fn serialize_comma_separated_list<W, T>(dest: &mut W, list: &[T])
-> fmt::Result where W: fmt::Write, T: ToCss {
if list.len() > 0 {
for item in &list[..list.len()-1] {
try!(item.to_css(dest));
try!(write!(dest, ", "));
}
list[list.len()-1].to_css(dest)
} else {
Ok(())
/// Serializes as CSS a comma-separated list of any `T` that supports being
/// serialized as CSS.
pub fn serialize_comma_separated_list<W, T>(dest: &mut W,
list: &[T])
-> fmt::Result
where W: fmt::Write,
T: ToCss,
{
if list.is_empty() {
return Ok(());
}
try!(list[0].to_css(dest));
for item in list.iter().skip(1) {
try!(write!(dest, ", "));
try!(item.to_css(dest));
}
Ok(())
}

Просмотреть файл

@ -20,6 +20,8 @@
//! easy to grep for. At the time of this writing, there is no other unsafe
//! code in the parallel traversal.
#![deny(missing_docs)]
use dom::{OpaqueNode, SendNode, TElement, TNode};
use rayon;
use scoped_tls::ScopedTLS;
@ -28,8 +30,12 @@ use std::sync::atomic::Ordering;
use traversal::{DomTraversal, PerLevelTraversalData, PreTraverseToken};
use traversal::{STYLE_SHARING_CACHE_HITS, STYLE_SHARING_CACHE_MISSES};
/// The chunk size used to split the parallel traversal nodes.
///
/// We send each `CHUNK_SIZE` nodes as a different work unit to the work queue.
pub const CHUNK_SIZE: usize = 64;
/// A parallel top down traversal, generic over `D`.
#[allow(unsafe_code)]
pub fn traverse_dom<N, D>(traversal: &D,
root: N::ConcreteElement,
@ -37,7 +43,7 @@ pub fn traverse_dom<N, D>(traversal: &D,
token: PreTraverseToken,
queue: &rayon::ThreadPool)
where N: TNode,
D: DomTraversal<N>
D: DomTraversal<N>,
{
if opts::get().style_sharing_stats {
STYLE_SHARING_CACHE_HITS.store(0, Ordering::SeqCst);
@ -181,7 +187,7 @@ fn bottom_up_dom<N, D>(traversal: &D,
root: OpaqueNode,
mut node: N)
where N: TNode,
D: DomTraversal<N>
D: DomTraversal<N>,
{
loop {
// Perform the appropriate operation.

Просмотреть файл

@ -405,9 +405,10 @@ pub fn append_serialization<'a, W, I, N>(dest: &mut W,
importance: Importance,
is_first_serialization: &mut bool)
-> fmt::Result
where W: fmt::Write,
I: Iterator<Item=&'a PropertyDeclaration>,
N: ToCss {
where W: fmt::Write,
I: Iterator<Item=&'a PropertyDeclaration>,
N: ToCss
{
try!(handle_first_serialization(dest, is_first_serialization));
// Overflow does not behave like a normal shorthand. When overflow-x and overflow-y are not of equal
@ -525,4 +526,3 @@ pub fn parse_property_declaration_list(context: &ParserContext, input: &mut Pars
super::deduplicate_property_declarations(&mut block);
block
}

Просмотреть файл

@ -73,16 +73,21 @@
use values::{computed, specified};
${caller.body()}
}
/// The definition of the computed value for ${name}.
pub mod computed_value {
pub use super::single_value::computed_value as single_value;
pub use self::single_value::T as SingleComputedValue;
/// The computed value, effectively a list of single values.
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct T(pub Vec<single_value::T>);
}
impl ToCss for computed_value::T {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write,
{
let mut iter = self.0.iter();
if let Some(val) = iter.next() {
try!(val.to_css(dest));
@ -101,12 +106,15 @@
}
}
/// The specified value of ${name}.
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedValue(pub Vec<single_value::SpecifiedValue>);
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write,
{
let mut iter = self.0.iter();
if let Some(val) = iter.next() {
try!(val.to_css(dest));
@ -405,7 +413,11 @@
}
impl<'a> LonghandsToSerialize<'a> {
pub fn from_iter<I: Iterator<Item=&'a PropertyDeclaration>>(iter: I) -> Result<Self, ()> {
/// Tries to get a serializable set of longhands given a set of
/// property declarations.
pub fn from_iter<I>(iter: I) -> Result<Self, ()>
where I: Iterator<Item=&'a PropertyDeclaration>,
{
// Define all of the expected variables that correspond to the shorthand
% for sub_property in shorthand.sub_properties:
let mut ${sub_property.ident} = None;
@ -446,7 +458,9 @@
}
impl<'a> ToCss for LonghandsToSerialize<'a> {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write,
{
let mut all_flags = SerializeFlags::all();
let mut with_variables = false;
% for sub_property in shorthand.sub_properties:
@ -477,7 +491,10 @@
}
pub fn parse(context: &ParserContext, input: &mut Parser,
/// Parse the given shorthand and fill the result into the
/// `declarations` vector.
pub fn parse(context: &ParserContext,
input: &mut Parser,
declarations: &mut Vec<PropertyDeclaration>)
-> Result<(), ()> {
input.look_for_var_functions();

Просмотреть файл

@ -32,14 +32,18 @@ use values::computed::ToComputedValue;
/// A given transition property, that is either `All`, or an animatable
/// property.
// NB: This needs to be here because it needs all the longhands generated
// beforehand.
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum TransitionProperty {
/// All, any animatable property changing should generate a transition.
All,
% for prop in data.longhands:
% if prop.animatable:
/// ${prop.name}
${prop.camel_case},
% endif
% endfor
@ -55,6 +59,7 @@ impl TransitionProperty {
% endfor
}
/// Parse a transition-property value.
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
match_ignore_ascii_case! { try!(input.expect_ident()),
"all" => Ok(TransitionProperty::All),
@ -67,6 +72,7 @@ impl TransitionProperty {
}
}
/// Get a transition property from a property declaration.
pub fn from_declaration(declaration: &PropertyDeclaration) -> Option<Self> {
match *declaration {
% for prop in data.longhands:
@ -81,7 +87,9 @@ impl TransitionProperty {
}
impl ToCss for TransitionProperty {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write,
{
match *self {
TransitionProperty::All => dest.write_str("all"),
% for prop in data.longhands:
@ -93,11 +101,14 @@ impl ToCss for TransitionProperty {
}
}
/// An animated property interpolation between two computed values for that
/// property.
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum AnimatedProperty {
% for prop in data.longhands:
% if prop.animatable:
/// ${prop.name}
${prop.camel_case}(longhands::${prop.ident}::computed_value::T,
longhands::${prop.ident}::computed_value::T),
% endif
@ -105,16 +116,19 @@ pub enum AnimatedProperty {
}
impl AnimatedProperty {
pub fn name(&self) -> String {
/// Get the name of this property.
pub fn name(&self) -> &'static str {
match *self {
% for prop in data.longhands:
% if prop.animatable:
AnimatedProperty::${prop.camel_case}(..) => "${prop.name}".to_owned(),
AnimatedProperty::${prop.camel_case}(..) => "${prop.name}",
% endif
% endfor
}
}
/// Whether this interpolation does animate, that is, whether the start and
/// end values are different.
pub fn does_animate(&self) -> bool {
match *self {
% for prop in data.longhands:
@ -125,7 +139,8 @@ impl AnimatedProperty {
}
}
pub fn has_the_same_end_value_as(&self, other: &AnimatedProperty) -> bool {
/// Whether an animated property has the same end value as another.
pub fn has_the_same_end_value_as(&self, other: &Self) -> bool {
match (self, other) {
% for prop in data.longhands:
% if prop.animatable:
@ -139,6 +154,8 @@ impl AnimatedProperty {
}
}
/// Update `style` with the proper computed style corresponding to this
/// animation at `progress`.
pub fn update(&self, style: &mut ComputedValues, progress: f64) {
match *self {
% for prop in data.longhands:
@ -153,6 +170,8 @@ impl AnimatedProperty {
}
}
/// Get an animatable value from a transition-property, an old style, and a
/// new style.
pub fn from_transition_property(transition_property: &TransitionProperty,
old_style: &ComputedValues,
new_style: &ComputedValues)
@ -188,12 +207,15 @@ impl AnimatedProperty {
pub enum AnimationValue {
% for prop in data.longhands:
% if prop.animatable:
/// ${prop.name}
${prop.camel_case}(longhands::${prop.ident}::computed_value::T),
% endif
% endfor
}
impl AnimationValue {
/// "Uncompute" this animation value in order to be used inside the CSS
/// cascade.
pub fn uncompute(&self) -> PropertyDeclaration {
use properties::{longhands, DeclaredValue};
match *self {
@ -234,6 +256,7 @@ impl Interpolate for AnimationValue {
///
/// [interpolated-types]: https://drafts.csswg.org/css-transitions/#interpolated-types
pub trait Interpolate: Sized {
/// Interpolate a value with another for a given property.
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()>;
}
@ -249,6 +272,7 @@ impl<T: RepeatableListInterpolate> Interpolate for Vec<T> {
}).collect()
}
}
/// https://drafts.csswg.org/css-transitions/#animtype-number
impl Interpolate for Au {
#[inline]
@ -257,7 +281,9 @@ impl Interpolate for Au {
}
}
impl <T> Interpolate for Option<T> where T: Interpolate {
impl <T> Interpolate for Option<T>
where T: Interpolate,
{
#[inline]
fn interpolate(&self, other: &Option<T>, progress: f64) -> Result<Option<T>, ()> {
match (self, other) {
@ -431,7 +457,7 @@ impl Interpolate for CalcLengthOrPercentage {
other: Option<T>,
progress: f64)
-> Result<Option<T>, ()>
where T: Default + Interpolate
where T: Default + Interpolate,
{
match (this, other) {
(None, None) => Ok(None),
@ -919,27 +945,36 @@ impl Interpolate for LengthOrNone {
}
}
/// A 2d matrix for interpolation.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct InnerMatrix2D {
pub m11: CSSFloat, pub m12: CSSFloat,
pub m21: CSSFloat, pub m22: CSSFloat,
}
/// A 2d translation function.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Translate2D(f32, f32);
/// A 2d scale function.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Scale2D(f32, f32);
/// A decomposed 2d matrix.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct MatrixDecomposed2D {
/// The translation function.
pub translate: Translate2D,
/// The scale function.
pub scale: Scale2D,
/// The rotation angle.
pub angle: f32,
/// The inner matrix.
pub matrix: InnerMatrix2D,
}
@ -1143,33 +1178,44 @@ impl Interpolate for LengthOrNone {
}
}
/// A 3d translation.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Translate3D(f32, f32, f32);
/// A 3d scale function.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Scale3D(f32, f32, f32);
/// A 3d skew function.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Skew(f32, f32, f32);
/// A 3d perspective transformation.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Perspective(f32, f32, f32, f32);
/// A quaternion used to represent a rotation.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Quaternion(f32, f32, f32, f32);
/// A decomposed 3d matrix.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct MatrixDecomposed3D {
/// A translation function.
pub translate: Translate3D,
/// A scale function.
pub scale: Scale3D,
/// The skew component of the transformation.
pub skew: Skew,
/// The perspective component of the transformation.
pub perspective: Perspective,
/// The quaternion used to represent the rotation.
pub quaternion: Quaternion,
}
@ -1513,7 +1559,7 @@ impl Interpolate for LengthOrNone {
self.m43 != 0.0 || self.m44 != 1.0
}
pub fn determinant(&self) -> CSSFloat {
fn determinant(&self) -> CSSFloat {
self.m14 * self.m23 * self.m32 * self.m41 -
self.m13 * self.m24 * self.m32 * self.m41 -
self.m14 * self.m22 * self.m33 * self.m41 +

Просмотреть файл

@ -87,89 +87,102 @@ ${helpers.predefined_type("background-color", "CSSColor",
</%helpers:vector_longhand>
<%helpers:vector_longhand name="background-position-x" animatable="True">
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
use values::specified::position::HorizontalPosition;
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
use values::specified::position::HorizontalPosition;
pub mod computed_value {
use values::computed::position::HorizontalPosition;
use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
#[allow(missing_docs)]
pub mod computed_value {
use values::computed::position::HorizontalPosition;
use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
pub type T = HorizontalPosition;
}
pub type T = HorizontalPosition;
}
pub type SpecifiedValue = HorizontalPosition;
#[allow(missing_docs)]
pub type SpecifiedValue = HorizontalPosition;
#[inline]
pub fn get_initial_value() -> computed_value::T {
use values::computed::position::HorizontalPosition;
HorizontalPosition(computed::LengthOrPercentage::Percentage(0.0))
#[inline]
#[allow(missing_docs)]
pub fn get_initial_value() -> computed_value::T {
use values::computed::position::HorizontalPosition;
HorizontalPosition(computed::LengthOrPercentage::Percentage(0.0))
}
#[inline]
#[allow(missing_docs)]
pub fn get_initial_specified_value() -> SpecifiedValue {
use values::specified::position::Keyword;
HorizontalPosition {
keyword: Some(Keyword::Left),
position: None,
}
#[inline]
pub fn get_initial_specified_value() -> SpecifiedValue {
use values::specified::position::Keyword;
HorizontalPosition {
keyword: Some(Keyword::Left),
position: None,
}
}
#[inline]
pub fn get_initial_position_value() -> SpecifiedValue {
use values::specified::{LengthOrPercentage, Percentage};
HorizontalPosition {
keyword: None,
position: Some(LengthOrPercentage::Percentage(Percentage(0.0))),
}
}
#[inline]
#[allow(missing_docs)]
pub fn get_initial_position_value() -> SpecifiedValue {
use values::specified::{LengthOrPercentage, Percentage};
HorizontalPosition {
keyword: None,
position: Some(LengthOrPercentage::Percentage(Percentage(0.0))),
}
}
pub fn parse(context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
HorizontalPosition::parse(context, input)
}
#[allow(missing_docs)]
pub fn parse(context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
HorizontalPosition::parse(context, input)
}
</%helpers:vector_longhand>
<%helpers:vector_longhand name="background-position-y" animatable="True">
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
use values::specified::position::VerticalPosition;
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
use values::specified::position::VerticalPosition;
pub mod computed_value {
use values::computed::position::VerticalPosition;
use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
#[allow(missing_docs)]
pub mod computed_value {
use values::computed::position::VerticalPosition;
use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
pub type T = VerticalPosition;
}
pub type T = VerticalPosition;
}
pub type SpecifiedValue = VerticalPosition;
#[allow(missing_docs)]
pub type SpecifiedValue = VerticalPosition;
#[inline]
pub fn get_initial_value() -> computed_value::T {
use values::computed::position::VerticalPosition;
VerticalPosition(computed::LengthOrPercentage::Percentage(0.0))
#[inline]
#[allow(missing_docs)]
pub fn get_initial_value() -> computed_value::T {
use values::computed::position::VerticalPosition;
VerticalPosition(computed::LengthOrPercentage::Percentage(0.0))
}
#[inline]
#[allow(missing_docs)]
pub fn get_initial_specified_value() -> SpecifiedValue {
use values::specified::position::Keyword;
VerticalPosition {
keyword: Some(Keyword::Top),
position: None,
}
#[inline]
pub fn get_initial_specified_value() -> SpecifiedValue {
use values::specified::position::Keyword;
VerticalPosition {
keyword: Some(Keyword::Top),
position: None,
}
}
#[inline]
pub fn get_initial_position_value() -> SpecifiedValue {
use values::specified::{LengthOrPercentage, Percentage};
VerticalPosition {
keyword: None,
position: Some(LengthOrPercentage::Percentage(Percentage(0.0))),
}
}
#[inline]
#[allow(missing_docs)]
pub fn get_initial_position_value() -> SpecifiedValue {
use values::specified::{LengthOrPercentage, Percentage};
VerticalPosition {
keyword: None,
position: Some(LengthOrPercentage::Percentage(Percentage(0.0))),
}
}
pub fn parse(context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
VerticalPosition::parse(context, input)
}
#[inline]
#[allow(missing_docs)]
pub fn parse(context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
VerticalPosition::parse(context, input)
}
</%helpers:vector_longhand>
${helpers.single_keyword("background-repeat",
@ -199,6 +212,7 @@ ${helpers.single_keyword("background-origin",
use style_traits::ToCss;
use values::HasViewportPercentage;
#[allow(missing_docs)]
pub mod computed_value {
use values::computed::LengthOrPercentageOrAuto;
use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
@ -254,6 +268,7 @@ ${helpers.single_keyword("background-origin",
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct ExplicitSize {
pub width: specified::LengthOrPercentageOrAuto,
pub height: specified::LengthOrPercentageOrAuto,

Просмотреть файл

@ -46,7 +46,8 @@
impl ToCss for T {
fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
where W: ::std::fmt::Write {
where W: ::std::fmt::Write,
{
match *self {
% for value in values:
T::${to_rust_ident(value)} => dest.write_str("${value}"),
@ -55,9 +56,14 @@
}
}
}
#[inline] pub fn get_initial_value() -> computed_value::T {
/// The initial display value.
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T::${to_rust_ident(values[0])}
}
/// Parse a display value.
pub fn parse(_context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
match_ignore_ascii_case! { try!(input.expect_ident()),
@ -144,119 +150,128 @@ ${helpers.single_keyword("clear", "none left right both",
</%helpers:longhand>
<%helpers:longhand name="vertical-align"
animatable="True">
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
<%helpers:longhand name="vertical-align" animatable="True">
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
<% vertical_align = data.longhands_by_name["vertical-align"] %>
<% vertical_align.keyword = Keyword("vertical-align",
"baseline sub super top text-top middle bottom text-bottom",
extra_gecko_values="middle-with-baseline") %>
<% vertical_align_keywords = vertical_align.keyword.values_for(product) %>
<% vertical_align = data.longhands_by_name["vertical-align"] %>
<% vertical_align.keyword = Keyword("vertical-align",
"baseline sub super top text-top middle bottom text-bottom",
extra_gecko_values="middle-with-baseline") %>
<% vertical_align_keywords = vertical_align.keyword.values_for(product) %>
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
match *self {
SpecifiedValue::LengthOrPercentage(length) => length.has_viewport_percentage(),
_ => false
}
}
}
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
match *self {
SpecifiedValue::LengthOrPercentage(length) => length.has_viewport_percentage(),
_ => false
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, PartialEq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum SpecifiedValue {
% for keyword in vertical_align_keywords:
${to_rust_ident(keyword)},
% endfor
LengthOrPercentage(specified::LengthOrPercentage),
}
/// The `vertical-align` value.
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, PartialEq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum SpecifiedValue {
% for keyword in vertical_align_keywords:
${to_rust_ident(keyword)},
% endfor
LengthOrPercentage(specified::LengthOrPercentage),
}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
% for keyword in vertical_align_keywords:
SpecifiedValue::${to_rust_ident(keyword)} => dest.write_str("${keyword}"),
% endfor
SpecifiedValue::LengthOrPercentage(value) => value.to_css(dest),
}
}
}
/// baseline | sub | super | top | text-top | middle | bottom | text-bottom
/// | <percentage> | <length>
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
input.try(|i| specified::LengthOrPercentage::parse(context, i))
.map(SpecifiedValue::LengthOrPercentage)
.or_else(|()| {
match_ignore_ascii_case! { try!(input.expect_ident()),
% for keyword in vertical_align_keywords:
"${keyword}" => Ok(SpecifiedValue::${to_rust_ident(keyword)}),
% endfor
_ => Err(())
}
})
}
pub mod computed_value {
use app_units::Au;
use std::fmt;
use style_traits::ToCss;
use values::{CSSFloat, computed};
#[allow(non_camel_case_types)]
#[derive(PartialEq, Copy, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum T {
% for keyword in vertical_align_keywords:
${to_rust_ident(keyword)},
% endfor
LengthOrPercentage(computed::LengthOrPercentage),
}
impl ToCss for T {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
% for keyword in vertical_align_keywords:
T::${to_rust_ident(keyword)} => dest.write_str("${keyword}"),
% endfor
T::LengthOrPercentage(value) => value.to_css(dest),
}
}
}
}
#[inline]
pub fn get_initial_value() -> computed_value::T { computed_value::T::baseline }
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
% for keyword in vertical_align_keywords:
SpecifiedValue::${to_rust_ident(keyword)} => dest.write_str("${keyword}"),
% endfor
SpecifiedValue::LengthOrPercentage(value) => value.to_css(dest),
}
}
}
/// baseline | sub | super | top | text-top | middle | bottom | text-bottom
/// | <percentage> | <length>
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
input.try(|i| specified::LengthOrPercentage::parse(context, i))
.map(SpecifiedValue::LengthOrPercentage)
.or_else(|_| {
match_ignore_ascii_case! { try!(input.expect_ident()),
% for keyword in vertical_align_keywords:
"${keyword}" => Ok(SpecifiedValue::${to_rust_ident(keyword)}),
% endfor
_ => Err(())
}
})
}
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
/// The computed value for `vertical-align`.
pub mod computed_value {
use app_units::Au;
use std::fmt;
use style_traits::ToCss;
use values::{CSSFloat, computed};
#[inline]
fn to_computed_value(&self, context: &Context) -> computed_value::T {
match *self {
% for keyword in vertical_align_keywords:
SpecifiedValue::${to_rust_ident(keyword)} => {
computed_value::T::${to_rust_ident(keyword)}
}
% endfor
SpecifiedValue::LengthOrPercentage(value) =>
computed_value::T::LengthOrPercentage(value.to_computed_value(context)),
}
}
#[inline]
fn from_computed_value(computed: &computed_value::T) -> Self {
match *computed {
% for keyword in vertical_align_keywords:
computed_value::T::${to_rust_ident(keyword)} => {
SpecifiedValue::${to_rust_ident(keyword)}
}
% endfor
computed_value::T::LengthOrPercentage(value) =>
SpecifiedValue::LengthOrPercentage(
ToComputedValue::from_computed_value(&value)
),
}
}
}
/// The keywords are the same, and the `LengthOrPercentage` is computed
/// here.
#[allow(non_camel_case_types)]
#[derive(PartialEq, Copy, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum T {
% for keyword in vertical_align_keywords:
${to_rust_ident(keyword)},
% endfor
LengthOrPercentage(computed::LengthOrPercentage),
}
impl ToCss for T {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
% for keyword in vertical_align_keywords:
T::${to_rust_ident(keyword)} => dest.write_str("${keyword}"),
% endfor
T::LengthOrPercentage(value) => value.to_css(dest),
}
}
}
}
/// The initial computed value for `vertical-align`.
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T::baseline
}
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline]
fn to_computed_value(&self, context: &Context) -> computed_value::T {
match *self {
% for keyword in vertical_align_keywords:
SpecifiedValue::${to_rust_ident(keyword)} => {
computed_value::T::${to_rust_ident(keyword)}
}
% endfor
SpecifiedValue::LengthOrPercentage(value) =>
computed_value::T::LengthOrPercentage(value.to_computed_value(context)),
}
}
#[inline]
fn from_computed_value(computed: &computed_value::T) -> Self {
match *computed {
% for keyword in vertical_align_keywords:
computed_value::T::${to_rust_ident(keyword)} => {
SpecifiedValue::${to_rust_ident(keyword)}
}
% endfor
computed_value::T::LengthOrPercentage(value) =>
SpecifiedValue::LengthOrPercentage(
ToComputedValue::from_computed_value(&value)
),
}
}
}
</%helpers:longhand>
@ -275,44 +290,51 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
gecko_constant_prefix="NS_STYLE_OVERFLOW")}
// FIXME(pcwalton, #2742): Implement scrolling for `scroll` and `auto`.
<%helpers:longhand name="overflow-y"
need_clone="True"
animatable="False">
use super::overflow_x;
<%helpers:longhand name="overflow-y" need_clone="True" animatable="False">
use super::overflow_x;
use std::fmt;
use style_traits::ToCss;
use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage;
use std::fmt;
use style_traits::ToCss;
use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage;
pub use self::computed_value::T as SpecifiedValue;
pub use self::computed_value::T as SpecifiedValue;
impl NoViewportPercentage for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
self.0.to_css(dest)
}
}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
self.0.to_css(dest)
}
}
pub mod computed_value {
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct T(pub super::super::overflow_x::computed_value::T);
}
impl ComputedValueAsSpecified for SpecifiedValue {}
/// The specified and computed value for overflow-y is a wrapper on top of
/// `overflow-x`, so we re-use the logic, but prevent errors from mistakenly
/// assign one to other.
///
/// TODO(Manishearth, emilio): We may want to just use the same value.
pub mod computed_value {
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct T(pub super::super::overflow_x::computed_value::T);
}
pub fn get_initial_value() -> computed_value::T {
computed_value::T(overflow_x::get_initial_value())
}
impl ComputedValueAsSpecified for SpecifiedValue {}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
overflow_x::parse(context, input).map(SpecifiedValue)
}
#[inline]
#[allow(missing_docs)]
pub fn get_initial_value() -> computed_value::T {
computed_value::T(overflow_x::get_initial_value())
}
#[inline]
#[allow(missing_docs)]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
overflow_x::parse(context, input).map(SpecifiedValue)
}
</%helpers:longhand>
// TODO(pcwalton): Multiple transitions.
<%helpers:longhand name="transition-duration"
need_index="True"
animatable="False">
@ -369,7 +391,6 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
</%helpers:longhand>
// TODO(pcwalton): Lots more timing functions.
// TODO(pcwalton): Multiple transitions.
<%helpers:longhand name="transition-timing-function"
need_index="True"
animatable="False">

Просмотреть файл

@ -315,7 +315,10 @@ ${helpers.single_keyword("font-variant-caps",
use app_units::Au;
pub type T = Au;
}
#[inline] pub fn get_initial_value() -> computed_value::T {
#[inline]
#[allow(missing_docs)]
pub fn get_initial_value() -> computed_value::T {
Au::from_px(FONT_MEDIUM_PX)
}

Просмотреть файл

@ -158,7 +158,13 @@ pub mod shorthands {
<%include file="/shorthand/text.mako.rs" />
}
/// A module with all the code related to animated properties.
///
/// This needs to be "included" by mako at least after all longhand modules,
/// given they populate the global data.
pub mod animated_properties {
#![deny(missing_docs)]
<%include file="/helpers/animated_properties.mako.rs" />
}
@ -461,15 +467,21 @@ impl ShorthandId {
}
}
/// Serializes possible shorthand name with value to input buffer given a list of longhand declarations.
/// On success, returns true if shorthand value is written and false if no shorthand value is present.
/// Serializes the possible shorthand name with value to input buffer given
/// a list of longhand declarations.
///
/// On success, returns true if the shorthand value is written, or false if
/// no shorthand value is present.
pub fn serialize_shorthand_to_buffer<'a, W, I>(self,
dest: &mut W,
declarations: I,
is_first_serialization: &mut bool,
importance: Importance)
-> Result<bool, fmt::Error>
where W: Write, I: IntoIterator<Item=&'a PropertyDeclaration>, I::IntoIter: Clone {
where W: Write,
I: IntoIterator<Item=&'a PropertyDeclaration>,
I::IntoIter: Clone,
{
match self.get_shorthand_appendable_value(declarations) {
None => Ok(false),
Some(appendable_value) => {
@ -484,60 +496,73 @@ impl ShorthandId {
}
}
fn get_shorthand_appendable_value<'a, I>(self, declarations: I)
fn get_shorthand_appendable_value<'a, I>(self,
declarations: I)
-> Option<AppendableValue<'a, I::IntoIter>>
where I: IntoIterator<Item=&'a PropertyDeclaration>, I::IntoIter: Clone {
let declarations = declarations.into_iter();
where I: IntoIterator<Item=&'a PropertyDeclaration>,
I::IntoIter: Clone,
{
let declarations = declarations.into_iter();
// Only cloning iterators (a few pointers each) not declarations.
let mut declarations2 = declarations.clone();
let mut declarations3 = declarations.clone();
// Only cloning iterators (a few pointers each) not declarations.
let mut declarations2 = declarations.clone();
let mut declarations3 = declarations.clone();
let first_declaration = match declarations2.next() {
Some(declaration) => declaration,
None => return None
};
let first_declaration = match declarations2.next() {
Some(declaration) => declaration,
None => return None
};
// https://drafts.csswg.org/css-variables/#variables-in-shorthands
if let Some(css) = first_declaration.with_variables_from_shorthand(self) {
if declarations2.all(|d| d.with_variables_from_shorthand(self) == Some(css)) {
return Some(AppendableValue::Css(css));
}
else {
return None;
}
}
// https://drafts.csswg.org/css-variables/#variables-in-shorthands
if let Some(css) = first_declaration.with_variables_from_shorthand(self) {
if declarations2.all(|d| d.with_variables_from_shorthand(self) == Some(css)) {
return Some(AppendableValue::Css(css));
}
return None;
}
if !declarations3.any(|d| d.with_variables()) {
return Some(AppendableValue::DeclarationsForShorthand(self, declarations));
}
if !declarations3.any(|d| d.with_variables()) {
return Some(AppendableValue::DeclarationsForShorthand(self, declarations));
}
None
None
}
}
/// Servo's representation of a declared value for a given `T`, which is the
/// declared value for that property.
#[derive(Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum DeclaredValue<T> {
/// A known specified value from the stylesheet.
Value(T),
/// A value that contained any css variables.
WithVariables {
/// The css serialization for this value.
css: String,
/// The first token type for this serialization.
first_token_type: TokenSerializationType,
/// The base url.
base_url: ServoUrl,
/// The shorthand this came from.
from_shorthand: Option<ShorthandId>,
},
/// The `initial` keyword.
Initial,
/// The `inherit` keyword.
Inherit,
/// The `unset` keyword.
Unset,
}
impl<T: HasViewportPercentage> HasViewportPercentage for DeclaredValue<T> {
fn has_viewport_percentage(&self) -> bool {
match *self {
DeclaredValue::Value(ref v)
=> v.has_viewport_percentage(),
DeclaredValue::WithVariables { .. }
=> panic!("DeclaredValue::has_viewport_percentage without resolving variables!"),
DeclaredValue::Value(ref v) => v.has_viewport_percentage(),
DeclaredValue::WithVariables { .. } => {
panic!("DeclaredValue::has_viewport_percentage without \
resolving variables!")
},
DeclaredValue::Initial |
DeclaredValue::Inherit |
DeclaredValue::Unset => false,
@ -615,7 +640,9 @@ impl fmt::Debug for PropertyId {
}
impl ToCss for PropertyId {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write,
{
match *self {
PropertyId::Longhand(id) => dest.write_str(id.name()),
PropertyId::Shorthand(id) => dest.write_str(id.name()),
@ -1150,19 +1177,22 @@ pub struct ComputedValues {
% endfor
custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
shareable: bool,
/// The writing mode of this computed values struct.
pub writing_mode: WritingMode,
/// The root element's computed font size.
pub root_font_size: Au,
}
#[cfg(feature = "servo")]
impl ComputedValues {
/// Construct a `ComputedValues` instance.
pub fn new(custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
shareable: bool,
writing_mode: WritingMode,
root_font_size: Au,
% for style_struct in data.active_style_structs():
${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
% endfor
shareable: bool,
writing_mode: WritingMode,
root_font_size: Au,
% for style_struct in data.active_style_structs():
${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
% endfor
) -> Self {
ComputedValues {
custom_properties: custom_properties,
@ -1322,11 +1352,6 @@ impl ComputedValues {
))
}
#[inline]
pub fn get_font_arc(&self) -> Arc<style_structs::Font> {
self.font.clone()
}
// http://dev.w3.org/csswg/css-transforms/#grouping-property-values
pub fn get_used_transform_style(&self) -> computed_values::transform_style::T {
use computed_values::mix_blend_mode;
@ -1820,16 +1845,21 @@ pub fn apply_declarations<'a, F, I>(viewport_size: Size2D<Au>,
}
if seen.get_font_style() || seen.get_font_weight() || seen.get_font_stretch() ||
seen.get_font_family() {
seen.get_font_family() {
style.mutate_font().compute_font_hash();
}
style
}
/// Modifies the style for an anonymous flow so it resets all its non-inherited
/// style structs, and set their borders and outlines to zero.
///
/// Also, it gets a new display value, which is honored except when it's
/// `inline`.
#[cfg(feature = "servo")]
pub fn modify_style_for_anonymous_flow(style: &mut Arc<ComputedValues>,
new_display_value: longhands::display::computed_value::T) {
new_display_value: longhands::display::computed_value::T) {
// The 'align-self' property needs some special treatment since
// its value depends on the 'align-items' value of its parent.
% if "align-items" in data.longhands_by_name:
@ -1869,12 +1899,17 @@ pub fn modify_style_for_anonymous_flow(style: &mut Arc<ComputedValues>,
outline.outline_width = Au(0);
}
/// Alters the given style to accommodate replaced content. This is called in flow construction. It
/// handles cases like `<div style="position: absolute">foo bar baz</div>` (in which `foo`, `bar`,
/// and `baz` must not be absolutely-positioned) and cases like `<sup>Foo</sup>` (in which the
/// `vertical-align: top` style of `sup` must not propagate down into `Foo`).
/// Alters the given style to accommodate replaced content. This is called in
/// flow construction. It handles cases like:
///
/// FIXME(#5625, pcwalton): It would probably be cleaner and faster to do this in the cascade.
/// <div style="position: absolute">foo bar baz</div>
///
/// (in which `foo`, `bar`, and `baz` must not be absolutely-positioned) and
/// cases like `<sup>Foo</sup>` (in which the `vertical-align: top` style of
/// `sup` must not propagate down into `Foo`).
///
/// FIXME(#5625, pcwalton): It would probably be cleaner and faster to do this
/// in the cascade.
#[cfg(feature = "servo")]
#[inline]
pub fn modify_style_for_replaced_content(style: &mut Arc<ComputedValues>) {
@ -1907,11 +1942,11 @@ pub fn modify_style_for_replaced_content(style: &mut Arc<ComputedValues>) {
}
}
/// Adjusts borders as appropriate to account for a fragment's status as the first or last fragment
/// within the range of an element.
/// Adjusts borders as appropriate to account for a fragment's status as the
/// first or last fragment within the range of an element.
///
/// Specifically, this function sets border widths to zero on the sides for which the fragment is
/// not outermost.
/// Specifically, this function sets border widths to zero on the sides for
/// which the fragment is not outermost.
#[cfg(feature = "servo")]
#[inline]
pub fn modify_border_style_for_inline_sides(style: &mut Arc<ComputedValues>,
@ -1963,7 +1998,8 @@ pub fn modify_border_style_for_inline_sides(style: &mut Arc<ComputedValues>,
}
}
/// Adjusts the `position` property as necessary for the outer fragment wrapper of an inline-block.
/// Adjusts the `position` property as necessary for the outer fragment wrapper
/// of an inline-block.
#[cfg(feature = "servo")]
#[inline]
pub fn modify_style_for_outer_inline_block_fragment(style: &mut Arc<ComputedValues>) {
@ -1972,10 +2008,11 @@ pub fn modify_style_for_outer_inline_block_fragment(style: &mut Arc<ComputedValu
box_style.position = longhands::position::computed_value::T::static_
}
/// Adjusts the `position` and `padding` properties as necessary to account for text.
/// Adjusts the `position` and `padding` properties as necessary to account for
/// text.
///
/// Text is never directly relatively positioned; it's always contained within an element that is
/// itself relatively positioned.
/// Text is never directly relatively positioned; it's always contained within
/// an element that is itself relatively positioned.
#[cfg(feature = "servo")]
#[inline]
pub fn modify_style_for_text(style: &mut Arc<ComputedValues>) {
@ -2009,8 +2046,8 @@ pub fn modify_style_for_text(style: &mut Arc<ComputedValues>) {
}
}
/// Adjusts the `clip` property so that an inline absolute hypothetical fragment doesn't clip its
/// children.
/// Adjusts the `clip` property so that an inline absolute hypothetical fragment
/// doesn't clip its children.
#[cfg(feature = "servo")]
pub fn modify_style_for_inline_absolute_hypothetical_fragment(style: &mut Arc<ComputedValues>) {
if style.get_effects().clip.0.is_some() {

Просмотреть файл

@ -7,8 +7,16 @@ use style_traits::ToCss;
use values::specified::{BorderStyle, CSSColor};
use std::fmt;
pub fn serialize_four_sides<W, I>(dest: &mut W, top: &I, right: &I, bottom: &I, left: &I)
-> fmt::Result where W: fmt::Write, I: ToCss + PartialEq {
#[allow(missing_docs)]
pub fn serialize_four_sides<W, I>(dest: &mut W,
top: &I,
right: &I,
bottom: &I,
left: &I)
-> fmt::Result
where W: fmt::Write,
I: ToCss + PartialEq,
{
if left == right {
let horizontal_value = left;
@ -85,8 +93,10 @@ fn serialize_directional_border<W, I>(dest: &mut W,
}
#[allow(missing_docs)]
pub fn is_overflow_shorthand<'a, I>(appendable_value: &AppendableValue<'a, I>) -> bool
where I: Iterator<Item=&'a PropertyDeclaration> {
where I: Iterator<Item=&'a PropertyDeclaration>
{
if let AppendableValue::DeclarationsForShorthand(shorthand, _) = *appendable_value {
if let ShorthandId::Overflow = shorthand {
return true;

Просмотреть файл

@ -3,6 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#![allow(unsafe_code)]
#![deny(missing_docs)]
//! The rule tree.
use arc_ptr_eq;
#[cfg(feature = "servo")]
@ -17,15 +20,40 @@ use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
use stylesheets::StyleRule;
use thread_state;
/// The rule tree, the structure servo uses to preserve the results of selector
/// matching.
///
/// This is organized as a tree of rules. When a node matches a set of rules,
/// they're inserted in order in the tree, starting with the less specific one.
///
/// When a rule is inserted in the tree, other elements may share the path up to
/// a given rule. If that's the case, we don't duplicate child nodes, but share
/// them.
///
/// When the rule node refcount drops to zero, it doesn't get freed. It gets
/// instead put into a free list, and it is potentially GC'd after a while in a
/// single-threaded fashion.
///
/// That way, a rule node that represents a likely-to-match-again rule (like a
/// :hover rule) can be reused if we haven't GC'd it yet.
#[derive(Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct RuleTree {
root: StrongRuleNode,
}
/// A style source for the rule node. It can either be a CSS style rule or a
/// declaration block.
///
/// Note that, even though the declaration block from inside the style rule
/// could be enough to implement the rule tree, keeping the whole rule provides
/// more debuggability, and also the ability of show those selectors to
/// devtools.
#[derive(Debug, Clone)]
pub enum StyleSource {
/// A style rule stable pointer.
Style(Arc<RwLock<StyleRule>>),
/// A declaration block stable pointer.
Declarations(Arc<RwLock<PropertyDeclarationBlock>>),
}
@ -34,8 +62,11 @@ type StyleSourceGuardHandle<'a> =
RwLockReadGuard<'a, StyleRule>,
RwLockReadGuard<'a, PropertyDeclarationBlock>>;
/// A guard for a given style source.
pub enum StyleSourceGuard<'a> {
/// A guard for a style rule.
Style(StyleSourceGuardHandle<'a>),
/// A guard for a declaration block.
Declarations(RwLockReadGuard<'a, PropertyDeclarationBlock>),
}
@ -71,6 +102,8 @@ impl StyleSource {
let _ = write!(writer, " -> {:?}", self.read().declarations);
}
/// Read the style source guard, and obtain thus read access to the
/// underlying property declaration block.
#[inline]
pub fn read<'a>(&'a self) -> StyleSourceGuard<'a> {
use self::StyleSource::*;
@ -87,15 +120,19 @@ impl StyleSource {
/// This value exists here so a node that pushes itself to the list can know
/// that is in the free list by looking at is next pointer, and comparing it
/// with null.
///
/// The root node doesn't have a null pointer in the free list, but this value.
const FREE_LIST_SENTINEL: *mut RuleNode = 0x01 as *mut RuleNode;
impl RuleTree {
/// Construct a new rule tree.
pub fn new() -> Self {
RuleTree {
root: StrongRuleNode::new(Box::new(RuleNode::root())),
}
}
/// Get the root rule node.
pub fn root(&self) -> StrongRuleNode {
self.root.clone()
}
@ -105,13 +142,16 @@ impl RuleTree {
self.root.get().dump(writer, 0);
}
/// Dump the rule tree to stdout.
pub fn dump_stdout(&self) {
let mut stdout = io::stdout();
self.dump(&mut stdout);
}
/// Insert the given rules, that must be in proper order by specifity, and
/// return the corresponding rule node representing the last inserted one.
pub fn insert_ordered_rules<'a, I>(&self, iter: I) -> StrongRuleNode
where I: Iterator<Item=(StyleSource, Importance)>
where I: Iterator<Item=(StyleSource, Importance)>,
{
let mut current = self.root.clone();
for (source, importance) in iter {
@ -294,6 +334,7 @@ struct WeakRuleNode {
ptr: *mut RuleNode,
}
/// A strong reference to a rule node.
#[derive(Debug)]
pub struct StrongRuleNode {
ptr: *mut RuleNode,
@ -412,14 +453,19 @@ impl StrongRuleNode {
unsafe { &*self.ptr }
}
/// Get the style source corresponding to this rule node. May return `None`
/// if it's the root node, which means that the node hasn't matched any
/// rules.
pub fn style_source(&self) -> Option<&StyleSource> {
self.get().source.as_ref()
}
/// Get the importance that this rule node represents.
pub fn importance(&self) -> Importance {
self.get().importance
}
/// Get an iterator for this rule node and its ancestors.
pub fn self_and_ancestors(&self) -> SelfAndAncestors {
SelfAndAncestors {
current: Some(self)
@ -527,6 +573,7 @@ impl StrongRuleNode {
}
}
/// An iterator over a rule node and its ancestors.
#[derive(Clone)]
pub struct SelfAndAncestors<'a> {
current: Option<&'a StrongRuleNode>,

Просмотреть файл

@ -4,14 +4,17 @@
//! Implements sequential traversal over the DOM tree.
#![deny(missing_docs)]
use dom::{TElement, TNode};
use traversal::{DomTraversal, PerLevelTraversalData, PreTraverseToken};
/// Do a sequential DOM traversal for layout or styling, generic over `D`.
pub fn traverse_dom<N, D>(traversal: &D,
root: N::ConcreteElement,
token: PreTraverseToken)
where N: TNode,
D: DomTraversal<N>
D: DomTraversal<N>,
{
debug_assert!(token.should_traverse());

Просмотреть файл

@ -2,6 +2,10 @@
* 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/. */
#![deny(missing_docs)]
//! Servo's selector parser.
use {Atom, Prefix, Namespace, LocalName};
use attr::{AttrIdentifier, AttrValue};
use cssparser::ToCss;
@ -15,9 +19,12 @@ use std::borrow::Cow;
use std::fmt;
use std::fmt::Debug;
/// A pseudo-element, both public and private.
///
/// NB: If you add to this list, be sure to update `each_pseudo_element` too.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum PseudoElement {
Before,
After,
@ -55,6 +62,7 @@ impl ToCss for PseudoElement {
impl PseudoElement {
/// Whether the current pseudo element is :before or :after.
#[inline]
pub fn is_before_or_after(&self) -> bool {
match *self {
@ -64,6 +72,9 @@ impl PseudoElement {
}
}
/// Returns which kind of cascade type has this pseudo.
///
/// For more info on cascade types, see docs/components/style.md
#[inline]
pub fn cascade_type(&self) -> PseudoElementCascadeType {
match *self {
@ -83,8 +94,11 @@ impl PseudoElement {
}
}
/// A non tree-structural pseudo-class.
/// See https://drafts.csswg.org/selectors-4/#structural-pseudos
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum NonTSPseudoClass {
AnyLink,
Link,
@ -129,6 +143,8 @@ impl ToCss for NonTSPseudoClass {
}
impl NonTSPseudoClass {
/// Gets a given state flag for this pseudo-class. This is used to do
/// selector matching, and it's set from the DOM.
pub fn state_flag(&self) -> ElementState {
use element_state::*;
use self::NonTSPseudoClass::*;
@ -153,6 +169,8 @@ impl NonTSPseudoClass {
}
}
/// The abstract struct we implement the selector parser implementation on top
/// of.
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SelectorImpl;
@ -289,14 +307,17 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
}
impl SelectorImpl {
/// Returns the pseudo-element cascade type of the given `pseudo`.
#[inline]
pub fn pseudo_element_cascade_type(pseudo: &PseudoElement) -> PseudoElementCascadeType {
pseudo.cascade_type()
}
/// Executes `fun` for each pseudo-element.
#[inline]
pub fn each_pseudo_element<F>(mut fun: F)
where F: FnMut(PseudoElement) {
where F: FnMut(PseudoElement),
{
fun(PseudoElement::Before);
fun(PseudoElement::After);
fun(PseudoElement::DetailsContent);
@ -311,11 +332,13 @@ impl SelectorImpl {
fun(PseudoElement::ServoAnonymousBlock);
}
/// Returns the pseudo-class state flag for selector matching.
#[inline]
pub fn pseudo_class_state_flag(pc: &NonTSPseudoClass) -> ElementState {
pc.state_flag()
}
/// Returns whether this pseudo is either :before or :after.
#[inline]
pub fn pseudo_is_before_or_after(pseudo: &PseudoElement) -> bool {
pseudo.is_before_or_after()
@ -326,12 +349,16 @@ impl SelectorImpl {
#[derive(Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct ServoElementSnapshot {
/// The stored state of the element.
pub state: Option<ElementState>,
/// The set of stored attributes and its values.
pub attrs: Option<Vec<(AttrIdentifier, AttrValue)>>,
/// Whether this element is an HTML element in an HTML document.
pub is_html_element_in_html_document: bool,
}
impl ServoElementSnapshot {
/// Create an empty element snapshot.
pub fn new(is_html_element_in_html_document: bool) -> Self {
ServoElementSnapshot {
state: None,
@ -373,7 +400,7 @@ impl ElementSnapshot for ServoElementSnapshot {
}
fn each_class<F>(&self, mut callback: F)
where F: FnMut(&Atom)
where F: FnMut(&Atom),
{
if let Some(v) = self.get_attr(&ns!(), &local_name!("class")) {
for class in v.as_tokens() {

Просмотреть файл

@ -2,6 +2,10 @@
* 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/. */
//! String utils for attributes and similar stuff.
#![deny(missing_docs)]
use num_traits::ToPrimitive;
use std::ascii::AsciiExt;
use std::borrow::Cow;
@ -9,7 +13,10 @@ use std::convert::AsRef;
use std::iter::{Filter, Peekable};
use std::str::Split;
/// A static slice of characters.
pub type StaticCharVec = &'static [char];
/// A static slice of `str`s.
pub type StaticStringVec = &'static [&'static str];
/// A "space character" according to:
@ -23,23 +30,31 @@ pub static HTML_SPACE_CHARACTERS: StaticCharVec = &[
'\u{000d}',
];
/// Whether a character is a HTML whitespace character.
#[inline]
pub fn char_is_whitespace(c: char) -> bool {
HTML_SPACE_CHARACTERS.contains(&c)
}
/// Whether all the string is HTML whitespace.
#[inline]
pub fn is_whitespace(s: &str) -> bool {
s.chars().all(char_is_whitespace)
}
#[inline]
fn not_empty(&split: &&str) -> bool { !split.is_empty() }
/// Split a string on HTML whitespace.
#[inline]
pub fn split_html_space_chars<'a>(s: &'a str) ->
Filter<Split<'a, StaticCharVec>, fn(&&str) -> bool> {
fn not_empty(&split: &&str) -> bool { !split.is_empty() }
s.split(HTML_SPACE_CHARACTERS).filter(not_empty as fn(&&str) -> bool)
}
/// Split a string on commas.
#[inline]
pub fn split_commas<'a>(s: &'a str) -> Filter<Split<'a, char>, fn(&&str) -> bool> {
fn not_empty(&split: &&str) -> bool { !split.is_empty() }
s.split(',').filter(not_empty as fn(&&str) -> bool)
}
@ -61,6 +76,7 @@ fn is_exponent_char(c: char) -> bool {
}
}
/// Read a set of ascii digits and read them into a number.
pub fn read_numbers<I: Iterator<Item=char>>(mut iter: Peekable<I>) -> (Option<i64>, usize) {
match iter.peek() {
Some(c) if is_ascii_digit(c) => (),
@ -79,6 +95,7 @@ pub fn read_numbers<I: Iterator<Item=char>>(mut iter: Peekable<I>) -> (Option<i6
})
}
/// Read a decimal fraction.
pub fn read_fraction<I: Iterator<Item=char>>(mut iter: Peekable<I>,
mut divisor: f64,
value: f64) -> (f64, usize) {
@ -92,11 +109,11 @@ pub fn read_fraction<I: Iterator<Item=char>>(mut iter: Peekable<I>,
d as i64 - '0' as i64
).fold((value, 1), |accumulator, d| {
divisor *= 10f64;
(accumulator.0 + d as f64 / divisor,
accumulator.1 + 1)
(accumulator.0 + d as f64 / divisor, accumulator.1 + 1)
})
}
/// Reads an exponent from an iterator over chars, for example `e100`.
pub fn read_exponent<I: Iterator<Item=char>>(mut iter: Peekable<I>) -> Option<i32> {
match iter.peek() {
Some(c) if is_exponent_char(*c) => (),
@ -118,8 +135,10 @@ pub fn read_exponent<I: Iterator<Item=char>>(mut iter: Peekable<I>) -> Option<i3
}
}
/// Join a set of strings with a given delimiter `join`.
pub fn str_join<I, T>(strs: I, join: &str) -> String
where I: IntoIterator<Item=T>, T: AsRef<str>,
where I: IntoIterator<Item=T>,
T: AsRef<str>,
{
strs.into_iter().enumerate().fold(String::new(), |mut acc, (i, s)| {
if i > 0 { acc.push_str(join); }

Просмотреть файл

@ -4,6 +4,8 @@
//! Style sheets and their CSS rules.
#![deny(missing_docs)]
use {Atom, Prefix, Namespace};
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, decode_stylesheet_bytes};
use cssparser::{AtRuleType, RuleListParser, SourcePosition, Token, parse_one_rule};
@ -46,22 +48,27 @@ pub enum Origin {
User,
}
/// A set of namespaces applying to a given stylesheet.
#[derive(Default, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct Namespaces {
pub default: Option<Namespace>,
pub prefixes: FnvHashMap<Prefix , Namespace>,
}
/// A list of CSS rules.
#[derive(Debug)]
pub struct CssRules(pub Vec<CssRule>);
impl CssRules {
/// Whether this CSS rules is empty.
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[allow(missing_docs)]
pub enum RulesMutateError {
Syntax,
IndexSize,
@ -79,6 +86,7 @@ impl From<SingleRuleParseError> for RulesMutateError {
}
impl CssRules {
#[allow(missing_docs)]
pub fn new(rules: Vec<CssRule>) -> Arc<RwLock<CssRules>> {
Arc::new(RwLock::new(CssRules(rules)))
}
@ -93,7 +101,7 @@ impl CssRules {
})
}
// https://drafts.csswg.org/cssom/#insert-a-css-rule
/// https://drafts.csswg.org/cssom/#insert-a-css-rule
pub fn insert_rule(&mut self, rule: &str, parent_stylesheet: &Stylesheet, index: usize, nested: bool)
-> Result<CssRule, RulesMutateError> {
// Step 1, 2
@ -136,7 +144,7 @@ impl CssRules {
Ok(new_rule)
}
// https://drafts.csswg.org/cssom/#remove-a-css-rule
/// https://drafts.csswg.org/cssom/#remove-a-css-rule
pub fn remove_rule(&mut self, index: usize) -> Result<(), RulesMutateError> {
// Step 1, 2
if index >= self.0.len() {
@ -161,6 +169,7 @@ impl CssRules {
}
}
/// The structure servo uses to represent a stylesheet.
#[derive(Debug)]
pub struct Stylesheet {
/// List of rules in the order they were found (important for
@ -168,22 +177,33 @@ pub struct Stylesheet {
pub rules: Arc<RwLock<CssRules>>,
/// List of media associated with the Stylesheet.
pub media: Arc<RwLock<MediaList>>,
/// The origin of this stylesheet.
pub origin: Origin,
/// The base url this stylesheet should use.
pub base_url: ServoUrl,
/// The namespaces that apply to this stylesheet.
pub namespaces: RwLock<Namespaces>,
/// Whether this stylesheet would be dirty when the viewport size changes.
pub dirty_on_viewport_size_change: AtomicBool,
/// Whether this stylesheet should be disabled.
pub disabled: AtomicBool,
}
/// This structure holds the user-agent and user stylesheets.
pub struct UserAgentStylesheets {
/// The user or user agent stylesheets.
pub user_or_user_agent_stylesheets: Vec<Stylesheet>,
/// The quirks mode stylesheet.
pub quirks_mode_stylesheet: Stylesheet,
}
/// A CSS rule.
///
/// TODO(emilio): Lots of spec links should be around.
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub enum CssRule {
// No Charset here, CSSCharsetRule has been removed from CSSOM
// https://drafts.csswg.org/cssom/#changes-from-5-december-2013
@ -197,6 +217,7 @@ pub enum CssRule {
Keyframes(Arc<RwLock<KeyframesRule>>),
}
#[allow(missing_docs)]
pub enum CssRuleType {
// https://drafts.csswg.org/cssom/#the-cssrule-interface
Style = 1,
@ -236,12 +257,14 @@ impl ParseErrorReporter for MemoryHoleReporter {
}
}
#[allow(missing_docs)]
pub enum SingleRuleParseError {
Syntax,
Hierarchy,
}
impl CssRule {
#[allow(missing_docs)]
pub fn rule_type(&self) -> CssRuleType {
match *self {
CssRule::Style(_) => CssRuleType::Style,
@ -268,7 +291,8 @@ impl CssRule {
/// Note that only some types of rules can contain rules. An empty slice is
/// used for others.
pub fn with_nested_rules_and_mq<F, R>(&self, mut f: F) -> R
where F: FnMut(&[CssRule], Option<&MediaList>) -> R {
where F: FnMut(&[CssRule], Option<&MediaList>) -> R
{
match *self {
CssRule::Import(ref lock) => {
let rule = lock.read();
@ -296,6 +320,7 @@ impl CssRule {
// input state is None for a nested rule
// Returns a parsed CSS rule and the final state of the parser
#[allow(missing_docs)]
pub fn parse(css: &str,
parent_stylesheet: &Stylesheet,
extra_data: ParserContextExtraData,
@ -348,6 +373,7 @@ impl ToCss for CssRule {
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct NamespaceRule {
/// `None` for the default Namespace
pub prefix: Option<Prefix>,
@ -374,6 +400,7 @@ impl ToCss for NamespaceRule {
/// [import]: https://drafts.csswg.org/css-cascade-3/#at-import
#[derive(Debug)]
pub struct ImportRule {
/// The `<url>` this `@import` rule is loading.
pub url: SpecifiedUrl,
/// The stylesheet is always present.
@ -396,9 +423,14 @@ impl ToCss for ImportRule {
}
}
/// A [`@keyframes`][keyframes] rule.
///
/// [keyframes]: https://drafts.csswg.org/css-animations/#keyframes
#[derive(Debug)]
pub struct KeyframesRule {
/// The name of the current animation.
pub name: Atom,
/// The keyframes specified for this CSS rule.
pub keyframes: Vec<Arc<RwLock<Keyframe>>>,
}
@ -417,6 +449,7 @@ impl ToCss for KeyframesRule {
}
}
#[allow(missing_docs)]
#[derive(Debug)]
pub struct MediaRule {
pub media_queries: Arc<RwLock<MediaList>>,
@ -438,6 +471,7 @@ impl ToCss for MediaRule {
}
}
#[allow(missing_docs)]
#[derive(Debug)]
pub struct StyleRule {
pub selectors: SelectorList<SelectorImpl>,
@ -465,6 +499,11 @@ impl ToCss for StyleRule {
}
impl Stylesheet {
/// Parse a stylesheet from a set of bytes, potentially received over the
/// network.
///
/// Takes care of decoding the network bytes and forwards the resulting
/// string to `Stylesheet::from_str`.
pub fn from_bytes(bytes: &[u8],
base_url: ServoUrl,
protocol_encoding_label: Option<&str>,
@ -486,6 +525,8 @@ impl Stylesheet {
extra_data)
}
/// Updates an empty stylesheet with a set of bytes that reached over the
/// network.
pub fn update_from_bytes(existing: &Stylesheet,
bytes: &[u8],
protocol_encoding_label: Option<&str>,
@ -493,7 +534,6 @@ impl Stylesheet {
stylesheet_loader: Option<&StylesheetLoader>,
error_reporter: Box<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData) {
assert!(existing.rules.read().is_empty());
let (string, _) = decode_stylesheet_bytes(
bytes, protocol_encoding_label, environment_encoding);
Self::update_from_str(existing,
@ -503,6 +543,7 @@ impl Stylesheet {
extra_data)
}
/// Updates an empty stylesheet from a given string of text.
pub fn update_from_str(existing: &Stylesheet,
css: &str,
stylesheet_loader: Option<&StylesheetLoader>,
@ -545,7 +586,14 @@ impl Stylesheet {
.store(input.seen_viewport_percentages(), Ordering::Release);
}
pub fn from_str(css: &str, base_url: ServoUrl, origin: Origin,
/// Creates an empty stylesheet and parses it with a given base url, origin
/// and media.
///
/// Effectively creates a new stylesheet and forwards the hard work to
/// `Stylesheet::update_from_str`.
pub fn from_str(css: &str,
base_url: ServoUrl,
origin: Origin,
media: MediaList,
stylesheet_loader: Option<&StylesheetLoader>,
error_reporter: Box<ParseErrorReporter + Send>,
@ -569,6 +617,7 @@ impl Stylesheet {
s
}
/// Whether this stylesheet can be dirty on viewport size change.
pub fn dirty_on_viewport_size_change(&self) -> bool {
self.dirty_on_viewport_size_change.load(Ordering::SeqCst)
}
@ -607,16 +656,19 @@ impl Stylesheet {
effective_rules(&self.rules.read().0, device, &mut f);
}
/// Returns whether the stylesheet has been explicitly disabled through the CSSOM.
/// Returns whether the stylesheet has been explicitly disabled through the
/// CSSOM.
pub fn disabled(&self) -> bool {
self.disabled.load(Ordering::SeqCst)
}
/// Records that the stylesheet has been explicitly disabled through the CSSOM.
/// Records that the stylesheet has been explicitly disabled through the
/// CSSOM.
///
/// Returns whether the the call resulted in a change in disabled state.
///
/// Disabled stylesheets remain in the document, but their rules are not added to
/// the Stylist.
/// Disabled stylesheets remain in the document, but their rules are not
/// added to the Stylist.
pub fn set_disabled(&self, disabled: bool) -> bool {
self.disabled.swap(disabled, Ordering::SeqCst) != disabled
}
@ -640,6 +692,7 @@ macro_rules! rule_filter {
($( $method: ident($variant:ident => $rule_type: ident), )+) => {
impl Stylesheet {
$(
#[allow(missing_docs)]
pub fn $method<F>(&self, device: &Device, mut f: F) where F: FnMut(&$rule_type) {
self.effective_rules(device, |rule| {
if let CssRule::$variant(ref lock) = *rule {
@ -690,6 +743,7 @@ impl<'b> TopLevelRuleParser<'b> {
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
#[allow(missing_docs)]
pub enum State {
Start = 1,
Imports = 2,

Просмотреть файл

@ -8,32 +8,42 @@
//! In release builds, `get` returns 0. All of the other functions inline
//! away to nothing.
#![deny(missing_docs)]
pub use self::imp::{enter, exit, get, initialize};
bitflags! {
/// A thread state flag, used for multiple assertions.
pub flags ThreadState: u32 {
/// Whether we're in a script thread.
const SCRIPT = 0x01,
/// Whether we're in a layout thread.
const LAYOUT = 0x02,
const PAINT = 0x04,
/// Whether we're in a script worker thread (actual web workers), or in
/// a layout worker thread.
const IN_WORKER = 0x0100,
/// Whether the current thread is going through a GC.
const IN_GC = 0x0200,
const IN_HTML_PARSER = 0x0400,
}
}
macro_rules! thread_types ( ( $( $fun:ident = $flag:ident ; )* ) => (
impl ThreadState {
/// Whether the current thread is a worker thread.
pub fn is_worker(self) -> bool {
self.contains(IN_WORKER)
}
$(
#[cfg(debug_assertions)]
#[allow(missing_docs)]
pub fn $fun(self) -> bool {
self.contains($flag)
}
#[cfg(not(debug_assertions))]
#[allow(missing_docs)]
pub fn $fun(self) -> bool {
true
}
@ -48,7 +58,6 @@ macro_rules! thread_types ( ( $( $fun:ident = $flag:ident ; )* ) => (
thread_types! {
is_script = SCRIPT;
is_layout = LAYOUT;
is_paint = PAINT;
}
#[cfg(debug_assertions)]
@ -58,6 +67,7 @@ mod imp {
thread_local!(static STATE: RefCell<Option<ThreadState>> = RefCell::new(None));
/// Initialize the current thread state.
pub fn initialize(x: ThreadState) {
STATE.with(|ref k| {
if let Some(ref s) = *k.borrow() {
@ -68,6 +78,7 @@ mod imp {
get(); // check the assertion below
}
/// Get the current thread state.
pub fn get() -> ThreadState {
let state = STATE.with(|ref k| {
match *k.borrow() {
@ -82,6 +93,7 @@ mod imp {
state
}
/// Enter into a given temporary state. Panics if re-entring.
pub fn enter(x: ThreadState) {
let state = get();
assert!(!state.intersects(x));
@ -90,6 +102,7 @@ mod imp {
})
}
/// Exit a given temporary state.
pub fn exit(x: ThreadState) {
let state = get();
assert!(state.contains(x));
@ -100,6 +113,7 @@ mod imp {
}
#[cfg(not(debug_assertions))]
#[allow(missing_docs)]
mod imp {
use super::ThreadState;
#[inline(always)] pub fn initialize(_: ThreadState) { }

Просмотреть файл

@ -1,14 +1,19 @@
/* 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/. */
#![deny(missing_docs)]
//! A timer module, used to define a `Timer` type, that is controlled by script.
use time;
/// The `TimerMode` is used to determine what time should the `Timer` return,
/// either a fixed value (in the `Test` mode), or the actual time (in the
/// `Current` mode).
/// The `TimerMode` is used to determine what time should the `Timer` return.
#[derive(Debug, Clone)]
enum TimerMode {
/// The timer should return a fixed value.
Test(f64),
/// The timer should return the actual time.
Current,
}

Просмотреть файл

@ -4,6 +4,8 @@
//! Traversing the DOM tree; the bloom filter.
#![deny(missing_docs)]
use atomic_refcell::{AtomicRefCell, AtomicRefMut};
use context::{SharedStyleContext, StyleContext};
use data::{ElementData, ElementStyles, StoredRestyleHint};
@ -18,14 +20,23 @@ use std::mem;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use stylist::Stylist;
/// Style sharing candidate cache stats. These are only used when
/// Style sharing candidate cache hits. These are only used when
/// `-Z style-sharing-stats` is given.
pub static STYLE_SHARING_CACHE_HITS: AtomicUsize = ATOMIC_USIZE_INIT;
/// Style sharing candidate cache misses.
pub static STYLE_SHARING_CACHE_MISSES: AtomicUsize = ATOMIC_USIZE_INIT;
// NB: Keep this as small as possible, please!
/// A per-traversal-level chunk of data. This is sent down by the traversal, and
/// currently only holds the dom depth for the bloom filter.
///
/// NB: Keep this as small as possible, please!
#[derive(Clone, Debug)]
pub struct PerLevelTraversalData {
/// The current dom depth, if known, or `None` otherwise.
///
/// This is kept with cooperation from the traversal code and the bloom
/// filter.
pub current_dom_depth: Option<usize>,
}
@ -37,10 +48,12 @@ pub struct PreTraverseToken {
}
impl PreTraverseToken {
/// Whether we should traverse children.
pub fn should_traverse(&self) -> bool {
self.traverse
}
/// Whether we should traverse only unstyled children.
pub fn traverse_unstyled_children_only(&self) -> bool {
self.unstyled_children_only
}
@ -48,15 +61,22 @@ impl PreTraverseToken {
/// Enum to prevent duplicate logging.
pub enum LogBehavior {
/// We should log.
MayLog,
/// We shouldn't log.
DontLog,
}
use self::LogBehavior::*;
impl LogBehavior {
fn allow(&self) -> bool { match *self { MayLog => true, DontLog => false, } }
fn allow(&self) -> bool { matches!(*self, MayLog) }
}
/// A DOM Traversal trait, that is used to generically implement styling for
/// Gecko and Servo.
pub trait DomTraversal<N: TNode> : Sync {
/// The thread-local context, used to store non-thread-safe stuff that needs
/// to be used in the traversal, and of which we use one per worker, like
/// the bloom filter, for example.
type ThreadLocalContext: Send;
/// Process `node` on the way down, before its children have been processed.
@ -249,8 +269,10 @@ pub trait DomTraversal<N: TNode> : Sync {
/// children of |element|.
unsafe fn clear_element_data(element: &N::ConcreteElement);
/// Return the shared style context common to all worker threads.
fn shared_context(&self) -> &SharedStyleContext;
/// Create a thread-local context.
fn create_thread_local_context(&self) -> Self::ThreadLocalContext;
}
@ -529,6 +551,7 @@ fn preprocess_children<E, D>(traversal: &D,
}
}
/// Clear style data for all the subtree under `el`.
pub fn clear_descendant_data<E: TElement, F: Fn(E)>(el: E, clear_data: &F) {
for kid in el.as_node().children() {
if let Some(kid) = kid.as_element() {

Просмотреть файл

@ -18,6 +18,7 @@ pub use values::specified::basic_shape::{FillRule, GeometryBox, ShapeBox};
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum ShapeSource<T> {
Url(SpecifiedUrl),
Shape(BasicShape, Option<T>),
@ -51,6 +52,7 @@ impl<T: ToCss> ToCss for ShapeSource<T> {
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum BasicShape {
Inset(InsetRect),
Circle(Circle),
@ -71,6 +73,7 @@ impl ToCss for BasicShape {
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct InsetRect {
pub top: LengthOrPercentage,
pub right: LengthOrPercentage,
@ -100,6 +103,7 @@ impl ToCss for InsetRect {
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct Circle {
pub radius: ShapeRadius,
pub position: Position,
@ -115,6 +119,7 @@ impl ToCss for Circle {
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct Ellipse {
pub semiaxis_x: ShapeRadius,
pub semiaxis_y: ShapeRadius,
@ -138,6 +143,7 @@ impl ToCss for Ellipse {
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
/// https://drafts.csswg.org/css-shapes/#funcdef-polygon
pub struct Polygon {
pub fill: FillRule,
@ -168,6 +174,7 @@ impl ToCss for Polygon {
/// https://drafts.csswg.org/css-shapes/#typedef-shape-radius
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum ShapeRadius {
Length(LengthOrPercentage),
ClosestSide,
@ -193,6 +200,7 @@ impl ToCss for ShapeRadius {
/// https://drafts.csswg.org/css-backgrounds-3/#border-radius
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct BorderRadius {
pub top_left: BorderRadiusSize,
pub top_right: BorderRadiusSize,

Просмотреть файл

@ -51,6 +51,7 @@ impl ToComputedValue for specified::Image {
/// https://drafts.csswg.org/css-images/#image-values
#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum Image {
Url(SpecifiedUrl),
Gradient(Gradient),
@ -174,6 +175,7 @@ impl ToComputedValue for specified::Gradient {
/// https://drafts.csswg.org/css-images/#gradients
#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum GradientKind {
Linear(AngleOrCorner),
Radial(EndingShape, Position),
@ -271,6 +273,7 @@ impl ToComputedValue for specified::ColorStop {
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-ending-shape
#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum EndingShape {
Circle(LengthOrKeyword),
Ellipse(LengthOrPercentageOrKeyword),
@ -336,6 +339,7 @@ impl ToComputedValue for specified::GradientEndingShape {
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum LengthOrKeyword {
Length(Length),
Keyword(SizeKeyword),
@ -394,6 +398,7 @@ impl ToComputedValue for specified::LengthOrKeyword {
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum LengthOrPercentageOrKeyword {
LengthOrPercentage(LengthOrPercentage, LengthOrPercentage),
Keyword(SizeKeyword),
@ -458,6 +463,7 @@ impl ToComputedValue for specified::LengthOrPercentageOrKeyword {
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum AngleOrCorner {
Angle(Angle),
Corner(HorizontalDirection, VerticalDirection)

Просмотреть файл

@ -2,6 +2,8 @@
* 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/. */
//! `<length>` computed values, and related ones.
use app_units::Au;
use ordered_float::NotNaN;
use std::fmt;
@ -16,6 +18,7 @@ pub use values::specified::{Angle, BorderStyle, Time, UrlOrNone};
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct CalcLengthOrPercentage {
pub length: Au,
pub percentage: Option<CSSFloat>,
@ -23,11 +26,13 @@ pub struct CalcLengthOrPercentage {
impl CalcLengthOrPercentage {
#[inline]
#[allow(missing_docs)]
pub fn length(&self) -> Au {
self.length
}
#[inline]
#[allow(missing_docs)]
pub fn percentage(&self) -> CSSFloat {
self.percentage.unwrap_or(0.)
}
@ -130,6 +135,7 @@ impl ToComputedValue for specified::CalcLengthOrPercentage {
#[derive(PartialEq, Clone, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum LengthOrPercentage {
Length(Au),
Percentage(CSSFloat),
@ -138,6 +144,7 @@ pub enum LengthOrPercentage {
impl LengthOrPercentage {
#[inline]
#[allow(missing_docs)]
pub fn zero() -> LengthOrPercentage {
LengthOrPercentage::Length(Au(0))
}
@ -154,6 +161,7 @@ impl LengthOrPercentage {
}
}
#[allow(missing_docs)]
pub fn to_hash_key(&self) -> (Au, NotNaN<f32>) {
use self::LengthOrPercentage::*;
match *self {
@ -223,6 +231,7 @@ impl ToCss for LengthOrPercentage {
#[derive(PartialEq, Clone, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum LengthOrPercentageOrAuto {
Length(Au),
Percentage(CSSFloat),
@ -311,6 +320,7 @@ impl ToCss for LengthOrPercentageOrAuto {
#[derive(PartialEq, Clone, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum LengthOrPercentageOrAutoOrContent {
Length(Au),
Percentage(CSSFloat),
@ -397,6 +407,7 @@ impl ToCss for LengthOrPercentageOrAutoOrContent {
#[derive(PartialEq, Clone, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum LengthOrPercentageOrNone {
Length(Au),
Percentage(CSSFloat),
@ -469,12 +480,17 @@ impl ToCss for LengthOrPercentageOrNone {
}
}
/// A computed `<length>` value.
pub type Length = Au;
/// Either a computed `<length>` or the `none` keyword.
pub type LengthOrNone = Either<Length, None_>;
/// Either a computed `<length>` or the `auto` keyword.
pub type LengthOrAuto = Either<Length, Auto>;
/// Either a computed `<length>` or a `<number>` value.
pub type LengthOrNumber = Either<Length, Number>;
/// Either a computed `<length>` or the `normal` keyword.
pub type LengthOrNormal = Either<Length, Normal>;
pub type Length = Au;

Просмотреть файл

@ -2,6 +2,8 @@
* 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/. */
//! Computed values.
use app_units::Au;
use euclid::size::Size2D;
use font_metrics::FontMetricsProvider;
@ -24,23 +26,41 @@ pub mod image;
pub mod length;
pub mod position;
/// A `Context` is all the data a specified value could ever need to compute
/// itself and be transformed to a computed value.
pub struct Context<'a> {
/// Whether the current element is the root element.
pub is_root_element: bool,
/// The current viewport size.
pub viewport_size: Size2D<Au>,
/// The style we're inheriting from.
pub inherited_style: &'a ComputedValues,
/// Values access through this need to be in the properties "computed
/// early": color, text-decoration, font-size, display, position, float,
/// border-*-style, outline-style, font-family, writing-mode...
pub style: ComputedValues,
/// A font metrics provider, used to access font metrics to implement
/// font-relative units.
///
/// TODO(emilio): This should be required, see #14079.
pub font_metrics_provider: Option<&'a FontMetricsProvider>,
}
impl<'a> Context<'a> {
/// Whether the current element is the root element.
pub fn is_root_element(&self) -> bool { self.is_root_element }
/// The current viewport size.
pub fn viewport_size(&self) -> Size2D<Au> { self.viewport_size }
/// The style we're inheriting from.
pub fn inherited_style(&self) -> &ComputedValues { &self.inherited_style }
/// The current style. Note that only "eager" properties should be accessed
/// from here, see the comment in the member.
pub fn style(&self) -> &ComputedValues { &self.style }
/// A mutable reference to the current style.
pub fn mutate_style(&mut self) -> &mut ComputedValues { &mut self.style }
/// Creates a dummy computed context for use in multiple places, like
@ -58,11 +78,15 @@ impl<'a> Context<'a> {
}
}
/// A trait to represent the conversion between computed and specified values.
pub trait ToComputedValue {
/// The computed value type we're going to be converted to.
type ComputedValue;
/// Convert a specified value to a computed value, using itself and the data
/// inside the `Context`.
#[inline]
fn to_computed_value(&self, _context: &Context) -> Self::ComputedValue;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue;
#[inline]
/// Convert a computed value to specified value form.
@ -72,9 +96,13 @@ pub trait ToComputedValue {
fn from_computed_value(computed: &Self::ComputedValue) -> Self;
}
/// A marker trait to represent that the specified value is also the computed
/// value.
pub trait ComputedValueAsSpecified {}
impl<T> ToComputedValue for T where T: ComputedValueAsSpecified + Clone {
impl<T> ToComputedValue for T
where T: ComputedValueAsSpecified + Clone,
{
type ComputedValue = T;
#[inline]
@ -133,9 +161,11 @@ impl ToComputedValue for specified::Length {
#[derive(Debug, PartialEq, Clone, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct BorderRadiusSize(pub Size2D<LengthOrPercentage>);
impl BorderRadiusSize {
#[allow(missing_docs)]
pub fn zero() -> BorderRadiusSize {
BorderRadiusSize(Size2D::new(LengthOrPercentage::Length(Au(0)), LengthOrPercentage::Length(Au(0))))
}
@ -169,6 +199,7 @@ impl ToCss for BorderRadiusSize {
#[derive(Debug, PartialEq, Clone, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct Shadow {
pub offset_x: Au,
pub offset_y: Au,
@ -178,5 +209,8 @@ pub struct Shadow {
pub inset: bool,
}
/// A `<number>` value.
pub type Number = CSSFloat;
/// A type used for opacity.
pub type Opacity = CSSFloat;

Просмотреть файл

@ -13,6 +13,7 @@ use values::computed::LengthOrPercentage;
#[derive(Debug, Clone, PartialEq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct Position {
pub horizontal: LengthOrPercentage,
pub vertical: LengthOrPercentage,
@ -29,6 +30,7 @@ impl ToCss for Position {
#[derive(Debug, Clone, PartialEq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct HorizontalPosition(pub LengthOrPercentage);
impl ToCss for HorizontalPosition {
@ -39,6 +41,7 @@ impl ToCss for HorizontalPosition {
#[derive(Debug, Clone, PartialEq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct VerticalPosition(pub LengthOrPercentage);
impl ToCss for VerticalPosition {

Просмотреть файл

@ -6,6 +6,8 @@
//!
//! [values]: https://drafts.csswg.org/css-values/
#![deny(missing_docs)]
pub use cssparser::{RGBA, Parser};
use parser::{Parse, ParserContext};
use std::fmt::{self, Debug};
@ -16,7 +18,7 @@ macro_rules! define_numbered_css_keyword_enum {
define_numbered_css_keyword_enum!($name: $( $css => $variant = $value ),+);
};
($name: ident: $( $css: expr => $variant: ident = $value: expr ),+) => {
#[allow(non_camel_case_types)]
#[allow(non_camel_case_types, missing_docs)]
#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Copy, RustcEncodable, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
pub enum $name {
@ -24,6 +26,7 @@ macro_rules! define_numbered_css_keyword_enum {
}
impl $name {
#[allow(missing_docs)]
pub fn parse(input: &mut ::cssparser::Parser) -> Result<$name, ()> {
match_ignore_ascii_case! { try!(input.expect_ident()),
$( $css => Ok($name::$variant), )+
@ -34,7 +37,8 @@ macro_rules! define_numbered_css_keyword_enum {
impl ToCss for $name {
fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
where W: ::std::fmt::Write {
where W: ::std::fmt::Write,
{
match *self {
$( $name::$variant => dest.write_str($css) ),+
}
@ -46,17 +50,26 @@ macro_rules! define_numbered_css_keyword_enum {
pub mod computed;
pub mod specified;
/// A CSS float value.
pub type CSSFloat = f32;
/// The default font size.
pub const FONT_MEDIUM_PX: i32 = 16;
/// A trait used to query whether this value has viewport units.
pub trait HasViewportPercentage {
/// Returns true if this value has viewport units.
fn has_viewport_percentage(&self) -> bool;
}
/// A trait used as a marker to represent that a given type may never contain
/// viewport units.
pub trait NoViewportPercentage {}
impl<T> HasViewportPercentage for T where T: NoViewportPercentage {
impl<T> HasViewportPercentage for T
where T: NoViewportPercentage,
{
#[inline]
fn has_viewport_percentage(&self) -> bool {
false
}
@ -68,6 +81,7 @@ macro_rules! define_keyword_type {
($name: ident, $css: expr) => {
#[derive(Clone, PartialEq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct $name;
impl ::style_traits::ToCss for $name {
@ -99,8 +113,11 @@ define_keyword_type!(Normal, "normal");
#[derive(Clone, PartialEq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// A struct representing one of two kinds of values.
pub enum Either<A, B> {
/// The first value.
First(A),
/// The second kind of value.
Second(B),
}

Просмотреть файл

@ -24,6 +24,7 @@ use values::specified::url::SpecifiedUrl;
/// shape-outside uses ShapeSource<ShapeBox>
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum ShapeSource<T> {
Url(SpecifiedUrl),
Shape(BasicShape, Option<T>),
@ -55,6 +56,7 @@ impl<T: ToCss> ToCss for ShapeSource<T> {
}
impl<T: Parse + PartialEq + Copy> ShapeSource<T> {
#[allow(missing_docs)]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
if let Ok(_) = input.try(|input| input.expect_ident_matching("none")) {
Ok(ShapeSource::None)
@ -129,6 +131,7 @@ impl<T: ToComputedValue> ToComputedValue for ShapeSource<T> {
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum BasicShape {
Inset(InsetRect),
Circle(Circle),
@ -205,6 +208,7 @@ impl ToComputedValue for BasicShape {
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// https://drafts.csswg.org/css-shapes/#funcdef-inset
#[allow(missing_docs)]
pub struct InsetRect {
pub top: LengthOrPercentage,
pub right: LengthOrPercentage,
@ -214,6 +218,7 @@ pub struct InsetRect {
}
impl InsetRect {
#[allow(missing_docs)]
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<InsetRect, ()> {
let (t, r, b, l) = try!(parse_four_sides(input, |i| LengthOrPercentage::parse(context, i)));
let mut rect = InsetRect {
@ -373,12 +378,14 @@ fn serialize_basicshape_position<W>(position: &Position, dest: &mut W)
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// https://drafts.csswg.org/css-shapes/#funcdef-circle
#[allow(missing_docs)]
pub struct Circle {
pub radius: ShapeRadius,
pub position: Position,
}
impl Circle {
#[allow(missing_docs)]
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Circle, ()> {
let radius = input.try(|i| ShapeRadius::parse(context, i)).ok().unwrap_or_else(Default::default);
let position = if let Ok(_) = input.try(|input| input.expect_ident_matching("at")) {
@ -450,6 +457,7 @@ impl ToComputedValue for Circle {
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// https://drafts.csswg.org/css-shapes/#funcdef-ellipse
#[allow(missing_docs)]
pub struct Ellipse {
pub semiaxis_x: ShapeRadius,
pub semiaxis_y: ShapeRadius,
@ -458,6 +466,7 @@ pub struct Ellipse {
impl Ellipse {
#[allow(missing_docs)]
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Ellipse, ()> {
let (a, b) = input.try(|input| -> Result<_, ()> {
Ok((try!(ShapeRadius::parse(context, input)), try!(ShapeRadius::parse(context, input))))
@ -537,12 +546,14 @@ impl ToComputedValue for Ellipse {
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// https://drafts.csswg.org/css-shapes/#funcdef-polygon
#[allow(missing_docs)]
pub struct Polygon {
pub fill: FillRule,
pub coordinates: Vec<(LengthOrPercentage, LengthOrPercentage)>,
}
impl Polygon {
#[allow(missing_docs)]
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Polygon, ()> {
let fill = input.try(|input| {
let fill = FillRule::parse(context, input);
@ -626,6 +637,7 @@ impl ToComputedValue for Polygon {
/// https://drafts.csswg.org/css-shapes/#typedef-shape-radius
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum ShapeRadius {
Length(LengthOrPercentage),
ClosestSide,
@ -690,6 +702,7 @@ impl ToComputedValue for ShapeRadius {
/// https://drafts.csswg.org/css-backgrounds-3/#border-radius
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct BorderRadius {
pub top_left: BorderRadiusSize,
pub top_right: BorderRadiusSize,
@ -792,6 +805,7 @@ impl ToComputedValue for BorderRadius {
/// https://drafts.csswg.org/css-shapes/#typedef-fill-rule
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum FillRule {
NonZero,
EvenOdd,
@ -830,6 +844,7 @@ impl ToCss for FillRule {
/// https://drafts.fxtf.org/css-masking-1/#typedef-geometry-box
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum GeometryBox {
Fill,
Stroke,
@ -868,6 +883,7 @@ impl ComputedValueAsSpecified for GeometryBox {}
// https://drafts.csswg.org/css-shapes-1/#typedef-shape-box
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum ShapeBox {
Margin,
// https://drafts.csswg.org/css-backgrounds-3/#box

Просмотреть файл

@ -2,6 +2,8 @@
* 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/. */
//! A grid line type.
use cssparser::Parser;
use parser::{Parse, ParserContext};
use std::fmt;
@ -9,9 +11,10 @@ use style_traits::ToCss;
use values::NoViewportPercentage;
use values::computed::ComputedValueAsSpecified;
// https://drafts.csswg.org/css-grid/#typedef-grid-row-start-grid-line
#[derive(PartialEq, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// https://drafts.csswg.org/css-grid/#typedef-grid-row-start-grid-line
#[allow(missing_docs)]
pub struct GridLine {
pub is_span: bool,
pub ident: Option<String>,

Просмотреть файл

@ -21,7 +21,9 @@ use values::specified::url::{SpecifiedUrl, UrlExtraData};
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Image {
/// A `<url()>` image.
Url(SpecifiedUrl),
/// A `<gradient>` image.
Gradient(Gradient),
}
@ -35,6 +37,7 @@ impl ToCss for Image {
}
impl Image {
#[allow(missing_docs)]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Image, ()> {
if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
return Ok(Image::Url(url));
@ -151,7 +154,14 @@ impl Gradient {
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum GradientKind {
/// A `<linear-gradient()>`:
///
/// https://drafts.csswg.org/css-images/#funcdef-linear-gradient
Linear(AngleOrCorner),
/// A `<radial-gradient()>`:
///
/// https://drafts.csswg.org/css-images/#radial-gradients
Radial(EndingShape, Position),
}
@ -234,6 +244,7 @@ fn parse_position(context: &ParserContext, input: &mut Parser) -> Result<Positio
/// Specified values for an angle or a corner in a linear gradient.
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum AngleOrCorner {
Angle(Angle),
Corner(Option<HorizontalDirection>, Option<VerticalDirection>),
@ -327,6 +338,7 @@ impl Parse for ColorStop {
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-ending-shape
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum EndingShape {
Circle(LengthOrKeyword),
Ellipse(LengthOrPercentageOrKeyword),
@ -351,6 +363,7 @@ impl ToCss for EndingShape {
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum LengthOrKeyword {
Length(Length),
Keyword(SizeKeyword),
@ -378,6 +391,7 @@ impl ToCss for LengthOrKeyword {
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum LengthOrPercentageOrKeyword {
LengthOrPercentage(LengthOrPercentage, LengthOrPercentage),
Keyword(SizeKeyword),

Просмотреть файл

@ -2,6 +2,10 @@
* 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/. */
//! [Length values][length].
//!
//! [length]: https://drafts.csswg.org/css-values/#lengths
use app_units::Au;
use cssparser::{Parser, Token};
use euclid::size::Size2D;
@ -23,15 +27,22 @@ pub use super::image::{SizeKeyword, VerticalDirection};
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// A font relative length.
pub enum FontRelativeLength {
/// A "em" value: https://drafts.csswg.org/css-values/#em
Em(CSSFloat),
/// A "ex" value: https://drafts.csswg.org/css-values/#ex
Ex(CSSFloat),
/// A "ch" value: https://drafts.csswg.org/css-values/#ch
Ch(CSSFloat),
/// A "rem" value: https://drafts.csswg.org/css-values/#rem
Rem(CSSFloat)
}
impl ToCss for FontRelativeLength {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write
{
match *self {
FontRelativeLength::Em(length) => write!(dest, "{}em", length),
FontRelativeLength::Ex(length) => write!(dest, "{}ex", length),
@ -42,6 +53,8 @@ impl ToCss for FontRelativeLength {
}
impl FontRelativeLength {
/// Gets the first available font metrics from the current context's
/// font-family list.
pub fn find_first_available_font_metrics(context: &Context) -> Option<FontMetrics> {
use font_metrics::FontMetricsQueryResult::*;
if let Some(ref metrics_provider) = context.font_metrics_provider {
@ -55,8 +68,8 @@ impl FontRelativeLength {
None
}
// NB: The use_inherited flag is used to special-case the computation of
// font-family.
/// Computes the font-relative length. We use the use_inherited flag to
/// special-case the computation of font-size.
pub fn to_computed_value(&self, context: &Context, use_inherited: bool) -> Au {
let reference_font_size = if use_inherited {
context.inherited_style().get_font().clone_font_size()
@ -121,10 +134,17 @@ impl FontRelativeLength {
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// A viewport-relative length.
///
/// https://drafts.csswg.org/css-values/#viewport-relative-lengths
pub enum ViewportPercentageLength {
/// A vw unit: https://drafts.csswg.org/css-values/#vw
Vw(CSSFloat),
/// A vh unit: https://drafts.csswg.org/css-values/#vh
Vh(CSSFloat),
/// https://drafts.csswg.org/css-values/#vmin
Vmin(CSSFloat),
/// https://drafts.csswg.org/css-values/#vmax
Vmax(CSSFloat)
}
@ -146,6 +166,7 @@ impl ToCss for ViewportPercentageLength {
}
impl ViewportPercentageLength {
/// Computes the given viewport-relative length for the given viewport size.
pub fn to_computed_value(&self, viewport_size: Size2D<Au>) -> Au {
macro_rules! to_unit {
($viewport_dimension:expr) => {
@ -167,11 +188,13 @@ impl ViewportPercentageLength {
}
}
/// HTML5 "character width", as defined in HTML5 § 14.5.4.
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct CharacterWidth(pub i32);
impl CharacterWidth {
/// Computes the given character width.
pub fn to_computed_value(&self, reference_font_size: Au) -> Au {
// This applies the *converting a character width to pixels* algorithm as specified
// in HTML5 § 14.5.4.
@ -183,11 +206,23 @@ impl CharacterWidth {
}
}
/// A length.
///
/// https://drafts.csswg.org/css-values/#lengths
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Length {
/// An absolute length: https://drafts.csswg.org/css-values/#absolute-length
Absolute(Au), // application units
/// A font-relative length:
///
/// https://drafts.csswg.org/css-values/#font-relative-lengths
FontRelative(FontRelativeLength),
/// A viewport-relative length.
///
/// https://drafts.csswg.org/css-values/#viewport-relative-lengths
ViewportPercentage(ViewportPercentageLength),
/// HTML5 "character width", as defined in HTML5 § 14.5.4.
@ -196,6 +231,12 @@ pub enum Length {
/// `Stylist::synthesize_rules_for_legacy_attributes()`.
ServoCharacterWidth(CharacterWidth),
/// A calc expression.
///
/// https://drafts.csswg.org/css-values/#calc-notation
///
/// TODO(emilio): We have more `Calc` variants around, we should only use
/// one.
Calc(CalcLengthOrPercentage, AllowedNumericType),
}
@ -274,7 +315,7 @@ const AU_PER_PT: CSSFloat = AU_PER_IN / 72.;
const AU_PER_PC: CSSFloat = AU_PER_PT * 12.;
impl Length {
// https://drafts.csswg.org/css-fonts-3/#font-size-prop
/// https://drafts.csswg.org/css-fonts-3/#font-size-prop
pub fn from_str(s: &str) -> Option<Length> {
Some(match_ignore_ascii_case! { s,
"xx-small" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 5),
@ -306,9 +347,13 @@ impl Length {
_ => Err(())
}
}
/// Parse a non-negative length
pub fn parse_non_negative(input: &mut Parser) -> Result<Length, ()> {
Length::parse_internal(input, AllowedNumericType::NonNegative)
}
/// Parse a given absolute or relative dimension.
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Length, ()> {
match_ignore_ascii_case! { unit,
"px" => Ok(Length::from_px(value)),
@ -331,6 +376,8 @@ impl Length {
_ => Err(())
}
}
/// Get an absolute length from a px values.
#[inline]
pub fn from_px(px_value: CSSFloat) -> Length {
Length::Absolute(Au((px_value * AU_PER_PX) as i32))
@ -345,22 +392,29 @@ impl Parse for Length {
impl<T> Either<Length, T> {
#[inline]
#[allow(missing_docs)]
pub fn parse_non_negative_length(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
Length::parse_internal(input, AllowedNumericType::NonNegative).map(Either::First)
}
}
/// A calc sum expression node.
#[derive(Clone, Debug)]
pub struct CalcSumNode {
/// The products of this node.
pub products: Vec<CalcProductNode>,
}
/// A calc product expression node.
#[derive(Clone, Debug)]
pub struct CalcProductNode {
/// The values inside this product node.
values: Vec<CalcValueNode>
}
/// A value inside a `Calc` expression.
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub enum CalcValueNode {
Length(Length),
Angle(Angle),
@ -371,6 +425,7 @@ pub enum CalcValueNode {
}
#[derive(Clone, Copy, PartialEq)]
#[allow(missing_docs)]
pub enum CalcUnit {
Number,
Integer,
@ -382,6 +437,7 @@ pub enum CalcUnit {
#[derive(Clone, PartialEq, Copy, Debug, Default)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct CalcLengthOrPercentage {
pub absolute: Option<Au>,
pub vw: Option<ViewportPercentageLength>,
@ -396,6 +452,7 @@ pub struct CalcLengthOrPercentage {
}
impl CalcLengthOrPercentage {
/// Parse a calc sum node.
pub fn parse_sum(input: &mut Parser, expected_unit: CalcUnit) -> Result<CalcSumNode, ()> {
let mut products = Vec::new();
products.push(try!(CalcLengthOrPercentage::parse_product(input, expected_unit)));
@ -516,6 +573,7 @@ impl CalcLengthOrPercentage {
}
}
#[allow(missing_docs)]
pub fn simplify_product(node: &CalcProductNode) -> Result<SimplifiedValueNode, ()> {
let mut multiplier = 1.;
let mut node_with_unit = None;
@ -554,6 +612,7 @@ impl CalcLengthOrPercentage {
CalcLengthOrPercentage::parse(input, CalcUnit::LengthOrPercentage)
}
#[allow(missing_docs)]
pub fn parse(input: &mut Parser,
expected_unit: CalcUnit) -> Result<CalcLengthOrPercentage, ()> {
let ast = try!(CalcLengthOrPercentage::parse_sum(input, expected_unit));
@ -624,6 +683,7 @@ impl CalcLengthOrPercentage {
})
}
#[allow(missing_docs)]
pub fn parse_time(input: &mut Parser) -> Result<Time, ()> {
let ast = try!(CalcLengthOrPercentage::parse_sum(input, CalcUnit::Time));
@ -651,6 +711,7 @@ impl CalcLengthOrPercentage {
}
}
#[allow(missing_docs)]
pub fn parse_angle(input: &mut Parser) -> Result<Angle, ()> {
let ast = try!(CalcLengthOrPercentage::parse_sum(input, CalcUnit::Angle));
@ -740,9 +801,12 @@ impl ToCss for CalcLengthOrPercentage {
}
}
/// A percentage value.
///
/// [0 .. 100%] maps to [0.0 .. 1.0]
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Percentage(pub CSSFloat); // [0 .. 100%] maps to [0.0 .. 1.0]
pub struct Percentage(pub CSSFloat);
impl ToCss for Percentage {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
@ -762,8 +826,12 @@ impl Parse for Percentage {
}
}
/// A length or a percentage value.
///
/// TODO(emilio): Does this make any sense vs. CalcLengthOrPercentage?
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum LengthOrPercentage {
Length(Length),
Percentage(Percentage),
@ -790,6 +858,7 @@ impl ToCss for LengthOrPercentage {
}
}
impl LengthOrPercentage {
/// Returns a `zero` length.
pub fn zero() -> LengthOrPercentage {
LengthOrPercentage::Length(Length::Absolute(Au(0)))
}
@ -812,6 +881,7 @@ impl LengthOrPercentage {
}
}
/// Parse a non-negative length.
#[inline]
pub fn parse_non_negative(input: &mut Parser) -> Result<LengthOrPercentage, ()> {
LengthOrPercentage::parse_internal(input, AllowedNumericType::NonNegative)
@ -825,8 +895,11 @@ impl Parse for LengthOrPercentage {
}
}
/// TODO(emilio): Do the Length and Percentage variants make any sense with
/// CalcLengthOrPercentage?
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum LengthOrPercentageOrAuto {
Length(Length),
Percentage(Percentage),
@ -875,6 +948,8 @@ impl LengthOrPercentageOrAuto {
_ => Err(())
}
}
/// Parse a non-negative length, percentage, or auto.
#[inline]
pub fn parse_non_negative(input: &mut Parser) -> Result<LengthOrPercentageOrAuto, ()> {
LengthOrPercentageOrAuto::parse_internal(input, AllowedNumericType::NonNegative)
@ -888,8 +963,11 @@ impl Parse for LengthOrPercentageOrAuto {
}
}
/// TODO(emilio): Do the Length and Percentage variants make any sense with
/// CalcLengthOrPercentage?
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum LengthOrPercentageOrNone {
Length(Length),
Percentage(Percentage),
@ -937,6 +1015,7 @@ impl LengthOrPercentageOrNone {
_ => Err(())
}
}
/// Parse a non-negative LengthOrPercentageOrNone.
#[inline]
pub fn parse_non_negative(input: &mut Parser) -> Result<LengthOrPercentageOrNone, ()> {
LengthOrPercentageOrNone::parse_internal(input, AllowedNumericType::NonNegative)
@ -950,19 +1029,31 @@ impl Parse for LengthOrPercentageOrNone {
}
}
/// Either a `<length>` or the `none` keyword.
pub type LengthOrNone = Either<Length, None_>;
/// Either a `<length>` or the `normal` keyword.
pub type LengthOrNormal = Either<Length, Normal>;
/// Either a `<length>` or the `auto` keyword.
pub type LengthOrAuto = Either<Length, Auto>;
/// Either a `<length>` or a `<percentage>` or the `auto` keyword or the
/// `content` keyword.
///
/// TODO(emilio): Do the Length and Percentage variants make any sense with
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum LengthOrPercentageOrAutoOrContent {
/// A `<length>`.
Length(Length),
/// A percentage.
Percentage(Percentage),
/// A `calc` node.
Calc(CalcLengthOrPercentage),
/// The `auto` keyword.
Auto,
/// The `content` keyword.
Content
}
@ -1011,9 +1102,11 @@ impl Parse for LengthOrPercentageOrAutoOrContent {
}
}
/// Either a `<length>` or a `<number>`.
pub type LengthOrNumber = Either<Length, Number>;
impl LengthOrNumber {
/// Parse a non-negative LengthOrNumber.
pub fn parse_non_negative(input: &mut Parser) -> Result<Self, ()> {
if let Ok(v) = input.try(Length::parse_non_negative) {
Ok(Either::First(v))

Просмотреть файл

@ -2,6 +2,10 @@
* 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/. */
//! Specified values.
//!
//! TODO(emilio): Enhance docs.
use app_units::Au;
use cssparser::{self, Parser, Token};
use euclid::size::Size2D;
@ -35,6 +39,7 @@ impl NoViewportPercentage for i32 {} // For PropertyDeclaration::Order
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct CSSColor {
pub parsed: cssparser::Color,
pub authored: Option<String>,
@ -68,6 +73,7 @@ impl ToCss for CSSColor {
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct CSSRGBA {
pub parsed: cssparser::RGBA,
pub authored: Option<String>,
@ -85,6 +91,7 @@ impl ToCss for CSSRGBA {
}
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub struct SimplifiedSumNode {
values: Vec<SimplifiedValueNode>,
}
@ -100,6 +107,7 @@ impl<'a> Mul<CSSFloat> for &'a SimplifiedSumNode {
}
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub enum SimplifiedValueNode {
Length(Length),
Angle(Angle),
@ -127,6 +135,7 @@ impl<'a> Mul<CSSFloat> for &'a SimplifiedValueNode {
}
}
#[allow(missing_docs)]
pub fn parse_integer(input: &mut Parser) -> Result<i32, ()> {
match try!(input.next()) {
Token::Number(ref value) => value.int_value.ok_or(()),
@ -152,6 +161,7 @@ pub fn parse_integer(input: &mut Parser) -> Result<i32, ()> {
}
}
#[allow(missing_docs)]
pub fn parse_number(input: &mut Parser) -> Result<f32, ()> {
match try!(input.next()) {
Token::Number(ref value) => Ok(value.value),
@ -179,20 +189,24 @@ pub fn parse_number(input: &mut Parser) -> Result<f32, ()> {
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct BorderRadiusSize(pub Size2D<LengthOrPercentage>);
impl NoViewportPercentage for BorderRadiusSize {}
impl BorderRadiusSize {
#[allow(missing_docs)]
pub fn zero() -> BorderRadiusSize {
let zero = LengthOrPercentage::Length(Length::Absolute(Au(0)));
BorderRadiusSize(Size2D::new(zero, zero))
}
#[allow(missing_docs)]
pub fn new(width: LengthOrPercentage, height: LengthOrPercentage) -> BorderRadiusSize {
BorderRadiusSize(Size2D::new(width, height))
}
#[allow(missing_docs)]
pub fn circle(radius: LengthOrPercentage) -> BorderRadiusSize {
BorderRadiusSize(Size2D::new(radius, radius))
}
@ -228,11 +242,13 @@ impl ToCss for Angle {
impl Angle {
#[inline]
#[allow(missing_docs)]
pub fn radians(self) -> f32 {
self.0
}
#[inline]
#[allow(missing_docs)]
pub fn from_radians(r: f32) -> Self {
Angle(r)
}
@ -257,6 +273,7 @@ impl Parse for Angle {
}
impl Angle {
#[allow(missing_docs)]
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Angle, ()> {
match_ignore_ascii_case! { unit,
"deg" => Ok(Angle(value * RAD_PER_DEG)),
@ -268,20 +285,22 @@ impl Angle {
}
}
#[allow(missing_docs)]
pub fn parse_border_radius(context: &ParserContext, input: &mut Parser) -> Result<BorderRadiusSize, ()> {
input.try(|i| BorderRadiusSize::parse(context, i)).or_else(|()| {
match_ignore_ascii_case! { try!(input.expect_ident()),
"thin" => Ok(BorderRadiusSize::circle(
LengthOrPercentage::Length(Length::from_px(1.)))),
"medium" => Ok(BorderRadiusSize::circle(
LengthOrPercentage::Length(Length::from_px(3.)))),
"thick" => Ok(BorderRadiusSize::circle(
LengthOrPercentage::Length(Length::from_px(5.)))),
_ => Err(())
}
})
input.try(|i| BorderRadiusSize::parse(context, i)).or_else(|_| {
match_ignore_ascii_case! { try!(input.expect_ident()),
"thin" => Ok(BorderRadiusSize::circle(
LengthOrPercentage::Length(Length::from_px(1.)))),
"medium" => Ok(BorderRadiusSize::circle(
LengthOrPercentage::Length(Length::from_px(3.)))),
"thick" => Ok(BorderRadiusSize::circle(
LengthOrPercentage::Length(Length::from_px(5.)))),
_ => Err(())
}
})
}
#[allow(missing_docs)]
pub fn parse_border_width(input: &mut Parser) -> Result<Length, ()> {
input.try(Length::parse_non_negative).or_else(|()| {
match_ignore_ascii_case! { try!(input.expect_ident()),
@ -295,6 +314,7 @@ pub fn parse_border_width(input: &mut Parser) -> Result<Length, ()> {
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum BorderWidth {
Thin,
Medium,
@ -317,6 +337,7 @@ impl Parse for BorderWidth {
}
impl BorderWidth {
#[allow(missing_docs)]
pub fn from_length(length: Length) -> Self {
BorderWidth::Width(length)
}
@ -382,6 +403,7 @@ define_numbered_css_keyword_enum! { BorderStyle:
impl NoViewportPercentage for BorderStyle {}
impl BorderStyle {
/// Whether this border style is either none or hidden.
pub fn none_or_hidden(&self) -> bool {
matches!(*self, BorderStyle::none | BorderStyle::hidden)
}
@ -435,6 +457,7 @@ impl ToCss for Time {
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct Number(pub CSSFloat);
impl NoViewportPercentage for Number {}
@ -453,10 +476,12 @@ impl Number {
}
}
#[allow(missing_docs)]
pub fn parse_non_negative(input: &mut Parser) -> Result<Number, ()> {
Number::parse_with_minimum(input, 0.0)
}
#[allow(missing_docs)]
pub fn parse_at_least_one(input: &mut Parser) -> Result<Number, ()> {
Number::parse_with_minimum(input, 1.0)
}
@ -482,6 +507,7 @@ impl ToCss for Number {
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct Opacity(pub CSSFloat);
impl NoViewportPercentage for Opacity {}
@ -518,10 +544,12 @@ impl ToCss for Opacity {
}
}
#[allow(missing_docs)]
pub type UrlOrNone = Either<SpecifiedUrl, None_>;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct Shadow {
pub offset_x: Length,
pub offset_y: Length,
@ -573,6 +601,7 @@ impl ToComputedValue for Shadow {
impl Shadow {
// disable_spread_and_inset is for filter: drop-shadow(...)
#[allow(missing_docs)]
pub fn parse(context: &ParserContext, input: &mut Parser, disable_spread_and_inset: bool) -> Result<Shadow, ()> {
use app_units::Au;
let length_count = if disable_spread_and_inset { 3 } else { 4 };

Просмотреть файл

@ -20,8 +20,13 @@ use values::specified::{LengthOrPercentage, Percentage};
#[derive(Debug, Clone, PartialEq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// A [position][pos].
///
/// [pos]: https://drafts.csswg.org/css-values/#position
pub struct Position {
/// The horizontal component.
pub horizontal: HorizontalPosition,
/// The vertical component.
pub vertical: VerticalPosition,
}
@ -59,9 +64,12 @@ impl HasViewportPercentage for Position {
}
impl Position {
pub fn new(mut first_position: Option<PositionComponent>, mut second_position: Option<PositionComponent>,
first_keyword: Option<PositionComponent>, second_keyword: Option<PositionComponent>)
-> Result<Position, ()> {
/// Create a new position value.
pub fn new(mut first_position: Option<PositionComponent>,
mut second_position: Option<PositionComponent>,
first_keyword: Option<PositionComponent>,
second_keyword: Option<PositionComponent>)
-> Result<Position, ()> {
// Unwrap for checking if values are at right place.
let first_key = first_keyword.unwrap_or(PositionComponent::Keyword(Keyword::Left));
let second_key = second_keyword.unwrap_or(PositionComponent::Keyword(Keyword::Top));
@ -150,6 +158,7 @@ impl Position {
})
}
/// Returns a "centered" position, as in "center center".
pub fn center() -> Position {
Position {
horizontal: HorizontalPosition {
@ -242,6 +251,7 @@ impl ToComputedValue for Position {
#[derive(Debug, Clone, PartialEq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct HorizontalPosition {
pub keyword: Option<Keyword>,
pub position: Option<LengthOrPercentage>,
@ -249,11 +259,7 @@ pub struct HorizontalPosition {
impl HasViewportPercentage for HorizontalPosition {
fn has_viewport_percentage(&self) -> bool {
if let Some(pos) = self.position {
pos.has_viewport_percentage()
} else {
false
}
self.position.map_or(false, |pos| pos.has_viewport_percentage())
}
}
@ -371,6 +377,7 @@ impl ToComputedValue for HorizontalPosition {
#[derive(Debug, Clone, PartialEq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct VerticalPosition {
pub keyword: Option<Keyword>,
pub position: Option<LengthOrPercentage>,
@ -378,11 +385,7 @@ pub struct VerticalPosition {
impl HasViewportPercentage for VerticalPosition {
fn has_viewport_percentage(&self) -> bool {
if let Some(pos) = self.position {
pos.has_viewport_percentage()
} else {
false
}
self.position.map_or(false, |pos| pos.has_viewport_percentage())
}
}
@ -510,6 +513,7 @@ define_css_keyword_enum!(Keyword:
"y-end" => YEnd);
impl Keyword {
/// Convert the given keyword to a length or a percentage.
pub fn to_length_or_percentage(self) -> LengthOrPercentage {
match self {
Keyword::Center => LengthOrPercentage::Percentage(Percentage(0.5)),
@ -532,10 +536,14 @@ enum PositionCategory {
LengthOrPercentage,
}
// http://dev.w3.org/csswg/css2/colors.html#propdef-background-position
/// A position component.
///
/// http://dev.w3.org/csswg/css2/colors.html#propdef-background-position
#[derive(Clone, PartialEq, Copy)]
pub enum PositionComponent {
/// A `<length>`
Length(LengthOrPercentage),
/// A position keyword.
Keyword(Keyword),
}
@ -568,6 +576,7 @@ impl HasViewportPercentage for PositionComponent {
}
impl PositionComponent {
/// Convert the given position component to a length or a percentage.
#[inline]
pub fn to_length_or_percentage(self) -> LengthOrPercentage {
match self {

Просмотреть файл

@ -18,23 +18,29 @@ use style_traits::ToCss;
use values::NoViewportPercentage;
use values::computed::ComputedValueAsSpecified;
/// A set of data needed in Gecko to represent a URL.
#[derive(PartialEq, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Serialize, Deserialize, Eq))]
pub struct UrlExtraData {
/// The base URI.
#[cfg(feature = "gecko")]
pub base: GeckoArcURI,
/// The referrer.
#[cfg(feature = "gecko")]
pub referrer: GeckoArcURI,
/// The principal that originated this URI.
#[cfg(feature = "gecko")]
pub principal: GeckoArcPrincipal,
}
impl UrlExtraData {
/// Constructs a `UrlExtraData`.
#[cfg(feature = "servo")]
pub fn make_from(_: &ParserContext) -> Option<UrlExtraData> {
Some(UrlExtraData { })
}
/// Constructs a `UrlExtraData`.
#[cfg(feature = "gecko")]
pub fn make_from(context: &ParserContext) -> Option<UrlExtraData> {
match context.extra_data {
@ -81,6 +87,11 @@ impl Parse for SpecifiedUrl {
}
impl SpecifiedUrl {
/// Try to parse a URL from a string value that is a valid CSS token for a
/// URL.
///
/// Only returns `Err` for Gecko, in the case we can't construct a
/// `URLExtraData`.
pub fn parse_from_string<'a>(url: Cow<'a, str>,
context: &ParserContext)
-> Result<Self, ()> {
@ -104,14 +115,19 @@ impl SpecifiedUrl {
})
}
/// Get this URL's extra data.
pub fn extra_data(&self) -> &UrlExtraData {
&self.extra_data
}
/// Returns the resolved url if it was valid.
pub fn url(&self) -> Option<&ServoUrl> {
self.resolved.as_ref()
}
/// Return the resolved url as string, or the empty string if it's invalid.
///
/// TODO(emilio): Should we return the original one if needed?
pub fn as_str(&self) -> &str {
match self.resolved {
Some(ref url) => url.as_str(),
@ -142,6 +158,7 @@ impl SpecifiedUrl {
}
}
/// Gets a new url from a string for unit tests.
#[cfg(feature = "servo")]
pub fn new_for_testing(url: &str) -> Self {
SpecifiedUrl {

Просмотреть файл

@ -7,6 +7,8 @@
//! [at]: https://drafts.csswg.org/css-device-adapt/#atviewport-rule
//! [meta]: https://drafts.csswg.org/css-device-adapt/#viewport-meta
#![deny(missing_docs)]
use app_units::Au;
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important};
use cssparser::ToCss as ParserToCss;
@ -60,6 +62,7 @@ macro_rules! declare_viewport_descriptor_inner {
) => {
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum ViewportDescriptor {
$(
$assigned_variant($assigned_data),
@ -69,6 +72,7 @@ macro_rules! declare_viewport_descriptor_inner {
const VIEWPORT_DESCRIPTOR_VARIANTS: usize = $number_of_variants;
impl ViewportDescriptor {
#[allow(missing_docs)]
pub fn discriminant_value(&self) -> usize {
match *self {
$(
@ -114,12 +118,13 @@ trait FromMeta: Sized {
fn from_meta(value: &str) -> Option<Self>;
}
// ViewportLength is a length | percentage | auto | extend-to-zoom
// See:
// * http://dev.w3.org/csswg/css-device-adapt/#min-max-width-desc
// * http://dev.w3.org/csswg/css-device-adapt/#extend-to-zoom
/// ViewportLength is a length | percentage | auto | extend-to-zoom
/// See:
/// * http://dev.w3.org/csswg/css-device-adapt/#min-max-width-desc
/// * http://dev.w3.org/csswg/css-device-adapt/#extend-to-zoom
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum ViewportLength {
Specified(LengthOrPercentageOrAuto),
ExtendToZoom
@ -127,7 +132,7 @@ pub enum ViewportLength {
impl ToCss for ViewportLength {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write
where W: fmt::Write,
{
match *self {
ViewportLength::Specified(length) => length.to_css(dest),
@ -209,6 +214,7 @@ struct ViewportRuleParser<'a, 'b: 'a> {
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct ViewportDescriptorDeclaration {
pub origin: Origin,
pub descriptor: ViewportDescriptor,
@ -216,6 +222,7 @@ pub struct ViewportDescriptorDeclaration {
}
impl ViewportDescriptorDeclaration {
#[allow(missing_docs)]
pub fn new(origin: Origin,
descriptor: ViewportDescriptor,
important: bool) -> ViewportDescriptorDeclaration
@ -313,9 +320,11 @@ impl<'a, 'b> DeclarationParser for ViewportRuleParser<'a, 'b> {
}
}
/// A `@viewport` rule.
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct ViewportRule {
/// The declarations contained in this @viewport rule.
pub declarations: Vec<ViewportDescriptorDeclaration>
}
@ -333,6 +342,7 @@ fn is_whitespace_separator_or_equals(c: &char) -> bool {
}
impl ViewportRule {
#[allow(missing_docs)]
pub fn parse(input: &mut Parser, context: &ParserContext)
-> Result<ViewportRule, ()>
{
@ -358,6 +368,7 @@ impl ViewportRule {
Ok(ViewportRule { declarations: cascade.finish() })
}
#[allow(missing_docs)]
pub fn from_meta(content: &str) -> Option<ViewportRule> {
let mut declarations = vec![None; VIEWPORT_DESCRIPTOR_VARIANTS];
macro_rules! push_descriptor {
@ -531,11 +542,13 @@ impl ViewportDescriptorDeclaration {
}
}
#[allow(missing_docs)]
pub struct Cascade {
declarations: Vec<Option<(usize, ViewportDescriptorDeclaration)>>,
count_so_far: usize,
}
#[allow(missing_docs)]
impl Cascade {
pub fn new() -> Self {
Cascade {
@ -545,7 +558,9 @@ impl Cascade {
}
pub fn from_stylesheets<'a, I>(stylesheets: I, device: &Device) -> Self
where I: IntoIterator, I::Item: AsRef<Stylesheet> {
where I: IntoIterator,
I::Item: AsRef<Stylesheet>,
{
let mut cascade = Self::new();
for stylesheet in stylesheets {
stylesheet.as_ref().effective_viewport_rules(device, |rule| {
@ -581,10 +596,13 @@ impl Cascade {
}
}
/// Just a helper trait to be able to implement methods on ViewportConstraints.
pub trait MaybeNew {
/// Create a ViewportConstraints from a viewport size and a `@viewport`
/// rule.
fn maybe_new(initial_viewport: TypedSize2D<f32, ViewportPx>,
rule: &ViewportRule)
-> Option<ViewportConstraints>;
rule: &ViewportRule)
-> Option<ViewportConstraints>;
}
impl MaybeNew for ViewportConstraints {

Просмотреть файл

@ -8,14 +8,17 @@ use super::ToCss;
macro_rules! define_cursor {
($( $css: expr => $variant: ident = $value: expr, )+) => {
/// https://drafts.csswg.org/css-ui/#cursor
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize, HeapSizeOf))]
#[repr(u8)]
#[allow(missing_docs)]
pub enum Cursor {
$( $variant = $value ),+
}
impl Cursor {
/// Given a CSS keyword, get the corresponding cursor enum.
pub fn from_css_keyword(keyword: &str) -> Result<Cursor, ()> {
match_ignore_ascii_case! { keyword,
$( concat!($css) => Ok(Cursor::$variant), )+

Просмотреть файл

@ -9,7 +9,7 @@
#![crate_name = "style_traits"]
#![crate_type = "rlib"]
#![deny(unsafe_code)]
#![deny(unsafe_code, missing_docs)]
#![cfg_attr(feature = "servo", feature(plugin))]
#![cfg_attr(feature = "servo", feature(proc_macro))]

Просмотреть файл

@ -2,6 +2,8 @@
* 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/. */
//! Helper types and traits for the handling of CSS values.
use app_units::Au;
use std::fmt;
@ -78,13 +80,14 @@ macro_rules! __define_css_keyword_enum__add_optional_traits {
#[macro_export]
macro_rules! __define_css_keyword_enum__actual {
($name: ident [ $( $derived_trait: ident),* ] [ $( $css: expr => $variant: ident ),+ ]) => {
#[allow(non_camel_case_types)]
#[allow(non_camel_case_types, missing_docs)]
#[derive(Clone, Eq, PartialEq, Copy, Hash, RustcEncodable, Debug $(, $derived_trait )* )]
pub enum $name {
$( $variant ),+
}
impl $name {
/// Parse this property from a CSS input stream.
pub fn parse(input: &mut ::cssparser::Parser) -> Result<$name, ()> {
match_ignore_ascii_case! { try!(input.expect_ident()),
$( $css => Ok($name::$variant), )+
@ -95,27 +98,33 @@ macro_rules! __define_css_keyword_enum__actual {
impl ToCss for $name {
fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
where W: ::std::fmt::Write {
match *self {
$( $name::$variant => dest.write_str($css) ),+
}
where W: ::std::fmt::Write
{
match *self {
$( $name::$variant => dest.write_str($css) ),+
}
}
}
}
}
/// Helper types for the handling of specified values.
pub mod specified {
use app_units::Au;
/// Whether to allow negative values or not.
#[repr(u8)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AllowedNumericType {
/// Allow all kind of numeric values.
All,
/// Allow only non-negative values.
NonNegative
}
impl AllowedNumericType {
/// Whether value is valid for this allowed numeric type.
#[inline]
pub fn is_ok(&self, value: f32) -> bool {
match *self {
@ -124,6 +133,7 @@ pub mod specified {
}
}
/// Clamp the value following the rules of this numeric type.
#[inline]
pub fn clamp(&self, val: Au) -> Au {
use std::cmp;

Просмотреть файл

@ -2,6 +2,8 @@
* 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/. */
//! Helper types for the `@viewport` rule.
use {PagePx, ViewportPx};
use cssparser::{Parser, ToCss};
use euclid::scale_factor::ScaleFactor;
@ -20,16 +22,25 @@ define_css_keyword_enum!(Orientation:
"landscape" => Landscape);
/// A set of viewport descriptors:
///
/// https://drafts.csswg.org/css-device-adapt/#viewport-desc
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize, HeapSizeOf))]
pub struct ViewportConstraints {
/// Width and height:
/// * https://drafts.csswg.org/css-device-adapt/#width-desc
/// * https://drafts.csswg.org/css-device-adapt/#height-desc
pub size: TypedSize2D<f32, ViewportPx>,
/// https://drafts.csswg.org/css-device-adapt/#zoom-desc
pub initial_zoom: ScaleFactor<f32, PagePx, ViewportPx>,
/// https://drafts.csswg.org/css-device-adapt/#min-max-width-desc
pub min_zoom: Option<ScaleFactor<f32, PagePx, ViewportPx>>,
/// https://drafts.csswg.org/css-device-adapt/#min-max-width-desc
pub max_zoom: Option<ScaleFactor<f32, PagePx, ViewportPx>>,
/// https://drafts.csswg.org/css-device-adapt/#user-zoom-desc
pub user_zoom: UserZoom,
/// https://drafts.csswg.org/css-device-adapt/#orientation-desc
pub orientation: Orientation
}
@ -53,19 +64,21 @@ impl ToCss for ViewportConstraints {
}
}
/// Zoom is a number | percentage | auto
/// See http://dev.w3.org/csswg/css-device-adapt/#descdef-viewport-zoom
/// https://drafts.csswg.org/css-device-adapt/#descdef-viewport-zoom
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Zoom {
/// A number value.
Number(f32),
/// A percentage value.
Percentage(f32),
/// The `auto` keyword.
Auto,
}
impl ToCss for Zoom {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write
where W: fmt::Write,
{
match *self {
Zoom::Number(number) => write!(dest, "{}", number),
@ -76,6 +89,9 @@ impl ToCss for Zoom {
}
impl Zoom {
/// Parse a zoom value per:
///
/// https://drafts.csswg.org/css-device-adapt/#descdef-viewport-zoom
pub fn parse(input: &mut Parser) -> Result<Zoom, ()> {
use cssparser::Token;
@ -90,6 +106,8 @@ impl Zoom {
}
}
/// Get this zoom value as a float value. Returns `None` if the value is the
/// `auto` keyword.
#[inline]
pub fn to_f32(&self) -> Option<f32> {
match *self {