mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Auto merge of #14801 - emilio:no-missing-docs, r=mbrubeck,Manishearth,Wafflespeanut
style: Document and force documentation in a big chunk of the style crate. 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. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/14801) <!-- Reviewable:end -->
This commit is contained in:
commit
bd67163438
44 changed files with 1216 additions and 462 deletions
|
@ -88,7 +88,7 @@ pub fn update_animation_state(constellation_chan: &IpcSender<ConstellationMsg>,
|
||||||
if let Animation::Transition(_, unsafe_node, _, ref frame, _) = running_animation {
|
if let Animation::Transition(_, unsafe_node, _, ref frame, _) = running_animation {
|
||||||
script_chan.send(ConstellationControlMsg::TransitionEnd(unsafe_node,
|
script_chan.send(ConstellationControlMsg::TransitionEnd(unsafe_node,
|
||||||
frame.property_animation
|
frame.property_animation
|
||||||
.property_name(),
|
.property_name().into(),
|
||||||
frame.duration))
|
frame.duration))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2005,7 +2005,7 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
// See CSS 2.1 § 10.8.1.
|
// See CSS 2.1 § 10.8.1.
|
||||||
let font_metrics = text::font_metrics_for_style(&mut layout_context.font_context(),
|
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);
|
let line_height = text::line_height_from_style(&*self.style, &font_metrics);
|
||||||
InlineMetrics::from_font_metrics(&info.run.font_metrics, line_height)
|
InlineMetrics::from_font_metrics(&info.run.font_metrics, line_height)
|
||||||
}
|
}
|
||||||
|
@ -2085,7 +2085,7 @@ impl Fragment {
|
||||||
vertical_align::T::middle => {
|
vertical_align::T::middle => {
|
||||||
let font_metrics =
|
let font_metrics =
|
||||||
text::font_metrics_for_style(&mut layout_context.font_context(),
|
text::font_metrics_for_style(&mut layout_context.font_context(),
|
||||||
style.get_font_arc());
|
style.clone_font());
|
||||||
offset += (content_inline_metrics.ascent -
|
offset += (content_inline_metrics.ascent -
|
||||||
content_inline_metrics.space_below_baseline -
|
content_inline_metrics.space_below_baseline -
|
||||||
font_metrics.x_height).scale_by(0.5)
|
font_metrics.x_height).scale_by(0.5)
|
||||||
|
|
|
@ -1089,7 +1089,7 @@ impl InlineFlow {
|
||||||
return LineMetrics::new(Au(0), Au(0))
|
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 font_metrics = text::font_metrics_for_style(font_context, font_style);
|
||||||
let line_height = text::line_height_from_style(style, &font_metrics);
|
let line_height = text::line_height_from_style(style, &font_metrics);
|
||||||
let inline_metrics = InlineMetrics::from_font_metrics(&font_metrics, line_height);
|
let inline_metrics = InlineMetrics::from_font_metrics(&font_metrics, line_height);
|
||||||
|
@ -1112,7 +1112,7 @@ impl InlineFlow {
|
||||||
for inline_context in fragments.iter()
|
for inline_context in fragments.iter()
|
||||||
.filter_map(|fragment| fragment.inline_context.as_ref()) {
|
.filter_map(|fragment| fragment.inline_context.as_ref()) {
|
||||||
for node in &inline_context.nodes {
|
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 font_metrics = text::font_metrics_for_style(font_context, font_style);
|
||||||
let line_height = text::line_height_from_style(&*node.style, &font_metrics);
|
let line_height = text::line_height_from_style(&*node.style, &font_metrics);
|
||||||
let inline_metrics = InlineMetrics::from_font_metrics(&font_metrics, line_height);
|
let inline_metrics = InlineMetrics::from_font_metrics(&font_metrics, line_height);
|
||||||
|
|
|
@ -154,7 +154,7 @@ impl TextRunScanner {
|
||||||
let word_break;
|
let word_break;
|
||||||
{
|
{
|
||||||
let in_fragment = self.clump.front().unwrap();
|
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();
|
let inherited_text_style = in_fragment.style().get_inheritedtext();
|
||||||
fontgroup = font_context.layout_font_group_for_style(font_style);
|
fontgroup = font_context.layout_font_group_for_style(font_style);
|
||||||
compression = match in_fragment.white_space() {
|
compression = match in_fragment.white_space() {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
//! CSS transitions and animations.
|
//! CSS transitions and animations.
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use Atom;
|
use Atom;
|
||||||
use bezier::Bezier;
|
use bezier::Bezier;
|
||||||
|
@ -28,8 +29,9 @@ use values::computed::Time;
|
||||||
/// have to keep track the current iteration and the max iteration count.
|
/// have to keep track the current iteration and the max iteration count.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum KeyframesIterationState {
|
pub enum KeyframesIterationState {
|
||||||
|
/// Infinite iterations, so no need to track a state.
|
||||||
Infinite,
|
Infinite,
|
||||||
// current, max
|
/// Current and max iterations.
|
||||||
Finite(u32, u32),
|
Finite(u32, u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,6 +194,7 @@ pub enum Animation {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Animation {
|
impl Animation {
|
||||||
|
/// Mark this animation as expired.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mark_as_expired(&mut self) {
|
pub fn mark_as_expired(&mut self) {
|
||||||
debug_assert!(!self.is_expired());
|
debug_assert!(!self.is_expired());
|
||||||
|
@ -201,6 +204,7 @@ impl Animation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether this animation is expired.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_expired(&self) -> bool {
|
pub fn is_expired(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -209,6 +213,7 @@ impl Animation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The opaque node that owns the animation.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn node(&self) -> &OpaqueNode {
|
pub fn node(&self) -> &OpaqueNode {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -217,6 +222,7 @@ impl Animation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether this animation is paused. A transition can never be paused.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_paused(&self) -> bool {
|
pub fn is_paused(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -237,6 +243,7 @@ pub struct AnimationFrame {
|
||||||
pub duration: f64,
|
pub duration: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents an animation for a given property.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PropertyAnimation {
|
pub struct PropertyAnimation {
|
||||||
property: AnimatedProperty,
|
property: AnimatedProperty,
|
||||||
|
@ -245,13 +252,15 @@ pub struct PropertyAnimation {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PropertyAnimation {
|
impl PropertyAnimation {
|
||||||
pub fn property_name(&self) -> String {
|
/// Returns the given property name.
|
||||||
|
pub fn property_name(&self) -> &'static str {
|
||||||
self.property.name()
|
self.property.name()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new property animation for the given transition index and old and new styles.
|
/// Creates a new property animation for the given transition index and old
|
||||||
/// Any number of animations may be returned, from zero (if the property did not animate) to
|
/// and new styles. Any number of animations may be returned, from zero (if
|
||||||
/// one (for a single transition property) to arbitrarily many (for `all`).
|
/// the property did not animate) to one (for a single transition property)
|
||||||
|
/// to arbitrarily many (for `all`).
|
||||||
pub fn from_transition(transition_index: usize,
|
pub fn from_transition(transition_index: usize,
|
||||||
old_style: &ComputedValues,
|
old_style: &ComputedValues,
|
||||||
new_style: &mut 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) {
|
pub fn update(&self, style: &mut ComputedValues, time: f64) {
|
||||||
let progress = match self.timing_function {
|
let progress = match self.timing_function {
|
||||||
TransitionTimingFunction::CubicBezier(p1, p2) => {
|
TransitionTimingFunction::CubicBezier(p1, p2) => {
|
||||||
|
@ -336,8 +346,9 @@ impl PropertyAnimation {
|
||||||
self.property.does_animate() && self.duration != Time(0.0)
|
self.property.does_animate() && self.duration != Time(0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether this animation has the same end value as another one.
|
||||||
#[inline]
|
#[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)
|
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,
|
pub fn maybe_start_animations(context: &SharedStyleContext,
|
||||||
new_animations_sender: &Sender<Animation>,
|
new_animations_sender: &Sender<Animation>,
|
||||||
node: OpaqueNode,
|
node: OpaqueNode,
|
||||||
|
|
|
@ -2,18 +2,22 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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};
|
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> {
|
pub struct LRUCache<K, V> {
|
||||||
entries: Vec<(K, V)>,
|
entries: Vec<(K, V)>,
|
||||||
cache_size: usize,
|
cache_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K: PartialEq, V: Clone> LRUCache<K, V> {
|
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> {
|
pub fn new(size: usize) -> LRUCache<K, V> {
|
||||||
LRUCache {
|
LRUCache {
|
||||||
entries: vec![],
|
entries: vec![],
|
||||||
|
@ -22,6 +26,7 @@ impl<K: PartialEq, V: Clone> LRUCache<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
/// Touch a given position, and put it in the last item on the list.
|
||||||
pub fn touch(&mut self, pos: usize) -> &V {
|
pub fn touch(&mut self, pos: usize) -> &V {
|
||||||
let last_index = self.entries.len() - 1;
|
let last_index = self.entries.len() - 1;
|
||||||
if pos != last_index {
|
if pos != last_index {
|
||||||
|
@ -31,14 +36,17 @@ impl<K: PartialEq, V: Clone> LRUCache<K, V> {
|
||||||
&self.entries[last_index].1
|
&self.entries[last_index].1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iterate over the contents of this cache.
|
||||||
pub fn iter(&self) -> Iter<(K, V)> {
|
pub fn iter(&self) -> Iter<(K, V)> {
|
||||||
self.entries.iter()
|
self.entries.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iterate mutably over the contents of this cache.
|
||||||
pub fn iter_mut(&mut self) -> IterMut<(K, V)> {
|
pub fn iter_mut(&mut self) -> IterMut<(K, V)> {
|
||||||
self.entries.iter_mut()
|
self.entries.iter_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Insert a given key and value in the cache.
|
||||||
pub fn insert(&mut self, key: K, val: V) {
|
pub fn insert(&mut self, key: K, val: V) {
|
||||||
if self.entries.len() == self.cache_size {
|
if self.entries.len() == self.cache_size {
|
||||||
self.entries.remove(0);
|
self.entries.remove(0);
|
||||||
|
@ -46,6 +54,7 @@ impl<K: PartialEq, V: Clone> LRUCache<K, V> {
|
||||||
self.entries.push((key, val));
|
self.entries.push((key, val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Try to find a key in the cache.
|
||||||
pub fn find(&mut self, key: &K) -> Option<V> {
|
pub fn find(&mut self, key: &K) -> Option<V> {
|
||||||
match self.entries.iter().position(|&(ref k, _)| key == k) {
|
match self.entries.iter().position(|&(ref k, _)| key == k) {
|
||||||
Some(pos) => Some(self.touch(pos).clone()),
|
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) {
|
match self.entries.iter().position(|&(ref k, _)| *k == key) {
|
||||||
Some(pos) => self.touch(pos).clone(),
|
Some(pos) => self.touch(pos).clone(),
|
||||||
None => {
|
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) {
|
pub fn evict_all(&mut self) {
|
||||||
self.entries.clear();
|
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.
|
//! Per-node data used in style calculation.
|
||||||
|
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use dom::TElement;
|
use dom::TElement;
|
||||||
use properties::ComputedValues;
|
use properties::ComputedValues;
|
||||||
use properties::longhands::display::computed_value as display;
|
use properties::longhands::display::computed_value as display;
|
||||||
|
@ -19,6 +21,9 @@ use std::sync::Arc;
|
||||||
use stylist::Stylist;
|
use stylist::Stylist;
|
||||||
use thread_state;
|
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)]
|
#[derive(Clone)]
|
||||||
pub struct ComputedStyle {
|
pub struct ComputedStyle {
|
||||||
/// The rule node representing the ordered list of rules matched for this
|
/// The rule node representing the ordered list of rules matched for this
|
||||||
|
@ -31,6 +36,7 @@ pub struct ComputedStyle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComputedStyle {
|
impl ComputedStyle {
|
||||||
|
/// Trivially construct a new `ComputedStyle`.
|
||||||
pub fn new(rules: StrongRuleNode, values: Arc<ComputedValues>) -> Self {
|
pub fn new(rules: StrongRuleNode, values: Arc<ComputedValues>) -> Self {
|
||||||
ComputedStyle {
|
ComputedStyle {
|
||||||
rules: rules,
|
rules: rules,
|
||||||
|
@ -49,10 +55,18 @@ impl fmt::Debug for ComputedStyle {
|
||||||
|
|
||||||
type PseudoStylesInner = HashMap<PseudoElement, ComputedStyle,
|
type PseudoStylesInner = HashMap<PseudoElement, ComputedStyle,
|
||||||
BuildHasherDefault<::fnv::FnvHasher>>;
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PseudoStyles(PseudoStylesInner);
|
pub struct PseudoStyles(PseudoStylesInner);
|
||||||
|
|
||||||
impl PseudoStyles {
|
impl PseudoStyles {
|
||||||
|
/// Construct an empty set of `PseudoStyles`.
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
PseudoStyles(HashMap::with_hasher(Default::default()))
|
PseudoStyles(HashMap::with_hasher(Default::default()))
|
||||||
}
|
}
|
||||||
|
@ -71,11 +85,14 @@ impl DerefMut for PseudoStyles {
|
||||||
/// pseudo-elements.
|
/// pseudo-elements.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ElementStyles {
|
pub struct ElementStyles {
|
||||||
|
/// The element's style.
|
||||||
pub primary: ComputedStyle,
|
pub primary: ComputedStyle,
|
||||||
|
/// The map of styles for the element's pseudos.
|
||||||
pub pseudos: PseudoStyles,
|
pub pseudos: PseudoStyles,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ElementStyles {
|
impl ElementStyles {
|
||||||
|
/// Trivially construct a new `ElementStyles`.
|
||||||
pub fn new(primary: ComputedStyle) -> Self {
|
pub fn new(primary: ComputedStyle) -> Self {
|
||||||
ElementStyles {
|
ElementStyles {
|
||||||
primary: primary,
|
primary: primary,
|
||||||
|
@ -83,6 +100,7 @@ impl ElementStyles {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether this element `display` value is `none`.
|
||||||
pub fn is_display_none(&self) -> bool {
|
pub fn is_display_none(&self) -> bool {
|
||||||
self.primary.values.get_box().clone_display() == display::T::none
|
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.
|
/// to provide more type safety while propagating restyle hints down the tree.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct StoredRestyleHint {
|
pub struct StoredRestyleHint {
|
||||||
|
/// Whether this element should be restyled during the traversal.
|
||||||
pub restyle_self: bool,
|
pub restyle_self: bool,
|
||||||
|
/// Whether the descendants of this element need to be restyled.
|
||||||
pub descendants: DescendantRestyleHint,
|
pub descendants: DescendantRestyleHint,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,6 +160,7 @@ impl StoredRestyleHint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an empty `StoredRestyleHint`.
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
StoredRestyleHint {
|
StoredRestyleHint {
|
||||||
restyle_self: false,
|
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 {
|
pub fn subtree() -> Self {
|
||||||
StoredRestyleHint {
|
StoredRestyleHint {
|
||||||
restyle_self: true,
|
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 {
|
pub fn is_empty(&self) -> bool {
|
||||||
!self.restyle_self && self.descendants == DescendantRestyleHint::Empty
|
!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) {
|
pub fn insert(&mut self, other: &Self) {
|
||||||
self.restyle_self = self.restyle_self || other.restyle_self;
|
self.restyle_self = self.restyle_self || other.restyle_self;
|
||||||
self.descendants = self.descendants.union(other.descendants);
|
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;
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct SnapshotOption {
|
pub struct SnapshotOption {
|
||||||
snapshot: Option<Snapshot>,
|
snapshot: Option<Snapshot>,
|
||||||
|
@ -197,6 +222,7 @@ pub struct SnapshotOption {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SnapshotOption {
|
impl SnapshotOption {
|
||||||
|
/// An empty snapshot.
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
SnapshotOption {
|
SnapshotOption {
|
||||||
snapshot: None,
|
snapshot: None,
|
||||||
|
@ -204,11 +230,13 @@ impl SnapshotOption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Destroy this snapshot.
|
||||||
pub fn destroy(&mut self) {
|
pub fn destroy(&mut self) {
|
||||||
self.destroyed = true;
|
self.destroyed = true;
|
||||||
debug_assert!(self.is_none());
|
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 {
|
pub fn ensure<F: FnOnce() -> Snapshot>(&mut self, create: F) -> &mut Snapshot {
|
||||||
debug_assert!(thread_state::get().is_layout());
|
debug_assert!(thread_state::get().is_layout());
|
||||||
if self.is_none() {
|
if self.is_none() {
|
||||||
|
@ -234,7 +262,12 @@ impl Deref for SnapshotOption {
|
||||||
/// Transient data used by the restyle algorithm. This structure is instantiated
|
/// 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
|
/// either before or during restyle traversal, and is cleared at the end of node
|
||||||
/// processing.
|
/// 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)]
|
#[derive(Debug)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct RestyleData {
|
pub struct RestyleData {
|
||||||
pub styles: ElementStyles,
|
pub styles: ElementStyles,
|
||||||
pub hint: StoredRestyleHint,
|
pub hint: StoredRestyleHint,
|
||||||
|
@ -254,8 +287,8 @@ impl RestyleData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expands the snapshot (if any) into a restyle hint. Returns true if later siblings
|
/// Expands the snapshot (if any) into a restyle hint. Returns true if later
|
||||||
/// must be restyled.
|
/// siblings must be restyled.
|
||||||
pub fn expand_snapshot<E: TElement>(&mut self, element: E, stylist: &Stylist) -> bool {
|
pub fn expand_snapshot<E: TElement>(&mut self, element: E, stylist: &Stylist) -> bool {
|
||||||
if self.snapshot.is_none() {
|
if self.snapshot.is_none() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -281,14 +314,17 @@ impl RestyleData {
|
||||||
later_siblings
|
later_siblings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return if the element style's are up to date.
|
||||||
pub fn has_current_styles(&self) -> bool {
|
pub fn has_current_styles(&self) -> bool {
|
||||||
!(self.hint.restyle_self || self.recascade || self.snapshot.is_some())
|
!(self.hint.restyle_self || self.recascade || self.snapshot.is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the element styles.
|
||||||
pub fn styles(&self) -> &ElementStyles {
|
pub fn styles(&self) -> &ElementStyles {
|
||||||
&self.styles
|
&self.styles
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable reference to the element styles.
|
||||||
pub fn styles_mut(&mut self) -> &mut ElementStyles {
|
pub fn styles_mut(&mut self) -> &mut ElementStyles {
|
||||||
&mut self.styles
|
&mut self.styles
|
||||||
}
|
}
|
||||||
|
@ -317,12 +353,18 @@ impl RestyleData {
|
||||||
/// safety.
|
/// safety.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ElementData {
|
pub enum ElementData {
|
||||||
|
/// This is the first styling for this element.
|
||||||
Initial(Option<ElementStyles>),
|
Initial(Option<ElementStyles>),
|
||||||
|
/// This element has been restyled already, and all the relevant data is
|
||||||
|
/// inside the `RestyleData`.
|
||||||
Restyle(RestyleData),
|
Restyle(RestyleData),
|
||||||
|
/// This element has already been restyled, and only keeps its styles
|
||||||
|
/// around.
|
||||||
Persistent(ElementStyles),
|
Persistent(ElementStyles),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ElementData {
|
impl ElementData {
|
||||||
|
/// Trivially construct an ElementData.
|
||||||
pub fn new(existing: Option<ElementStyles>) -> Self {
|
pub fn new(existing: Option<ElementStyles>) -> Self {
|
||||||
if let Some(s) = existing {
|
if let Some(s) = existing {
|
||||||
ElementData::Persistent(s)
|
ElementData::Persistent(s)
|
||||||
|
@ -331,6 +373,7 @@ impl ElementData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return whether this data is from an initial restyle.
|
||||||
pub fn is_initial(&self) -> bool {
|
pub fn is_initial(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
ElementData::Initial(_) => true,
|
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 {
|
pub fn is_unstyled_initial(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
ElementData::Initial(None) => true,
|
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 {
|
pub fn is_styled_initial(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
ElementData::Initial(Some(_)) => true,
|
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 {
|
pub fn is_restyle(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
ElementData::Restyle(_) => true,
|
ElementData::Restyle(_) => true,
|
||||||
|
@ -359,6 +407,7 @@ impl ElementData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the `RestyleData` if it exists.
|
||||||
pub fn as_restyle(&self) -> Option<&RestyleData> {
|
pub fn as_restyle(&self) -> Option<&RestyleData> {
|
||||||
match *self {
|
match *self {
|
||||||
ElementData::Restyle(ref x) => Some(x),
|
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> {
|
pub fn as_restyle_mut(&mut self) -> Option<&mut RestyleData> {
|
||||||
match *self {
|
match *self {
|
||||||
ElementData::Restyle(ref mut x) => Some(x),
|
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 {
|
pub fn is_persistent(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
ElementData::Persistent(_) => true,
|
ElementData::Persistent(_) => true,
|
||||||
|
@ -428,6 +479,7 @@ impl ElementData {
|
||||||
*self = ElementData::Persistent(styles);
|
*self = ElementData::Persistent(styles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the restyle damage (if any).
|
||||||
pub fn damage(&self) -> RestyleDamage {
|
pub fn damage(&self) -> RestyleDamage {
|
||||||
use self::ElementData::*;
|
use self::ElementData::*;
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -443,8 +495,8 @@ impl ElementData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A version of the above, with the assertions replaced with warnings to
|
/// A version of the above, with the assertions replaced with warnings to
|
||||||
// be more robust in corner-cases. This will go away soon.
|
/// be more robust in corner-cases. This will go away soon.
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub fn damage_sloppy(&self) -> RestyleDamage {
|
pub fn damage_sloppy(&self) -> RestyleDamage {
|
||||||
use self::ElementData::*;
|
use self::ElementData::*;
|
||||||
|
@ -476,6 +528,7 @@ impl ElementData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the element styles, if any.
|
||||||
pub fn get_styles(&self) -> Option<&ElementStyles> {
|
pub fn get_styles(&self) -> Option<&ElementStyles> {
|
||||||
use self::ElementData::*;
|
use self::ElementData::*;
|
||||||
match *self {
|
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 {
|
pub fn styles(&self) -> &ElementStyles {
|
||||||
self.get_styles().expect("Calling styles() on unstyled ElementData")
|
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> {
|
pub fn get_styles_mut(&mut self) -> Option<&mut ElementStyles> {
|
||||||
use self::ElementData::*;
|
use self::ElementData::*;
|
||||||
match *self {
|
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 {
|
pub fn styles_mut(&mut self) -> &mut ElementStyles {
|
||||||
self.get_styles_mut().expect("Calling styles_mut() on unstyled ElementData")
|
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) {
|
pub fn finish_styling(&mut self, styles: ElementStyles, damage: RestyleDamage) {
|
||||||
use self::ElementData::*;
|
use self::ElementData::*;
|
||||||
match *self {
|
match *self {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
//! Types and traits used to access the DOM from style calculation.
|
//! Types and traits used to access the DOM from style calculation.
|
||||||
|
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use {Atom, Namespace, LocalName};
|
use {Atom, Namespace, LocalName};
|
||||||
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
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
|
/// We avoid exposing the full type id, since computing it in the general case
|
||||||
/// would be difficult for Gecko nodes.
|
/// would be difficult for Gecko nodes.
|
||||||
pub trait NodeInfo {
|
pub trait NodeInfo {
|
||||||
|
/// Whether this node is an element.
|
||||||
fn is_element(&self) -> bool;
|
fn is_element(&self) -> bool;
|
||||||
|
/// Whether this node is a text node.
|
||||||
fn is_text_node(&self) -> bool;
|
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() }
|
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);
|
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;
|
type Item = I;
|
||||||
fn next(&mut self) -> Option<I> {
|
fn next(&mut self) -> Option<I> {
|
||||||
loop {
|
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 {
|
pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo {
|
||||||
|
/// The concrete `TElement` type.
|
||||||
type ConcreteElement: TElement<ConcreteNode = Self>;
|
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>;
|
type ConcreteChildrenIterator: Iterator<Item = Self>;
|
||||||
|
|
||||||
|
/// Convert this node in an `UnsafeNode`.
|
||||||
fn to_unsafe(&self) -> UnsafeNode;
|
fn to_unsafe(&self) -> UnsafeNode;
|
||||||
|
|
||||||
|
/// Get a node back from an `UnsafeNode`.
|
||||||
unsafe fn from_unsafe(n: &UnsafeNode) -> Self;
|
unsafe fn from_unsafe(n: &UnsafeNode) -> Self;
|
||||||
|
|
||||||
/// Returns an iterator over this node's children.
|
/// 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`.
|
/// Converts self into an `OpaqueNode`.
|
||||||
fn opaque(&self) -> OpaqueNode;
|
fn opaque(&self) -> OpaqueNode;
|
||||||
|
|
||||||
|
/// Get this node's parent element if present.
|
||||||
fn parent_element(&self) -> Option<Self::ConcreteElement> {
|
fn parent_element(&self) -> Option<Self::ConcreteElement> {
|
||||||
self.parent_node().and_then(|n| n.as_element())
|
self.parent_node().and_then(|n| n.as_element())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A debug id, only useful, mm... for debugging.
|
||||||
fn debug_id(self) -> usize;
|
fn debug_id(self) -> usize;
|
||||||
|
|
||||||
|
/// Get this node as an element, if it's one.
|
||||||
fn as_element(&self) -> Option<Self::ConcreteElement>;
|
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;
|
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);
|
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;
|
fn can_be_fragmented(&self) -> bool;
|
||||||
|
|
||||||
|
/// Set whether this node can be fragmented.
|
||||||
unsafe fn set_can_be_fragmented(&self, value: bool);
|
unsafe fn set_can_be_fragmented(&self, value: bool);
|
||||||
|
|
||||||
|
/// Get this node's parent node.
|
||||||
fn parent_node(&self) -> Option<Self>;
|
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;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A trait used to synthesize presentational hints for HTML element attributes.
|
||||||
pub trait PresentationalHintsSynthetizer {
|
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)
|
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
|
||||||
where V: Push<ApplicableDeclarationBlock>;
|
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 {
|
pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + PresentationalHintsSynthetizer {
|
||||||
|
/// The concrete node type.
|
||||||
type ConcreteNode: TNode<ConcreteElement = Self>;
|
type ConcreteNode: TNode<ConcreteElement = Self>;
|
||||||
|
|
||||||
|
/// Get this element as a node.
|
||||||
fn as_node(&self) -> Self::ConcreteNode;
|
fn as_node(&self) -> Self::ConcreteNode;
|
||||||
|
|
||||||
/// While doing a reflow, the element at the root has no parent, as far as we're
|
/// 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>>>;
|
fn style_attribute(&self) -> Option<&Arc<RwLock<PropertyDeclarationBlock>>>;
|
||||||
|
|
||||||
|
/// Get this element's state, for non-tree-structural pseudos.
|
||||||
fn get_state(&self) -> ElementState;
|
fn get_state(&self) -> ElementState;
|
||||||
|
|
||||||
|
/// Whether this element has an attribute with a given namespace.
|
||||||
fn has_attr(&self, namespace: &Namespace, attr: &LocalName) -> bool;
|
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;
|
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
|
/// Get the pre-existing style to calculate restyle damage (change hints).
|
||||||
/// as an argument here, but otherwise Servo would crash due to double
|
///
|
||||||
/// borrows to return it.
|
/// 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,
|
fn existing_style_for_restyle_damage<'a>(&'a self,
|
||||||
current_computed_values: Option<&'a Arc<ComputedValues>>,
|
current_computed_values: Option<&'a Arc<ComputedValues>>,
|
||||||
pseudo: Option<&PseudoElement>)
|
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
|
/// about our parallel traversal. However, there are certain situations
|
||||||
/// (including but not limited to the traversal) where we need to send DOM
|
/// (including but not limited to the traversal) where we need to send DOM
|
||||||
/// objects to other threads.
|
/// objects to other threads.
|
||||||
|
///
|
||||||
|
/// That's the reason why `SendNode` exists.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct SendNode<N: TNode>(N);
|
pub struct SendNode<N: TNode>(N);
|
||||||
unsafe impl<N: TNode> Send for SendNode<N> {}
|
unsafe impl<N: TNode> Send for SendNode<N> {}
|
||||||
impl<N: TNode> SendNode<N> {
|
impl<N: TNode> SendNode<N> {
|
||||||
|
/// Unsafely construct a SendNode.
|
||||||
pub unsafe fn new(node: N) -> Self {
|
pub unsafe fn new(node: N) -> Self {
|
||||||
SendNode(node)
|
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)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct SendElement<E: TElement>(E);
|
pub struct SendElement<E: TElement>(E);
|
||||||
unsafe impl<E: TElement> Send for SendElement<E> {}
|
unsafe impl<E: TElement> Send for SendElement<E> {}
|
||||||
impl<E: TElement> SendElement<E> {
|
impl<E: TElement> SendElement<E> {
|
||||||
|
/// Unsafely construct a SendElement.
|
||||||
pub unsafe fn new(el: E) -> Self {
|
pub unsafe fn new(el: E) -> Self {
|
||||||
SendElement(el)
|
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)
|
(a as *const T) == (b as *const T)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serialize_comma_separated_list<W, T>(dest: &mut W, list: &[T])
|
/// Serializes as CSS a comma-separated list of any `T` that supports being
|
||||||
-> fmt::Result where W: fmt::Write, T: ToCss {
|
/// serialized as CSS.
|
||||||
if list.len() > 0 {
|
pub fn serialize_comma_separated_list<W, T>(dest: &mut W,
|
||||||
for item in &list[..list.len()-1] {
|
list: &[T])
|
||||||
try!(item.to_css(dest));
|
-> fmt::Result
|
||||||
try!(write!(dest, ", "));
|
where W: fmt::Write,
|
||||||
}
|
T: ToCss,
|
||||||
list[list.len()-1].to_css(dest)
|
{
|
||||||
} else {
|
if list.is_empty() {
|
||||||
Ok(())
|
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
|
//! easy to grep for. At the time of this writing, there is no other unsafe
|
||||||
//! code in the parallel traversal.
|
//! code in the parallel traversal.
|
||||||
|
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use dom::{OpaqueNode, SendNode, TElement, TNode};
|
use dom::{OpaqueNode, SendNode, TElement, TNode};
|
||||||
use rayon;
|
use rayon;
|
||||||
use scoped_tls::ScopedTLS;
|
use scoped_tls::ScopedTLS;
|
||||||
|
@ -28,8 +30,12 @@ use std::sync::atomic::Ordering;
|
||||||
use traversal::{DomTraversal, PerLevelTraversalData, PreTraverseToken};
|
use traversal::{DomTraversal, PerLevelTraversalData, PreTraverseToken};
|
||||||
use traversal::{STYLE_SHARING_CACHE_HITS, STYLE_SHARING_CACHE_MISSES};
|
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;
|
pub const CHUNK_SIZE: usize = 64;
|
||||||
|
|
||||||
|
/// A parallel top down traversal, generic over `D`.
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub fn traverse_dom<N, D>(traversal: &D,
|
pub fn traverse_dom<N, D>(traversal: &D,
|
||||||
root: N::ConcreteElement,
|
root: N::ConcreteElement,
|
||||||
|
@ -37,7 +43,7 @@ pub fn traverse_dom<N, D>(traversal: &D,
|
||||||
token: PreTraverseToken,
|
token: PreTraverseToken,
|
||||||
queue: &rayon::ThreadPool)
|
queue: &rayon::ThreadPool)
|
||||||
where N: TNode,
|
where N: TNode,
|
||||||
D: DomTraversal<N>
|
D: DomTraversal<N>,
|
||||||
{
|
{
|
||||||
if opts::get().style_sharing_stats {
|
if opts::get().style_sharing_stats {
|
||||||
STYLE_SHARING_CACHE_HITS.store(0, Ordering::SeqCst);
|
STYLE_SHARING_CACHE_HITS.store(0, Ordering::SeqCst);
|
||||||
|
@ -181,7 +187,7 @@ fn bottom_up_dom<N, D>(traversal: &D,
|
||||||
root: OpaqueNode,
|
root: OpaqueNode,
|
||||||
mut node: N)
|
mut node: N)
|
||||||
where N: TNode,
|
where N: TNode,
|
||||||
D: DomTraversal<N>
|
D: DomTraversal<N>,
|
||||||
{
|
{
|
||||||
loop {
|
loop {
|
||||||
// Perform the appropriate operation.
|
// Perform the appropriate operation.
|
||||||
|
|
|
@ -405,9 +405,10 @@ pub fn append_serialization<'a, W, I, N>(dest: &mut W,
|
||||||
importance: Importance,
|
importance: Importance,
|
||||||
is_first_serialization: &mut bool)
|
is_first_serialization: &mut bool)
|
||||||
-> fmt::Result
|
-> fmt::Result
|
||||||
where W: fmt::Write,
|
where W: fmt::Write,
|
||||||
I: Iterator<Item=&'a PropertyDeclaration>,
|
I: Iterator<Item=&'a PropertyDeclaration>,
|
||||||
N: ToCss {
|
N: ToCss
|
||||||
|
{
|
||||||
try!(handle_first_serialization(dest, is_first_serialization));
|
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
|
// 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);
|
super::deduplicate_property_declarations(&mut block);
|
||||||
block
|
block
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,16 +73,21 @@
|
||||||
use values::{computed, specified};
|
use values::{computed, specified};
|
||||||
${caller.body()}
|
${caller.body()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The definition of the computed value for ${name}.
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
pub use super::single_value::computed_value as single_value;
|
pub use super::single_value::computed_value as single_value;
|
||||||
pub use self::single_value::T as SingleComputedValue;
|
pub use self::single_value::T as SingleComputedValue;
|
||||||
|
/// The computed value, effectively a list of single values.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct T(pub Vec<single_value::T>);
|
pub struct T(pub Vec<single_value::T>);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for computed_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();
|
let mut iter = self.0.iter();
|
||||||
if let Some(val) = iter.next() {
|
if let Some(val) = iter.next() {
|
||||||
try!(val.to_css(dest));
|
try!(val.to_css(dest));
|
||||||
|
@ -101,12 +106,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The specified value of ${name}.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct SpecifiedValue(pub Vec<single_value::SpecifiedValue>);
|
pub struct SpecifiedValue(pub Vec<single_value::SpecifiedValue>);
|
||||||
|
|
||||||
impl ToCss for 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();
|
let mut iter = self.0.iter();
|
||||||
if let Some(val) = iter.next() {
|
if let Some(val) = iter.next() {
|
||||||
try!(val.to_css(dest));
|
try!(val.to_css(dest));
|
||||||
|
@ -405,7 +413,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LonghandsToSerialize<'a> {
|
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
|
// Define all of the expected variables that correspond to the shorthand
|
||||||
% for sub_property in shorthand.sub_properties:
|
% for sub_property in shorthand.sub_properties:
|
||||||
let mut ${sub_property.ident} = None;
|
let mut ${sub_property.ident} = None;
|
||||||
|
@ -446,7 +458,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
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 all_flags = SerializeFlags::all();
|
||||||
let mut with_variables = false;
|
let mut with_variables = false;
|
||||||
% for sub_property in shorthand.sub_properties:
|
% 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>)
|
declarations: &mut Vec<PropertyDeclaration>)
|
||||||
-> Result<(), ()> {
|
-> Result<(), ()> {
|
||||||
input.look_for_var_functions();
|
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
|
// NB: This needs to be here because it needs all the longhands generated
|
||||||
// beforehand.
|
// beforehand.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub enum TransitionProperty {
|
pub enum TransitionProperty {
|
||||||
|
/// All, any animatable property changing should generate a transition.
|
||||||
All,
|
All,
|
||||||
% for prop in data.longhands:
|
% for prop in data.longhands:
|
||||||
% if prop.animatable:
|
% if prop.animatable:
|
||||||
|
/// ${prop.name}
|
||||||
${prop.camel_case},
|
${prop.camel_case},
|
||||||
% endif
|
% endif
|
||||||
% endfor
|
% endfor
|
||||||
|
@ -55,6 +59,7 @@ impl TransitionProperty {
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a transition-property value.
|
||||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
||||||
match_ignore_ascii_case! { try!(input.expect_ident()),
|
match_ignore_ascii_case! { try!(input.expect_ident()),
|
||||||
"all" => Ok(TransitionProperty::All),
|
"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> {
|
pub fn from_declaration(declaration: &PropertyDeclaration) -> Option<Self> {
|
||||||
match *declaration {
|
match *declaration {
|
||||||
% for prop in data.longhands:
|
% for prop in data.longhands:
|
||||||
|
@ -81,7 +87,9 @@ impl TransitionProperty {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for 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 {
|
match *self {
|
||||||
TransitionProperty::All => dest.write_str("all"),
|
TransitionProperty::All => dest.write_str("all"),
|
||||||
% for prop in data.longhands:
|
% 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)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub enum AnimatedProperty {
|
pub enum AnimatedProperty {
|
||||||
% for prop in data.longhands:
|
% for prop in data.longhands:
|
||||||
% if prop.animatable:
|
% if prop.animatable:
|
||||||
|
/// ${prop.name}
|
||||||
${prop.camel_case}(longhands::${prop.ident}::computed_value::T,
|
${prop.camel_case}(longhands::${prop.ident}::computed_value::T,
|
||||||
longhands::${prop.ident}::computed_value::T),
|
longhands::${prop.ident}::computed_value::T),
|
||||||
% endif
|
% endif
|
||||||
|
@ -105,16 +116,19 @@ pub enum AnimatedProperty {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnimatedProperty {
|
impl AnimatedProperty {
|
||||||
pub fn name(&self) -> String {
|
/// Get the name of this property.
|
||||||
|
pub fn name(&self) -> &'static str {
|
||||||
match *self {
|
match *self {
|
||||||
% for prop in data.longhands:
|
% for prop in data.longhands:
|
||||||
% if prop.animatable:
|
% if prop.animatable:
|
||||||
AnimatedProperty::${prop.camel_case}(..) => "${prop.name}".to_owned(),
|
AnimatedProperty::${prop.camel_case}(..) => "${prop.name}",
|
||||||
% endif
|
% endif
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether this interpolation does animate, that is, whether the start and
|
||||||
|
/// end values are different.
|
||||||
pub fn does_animate(&self) -> bool {
|
pub fn does_animate(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
% for prop in data.longhands:
|
% 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) {
|
match (self, other) {
|
||||||
% for prop in data.longhands:
|
% for prop in data.longhands:
|
||||||
% if prop.animatable:
|
% 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) {
|
pub fn update(&self, style: &mut ComputedValues, progress: f64) {
|
||||||
match *self {
|
match *self {
|
||||||
% for prop in data.longhands:
|
% 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,
|
pub fn from_transition_property(transition_property: &TransitionProperty,
|
||||||
old_style: &ComputedValues,
|
old_style: &ComputedValues,
|
||||||
new_style: &ComputedValues)
|
new_style: &ComputedValues)
|
||||||
|
@ -188,12 +207,15 @@ impl AnimatedProperty {
|
||||||
pub enum AnimationValue {
|
pub enum AnimationValue {
|
||||||
% for prop in data.longhands:
|
% for prop in data.longhands:
|
||||||
% if prop.animatable:
|
% if prop.animatable:
|
||||||
|
/// ${prop.name}
|
||||||
${prop.camel_case}(longhands::${prop.ident}::computed_value::T),
|
${prop.camel_case}(longhands::${prop.ident}::computed_value::T),
|
||||||
% endif
|
% endif
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnimationValue {
|
impl AnimationValue {
|
||||||
|
/// "Uncompute" this animation value in order to be used inside the CSS
|
||||||
|
/// cascade.
|
||||||
pub fn uncompute(&self) -> PropertyDeclaration {
|
pub fn uncompute(&self) -> PropertyDeclaration {
|
||||||
use properties::{longhands, DeclaredValue};
|
use properties::{longhands, DeclaredValue};
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -234,6 +256,7 @@ impl Interpolate for AnimationValue {
|
||||||
///
|
///
|
||||||
/// [interpolated-types]: https://drafts.csswg.org/css-transitions/#interpolated-types
|
/// [interpolated-types]: https://drafts.csswg.org/css-transitions/#interpolated-types
|
||||||
pub trait Interpolate: Sized {
|
pub trait Interpolate: Sized {
|
||||||
|
/// Interpolate a value with another for a given property.
|
||||||
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()>;
|
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,6 +272,7 @@ impl<T: RepeatableListInterpolate> Interpolate for Vec<T> {
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css-transitions/#animtype-number
|
/// https://drafts.csswg.org/css-transitions/#animtype-number
|
||||||
impl Interpolate for Au {
|
impl Interpolate for Au {
|
||||||
#[inline]
|
#[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]
|
#[inline]
|
||||||
fn interpolate(&self, other: &Option<T>, progress: f64) -> Result<Option<T>, ()> {
|
fn interpolate(&self, other: &Option<T>, progress: f64) -> Result<Option<T>, ()> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
|
@ -431,7 +457,7 @@ impl Interpolate for CalcLengthOrPercentage {
|
||||||
other: Option<T>,
|
other: Option<T>,
|
||||||
progress: f64)
|
progress: f64)
|
||||||
-> Result<Option<T>, ()>
|
-> Result<Option<T>, ()>
|
||||||
where T: Default + Interpolate
|
where T: Default + Interpolate,
|
||||||
{
|
{
|
||||||
match (this, other) {
|
match (this, other) {
|
||||||
(None, None) => Ok(None),
|
(None, None) => Ok(None),
|
||||||
|
@ -919,27 +945,36 @@ impl Interpolate for LengthOrNone {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A 2d matrix for interpolation.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct InnerMatrix2D {
|
pub struct InnerMatrix2D {
|
||||||
pub m11: CSSFloat, pub m12: CSSFloat,
|
pub m11: CSSFloat, pub m12: CSSFloat,
|
||||||
pub m21: CSSFloat, pub m22: CSSFloat,
|
pub m21: CSSFloat, pub m22: CSSFloat,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A 2d translation function.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Translate2D(f32, f32);
|
pub struct Translate2D(f32, f32);
|
||||||
|
|
||||||
|
/// A 2d scale function.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Scale2D(f32, f32);
|
pub struct Scale2D(f32, f32);
|
||||||
|
|
||||||
|
/// A decomposed 2d matrix.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct MatrixDecomposed2D {
|
pub struct MatrixDecomposed2D {
|
||||||
|
/// The translation function.
|
||||||
pub translate: Translate2D,
|
pub translate: Translate2D,
|
||||||
|
/// The scale function.
|
||||||
pub scale: Scale2D,
|
pub scale: Scale2D,
|
||||||
|
/// The rotation angle.
|
||||||
pub angle: f32,
|
pub angle: f32,
|
||||||
|
/// The inner matrix.
|
||||||
pub matrix: InnerMatrix2D,
|
pub matrix: InnerMatrix2D,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1143,33 +1178,44 @@ impl Interpolate for LengthOrNone {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A 3d translation.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Translate3D(f32, f32, f32);
|
pub struct Translate3D(f32, f32, f32);
|
||||||
|
|
||||||
|
/// A 3d scale function.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Scale3D(f32, f32, f32);
|
pub struct Scale3D(f32, f32, f32);
|
||||||
|
|
||||||
|
/// A 3d skew function.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Skew(f32, f32, f32);
|
pub struct Skew(f32, f32, f32);
|
||||||
|
|
||||||
|
/// A 3d perspective transformation.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Perspective(f32, f32, f32, f32);
|
pub struct Perspective(f32, f32, f32, f32);
|
||||||
|
|
||||||
|
/// A quaternion used to represent a rotation.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Quaternion(f32, f32, f32, f32);
|
pub struct Quaternion(f32, f32, f32, f32);
|
||||||
|
|
||||||
|
/// A decomposed 3d matrix.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct MatrixDecomposed3D {
|
pub struct MatrixDecomposed3D {
|
||||||
|
/// A translation function.
|
||||||
pub translate: Translate3D,
|
pub translate: Translate3D,
|
||||||
|
/// A scale function.
|
||||||
pub scale: Scale3D,
|
pub scale: Scale3D,
|
||||||
|
/// The skew component of the transformation.
|
||||||
pub skew: Skew,
|
pub skew: Skew,
|
||||||
|
/// The perspective component of the transformation.
|
||||||
pub perspective: Perspective,
|
pub perspective: Perspective,
|
||||||
|
/// The quaternion used to represent the rotation.
|
||||||
pub quaternion: Quaternion,
|
pub quaternion: Quaternion,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1513,7 +1559,7 @@ impl Interpolate for LengthOrNone {
|
||||||
self.m43 != 0.0 || self.m44 != 1.0
|
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.m14 * self.m23 * self.m32 * self.m41 -
|
||||||
self.m13 * self.m24 * self.m32 * self.m41 -
|
self.m13 * self.m24 * self.m32 * self.m41 -
|
||||||
self.m14 * self.m22 * self.m33 * 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>
|
||||||
|
|
||||||
<%helpers:vector_longhand name="background-position-x" animatable="True">
|
<%helpers:vector_longhand name="background-position-x" animatable="True">
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::HasViewportPercentage;
|
use values::HasViewportPercentage;
|
||||||
use values::specified::position::HorizontalPosition;
|
use values::specified::position::HorizontalPosition;
|
||||||
|
|
||||||
pub mod computed_value {
|
#[allow(missing_docs)]
|
||||||
use values::computed::position::HorizontalPosition;
|
pub mod computed_value {
|
||||||
use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
|
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]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
#[allow(missing_docs)]
|
||||||
use values::computed::position::HorizontalPosition;
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
HorizontalPosition(computed::LengthOrPercentage::Percentage(0.0))
|
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 {
|
#[inline]
|
||||||
use values::specified::position::Keyword;
|
#[allow(missing_docs)]
|
||||||
HorizontalPosition {
|
pub fn get_initial_position_value() -> SpecifiedValue {
|
||||||
keyword: Some(Keyword::Left),
|
use values::specified::{LengthOrPercentage, Percentage};
|
||||||
position: None,
|
HorizontalPosition {
|
||||||
}
|
keyword: None,
|
||||||
}
|
position: Some(LengthOrPercentage::Percentage(Percentage(0.0))),
|
||||||
#[inline]
|
|
||||||
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)
|
#[allow(missing_docs)]
|
||||||
-> Result<SpecifiedValue, ()> {
|
pub fn parse(context: &ParserContext, input: &mut Parser)
|
||||||
HorizontalPosition::parse(context, input)
|
-> Result<SpecifiedValue, ()> {
|
||||||
}
|
HorizontalPosition::parse(context, input)
|
||||||
|
}
|
||||||
</%helpers:vector_longhand>
|
</%helpers:vector_longhand>
|
||||||
|
|
||||||
<%helpers:vector_longhand name="background-position-y" animatable="True">
|
<%helpers:vector_longhand name="background-position-y" animatable="True">
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::HasViewportPercentage;
|
use values::HasViewportPercentage;
|
||||||
use values::specified::position::VerticalPosition;
|
use values::specified::position::VerticalPosition;
|
||||||
|
|
||||||
pub mod computed_value {
|
#[allow(missing_docs)]
|
||||||
use values::computed::position::VerticalPosition;
|
pub mod computed_value {
|
||||||
use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
|
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]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
#[allow(missing_docs)]
|
||||||
use values::computed::position::VerticalPosition;
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
VerticalPosition(computed::LengthOrPercentage::Percentage(0.0))
|
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 {
|
#[inline]
|
||||||
use values::specified::position::Keyword;
|
#[allow(missing_docs)]
|
||||||
VerticalPosition {
|
pub fn get_initial_position_value() -> SpecifiedValue {
|
||||||
keyword: Some(Keyword::Top),
|
use values::specified::{LengthOrPercentage, Percentage};
|
||||||
position: None,
|
VerticalPosition {
|
||||||
}
|
keyword: None,
|
||||||
}
|
position: Some(LengthOrPercentage::Percentage(Percentage(0.0))),
|
||||||
#[inline]
|
|
||||||
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)
|
#[inline]
|
||||||
-> Result<SpecifiedValue, ()> {
|
#[allow(missing_docs)]
|
||||||
VerticalPosition::parse(context, input)
|
pub fn parse(context: &ParserContext, input: &mut Parser)
|
||||||
}
|
-> Result<SpecifiedValue, ()> {
|
||||||
|
VerticalPosition::parse(context, input)
|
||||||
|
}
|
||||||
</%helpers:vector_longhand>
|
</%helpers:vector_longhand>
|
||||||
|
|
||||||
${helpers.single_keyword("background-repeat",
|
${helpers.single_keyword("background-repeat",
|
||||||
|
@ -199,6 +212,7 @@ ${helpers.single_keyword("background-origin",
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::HasViewportPercentage;
|
use values::HasViewportPercentage;
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use values::computed::LengthOrPercentageOrAuto;
|
use values::computed::LengthOrPercentageOrAuto;
|
||||||
use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
|
use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
|
||||||
|
@ -254,6 +268,7 @@ ${helpers.single_keyword("background-origin",
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct ExplicitSize {
|
pub struct ExplicitSize {
|
||||||
pub width: specified::LengthOrPercentageOrAuto,
|
pub width: specified::LengthOrPercentageOrAuto,
|
||||||
pub height: specified::LengthOrPercentageOrAuto,
|
pub height: specified::LengthOrPercentageOrAuto,
|
||||||
|
|
|
@ -46,7 +46,8 @@
|
||||||
|
|
||||||
impl ToCss for T {
|
impl ToCss for T {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
|
fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
|
||||||
where W: ::std::fmt::Write {
|
where W: ::std::fmt::Write,
|
||||||
|
{
|
||||||
match *self {
|
match *self {
|
||||||
% for value in values:
|
% for value in values:
|
||||||
T::${to_rust_ident(value)} => dest.write_str("${value}"),
|
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])}
|
computed_value::T::${to_rust_ident(values[0])}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a display value.
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser)
|
pub fn parse(_context: &ParserContext, input: &mut Parser)
|
||||||
-> Result<SpecifiedValue, ()> {
|
-> Result<SpecifiedValue, ()> {
|
||||||
match_ignore_ascii_case! { try!(input.expect_ident()),
|
match_ignore_ascii_case! { try!(input.expect_ident()),
|
||||||
|
@ -144,119 +150,128 @@ ${helpers.single_keyword("clear", "none left right both",
|
||||||
|
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
<%helpers:longhand name="vertical-align"
|
<%helpers:longhand name="vertical-align" animatable="True">
|
||||||
animatable="True">
|
use std::fmt;
|
||||||
use std::fmt;
|
use style_traits::ToCss;
|
||||||
use style_traits::ToCss;
|
use values::HasViewportPercentage;
|
||||||
use values::HasViewportPercentage;
|
|
||||||
|
|
||||||
<% vertical_align = data.longhands_by_name["vertical-align"] %>
|
<% vertical_align = data.longhands_by_name["vertical-align"] %>
|
||||||
<% vertical_align.keyword = Keyword("vertical-align",
|
<% vertical_align.keyword = Keyword("vertical-align",
|
||||||
"baseline sub super top text-top middle bottom text-bottom",
|
"baseline sub super top text-top middle bottom text-bottom",
|
||||||
extra_gecko_values="middle-with-baseline") %>
|
extra_gecko_values="middle-with-baseline") %>
|
||||||
<% vertical_align_keywords = vertical_align.keyword.values_for(product) %>
|
<% vertical_align_keywords = vertical_align.keyword.values_for(product) %>
|
||||||
|
|
||||||
impl HasViewportPercentage for SpecifiedValue {
|
impl HasViewportPercentage for SpecifiedValue {
|
||||||
fn has_viewport_percentage(&self) -> bool {
|
fn has_viewport_percentage(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
SpecifiedValue::LengthOrPercentage(length) => length.has_viewport_percentage(),
|
SpecifiedValue::LengthOrPercentage(length) => length.has_viewport_percentage(),
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
/// The `vertical-align` value.
|
||||||
#[derive(Debug, Clone, PartialEq, Copy)]
|
#[allow(non_camel_case_types)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||||
pub enum SpecifiedValue {
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
% for keyword in vertical_align_keywords:
|
pub enum SpecifiedValue {
|
||||||
${to_rust_ident(keyword)},
|
% for keyword in vertical_align_keywords:
|
||||||
% endfor
|
${to_rust_ident(keyword)},
|
||||||
LengthOrPercentage(specified::LengthOrPercentage),
|
% endfor
|
||||||
}
|
LengthOrPercentage(specified::LengthOrPercentage),
|
||||||
|
}
|
||||||
|
|
||||||
impl ToCss for 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 {
|
||||||
match *self {
|
match *self {
|
||||||
% for keyword in vertical_align_keywords:
|
% for keyword in vertical_align_keywords:
|
||||||
SpecifiedValue::${to_rust_ident(keyword)} => dest.write_str("${keyword}"),
|
SpecifiedValue::${to_rust_ident(keyword)} => dest.write_str("${keyword}"),
|
||||||
% endfor
|
% endfor
|
||||||
SpecifiedValue::LengthOrPercentage(value) => value.to_css(dest),
|
SpecifiedValue::LengthOrPercentage(value) => value.to_css(dest),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// baseline | sub | super | top | text-top | middle | bottom | text-bottom
|
/// baseline | sub | super | top | text-top | middle | bottom | text-bottom
|
||||||
/// | <percentage> | <length>
|
/// | <percentage> | <length>
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
input.try(|i| specified::LengthOrPercentage::parse(context, i))
|
input.try(|i| specified::LengthOrPercentage::parse(context, i))
|
||||||
.map(SpecifiedValue::LengthOrPercentage)
|
.map(SpecifiedValue::LengthOrPercentage)
|
||||||
.or_else(|()| {
|
.or_else(|_| {
|
||||||
match_ignore_ascii_case! { try!(input.expect_ident()),
|
match_ignore_ascii_case! { try!(input.expect_ident()),
|
||||||
% for keyword in vertical_align_keywords:
|
% for keyword in vertical_align_keywords:
|
||||||
"${keyword}" => Ok(SpecifiedValue::${to_rust_ident(keyword)}),
|
"${keyword}" => Ok(SpecifiedValue::${to_rust_ident(keyword)}),
|
||||||
% endfor
|
% endfor
|
||||||
_ => Err(())
|
_ => 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 ToComputedValue for SpecifiedValue {
|
/// The computed value for `vertical-align`.
|
||||||
type ComputedValue = computed_value::T;
|
pub mod computed_value {
|
||||||
|
use app_units::Au;
|
||||||
|
use std::fmt;
|
||||||
|
use style_traits::ToCss;
|
||||||
|
use values::{CSSFloat, computed};
|
||||||
|
|
||||||
#[inline]
|
/// The keywords are the same, and the `LengthOrPercentage` is computed
|
||||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
/// here.
|
||||||
match *self {
|
#[allow(non_camel_case_types)]
|
||||||
% for keyword in vertical_align_keywords:
|
#[derive(PartialEq, Copy, Clone, Debug)]
|
||||||
SpecifiedValue::${to_rust_ident(keyword)} => {
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
computed_value::T::${to_rust_ident(keyword)}
|
pub enum T {
|
||||||
}
|
% for keyword in vertical_align_keywords:
|
||||||
% endfor
|
${to_rust_ident(keyword)},
|
||||||
SpecifiedValue::LengthOrPercentage(value) =>
|
% endfor
|
||||||
computed_value::T::LengthOrPercentage(value.to_computed_value(context)),
|
LengthOrPercentage(computed::LengthOrPercentage),
|
||||||
}
|
}
|
||||||
}
|
impl ToCss for T {
|
||||||
#[inline]
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
fn from_computed_value(computed: &computed_value::T) -> Self {
|
match *self {
|
||||||
match *computed {
|
% for keyword in vertical_align_keywords:
|
||||||
% for keyword in vertical_align_keywords:
|
T::${to_rust_ident(keyword)} => dest.write_str("${keyword}"),
|
||||||
computed_value::T::${to_rust_ident(keyword)} => {
|
% endfor
|
||||||
SpecifiedValue::${to_rust_ident(keyword)}
|
T::LengthOrPercentage(value) => value.to_css(dest),
|
||||||
}
|
}
|
||||||
% endfor
|
}
|
||||||
computed_value::T::LengthOrPercentage(value) =>
|
}
|
||||||
SpecifiedValue::LengthOrPercentage(
|
}
|
||||||
ToComputedValue::from_computed_value(&value)
|
|
||||||
),
|
/// 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>
|
</%helpers:longhand>
|
||||||
|
|
||||||
|
|
||||||
|
@ -275,44 +290,51 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
||||||
gecko_constant_prefix="NS_STYLE_OVERFLOW")}
|
gecko_constant_prefix="NS_STYLE_OVERFLOW")}
|
||||||
|
|
||||||
// FIXME(pcwalton, #2742): Implement scrolling for `scroll` and `auto`.
|
// FIXME(pcwalton, #2742): Implement scrolling for `scroll` and `auto`.
|
||||||
<%helpers:longhand name="overflow-y"
|
<%helpers:longhand name="overflow-y" need_clone="True" animatable="False">
|
||||||
need_clone="True"
|
use super::overflow_x;
|
||||||
animatable="False">
|
|
||||||
use super::overflow_x;
|
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::computed::ComputedValueAsSpecified;
|
use values::computed::ComputedValueAsSpecified;
|
||||||
use values::NoViewportPercentage;
|
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 {
|
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 {
|
||||||
self.0.to_css(dest)
|
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 {
|
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||||
computed_value::T(overflow_x::get_initial_value())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
#[inline]
|
||||||
overflow_x::parse(context, input).map(SpecifiedValue)
|
#[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>
|
</%helpers:longhand>
|
||||||
|
|
||||||
// TODO(pcwalton): Multiple transitions.
|
|
||||||
<%helpers:longhand name="transition-duration"
|
<%helpers:longhand name="transition-duration"
|
||||||
need_index="True"
|
need_index="True"
|
||||||
animatable="False">
|
animatable="False">
|
||||||
|
@ -369,7 +391,6 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
// TODO(pcwalton): Lots more timing functions.
|
// TODO(pcwalton): Lots more timing functions.
|
||||||
// TODO(pcwalton): Multiple transitions.
|
|
||||||
<%helpers:longhand name="transition-timing-function"
|
<%helpers:longhand name="transition-timing-function"
|
||||||
need_index="True"
|
need_index="True"
|
||||||
animatable="False">
|
animatable="False">
|
||||||
|
|
|
@ -315,7 +315,10 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
pub type T = 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)
|
Au::from_px(FONT_MEDIUM_PX)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,13 @@ pub mod shorthands {
|
||||||
<%include file="/shorthand/text.mako.rs" />
|
<%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 {
|
pub mod animated_properties {
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
<%include file="/helpers/animated_properties.mako.rs" />
|
<%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.
|
/// Serializes the possible shorthand name with value to input buffer given
|
||||||
/// On success, returns true if shorthand value is written and false if no shorthand value is present.
|
/// 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,
|
pub fn serialize_shorthand_to_buffer<'a, W, I>(self,
|
||||||
dest: &mut W,
|
dest: &mut W,
|
||||||
declarations: I,
|
declarations: I,
|
||||||
is_first_serialization: &mut bool,
|
is_first_serialization: &mut bool,
|
||||||
importance: Importance)
|
importance: Importance)
|
||||||
-> Result<bool, fmt::Error>
|
-> 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) {
|
match self.get_shorthand_appendable_value(declarations) {
|
||||||
None => Ok(false),
|
None => Ok(false),
|
||||||
Some(appendable_value) => {
|
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>>
|
-> Option<AppendableValue<'a, I::IntoIter>>
|
||||||
where I: IntoIterator<Item=&'a PropertyDeclaration>, I::IntoIter: Clone {
|
where I: IntoIterator<Item=&'a PropertyDeclaration>,
|
||||||
let declarations = declarations.into_iter();
|
I::IntoIter: Clone,
|
||||||
|
{
|
||||||
|
let declarations = declarations.into_iter();
|
||||||
|
|
||||||
// Only cloning iterators (a few pointers each) not declarations.
|
// Only cloning iterators (a few pointers each) not declarations.
|
||||||
let mut declarations2 = declarations.clone();
|
let mut declarations2 = declarations.clone();
|
||||||
let mut declarations3 = declarations.clone();
|
let mut declarations3 = declarations.clone();
|
||||||
|
|
||||||
let first_declaration = match declarations2.next() {
|
let first_declaration = match declarations2.next() {
|
||||||
Some(declaration) => declaration,
|
Some(declaration) => declaration,
|
||||||
None => return None
|
None => return None
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-variables/#variables-in-shorthands
|
// https://drafts.csswg.org/css-variables/#variables-in-shorthands
|
||||||
if let Some(css) = first_declaration.with_variables_from_shorthand(self) {
|
if let Some(css) = first_declaration.with_variables_from_shorthand(self) {
|
||||||
if declarations2.all(|d| d.with_variables_from_shorthand(self) == Some(css)) {
|
if declarations2.all(|d| d.with_variables_from_shorthand(self) == Some(css)) {
|
||||||
return Some(AppendableValue::Css(css));
|
return Some(AppendableValue::Css(css));
|
||||||
}
|
}
|
||||||
else {
|
return None;
|
||||||
return None;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !declarations3.any(|d| d.with_variables()) {
|
if !declarations3.any(|d| d.with_variables()) {
|
||||||
return Some(AppendableValue::DeclarationsForShorthand(self, declarations));
|
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)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub enum DeclaredValue<T> {
|
pub enum DeclaredValue<T> {
|
||||||
|
/// A known specified value from the stylesheet.
|
||||||
Value(T),
|
Value(T),
|
||||||
|
/// A value that contained any css variables.
|
||||||
WithVariables {
|
WithVariables {
|
||||||
|
/// The css serialization for this value.
|
||||||
css: String,
|
css: String,
|
||||||
|
/// The first token type for this serialization.
|
||||||
first_token_type: TokenSerializationType,
|
first_token_type: TokenSerializationType,
|
||||||
|
/// The base url.
|
||||||
base_url: ServoUrl,
|
base_url: ServoUrl,
|
||||||
|
/// The shorthand this came from.
|
||||||
from_shorthand: Option<ShorthandId>,
|
from_shorthand: Option<ShorthandId>,
|
||||||
},
|
},
|
||||||
|
/// The `initial` keyword.
|
||||||
Initial,
|
Initial,
|
||||||
|
/// The `inherit` keyword.
|
||||||
Inherit,
|
Inherit,
|
||||||
|
/// The `unset` keyword.
|
||||||
Unset,
|
Unset,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: HasViewportPercentage> HasViewportPercentage for DeclaredValue<T> {
|
impl<T: HasViewportPercentage> HasViewportPercentage for DeclaredValue<T> {
|
||||||
fn has_viewport_percentage(&self) -> bool {
|
fn has_viewport_percentage(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
DeclaredValue::Value(ref v)
|
DeclaredValue::Value(ref v) => v.has_viewport_percentage(),
|
||||||
=> v.has_viewport_percentage(),
|
DeclaredValue::WithVariables { .. } => {
|
||||||
DeclaredValue::WithVariables { .. }
|
panic!("DeclaredValue::has_viewport_percentage without \
|
||||||
=> panic!("DeclaredValue::has_viewport_percentage without resolving variables!"),
|
resolving variables!")
|
||||||
|
},
|
||||||
DeclaredValue::Initial |
|
DeclaredValue::Initial |
|
||||||
DeclaredValue::Inherit |
|
DeclaredValue::Inherit |
|
||||||
DeclaredValue::Unset => false,
|
DeclaredValue::Unset => false,
|
||||||
|
@ -615,7 +640,9 @@ impl fmt::Debug for PropertyId {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss 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 {
|
match *self {
|
||||||
PropertyId::Longhand(id) => dest.write_str(id.name()),
|
PropertyId::Longhand(id) => dest.write_str(id.name()),
|
||||||
PropertyId::Shorthand(id) => dest.write_str(id.name()),
|
PropertyId::Shorthand(id) => dest.write_str(id.name()),
|
||||||
|
@ -1150,19 +1177,22 @@ pub struct ComputedValues {
|
||||||
% endfor
|
% endfor
|
||||||
custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
|
custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
|
||||||
shareable: bool,
|
shareable: bool,
|
||||||
|
/// The writing mode of this computed values struct.
|
||||||
pub writing_mode: WritingMode,
|
pub writing_mode: WritingMode,
|
||||||
|
/// The root element's computed font size.
|
||||||
pub root_font_size: Au,
|
pub root_font_size: Au,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
impl ComputedValues {
|
impl ComputedValues {
|
||||||
|
/// Construct a `ComputedValues` instance.
|
||||||
pub fn new(custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
|
pub fn new(custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
|
||||||
shareable: bool,
|
shareable: bool,
|
||||||
writing_mode: WritingMode,
|
writing_mode: WritingMode,
|
||||||
root_font_size: Au,
|
root_font_size: Au,
|
||||||
% for style_struct in data.active_style_structs():
|
% for style_struct in data.active_style_structs():
|
||||||
${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
|
${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
|
||||||
% endfor
|
% endfor
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ComputedValues {
|
ComputedValues {
|
||||||
custom_properties: custom_properties,
|
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
|
// http://dev.w3.org/csswg/css-transforms/#grouping-property-values
|
||||||
pub fn get_used_transform_style(&self) -> computed_values::transform_style::T {
|
pub fn get_used_transform_style(&self) -> computed_values::transform_style::T {
|
||||||
use computed_values::mix_blend_mode;
|
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() ||
|
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.mutate_font().compute_font_hash();
|
||||||
}
|
}
|
||||||
|
|
||||||
style
|
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")]
|
#[cfg(feature = "servo")]
|
||||||
pub fn modify_style_for_anonymous_flow(style: &mut Arc<ComputedValues>,
|
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
|
// The 'align-self' property needs some special treatment since
|
||||||
// its value depends on the 'align-items' value of its parent.
|
// its value depends on the 'align-items' value of its parent.
|
||||||
% if "align-items" in data.longhands_by_name:
|
% 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);
|
outline.outline_width = Au(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Alters the given style to accommodate replaced content. This is called in flow construction. It
|
/// Alters the given style to accommodate replaced content. This is called in
|
||||||
/// handles cases like `<div style="position: absolute">foo bar baz</div>` (in which `foo`, `bar`,
|
/// flow construction. It handles cases like:
|
||||||
/// 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.
|
/// <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")]
|
#[cfg(feature = "servo")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn modify_style_for_replaced_content(style: &mut Arc<ComputedValues>) {
|
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
|
/// Adjusts borders as appropriate to account for a fragment's status as the
|
||||||
/// within the range of an element.
|
/// 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
|
/// Specifically, this function sets border widths to zero on the sides for
|
||||||
/// not outermost.
|
/// which the fragment is not outermost.
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn modify_border_style_for_inline_sides(style: &mut Arc<ComputedValues>,
|
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")]
|
#[cfg(feature = "servo")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn modify_style_for_outer_inline_block_fragment(style: &mut Arc<ComputedValues>) {
|
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_
|
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
|
/// Text is never directly relatively positioned; it's always contained within
|
||||||
/// itself relatively positioned.
|
/// an element that is itself relatively positioned.
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn modify_style_for_text(style: &mut Arc<ComputedValues>) {
|
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
|
/// Adjusts the `clip` property so that an inline absolute hypothetical fragment
|
||||||
/// children.
|
/// doesn't clip its children.
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
pub fn modify_style_for_inline_absolute_hypothetical_fragment(style: &mut Arc<ComputedValues>) {
|
pub fn modify_style_for_inline_absolute_hypothetical_fragment(style: &mut Arc<ComputedValues>) {
|
||||||
if style.get_effects().clip.0.is_some() {
|
if style.get_effects().clip.0.is_some() {
|
||||||
|
|
|
@ -7,8 +7,16 @@ use style_traits::ToCss;
|
||||||
use values::specified::{BorderStyle, CSSColor};
|
use values::specified::{BorderStyle, CSSColor};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
pub fn serialize_four_sides<W, I>(dest: &mut W, top: &I, right: &I, bottom: &I, left: &I)
|
#[allow(missing_docs)]
|
||||||
-> fmt::Result where W: fmt::Write, I: ToCss + PartialEq {
|
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 {
|
if left == right {
|
||||||
let horizontal_value = left;
|
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
|
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 AppendableValue::DeclarationsForShorthand(shorthand, _) = *appendable_value {
|
||||||
if let ShorthandId::Overflow = shorthand {
|
if let ShorthandId::Overflow = shorthand {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
//! The rule tree.
|
||||||
|
|
||||||
use arc_ptr_eq;
|
use arc_ptr_eq;
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
|
@ -17,15 +20,40 @@ use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
|
||||||
use stylesheets::StyleRule;
|
use stylesheets::StyleRule;
|
||||||
use thread_state;
|
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)]
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct RuleTree {
|
pub struct RuleTree {
|
||||||
root: StrongRuleNode,
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum StyleSource {
|
pub enum StyleSource {
|
||||||
|
/// A style rule stable pointer.
|
||||||
Style(Arc<RwLock<StyleRule>>),
|
Style(Arc<RwLock<StyleRule>>),
|
||||||
|
/// A declaration block stable pointer.
|
||||||
Declarations(Arc<RwLock<PropertyDeclarationBlock>>),
|
Declarations(Arc<RwLock<PropertyDeclarationBlock>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,8 +62,11 @@ type StyleSourceGuardHandle<'a> =
|
||||||
RwLockReadGuard<'a, StyleRule>,
|
RwLockReadGuard<'a, StyleRule>,
|
||||||
RwLockReadGuard<'a, PropertyDeclarationBlock>>;
|
RwLockReadGuard<'a, PropertyDeclarationBlock>>;
|
||||||
|
|
||||||
|
/// A guard for a given style source.
|
||||||
pub enum StyleSourceGuard<'a> {
|
pub enum StyleSourceGuard<'a> {
|
||||||
|
/// A guard for a style rule.
|
||||||
Style(StyleSourceGuardHandle<'a>),
|
Style(StyleSourceGuardHandle<'a>),
|
||||||
|
/// A guard for a declaration block.
|
||||||
Declarations(RwLockReadGuard<'a, PropertyDeclarationBlock>),
|
Declarations(RwLockReadGuard<'a, PropertyDeclarationBlock>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +102,8 @@ impl StyleSource {
|
||||||
let _ = write!(writer, " -> {:?}", self.read().declarations);
|
let _ = write!(writer, " -> {:?}", self.read().declarations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read the style source guard, and obtain thus read access to the
|
||||||
|
/// underlying property declaration block.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read<'a>(&'a self) -> StyleSourceGuard<'a> {
|
pub fn read<'a>(&'a self) -> StyleSourceGuard<'a> {
|
||||||
use self::StyleSource::*;
|
use self::StyleSource::*;
|
||||||
|
@ -87,15 +120,19 @@ impl StyleSource {
|
||||||
/// This value exists here so a node that pushes itself to the list can know
|
/// 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
|
/// that is in the free list by looking at is next pointer, and comparing it
|
||||||
/// with null.
|
/// 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;
|
const FREE_LIST_SENTINEL: *mut RuleNode = 0x01 as *mut RuleNode;
|
||||||
|
|
||||||
impl RuleTree {
|
impl RuleTree {
|
||||||
|
/// Construct a new rule tree.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
RuleTree {
|
RuleTree {
|
||||||
root: StrongRuleNode::new(Box::new(RuleNode::root())),
|
root: StrongRuleNode::new(Box::new(RuleNode::root())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the root rule node.
|
||||||
pub fn root(&self) -> StrongRuleNode {
|
pub fn root(&self) -> StrongRuleNode {
|
||||||
self.root.clone()
|
self.root.clone()
|
||||||
}
|
}
|
||||||
|
@ -105,13 +142,16 @@ impl RuleTree {
|
||||||
self.root.get().dump(writer, 0);
|
self.root.get().dump(writer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Dump the rule tree to stdout.
|
||||||
pub fn dump_stdout(&self) {
|
pub fn dump_stdout(&self) {
|
||||||
let mut stdout = io::stdout();
|
let mut stdout = io::stdout();
|
||||||
self.dump(&mut 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
|
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();
|
let mut current = self.root.clone();
|
||||||
for (source, importance) in iter {
|
for (source, importance) in iter {
|
||||||
|
@ -294,6 +334,7 @@ struct WeakRuleNode {
|
||||||
ptr: *mut RuleNode,
|
ptr: *mut RuleNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A strong reference to a rule node.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StrongRuleNode {
|
pub struct StrongRuleNode {
|
||||||
ptr: *mut RuleNode,
|
ptr: *mut RuleNode,
|
||||||
|
@ -412,14 +453,19 @@ impl StrongRuleNode {
|
||||||
unsafe { &*self.ptr }
|
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> {
|
pub fn style_source(&self) -> Option<&StyleSource> {
|
||||||
self.get().source.as_ref()
|
self.get().source.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the importance that this rule node represents.
|
||||||
pub fn importance(&self) -> Importance {
|
pub fn importance(&self) -> Importance {
|
||||||
self.get().importance
|
self.get().importance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get an iterator for this rule node and its ancestors.
|
||||||
pub fn self_and_ancestors(&self) -> SelfAndAncestors {
|
pub fn self_and_ancestors(&self) -> SelfAndAncestors {
|
||||||
SelfAndAncestors {
|
SelfAndAncestors {
|
||||||
current: Some(self)
|
current: Some(self)
|
||||||
|
@ -527,6 +573,7 @@ impl StrongRuleNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An iterator over a rule node and its ancestors.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SelfAndAncestors<'a> {
|
pub struct SelfAndAncestors<'a> {
|
||||||
current: Option<&'a StrongRuleNode>,
|
current: Option<&'a StrongRuleNode>,
|
||||||
|
|
|
@ -4,14 +4,17 @@
|
||||||
|
|
||||||
//! Implements sequential traversal over the DOM tree.
|
//! Implements sequential traversal over the DOM tree.
|
||||||
|
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use dom::{TElement, TNode};
|
use dom::{TElement, TNode};
|
||||||
use traversal::{DomTraversal, PerLevelTraversalData, PreTraverseToken};
|
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,
|
pub fn traverse_dom<N, D>(traversal: &D,
|
||||||
root: N::ConcreteElement,
|
root: N::ConcreteElement,
|
||||||
token: PreTraverseToken)
|
token: PreTraverseToken)
|
||||||
where N: TNode,
|
where N: TNode,
|
||||||
D: DomTraversal<N>
|
D: DomTraversal<N>,
|
||||||
{
|
{
|
||||||
debug_assert!(token.should_traverse());
|
debug_assert!(token.should_traverse());
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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 {Atom, Prefix, Namespace, LocalName};
|
||||||
use attr::{AttrIdentifier, AttrValue};
|
use attr::{AttrIdentifier, AttrValue};
|
||||||
use cssparser::ToCss;
|
use cssparser::ToCss;
|
||||||
|
@ -15,9 +19,12 @@ use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Debug;
|
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.
|
/// NB: If you add to this list, be sure to update `each_pseudo_element` too.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum PseudoElement {
|
pub enum PseudoElement {
|
||||||
Before,
|
Before,
|
||||||
After,
|
After,
|
||||||
|
@ -55,6 +62,7 @@ impl ToCss for PseudoElement {
|
||||||
|
|
||||||
|
|
||||||
impl PseudoElement {
|
impl PseudoElement {
|
||||||
|
/// Whether the current pseudo element is :before or :after.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_before_or_after(&self) -> bool {
|
pub fn is_before_or_after(&self) -> bool {
|
||||||
match *self {
|
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]
|
#[inline]
|
||||||
pub fn cascade_type(&self) -> PseudoElementCascadeType {
|
pub fn cascade_type(&self) -> PseudoElementCascadeType {
|
||||||
match *self {
|
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)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum NonTSPseudoClass {
|
pub enum NonTSPseudoClass {
|
||||||
AnyLink,
|
AnyLink,
|
||||||
Link,
|
Link,
|
||||||
|
@ -129,6 +143,8 @@ impl ToCss for NonTSPseudoClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
pub fn state_flag(&self) -> ElementState {
|
||||||
use element_state::*;
|
use element_state::*;
|
||||||
use self::NonTSPseudoClass::*;
|
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)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct SelectorImpl;
|
pub struct SelectorImpl;
|
||||||
|
@ -289,14 +307,17 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SelectorImpl {
|
impl SelectorImpl {
|
||||||
|
/// Returns the pseudo-element cascade type of the given `pseudo`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pseudo_element_cascade_type(pseudo: &PseudoElement) -> PseudoElementCascadeType {
|
pub fn pseudo_element_cascade_type(pseudo: &PseudoElement) -> PseudoElementCascadeType {
|
||||||
pseudo.cascade_type()
|
pseudo.cascade_type()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Executes `fun` for each pseudo-element.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn each_pseudo_element<F>(mut fun: F)
|
pub fn each_pseudo_element<F>(mut fun: F)
|
||||||
where F: FnMut(PseudoElement) {
|
where F: FnMut(PseudoElement),
|
||||||
|
{
|
||||||
fun(PseudoElement::Before);
|
fun(PseudoElement::Before);
|
||||||
fun(PseudoElement::After);
|
fun(PseudoElement::After);
|
||||||
fun(PseudoElement::DetailsContent);
|
fun(PseudoElement::DetailsContent);
|
||||||
|
@ -311,11 +332,13 @@ impl SelectorImpl {
|
||||||
fun(PseudoElement::ServoAnonymousBlock);
|
fun(PseudoElement::ServoAnonymousBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the pseudo-class state flag for selector matching.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pseudo_class_state_flag(pc: &NonTSPseudoClass) -> ElementState {
|
pub fn pseudo_class_state_flag(pc: &NonTSPseudoClass) -> ElementState {
|
||||||
pc.state_flag()
|
pc.state_flag()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether this pseudo is either :before or :after.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pseudo_is_before_or_after(pseudo: &PseudoElement) -> bool {
|
pub fn pseudo_is_before_or_after(pseudo: &PseudoElement) -> bool {
|
||||||
pseudo.is_before_or_after()
|
pseudo.is_before_or_after()
|
||||||
|
@ -326,12 +349,16 @@ impl SelectorImpl {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct ServoElementSnapshot {
|
pub struct ServoElementSnapshot {
|
||||||
|
/// The stored state of the element.
|
||||||
pub state: Option<ElementState>,
|
pub state: Option<ElementState>,
|
||||||
|
/// The set of stored attributes and its values.
|
||||||
pub attrs: Option<Vec<(AttrIdentifier, AttrValue)>>,
|
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,
|
pub is_html_element_in_html_document: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServoElementSnapshot {
|
impl ServoElementSnapshot {
|
||||||
|
/// Create an empty element snapshot.
|
||||||
pub fn new(is_html_element_in_html_document: bool) -> Self {
|
pub fn new(is_html_element_in_html_document: bool) -> Self {
|
||||||
ServoElementSnapshot {
|
ServoElementSnapshot {
|
||||||
state: None,
|
state: None,
|
||||||
|
@ -373,7 +400,7 @@ impl ElementSnapshot for ServoElementSnapshot {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn each_class<F>(&self, mut callback: F)
|
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")) {
|
if let Some(v) = self.get_attr(&ns!(), &local_name!("class")) {
|
||||||
for class in v.as_tokens() {
|
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
|
* 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/. */
|
* 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 num_traits::ToPrimitive;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -9,7 +13,10 @@ use std::convert::AsRef;
|
||||||
use std::iter::{Filter, Peekable};
|
use std::iter::{Filter, Peekable};
|
||||||
use std::str::Split;
|
use std::str::Split;
|
||||||
|
|
||||||
|
/// A static slice of characters.
|
||||||
pub type StaticCharVec = &'static [char];
|
pub type StaticCharVec = &'static [char];
|
||||||
|
|
||||||
|
/// A static slice of `str`s.
|
||||||
pub type StaticStringVec = &'static [&'static str];
|
pub type StaticStringVec = &'static [&'static str];
|
||||||
|
|
||||||
/// A "space character" according to:
|
/// A "space character" according to:
|
||||||
|
@ -23,23 +30,31 @@ pub static HTML_SPACE_CHARACTERS: StaticCharVec = &[
|
||||||
'\u{000d}',
|
'\u{000d}',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/// Whether a character is a HTML whitespace character.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn char_is_whitespace(c: char) -> bool {
|
pub fn char_is_whitespace(c: char) -> bool {
|
||||||
HTML_SPACE_CHARACTERS.contains(&c)
|
HTML_SPACE_CHARACTERS.contains(&c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether all the string is HTML whitespace.
|
||||||
|
#[inline]
|
||||||
pub fn is_whitespace(s: &str) -> bool {
|
pub fn is_whitespace(s: &str) -> bool {
|
||||||
s.chars().all(char_is_whitespace)
|
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) ->
|
pub fn split_html_space_chars<'a>(s: &'a str) ->
|
||||||
Filter<Split<'a, StaticCharVec>, fn(&&str) -> bool> {
|
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)
|
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> {
|
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)
|
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) {
|
pub fn read_numbers<I: Iterator<Item=char>>(mut iter: Peekable<I>) -> (Option<i64>, usize) {
|
||||||
match iter.peek() {
|
match iter.peek() {
|
||||||
Some(c) if is_ascii_digit(c) => (),
|
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>,
|
pub fn read_fraction<I: Iterator<Item=char>>(mut iter: Peekable<I>,
|
||||||
mut divisor: f64,
|
mut divisor: f64,
|
||||||
value: f64) -> (f64, usize) {
|
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
|
d as i64 - '0' as i64
|
||||||
).fold((value, 1), |accumulator, d| {
|
).fold((value, 1), |accumulator, d| {
|
||||||
divisor *= 10f64;
|
divisor *= 10f64;
|
||||||
(accumulator.0 + d as f64 / divisor,
|
(accumulator.0 + d as f64 / divisor, accumulator.1 + 1)
|
||||||
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> {
|
pub fn read_exponent<I: Iterator<Item=char>>(mut iter: Peekable<I>) -> Option<i32> {
|
||||||
match iter.peek() {
|
match iter.peek() {
|
||||||
Some(c) if is_exponent_char(*c) => (),
|
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
|
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)| {
|
strs.into_iter().enumerate().fold(String::new(), |mut acc, (i, s)| {
|
||||||
if i > 0 { acc.push_str(join); }
|
if i > 0 { acc.push_str(join); }
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
//! Style sheets and their CSS rules.
|
//! Style sheets and their CSS rules.
|
||||||
|
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use {Atom, Prefix, Namespace};
|
use {Atom, Prefix, Namespace};
|
||||||
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, decode_stylesheet_bytes};
|
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, decode_stylesheet_bytes};
|
||||||
use cssparser::{AtRuleType, RuleListParser, SourcePosition, Token, parse_one_rule};
|
use cssparser::{AtRuleType, RuleListParser, SourcePosition, Token, parse_one_rule};
|
||||||
|
@ -46,22 +48,27 @@ pub enum Origin {
|
||||||
User,
|
User,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A set of namespaces applying to a given stylesheet.
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct Namespaces {
|
pub struct Namespaces {
|
||||||
pub default: Option<Namespace>,
|
pub default: Option<Namespace>,
|
||||||
pub prefixes: FnvHashMap<Prefix , Namespace>,
|
pub prefixes: FnvHashMap<Prefix , Namespace>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A list of CSS rules.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CssRules(pub Vec<CssRule>);
|
pub struct CssRules(pub Vec<CssRule>);
|
||||||
|
|
||||||
impl CssRules {
|
impl CssRules {
|
||||||
|
/// Whether this CSS rules is empty.
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.0.is_empty()
|
self.0.is_empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum RulesMutateError {
|
pub enum RulesMutateError {
|
||||||
Syntax,
|
Syntax,
|
||||||
IndexSize,
|
IndexSize,
|
||||||
|
@ -79,6 +86,7 @@ impl From<SingleRuleParseError> for RulesMutateError {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CssRules {
|
impl CssRules {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn new(rules: Vec<CssRule>) -> Arc<RwLock<CssRules>> {
|
pub fn new(rules: Vec<CssRule>) -> Arc<RwLock<CssRules>> {
|
||||||
Arc::new(RwLock::new(CssRules(rules)))
|
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)
|
pub fn insert_rule(&mut self, rule: &str, parent_stylesheet: &Stylesheet, index: usize, nested: bool)
|
||||||
-> Result<CssRule, RulesMutateError> {
|
-> Result<CssRule, RulesMutateError> {
|
||||||
// Step 1, 2
|
// Step 1, 2
|
||||||
|
@ -136,7 +144,7 @@ impl CssRules {
|
||||||
Ok(new_rule)
|
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> {
|
pub fn remove_rule(&mut self, index: usize) -> Result<(), RulesMutateError> {
|
||||||
// Step 1, 2
|
// Step 1, 2
|
||||||
if index >= self.0.len() {
|
if index >= self.0.len() {
|
||||||
|
@ -161,6 +169,7 @@ impl CssRules {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The structure servo uses to represent a stylesheet.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Stylesheet {
|
pub struct Stylesheet {
|
||||||
/// List of rules in the order they were found (important for
|
/// List of rules in the order they were found (important for
|
||||||
|
@ -168,22 +177,33 @@ pub struct Stylesheet {
|
||||||
pub rules: Arc<RwLock<CssRules>>,
|
pub rules: Arc<RwLock<CssRules>>,
|
||||||
/// List of media associated with the Stylesheet.
|
/// List of media associated with the Stylesheet.
|
||||||
pub media: Arc<RwLock<MediaList>>,
|
pub media: Arc<RwLock<MediaList>>,
|
||||||
|
/// The origin of this stylesheet.
|
||||||
pub origin: Origin,
|
pub origin: Origin,
|
||||||
|
/// The base url this stylesheet should use.
|
||||||
pub base_url: ServoUrl,
|
pub base_url: ServoUrl,
|
||||||
|
/// The namespaces that apply to this stylesheet.
|
||||||
pub namespaces: RwLock<Namespaces>,
|
pub namespaces: RwLock<Namespaces>,
|
||||||
|
/// Whether this stylesheet would be dirty when the viewport size changes.
|
||||||
pub dirty_on_viewport_size_change: AtomicBool,
|
pub dirty_on_viewport_size_change: AtomicBool,
|
||||||
|
/// Whether this stylesheet should be disabled.
|
||||||
pub disabled: AtomicBool,
|
pub disabled: AtomicBool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// This structure holds the user-agent and user stylesheets.
|
/// This structure holds the user-agent and user stylesheets.
|
||||||
pub struct UserAgentStylesheets {
|
pub struct UserAgentStylesheets {
|
||||||
|
/// The user or user agent stylesheets.
|
||||||
pub user_or_user_agent_stylesheets: Vec<Stylesheet>,
|
pub user_or_user_agent_stylesheets: Vec<Stylesheet>,
|
||||||
|
/// The quirks mode stylesheet.
|
||||||
pub quirks_mode_stylesheet: Stylesheet,
|
pub quirks_mode_stylesheet: Stylesheet,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// A CSS rule.
|
||||||
|
///
|
||||||
|
/// TODO(emilio): Lots of spec links should be around.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum CssRule {
|
pub enum CssRule {
|
||||||
// No Charset here, CSSCharsetRule has been removed from CSSOM
|
// No Charset here, CSSCharsetRule has been removed from CSSOM
|
||||||
// https://drafts.csswg.org/cssom/#changes-from-5-december-2013
|
// https://drafts.csswg.org/cssom/#changes-from-5-december-2013
|
||||||
|
@ -197,6 +217,7 @@ pub enum CssRule {
|
||||||
Keyframes(Arc<RwLock<KeyframesRule>>),
|
Keyframes(Arc<RwLock<KeyframesRule>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum CssRuleType {
|
pub enum CssRuleType {
|
||||||
// https://drafts.csswg.org/cssom/#the-cssrule-interface
|
// https://drafts.csswg.org/cssom/#the-cssrule-interface
|
||||||
Style = 1,
|
Style = 1,
|
||||||
|
@ -236,12 +257,14 @@ impl ParseErrorReporter for MemoryHoleReporter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum SingleRuleParseError {
|
pub enum SingleRuleParseError {
|
||||||
Syntax,
|
Syntax,
|
||||||
Hierarchy,
|
Hierarchy,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CssRule {
|
impl CssRule {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn rule_type(&self) -> CssRuleType {
|
pub fn rule_type(&self) -> CssRuleType {
|
||||||
match *self {
|
match *self {
|
||||||
CssRule::Style(_) => CssRuleType::Style,
|
CssRule::Style(_) => CssRuleType::Style,
|
||||||
|
@ -268,7 +291,8 @@ impl CssRule {
|
||||||
/// Note that only some types of rules can contain rules. An empty slice is
|
/// Note that only some types of rules can contain rules. An empty slice is
|
||||||
/// used for others.
|
/// used for others.
|
||||||
pub fn with_nested_rules_and_mq<F, R>(&self, mut f: F) -> R
|
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 {
|
match *self {
|
||||||
CssRule::Import(ref lock) => {
|
CssRule::Import(ref lock) => {
|
||||||
let rule = lock.read();
|
let rule = lock.read();
|
||||||
|
@ -296,6 +320,7 @@ impl CssRule {
|
||||||
|
|
||||||
// input state is None for a nested rule
|
// input state is None for a nested rule
|
||||||
// Returns a parsed CSS rule and the final state of the parser
|
// Returns a parsed CSS rule and the final state of the parser
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn parse(css: &str,
|
pub fn parse(css: &str,
|
||||||
parent_stylesheet: &Stylesheet,
|
parent_stylesheet: &Stylesheet,
|
||||||
extra_data: ParserContextExtraData,
|
extra_data: ParserContextExtraData,
|
||||||
|
@ -348,6 +373,7 @@ impl ToCss for CssRule {
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct NamespaceRule {
|
pub struct NamespaceRule {
|
||||||
/// `None` for the default Namespace
|
/// `None` for the default Namespace
|
||||||
pub prefix: Option<Prefix>,
|
pub prefix: Option<Prefix>,
|
||||||
|
@ -374,6 +400,7 @@ impl ToCss for NamespaceRule {
|
||||||
/// [import]: https://drafts.csswg.org/css-cascade-3/#at-import
|
/// [import]: https://drafts.csswg.org/css-cascade-3/#at-import
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ImportRule {
|
pub struct ImportRule {
|
||||||
|
/// The `<url>` this `@import` rule is loading.
|
||||||
pub url: SpecifiedUrl,
|
pub url: SpecifiedUrl,
|
||||||
|
|
||||||
/// The stylesheet is always present.
|
/// 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)]
|
#[derive(Debug)]
|
||||||
pub struct KeyframesRule {
|
pub struct KeyframesRule {
|
||||||
|
/// The name of the current animation.
|
||||||
pub name: Atom,
|
pub name: Atom,
|
||||||
|
/// The keyframes specified for this CSS rule.
|
||||||
pub keyframes: Vec<Arc<RwLock<Keyframe>>>,
|
pub keyframes: Vec<Arc<RwLock<Keyframe>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,6 +449,7 @@ impl ToCss for KeyframesRule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MediaRule {
|
pub struct MediaRule {
|
||||||
pub media_queries: Arc<RwLock<MediaList>>,
|
pub media_queries: Arc<RwLock<MediaList>>,
|
||||||
|
@ -438,6 +471,7 @@ impl ToCss for MediaRule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StyleRule {
|
pub struct StyleRule {
|
||||||
pub selectors: SelectorList<SelectorImpl>,
|
pub selectors: SelectorList<SelectorImpl>,
|
||||||
|
@ -465,6 +499,11 @@ impl ToCss for StyleRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stylesheet {
|
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],
|
pub fn from_bytes(bytes: &[u8],
|
||||||
base_url: ServoUrl,
|
base_url: ServoUrl,
|
||||||
protocol_encoding_label: Option<&str>,
|
protocol_encoding_label: Option<&str>,
|
||||||
|
@ -486,6 +525,8 @@ impl Stylesheet {
|
||||||
extra_data)
|
extra_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates an empty stylesheet with a set of bytes that reached over the
|
||||||
|
/// network.
|
||||||
pub fn update_from_bytes(existing: &Stylesheet,
|
pub fn update_from_bytes(existing: &Stylesheet,
|
||||||
bytes: &[u8],
|
bytes: &[u8],
|
||||||
protocol_encoding_label: Option<&str>,
|
protocol_encoding_label: Option<&str>,
|
||||||
|
@ -493,7 +534,6 @@ impl Stylesheet {
|
||||||
stylesheet_loader: Option<&StylesheetLoader>,
|
stylesheet_loader: Option<&StylesheetLoader>,
|
||||||
error_reporter: Box<ParseErrorReporter + Send>,
|
error_reporter: Box<ParseErrorReporter + Send>,
|
||||||
extra_data: ParserContextExtraData) {
|
extra_data: ParserContextExtraData) {
|
||||||
assert!(existing.rules.read().is_empty());
|
|
||||||
let (string, _) = decode_stylesheet_bytes(
|
let (string, _) = decode_stylesheet_bytes(
|
||||||
bytes, protocol_encoding_label, environment_encoding);
|
bytes, protocol_encoding_label, environment_encoding);
|
||||||
Self::update_from_str(existing,
|
Self::update_from_str(existing,
|
||||||
|
@ -503,6 +543,7 @@ impl Stylesheet {
|
||||||
extra_data)
|
extra_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates an empty stylesheet from a given string of text.
|
||||||
pub fn update_from_str(existing: &Stylesheet,
|
pub fn update_from_str(existing: &Stylesheet,
|
||||||
css: &str,
|
css: &str,
|
||||||
stylesheet_loader: Option<&StylesheetLoader>,
|
stylesheet_loader: Option<&StylesheetLoader>,
|
||||||
|
@ -545,7 +586,14 @@ impl Stylesheet {
|
||||||
.store(input.seen_viewport_percentages(), Ordering::Release);
|
.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,
|
media: MediaList,
|
||||||
stylesheet_loader: Option<&StylesheetLoader>,
|
stylesheet_loader: Option<&StylesheetLoader>,
|
||||||
error_reporter: Box<ParseErrorReporter + Send>,
|
error_reporter: Box<ParseErrorReporter + Send>,
|
||||||
|
@ -569,6 +617,7 @@ impl Stylesheet {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether this stylesheet can be dirty on viewport size change.
|
||||||
pub fn dirty_on_viewport_size_change(&self) -> bool {
|
pub fn dirty_on_viewport_size_change(&self) -> bool {
|
||||||
self.dirty_on_viewport_size_change.load(Ordering::SeqCst)
|
self.dirty_on_viewport_size_change.load(Ordering::SeqCst)
|
||||||
}
|
}
|
||||||
|
@ -607,16 +656,19 @@ impl Stylesheet {
|
||||||
effective_rules(&self.rules.read().0, device, &mut f);
|
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 {
|
pub fn disabled(&self) -> bool {
|
||||||
self.disabled.load(Ordering::SeqCst)
|
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.
|
/// 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
|
/// Disabled stylesheets remain in the document, but their rules are not
|
||||||
/// the Stylist.
|
/// added to the Stylist.
|
||||||
pub fn set_disabled(&self, disabled: bool) -> bool {
|
pub fn set_disabled(&self, disabled: bool) -> bool {
|
||||||
self.disabled.swap(disabled, Ordering::SeqCst) != disabled
|
self.disabled.swap(disabled, Ordering::SeqCst) != disabled
|
||||||
}
|
}
|
||||||
|
@ -640,6 +692,7 @@ macro_rules! rule_filter {
|
||||||
($( $method: ident($variant:ident => $rule_type: ident), )+) => {
|
($( $method: ident($variant:ident => $rule_type: ident), )+) => {
|
||||||
impl Stylesheet {
|
impl Stylesheet {
|
||||||
$(
|
$(
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn $method<F>(&self, device: &Device, mut f: F) where F: FnMut(&$rule_type) {
|
pub fn $method<F>(&self, device: &Device, mut f: F) where F: FnMut(&$rule_type) {
|
||||||
self.effective_rules(device, |rule| {
|
self.effective_rules(device, |rule| {
|
||||||
if let CssRule::$variant(ref lock) = *rule {
|
if let CssRule::$variant(ref lock) = *rule {
|
||||||
|
@ -690,6 +743,7 @@ impl<'b> TopLevelRuleParser<'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
|
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum State {
|
pub enum State {
|
||||||
Start = 1,
|
Start = 1,
|
||||||
Imports = 2,
|
Imports = 2,
|
||||||
|
|
|
@ -8,32 +8,42 @@
|
||||||
//! In release builds, `get` returns 0. All of the other functions inline
|
//! In release builds, `get` returns 0. All of the other functions inline
|
||||||
//! away to nothing.
|
//! away to nothing.
|
||||||
|
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
pub use self::imp::{enter, exit, get, initialize};
|
pub use self::imp::{enter, exit, get, initialize};
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
|
/// A thread state flag, used for multiple assertions.
|
||||||
pub flags ThreadState: u32 {
|
pub flags ThreadState: u32 {
|
||||||
|
/// Whether we're in a script thread.
|
||||||
const SCRIPT = 0x01,
|
const SCRIPT = 0x01,
|
||||||
|
/// Whether we're in a layout thread.
|
||||||
const LAYOUT = 0x02,
|
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,
|
const IN_WORKER = 0x0100,
|
||||||
|
|
||||||
|
/// Whether the current thread is going through a GC.
|
||||||
const IN_GC = 0x0200,
|
const IN_GC = 0x0200,
|
||||||
const IN_HTML_PARSER = 0x0400,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! thread_types ( ( $( $fun:ident = $flag:ident ; )* ) => (
|
macro_rules! thread_types ( ( $( $fun:ident = $flag:ident ; )* ) => (
|
||||||
impl ThreadState {
|
impl ThreadState {
|
||||||
|
/// Whether the current thread is a worker thread.
|
||||||
pub fn is_worker(self) -> bool {
|
pub fn is_worker(self) -> bool {
|
||||||
self.contains(IN_WORKER)
|
self.contains(IN_WORKER)
|
||||||
}
|
}
|
||||||
|
|
||||||
$(
|
$(
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn $fun(self) -> bool {
|
pub fn $fun(self) -> bool {
|
||||||
self.contains($flag)
|
self.contains($flag)
|
||||||
}
|
}
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn $fun(self) -> bool {
|
pub fn $fun(self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -48,7 +58,6 @@ macro_rules! thread_types ( ( $( $fun:ident = $flag:ident ; )* ) => (
|
||||||
thread_types! {
|
thread_types! {
|
||||||
is_script = SCRIPT;
|
is_script = SCRIPT;
|
||||||
is_layout = LAYOUT;
|
is_layout = LAYOUT;
|
||||||
is_paint = PAINT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
|
@ -58,6 +67,7 @@ mod imp {
|
||||||
|
|
||||||
thread_local!(static STATE: RefCell<Option<ThreadState>> = RefCell::new(None));
|
thread_local!(static STATE: RefCell<Option<ThreadState>> = RefCell::new(None));
|
||||||
|
|
||||||
|
/// Initialize the current thread state.
|
||||||
pub fn initialize(x: ThreadState) {
|
pub fn initialize(x: ThreadState) {
|
||||||
STATE.with(|ref k| {
|
STATE.with(|ref k| {
|
||||||
if let Some(ref s) = *k.borrow() {
|
if let Some(ref s) = *k.borrow() {
|
||||||
|
@ -68,6 +78,7 @@ mod imp {
|
||||||
get(); // check the assertion below
|
get(); // check the assertion below
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the current thread state.
|
||||||
pub fn get() -> ThreadState {
|
pub fn get() -> ThreadState {
|
||||||
let state = STATE.with(|ref k| {
|
let state = STATE.with(|ref k| {
|
||||||
match *k.borrow() {
|
match *k.borrow() {
|
||||||
|
@ -82,6 +93,7 @@ mod imp {
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enter into a given temporary state. Panics if re-entring.
|
||||||
pub fn enter(x: ThreadState) {
|
pub fn enter(x: ThreadState) {
|
||||||
let state = get();
|
let state = get();
|
||||||
assert!(!state.intersects(x));
|
assert!(!state.intersects(x));
|
||||||
|
@ -90,6 +102,7 @@ mod imp {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Exit a given temporary state.
|
||||||
pub fn exit(x: ThreadState) {
|
pub fn exit(x: ThreadState) {
|
||||||
let state = get();
|
let state = get();
|
||||||
assert!(state.contains(x));
|
assert!(state.contains(x));
|
||||||
|
@ -100,6 +113,7 @@ mod imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
mod imp {
|
mod imp {
|
||||||
use super::ThreadState;
|
use super::ThreadState;
|
||||||
#[inline(always)] pub fn initialize(_: ThreadState) { }
|
#[inline(always)] pub fn initialize(_: ThreadState) { }
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/* 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
|
* 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/. */
|
* 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;
|
use time;
|
||||||
|
|
||||||
/// The `TimerMode` is used to determine what time should the `Timer` return,
|
/// 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).
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum TimerMode {
|
enum TimerMode {
|
||||||
|
/// The timer should return a fixed value.
|
||||||
Test(f64),
|
Test(f64),
|
||||||
|
/// The timer should return the actual time.
|
||||||
Current,
|
Current,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
//! Traversing the DOM tree; the bloom filter.
|
//! Traversing the DOM tree; the bloom filter.
|
||||||
|
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use atomic_refcell::{AtomicRefCell, AtomicRefMut};
|
use atomic_refcell::{AtomicRefCell, AtomicRefMut};
|
||||||
use context::{SharedStyleContext, StyleContext};
|
use context::{SharedStyleContext, StyleContext};
|
||||||
use data::{ElementData, ElementStyles, StoredRestyleHint};
|
use data::{ElementData, ElementStyles, StoredRestyleHint};
|
||||||
|
@ -18,14 +20,23 @@ use std::mem;
|
||||||
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
||||||
use stylist::Stylist;
|
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.
|
/// `-Z style-sharing-stats` is given.
|
||||||
pub static STYLE_SHARING_CACHE_HITS: AtomicUsize = ATOMIC_USIZE_INIT;
|
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;
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PerLevelTraversalData {
|
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>,
|
pub current_dom_depth: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,10 +48,12 @@ pub struct PreTraverseToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreTraverseToken {
|
impl PreTraverseToken {
|
||||||
|
/// Whether we should traverse children.
|
||||||
pub fn should_traverse(&self) -> bool {
|
pub fn should_traverse(&self) -> bool {
|
||||||
self.traverse
|
self.traverse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether we should traverse only unstyled children.
|
||||||
pub fn traverse_unstyled_children_only(&self) -> bool {
|
pub fn traverse_unstyled_children_only(&self) -> bool {
|
||||||
self.unstyled_children_only
|
self.unstyled_children_only
|
||||||
}
|
}
|
||||||
|
@ -48,15 +61,22 @@ impl PreTraverseToken {
|
||||||
|
|
||||||
/// Enum to prevent duplicate logging.
|
/// Enum to prevent duplicate logging.
|
||||||
pub enum LogBehavior {
|
pub enum LogBehavior {
|
||||||
|
/// We should log.
|
||||||
MayLog,
|
MayLog,
|
||||||
|
/// We shouldn't log.
|
||||||
DontLog,
|
DontLog,
|
||||||
}
|
}
|
||||||
use self::LogBehavior::*;
|
use self::LogBehavior::*;
|
||||||
impl 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 {
|
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;
|
type ThreadLocalContext: Send;
|
||||||
|
|
||||||
/// Process `node` on the way down, before its children have been processed.
|
/// 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|.
|
/// children of |element|.
|
||||||
unsafe fn clear_element_data(element: &N::ConcreteElement);
|
unsafe fn clear_element_data(element: &N::ConcreteElement);
|
||||||
|
|
||||||
|
/// Return the shared style context common to all worker threads.
|
||||||
fn shared_context(&self) -> &SharedStyleContext;
|
fn shared_context(&self) -> &SharedStyleContext;
|
||||||
|
|
||||||
|
/// Create a thread-local context.
|
||||||
fn create_thread_local_context(&self) -> Self::ThreadLocalContext;
|
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) {
|
pub fn clear_descendant_data<E: TElement, F: Fn(E)>(el: E, clear_data: &F) {
|
||||||
for kid in el.as_node().children() {
|
for kid in el.as_node().children() {
|
||||||
if let Some(kid) = kid.as_element() {
|
if let Some(kid) = kid.as_element() {
|
||||||
|
|
|
@ -18,6 +18,7 @@ pub use values::specified::basic_shape::{FillRule, GeometryBox, ShapeBox};
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum ShapeSource<T> {
|
pub enum ShapeSource<T> {
|
||||||
Url(SpecifiedUrl),
|
Url(SpecifiedUrl),
|
||||||
Shape(BasicShape, Option<T>),
|
Shape(BasicShape, Option<T>),
|
||||||
|
@ -51,6 +52,7 @@ impl<T: ToCss> ToCss for ShapeSource<T> {
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum BasicShape {
|
pub enum BasicShape {
|
||||||
Inset(InsetRect),
|
Inset(InsetRect),
|
||||||
Circle(Circle),
|
Circle(Circle),
|
||||||
|
@ -71,6 +73,7 @@ impl ToCss for BasicShape {
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct InsetRect {
|
pub struct InsetRect {
|
||||||
pub top: LengthOrPercentage,
|
pub top: LengthOrPercentage,
|
||||||
pub right: LengthOrPercentage,
|
pub right: LengthOrPercentage,
|
||||||
|
@ -100,6 +103,7 @@ impl ToCss for InsetRect {
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct Circle {
|
pub struct Circle {
|
||||||
pub radius: ShapeRadius,
|
pub radius: ShapeRadius,
|
||||||
pub position: Position,
|
pub position: Position,
|
||||||
|
@ -115,6 +119,7 @@ impl ToCss for Circle {
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct Ellipse {
|
pub struct Ellipse {
|
||||||
pub semiaxis_x: ShapeRadius,
|
pub semiaxis_x: ShapeRadius,
|
||||||
pub semiaxis_y: ShapeRadius,
|
pub semiaxis_y: ShapeRadius,
|
||||||
|
@ -138,6 +143,7 @@ impl ToCss for Ellipse {
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
/// https://drafts.csswg.org/css-shapes/#funcdef-polygon
|
/// https://drafts.csswg.org/css-shapes/#funcdef-polygon
|
||||||
pub struct Polygon {
|
pub struct Polygon {
|
||||||
pub fill: FillRule,
|
pub fill: FillRule,
|
||||||
|
@ -168,6 +174,7 @@ impl ToCss for Polygon {
|
||||||
/// https://drafts.csswg.org/css-shapes/#typedef-shape-radius
|
/// https://drafts.csswg.org/css-shapes/#typedef-shape-radius
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum ShapeRadius {
|
pub enum ShapeRadius {
|
||||||
Length(LengthOrPercentage),
|
Length(LengthOrPercentage),
|
||||||
ClosestSide,
|
ClosestSide,
|
||||||
|
@ -193,6 +200,7 @@ impl ToCss for ShapeRadius {
|
||||||
/// https://drafts.csswg.org/css-backgrounds-3/#border-radius
|
/// https://drafts.csswg.org/css-backgrounds-3/#border-radius
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct BorderRadius {
|
pub struct BorderRadius {
|
||||||
pub top_left: BorderRadiusSize,
|
pub top_left: BorderRadiusSize,
|
||||||
pub top_right: BorderRadiusSize,
|
pub top_right: BorderRadiusSize,
|
||||||
|
|
|
@ -51,6 +51,7 @@ impl ToComputedValue for specified::Image {
|
||||||
/// https://drafts.csswg.org/css-images/#image-values
|
/// https://drafts.csswg.org/css-images/#image-values
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum Image {
|
pub enum Image {
|
||||||
Url(SpecifiedUrl),
|
Url(SpecifiedUrl),
|
||||||
Gradient(Gradient),
|
Gradient(Gradient),
|
||||||
|
@ -174,6 +175,7 @@ impl ToComputedValue for specified::Gradient {
|
||||||
/// https://drafts.csswg.org/css-images/#gradients
|
/// https://drafts.csswg.org/css-images/#gradients
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum GradientKind {
|
pub enum GradientKind {
|
||||||
Linear(AngleOrCorner),
|
Linear(AngleOrCorner),
|
||||||
Radial(EndingShape, Position),
|
Radial(EndingShape, Position),
|
||||||
|
@ -271,6 +273,7 @@ impl ToComputedValue for specified::ColorStop {
|
||||||
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-ending-shape
|
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-ending-shape
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum EndingShape {
|
pub enum EndingShape {
|
||||||
Circle(LengthOrKeyword),
|
Circle(LengthOrKeyword),
|
||||||
Ellipse(LengthOrPercentageOrKeyword),
|
Ellipse(LengthOrPercentageOrKeyword),
|
||||||
|
@ -336,6 +339,7 @@ impl ToComputedValue for specified::GradientEndingShape {
|
||||||
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
|
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum LengthOrKeyword {
|
pub enum LengthOrKeyword {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Keyword(SizeKeyword),
|
Keyword(SizeKeyword),
|
||||||
|
@ -394,6 +398,7 @@ impl ToComputedValue for specified::LengthOrKeyword {
|
||||||
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
|
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum LengthOrPercentageOrKeyword {
|
pub enum LengthOrPercentageOrKeyword {
|
||||||
LengthOrPercentage(LengthOrPercentage, LengthOrPercentage),
|
LengthOrPercentage(LengthOrPercentage, LengthOrPercentage),
|
||||||
Keyword(SizeKeyword),
|
Keyword(SizeKeyword),
|
||||||
|
@ -458,6 +463,7 @@ impl ToComputedValue for specified::LengthOrPercentageOrKeyword {
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum AngleOrCorner {
|
pub enum AngleOrCorner {
|
||||||
Angle(Angle),
|
Angle(Angle),
|
||||||
Corner(HorizontalDirection, VerticalDirection)
|
Corner(HorizontalDirection, VerticalDirection)
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
//! `<length>` computed values, and related ones.
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use ordered_float::NotNaN;
|
use ordered_float::NotNaN;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -16,6 +18,7 @@ pub use values::specified::{Angle, BorderStyle, Time, UrlOrNone};
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct CalcLengthOrPercentage {
|
pub struct CalcLengthOrPercentage {
|
||||||
pub length: Au,
|
pub length: Au,
|
||||||
pub percentage: Option<CSSFloat>,
|
pub percentage: Option<CSSFloat>,
|
||||||
|
@ -23,11 +26,13 @@ pub struct CalcLengthOrPercentage {
|
||||||
|
|
||||||
impl CalcLengthOrPercentage {
|
impl CalcLengthOrPercentage {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn length(&self) -> Au {
|
pub fn length(&self) -> Au {
|
||||||
self.length
|
self.length
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn percentage(&self) -> CSSFloat {
|
pub fn percentage(&self) -> CSSFloat {
|
||||||
self.percentage.unwrap_or(0.)
|
self.percentage.unwrap_or(0.)
|
||||||
}
|
}
|
||||||
|
@ -130,6 +135,7 @@ impl ToComputedValue for specified::CalcLengthOrPercentage {
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
#[derive(PartialEq, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum LengthOrPercentage {
|
pub enum LengthOrPercentage {
|
||||||
Length(Au),
|
Length(Au),
|
||||||
Percentage(CSSFloat),
|
Percentage(CSSFloat),
|
||||||
|
@ -138,6 +144,7 @@ pub enum LengthOrPercentage {
|
||||||
|
|
||||||
impl LengthOrPercentage {
|
impl LengthOrPercentage {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn zero() -> LengthOrPercentage {
|
pub fn zero() -> LengthOrPercentage {
|
||||||
LengthOrPercentage::Length(Au(0))
|
LengthOrPercentage::Length(Au(0))
|
||||||
}
|
}
|
||||||
|
@ -154,6 +161,7 @@ impl LengthOrPercentage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn to_hash_key(&self) -> (Au, NotNaN<f32>) {
|
pub fn to_hash_key(&self) -> (Au, NotNaN<f32>) {
|
||||||
use self::LengthOrPercentage::*;
|
use self::LengthOrPercentage::*;
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -223,6 +231,7 @@ impl ToCss for LengthOrPercentage {
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
#[derive(PartialEq, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum LengthOrPercentageOrAuto {
|
pub enum LengthOrPercentageOrAuto {
|
||||||
Length(Au),
|
Length(Au),
|
||||||
Percentage(CSSFloat),
|
Percentage(CSSFloat),
|
||||||
|
@ -311,6 +320,7 @@ impl ToCss for LengthOrPercentageOrAuto {
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
#[derive(PartialEq, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum LengthOrPercentageOrAutoOrContent {
|
pub enum LengthOrPercentageOrAutoOrContent {
|
||||||
Length(Au),
|
Length(Au),
|
||||||
Percentage(CSSFloat),
|
Percentage(CSSFloat),
|
||||||
|
@ -397,6 +407,7 @@ impl ToCss for LengthOrPercentageOrAutoOrContent {
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
#[derive(PartialEq, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum LengthOrPercentageOrNone {
|
pub enum LengthOrPercentageOrNone {
|
||||||
Length(Au),
|
Length(Au),
|
||||||
Percentage(CSSFloat),
|
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_>;
|
pub type LengthOrNone = Either<Length, None_>;
|
||||||
|
|
||||||
|
/// Either a computed `<length>` or the `auto` keyword.
|
||||||
pub type LengthOrAuto = Either<Length, Auto>;
|
pub type LengthOrAuto = Either<Length, Auto>;
|
||||||
|
|
||||||
|
/// Either a computed `<length>` or a `<number>` value.
|
||||||
pub type LengthOrNumber = Either<Length, Number>;
|
pub type LengthOrNumber = Either<Length, Number>;
|
||||||
|
|
||||||
|
/// Either a computed `<length>` or the `normal` keyword.
|
||||||
pub type LengthOrNormal = Either<Length, Normal>;
|
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
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
//! Computed values.
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use euclid::size::Size2D;
|
use euclid::size::Size2D;
|
||||||
use font_metrics::FontMetricsProvider;
|
use font_metrics::FontMetricsProvider;
|
||||||
|
@ -24,23 +26,41 @@ pub mod image;
|
||||||
pub mod length;
|
pub mod length;
|
||||||
pub mod position;
|
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> {
|
pub struct Context<'a> {
|
||||||
|
/// Whether the current element is the root element.
|
||||||
pub is_root_element: bool,
|
pub is_root_element: bool,
|
||||||
|
|
||||||
|
/// The current viewport size.
|
||||||
pub viewport_size: Size2D<Au>,
|
pub viewport_size: Size2D<Au>,
|
||||||
|
|
||||||
|
/// The style we're inheriting from.
|
||||||
pub inherited_style: &'a ComputedValues,
|
pub inherited_style: &'a ComputedValues,
|
||||||
|
|
||||||
/// Values access through this need to be in the properties "computed
|
/// Values access through this need to be in the properties "computed
|
||||||
/// early": color, text-decoration, font-size, display, position, float,
|
/// early": color, text-decoration, font-size, display, position, float,
|
||||||
/// border-*-style, outline-style, font-family, writing-mode...
|
/// border-*-style, outline-style, font-family, writing-mode...
|
||||||
pub style: ComputedValues,
|
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>,
|
pub font_metrics_provider: Option<&'a FontMetricsProvider>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Context<'a> {
|
impl<'a> Context<'a> {
|
||||||
|
/// Whether the current element is the root element.
|
||||||
pub fn is_root_element(&self) -> bool { self.is_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 }
|
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 }
|
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 }
|
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 }
|
pub fn mutate_style(&mut self) -> &mut ComputedValues { &mut self.style }
|
||||||
|
|
||||||
/// Creates a dummy computed context for use in multiple places, like
|
/// 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 {
|
pub trait ToComputedValue {
|
||||||
|
/// The computed value type we're going to be converted to.
|
||||||
type ComputedValue;
|
type ComputedValue;
|
||||||
|
|
||||||
|
/// Convert a specified value to a computed value, using itself and the data
|
||||||
|
/// inside the `Context`.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, _context: &Context) -> Self::ComputedValue;
|
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Convert a computed value to specified value form.
|
/// Convert a computed value to specified value form.
|
||||||
|
@ -72,9 +96,13 @@ pub trait ToComputedValue {
|
||||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self;
|
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 {}
|
pub trait ComputedValueAsSpecified {}
|
||||||
|
|
||||||
impl<T> ToComputedValue for T where T: ComputedValueAsSpecified + Clone {
|
impl<T> ToComputedValue for T
|
||||||
|
where T: ComputedValueAsSpecified + Clone,
|
||||||
|
{
|
||||||
type ComputedValue = T;
|
type ComputedValue = T;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -133,9 +161,11 @@ impl ToComputedValue for specified::Length {
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct BorderRadiusSize(pub Size2D<LengthOrPercentage>);
|
pub struct BorderRadiusSize(pub Size2D<LengthOrPercentage>);
|
||||||
|
|
||||||
impl BorderRadiusSize {
|
impl BorderRadiusSize {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn zero() -> BorderRadiusSize {
|
pub fn zero() -> BorderRadiusSize {
|
||||||
BorderRadiusSize(Size2D::new(LengthOrPercentage::Length(Au(0)), LengthOrPercentage::Length(Au(0))))
|
BorderRadiusSize(Size2D::new(LengthOrPercentage::Length(Au(0)), LengthOrPercentage::Length(Au(0))))
|
||||||
}
|
}
|
||||||
|
@ -169,6 +199,7 @@ impl ToCss for BorderRadiusSize {
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct Shadow {
|
pub struct Shadow {
|
||||||
pub offset_x: Au,
|
pub offset_x: Au,
|
||||||
pub offset_y: Au,
|
pub offset_y: Au,
|
||||||
|
@ -178,5 +209,8 @@ pub struct Shadow {
|
||||||
pub inset: bool,
|
pub inset: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A `<number>` value.
|
||||||
pub type Number = CSSFloat;
|
pub type Number = CSSFloat;
|
||||||
|
|
||||||
|
/// A type used for opacity.
|
||||||
pub type Opacity = CSSFloat;
|
pub type Opacity = CSSFloat;
|
||||||
|
|
|
@ -13,6 +13,7 @@ use values::computed::LengthOrPercentage;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Copy)]
|
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct Position {
|
pub struct Position {
|
||||||
pub horizontal: LengthOrPercentage,
|
pub horizontal: LengthOrPercentage,
|
||||||
pub vertical: LengthOrPercentage,
|
pub vertical: LengthOrPercentage,
|
||||||
|
@ -29,6 +30,7 @@ impl ToCss for Position {
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Copy)]
|
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct HorizontalPosition(pub LengthOrPercentage);
|
pub struct HorizontalPosition(pub LengthOrPercentage);
|
||||||
|
|
||||||
impl ToCss for HorizontalPosition {
|
impl ToCss for HorizontalPosition {
|
||||||
|
@ -39,6 +41,7 @@ impl ToCss for HorizontalPosition {
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Copy)]
|
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct VerticalPosition(pub LengthOrPercentage);
|
pub struct VerticalPosition(pub LengthOrPercentage);
|
||||||
|
|
||||||
impl ToCss for VerticalPosition {
|
impl ToCss for VerticalPosition {
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
//!
|
//!
|
||||||
//! [values]: https://drafts.csswg.org/css-values/
|
//! [values]: https://drafts.csswg.org/css-values/
|
||||||
|
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
pub use cssparser::{RGBA, Parser};
|
pub use cssparser::{RGBA, Parser};
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use std::fmt::{self, Debug};
|
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 ),+);
|
define_numbered_css_keyword_enum!($name: $( $css => $variant = $value ),+);
|
||||||
};
|
};
|
||||||
($name: ident: $( $css: expr => $variant: ident = $value: expr ),+) => {
|
($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)]
|
#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Copy, RustcEncodable, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
|
||||||
pub enum $name {
|
pub enum $name {
|
||||||
|
@ -24,6 +26,7 @@ macro_rules! define_numbered_css_keyword_enum {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $name {
|
impl $name {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn parse(input: &mut ::cssparser::Parser) -> Result<$name, ()> {
|
pub fn parse(input: &mut ::cssparser::Parser) -> Result<$name, ()> {
|
||||||
match_ignore_ascii_case! { try!(input.expect_ident()),
|
match_ignore_ascii_case! { try!(input.expect_ident()),
|
||||||
$( $css => Ok($name::$variant), )+
|
$( $css => Ok($name::$variant), )+
|
||||||
|
@ -34,7 +37,8 @@ macro_rules! define_numbered_css_keyword_enum {
|
||||||
|
|
||||||
impl ToCss for $name {
|
impl ToCss for $name {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
|
fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
|
||||||
where W: ::std::fmt::Write {
|
where W: ::std::fmt::Write,
|
||||||
|
{
|
||||||
match *self {
|
match *self {
|
||||||
$( $name::$variant => dest.write_str($css) ),+
|
$( $name::$variant => dest.write_str($css) ),+
|
||||||
}
|
}
|
||||||
|
@ -46,17 +50,26 @@ macro_rules! define_numbered_css_keyword_enum {
|
||||||
pub mod computed;
|
pub mod computed;
|
||||||
pub mod specified;
|
pub mod specified;
|
||||||
|
|
||||||
|
/// A CSS float value.
|
||||||
pub type CSSFloat = f32;
|
pub type CSSFloat = f32;
|
||||||
|
|
||||||
|
/// The default font size.
|
||||||
pub const FONT_MEDIUM_PX: i32 = 16;
|
pub const FONT_MEDIUM_PX: i32 = 16;
|
||||||
|
|
||||||
|
/// A trait used to query whether this value has viewport units.
|
||||||
pub trait HasViewportPercentage {
|
pub trait HasViewportPercentage {
|
||||||
|
/// Returns true if this value has viewport units.
|
||||||
fn has_viewport_percentage(&self) -> bool;
|
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 {}
|
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 {
|
fn has_viewport_percentage(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -68,6 +81,7 @@ macro_rules! define_keyword_type {
|
||||||
($name: ident, $css: expr) => {
|
($name: ident, $css: expr) => {
|
||||||
#[derive(Clone, PartialEq, Copy)]
|
#[derive(Clone, PartialEq, Copy)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct $name;
|
pub struct $name;
|
||||||
|
|
||||||
impl ::style_traits::ToCss for $name {
|
impl ::style_traits::ToCss for $name {
|
||||||
|
@ -99,8 +113,11 @@ define_keyword_type!(Normal, "normal");
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy)]
|
#[derive(Clone, PartialEq, Copy)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
/// A struct representing one of two kinds of values.
|
||||||
pub enum Either<A, B> {
|
pub enum Either<A, B> {
|
||||||
|
/// The first value.
|
||||||
First(A),
|
First(A),
|
||||||
|
/// The second kind of value.
|
||||||
Second(B),
|
Second(B),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ use values::specified::url::SpecifiedUrl;
|
||||||
/// shape-outside uses ShapeSource<ShapeBox>
|
/// shape-outside uses ShapeSource<ShapeBox>
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum ShapeSource<T> {
|
pub enum ShapeSource<T> {
|
||||||
Url(SpecifiedUrl),
|
Url(SpecifiedUrl),
|
||||||
Shape(BasicShape, Option<T>),
|
Shape(BasicShape, Option<T>),
|
||||||
|
@ -55,6 +56,7 @@ impl<T: ToCss> ToCss for ShapeSource<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Parse + PartialEq + Copy> ShapeSource<T> {
|
impl<T: Parse + PartialEq + Copy> ShapeSource<T> {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||||
if let Ok(_) = input.try(|input| input.expect_ident_matching("none")) {
|
if let Ok(_) = input.try(|input| input.expect_ident_matching("none")) {
|
||||||
Ok(ShapeSource::None)
|
Ok(ShapeSource::None)
|
||||||
|
@ -129,6 +131,7 @@ impl<T: ToComputedValue> ToComputedValue for ShapeSource<T> {
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum BasicShape {
|
pub enum BasicShape {
|
||||||
Inset(InsetRect),
|
Inset(InsetRect),
|
||||||
Circle(Circle),
|
Circle(Circle),
|
||||||
|
@ -205,6 +208,7 @@ impl ToComputedValue for BasicShape {
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
/// https://drafts.csswg.org/css-shapes/#funcdef-inset
|
/// https://drafts.csswg.org/css-shapes/#funcdef-inset
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct InsetRect {
|
pub struct InsetRect {
|
||||||
pub top: LengthOrPercentage,
|
pub top: LengthOrPercentage,
|
||||||
pub right: LengthOrPercentage,
|
pub right: LengthOrPercentage,
|
||||||
|
@ -214,6 +218,7 @@ pub struct InsetRect {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InsetRect {
|
impl InsetRect {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<InsetRect, ()> {
|
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 (t, r, b, l) = try!(parse_four_sides(input, |i| LengthOrPercentage::parse(context, i)));
|
||||||
let mut rect = InsetRect {
|
let mut rect = InsetRect {
|
||||||
|
@ -373,12 +378,14 @@ fn serialize_basicshape_position<W>(position: &Position, dest: &mut W)
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
/// https://drafts.csswg.org/css-shapes/#funcdef-circle
|
/// https://drafts.csswg.org/css-shapes/#funcdef-circle
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct Circle {
|
pub struct Circle {
|
||||||
pub radius: ShapeRadius,
|
pub radius: ShapeRadius,
|
||||||
pub position: Position,
|
pub position: Position,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Circle {
|
impl Circle {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Circle, ()> {
|
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 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")) {
|
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)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
/// https://drafts.csswg.org/css-shapes/#funcdef-ellipse
|
/// https://drafts.csswg.org/css-shapes/#funcdef-ellipse
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct Ellipse {
|
pub struct Ellipse {
|
||||||
pub semiaxis_x: ShapeRadius,
|
pub semiaxis_x: ShapeRadius,
|
||||||
pub semiaxis_y: ShapeRadius,
|
pub semiaxis_y: ShapeRadius,
|
||||||
|
@ -458,6 +466,7 @@ pub struct Ellipse {
|
||||||
|
|
||||||
|
|
||||||
impl Ellipse {
|
impl Ellipse {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Ellipse, ()> {
|
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Ellipse, ()> {
|
||||||
let (a, b) = input.try(|input| -> Result<_, ()> {
|
let (a, b) = input.try(|input| -> Result<_, ()> {
|
||||||
Ok((try!(ShapeRadius::parse(context, input)), try!(ShapeRadius::parse(context, input))))
|
Ok((try!(ShapeRadius::parse(context, input)), try!(ShapeRadius::parse(context, input))))
|
||||||
|
@ -537,12 +546,14 @@ impl ToComputedValue for Ellipse {
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
/// https://drafts.csswg.org/css-shapes/#funcdef-polygon
|
/// https://drafts.csswg.org/css-shapes/#funcdef-polygon
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct Polygon {
|
pub struct Polygon {
|
||||||
pub fill: FillRule,
|
pub fill: FillRule,
|
||||||
pub coordinates: Vec<(LengthOrPercentage, LengthOrPercentage)>,
|
pub coordinates: Vec<(LengthOrPercentage, LengthOrPercentage)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Polygon {
|
impl Polygon {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Polygon, ()> {
|
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Polygon, ()> {
|
||||||
let fill = input.try(|input| {
|
let fill = input.try(|input| {
|
||||||
let fill = FillRule::parse(context, input);
|
let fill = FillRule::parse(context, input);
|
||||||
|
@ -626,6 +637,7 @@ impl ToComputedValue for Polygon {
|
||||||
/// https://drafts.csswg.org/css-shapes/#typedef-shape-radius
|
/// https://drafts.csswg.org/css-shapes/#typedef-shape-radius
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum ShapeRadius {
|
pub enum ShapeRadius {
|
||||||
Length(LengthOrPercentage),
|
Length(LengthOrPercentage),
|
||||||
ClosestSide,
|
ClosestSide,
|
||||||
|
@ -690,6 +702,7 @@ impl ToComputedValue for ShapeRadius {
|
||||||
/// https://drafts.csswg.org/css-backgrounds-3/#border-radius
|
/// https://drafts.csswg.org/css-backgrounds-3/#border-radius
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct BorderRadius {
|
pub struct BorderRadius {
|
||||||
pub top_left: BorderRadiusSize,
|
pub top_left: BorderRadiusSize,
|
||||||
pub top_right: BorderRadiusSize,
|
pub top_right: BorderRadiusSize,
|
||||||
|
@ -792,6 +805,7 @@ impl ToComputedValue for BorderRadius {
|
||||||
/// https://drafts.csswg.org/css-shapes/#typedef-fill-rule
|
/// https://drafts.csswg.org/css-shapes/#typedef-fill-rule
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum FillRule {
|
pub enum FillRule {
|
||||||
NonZero,
|
NonZero,
|
||||||
EvenOdd,
|
EvenOdd,
|
||||||
|
@ -830,6 +844,7 @@ impl ToCss for FillRule {
|
||||||
/// https://drafts.fxtf.org/css-masking-1/#typedef-geometry-box
|
/// https://drafts.fxtf.org/css-masking-1/#typedef-geometry-box
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum GeometryBox {
|
pub enum GeometryBox {
|
||||||
Fill,
|
Fill,
|
||||||
Stroke,
|
Stroke,
|
||||||
|
@ -868,6 +883,7 @@ impl ComputedValueAsSpecified for GeometryBox {}
|
||||||
// https://drafts.csswg.org/css-shapes-1/#typedef-shape-box
|
// https://drafts.csswg.org/css-shapes-1/#typedef-shape-box
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum ShapeBox {
|
pub enum ShapeBox {
|
||||||
Margin,
|
Margin,
|
||||||
// https://drafts.csswg.org/css-backgrounds-3/#box
|
// 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
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
//! A grid line type.
|
||||||
|
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -9,9 +11,10 @@ use style_traits::ToCss;
|
||||||
use values::NoViewportPercentage;
|
use values::NoViewportPercentage;
|
||||||
use values::computed::ComputedValueAsSpecified;
|
use values::computed::ComputedValueAsSpecified;
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-grid/#typedef-grid-row-start-grid-line
|
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[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 struct GridLine {
|
||||||
pub is_span: bool,
|
pub is_span: bool,
|
||||||
pub ident: Option<String>,
|
pub ident: Option<String>,
|
||||||
|
|
|
@ -21,7 +21,9 @@ use values::specified::url::{SpecifiedUrl, UrlExtraData};
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub enum Image {
|
pub enum Image {
|
||||||
|
/// A `<url()>` image.
|
||||||
Url(SpecifiedUrl),
|
Url(SpecifiedUrl),
|
||||||
|
/// A `<gradient>` image.
|
||||||
Gradient(Gradient),
|
Gradient(Gradient),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +37,7 @@ impl ToCss for Image {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Image {
|
impl Image {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Image, ()> {
|
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Image, ()> {
|
||||||
if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
|
if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
|
||||||
return Ok(Image::Url(url));
|
return Ok(Image::Url(url));
|
||||||
|
@ -151,7 +154,14 @@ impl Gradient {
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub enum GradientKind {
|
pub enum GradientKind {
|
||||||
|
/// A `<linear-gradient()>`:
|
||||||
|
///
|
||||||
|
/// https://drafts.csswg.org/css-images/#funcdef-linear-gradient
|
||||||
Linear(AngleOrCorner),
|
Linear(AngleOrCorner),
|
||||||
|
|
||||||
|
/// A `<radial-gradient()>`:
|
||||||
|
///
|
||||||
|
/// https://drafts.csswg.org/css-images/#radial-gradients
|
||||||
Radial(EndingShape, Position),
|
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.
|
/// Specified values for an angle or a corner in a linear gradient.
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum AngleOrCorner {
|
pub enum AngleOrCorner {
|
||||||
Angle(Angle),
|
Angle(Angle),
|
||||||
Corner(Option<HorizontalDirection>, Option<VerticalDirection>),
|
Corner(Option<HorizontalDirection>, Option<VerticalDirection>),
|
||||||
|
@ -327,6 +338,7 @@ impl Parse for ColorStop {
|
||||||
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-ending-shape
|
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-ending-shape
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum EndingShape {
|
pub enum EndingShape {
|
||||||
Circle(LengthOrKeyword),
|
Circle(LengthOrKeyword),
|
||||||
Ellipse(LengthOrPercentageOrKeyword),
|
Ellipse(LengthOrPercentageOrKeyword),
|
||||||
|
@ -351,6 +363,7 @@ impl ToCss for EndingShape {
|
||||||
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
|
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum LengthOrKeyword {
|
pub enum LengthOrKeyword {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Keyword(SizeKeyword),
|
Keyword(SizeKeyword),
|
||||||
|
@ -378,6 +391,7 @@ impl ToCss for LengthOrKeyword {
|
||||||
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
|
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum LengthOrPercentageOrKeyword {
|
pub enum LengthOrPercentageOrKeyword {
|
||||||
LengthOrPercentage(LengthOrPercentage, LengthOrPercentage),
|
LengthOrPercentage(LengthOrPercentage, LengthOrPercentage),
|
||||||
Keyword(SizeKeyword),
|
Keyword(SizeKeyword),
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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 app_units::Au;
|
||||||
use cssparser::{Parser, Token};
|
use cssparser::{Parser, Token};
|
||||||
use euclid::size::Size2D;
|
use euclid::size::Size2D;
|
||||||
|
@ -23,15 +27,22 @@ pub use super::image::{SizeKeyword, VerticalDirection};
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
/// A font relative length.
|
||||||
pub enum FontRelativeLength {
|
pub enum FontRelativeLength {
|
||||||
|
/// A "em" value: https://drafts.csswg.org/css-values/#em
|
||||||
Em(CSSFloat),
|
Em(CSSFloat),
|
||||||
|
/// A "ex" value: https://drafts.csswg.org/css-values/#ex
|
||||||
Ex(CSSFloat),
|
Ex(CSSFloat),
|
||||||
|
/// A "ch" value: https://drafts.csswg.org/css-values/#ch
|
||||||
Ch(CSSFloat),
|
Ch(CSSFloat),
|
||||||
|
/// A "rem" value: https://drafts.csswg.org/css-values/#rem
|
||||||
Rem(CSSFloat)
|
Rem(CSSFloat)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for FontRelativeLength {
|
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 {
|
match *self {
|
||||||
FontRelativeLength::Em(length) => write!(dest, "{}em", length),
|
FontRelativeLength::Em(length) => write!(dest, "{}em", length),
|
||||||
FontRelativeLength::Ex(length) => write!(dest, "{}ex", length),
|
FontRelativeLength::Ex(length) => write!(dest, "{}ex", length),
|
||||||
|
@ -42,6 +53,8 @@ impl ToCss for FontRelativeLength {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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> {
|
pub fn find_first_available_font_metrics(context: &Context) -> Option<FontMetrics> {
|
||||||
use font_metrics::FontMetricsQueryResult::*;
|
use font_metrics::FontMetricsQueryResult::*;
|
||||||
if let Some(ref metrics_provider) = context.font_metrics_provider {
|
if let Some(ref metrics_provider) = context.font_metrics_provider {
|
||||||
|
@ -55,8 +68,8 @@ impl FontRelativeLength {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB: The use_inherited flag is used to special-case the computation of
|
/// Computes the font-relative length. We use the use_inherited flag to
|
||||||
// font-family.
|
/// special-case the computation of font-size.
|
||||||
pub fn to_computed_value(&self, context: &Context, use_inherited: bool) -> Au {
|
pub fn to_computed_value(&self, context: &Context, use_inherited: bool) -> Au {
|
||||||
let reference_font_size = if use_inherited {
|
let reference_font_size = if use_inherited {
|
||||||
context.inherited_style().get_font().clone_font_size()
|
context.inherited_style().get_font().clone_font_size()
|
||||||
|
@ -121,10 +134,17 @@ impl FontRelativeLength {
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
/// A viewport-relative length.
|
||||||
|
///
|
||||||
|
/// https://drafts.csswg.org/css-values/#viewport-relative-lengths
|
||||||
pub enum ViewportPercentageLength {
|
pub enum ViewportPercentageLength {
|
||||||
|
/// A vw unit: https://drafts.csswg.org/css-values/#vw
|
||||||
Vw(CSSFloat),
|
Vw(CSSFloat),
|
||||||
|
/// A vh unit: https://drafts.csswg.org/css-values/#vh
|
||||||
Vh(CSSFloat),
|
Vh(CSSFloat),
|
||||||
|
/// https://drafts.csswg.org/css-values/#vmin
|
||||||
Vmin(CSSFloat),
|
Vmin(CSSFloat),
|
||||||
|
/// https://drafts.csswg.org/css-values/#vmax
|
||||||
Vmax(CSSFloat)
|
Vmax(CSSFloat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +166,7 @@ impl ToCss for ViewportPercentageLength {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
pub fn to_computed_value(&self, viewport_size: Size2D<Au>) -> Au {
|
||||||
macro_rules! to_unit {
|
macro_rules! to_unit {
|
||||||
($viewport_dimension:expr) => {
|
($viewport_dimension:expr) => {
|
||||||
|
@ -167,11 +188,13 @@ impl ViewportPercentageLength {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// HTML5 "character width", as defined in HTML5 § 14.5.4.
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct CharacterWidth(pub i32);
|
pub struct CharacterWidth(pub i32);
|
||||||
|
|
||||||
impl CharacterWidth {
|
impl CharacterWidth {
|
||||||
|
/// Computes the given character width.
|
||||||
pub fn to_computed_value(&self, reference_font_size: Au) -> Au {
|
pub fn to_computed_value(&self, reference_font_size: Au) -> Au {
|
||||||
// This applies the *converting a character width to pixels* algorithm as specified
|
// This applies the *converting a character width to pixels* algorithm as specified
|
||||||
// in HTML5 § 14.5.4.
|
// 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)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub enum Length {
|
pub enum Length {
|
||||||
|
/// An absolute length: https://drafts.csswg.org/css-values/#absolute-length
|
||||||
Absolute(Au), // application units
|
Absolute(Au), // application units
|
||||||
|
|
||||||
|
/// A font-relative length:
|
||||||
|
///
|
||||||
|
/// https://drafts.csswg.org/css-values/#font-relative-lengths
|
||||||
FontRelative(FontRelativeLength),
|
FontRelative(FontRelativeLength),
|
||||||
|
|
||||||
|
/// A viewport-relative length.
|
||||||
|
///
|
||||||
|
/// https://drafts.csswg.org/css-values/#viewport-relative-lengths
|
||||||
ViewportPercentage(ViewportPercentageLength),
|
ViewportPercentage(ViewportPercentageLength),
|
||||||
|
|
||||||
/// HTML5 "character width", as defined in HTML5 § 14.5.4.
|
/// HTML5 "character width", as defined in HTML5 § 14.5.4.
|
||||||
|
@ -196,6 +231,12 @@ pub enum Length {
|
||||||
/// `Stylist::synthesize_rules_for_legacy_attributes()`.
|
/// `Stylist::synthesize_rules_for_legacy_attributes()`.
|
||||||
ServoCharacterWidth(CharacterWidth),
|
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),
|
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.;
|
const AU_PER_PC: CSSFloat = AU_PER_PT * 12.;
|
||||||
|
|
||||||
impl Length {
|
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> {
|
pub fn from_str(s: &str) -> Option<Length> {
|
||||||
Some(match_ignore_ascii_case! { s,
|
Some(match_ignore_ascii_case! { s,
|
||||||
"xx-small" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 5),
|
"xx-small" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 5),
|
||||||
|
@ -306,9 +347,13 @@ impl Length {
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a non-negative length
|
||||||
pub fn parse_non_negative(input: &mut Parser) -> Result<Length, ()> {
|
pub fn parse_non_negative(input: &mut Parser) -> Result<Length, ()> {
|
||||||
Length::parse_internal(input, AllowedNumericType::NonNegative)
|
Length::parse_internal(input, AllowedNumericType::NonNegative)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a given absolute or relative dimension.
|
||||||
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Length, ()> {
|
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Length, ()> {
|
||||||
match_ignore_ascii_case! { unit,
|
match_ignore_ascii_case! { unit,
|
||||||
"px" => Ok(Length::from_px(value)),
|
"px" => Ok(Length::from_px(value)),
|
||||||
|
@ -331,6 +376,8 @@ impl Length {
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get an absolute length from a px values.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_px(px_value: CSSFloat) -> Length {
|
pub fn from_px(px_value: CSSFloat) -> Length {
|
||||||
Length::Absolute(Au((px_value * AU_PER_PX) as i32))
|
Length::Absolute(Au((px_value * AU_PER_PX) as i32))
|
||||||
|
@ -345,22 +392,29 @@ impl Parse for Length {
|
||||||
|
|
||||||
impl<T> Either<Length, T> {
|
impl<T> Either<Length, T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn parse_non_negative_length(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_non_negative_length(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||||
Length::parse_internal(input, AllowedNumericType::NonNegative).map(Either::First)
|
Length::parse_internal(input, AllowedNumericType::NonNegative).map(Either::First)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A calc sum expression node.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CalcSumNode {
|
pub struct CalcSumNode {
|
||||||
|
/// The products of this node.
|
||||||
pub products: Vec<CalcProductNode>,
|
pub products: Vec<CalcProductNode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A calc product expression node.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CalcProductNode {
|
pub struct CalcProductNode {
|
||||||
|
/// The values inside this product node.
|
||||||
values: Vec<CalcValueNode>
|
values: Vec<CalcValueNode>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A value inside a `Calc` expression.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum CalcValueNode {
|
pub enum CalcValueNode {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Angle(Angle),
|
Angle(Angle),
|
||||||
|
@ -371,6 +425,7 @@ pub enum CalcValueNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum CalcUnit {
|
pub enum CalcUnit {
|
||||||
Number,
|
Number,
|
||||||
Integer,
|
Integer,
|
||||||
|
@ -382,6 +437,7 @@ pub enum CalcUnit {
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy, Debug, Default)]
|
#[derive(Clone, PartialEq, Copy, Debug, Default)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct CalcLengthOrPercentage {
|
pub struct CalcLengthOrPercentage {
|
||||||
pub absolute: Option<Au>,
|
pub absolute: Option<Au>,
|
||||||
pub vw: Option<ViewportPercentageLength>,
|
pub vw: Option<ViewportPercentageLength>,
|
||||||
|
@ -396,6 +452,7 @@ pub struct CalcLengthOrPercentage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CalcLengthOrPercentage {
|
impl CalcLengthOrPercentage {
|
||||||
|
/// Parse a calc sum node.
|
||||||
pub fn parse_sum(input: &mut Parser, expected_unit: CalcUnit) -> Result<CalcSumNode, ()> {
|
pub fn parse_sum(input: &mut Parser, expected_unit: CalcUnit) -> Result<CalcSumNode, ()> {
|
||||||
let mut products = Vec::new();
|
let mut products = Vec::new();
|
||||||
products.push(try!(CalcLengthOrPercentage::parse_product(input, expected_unit)));
|
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, ()> {
|
pub fn simplify_product(node: &CalcProductNode) -> Result<SimplifiedValueNode, ()> {
|
||||||
let mut multiplier = 1.;
|
let mut multiplier = 1.;
|
||||||
let mut node_with_unit = None;
|
let mut node_with_unit = None;
|
||||||
|
@ -554,6 +612,7 @@ impl CalcLengthOrPercentage {
|
||||||
CalcLengthOrPercentage::parse(input, CalcUnit::LengthOrPercentage)
|
CalcLengthOrPercentage::parse(input, CalcUnit::LengthOrPercentage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn parse(input: &mut Parser,
|
pub fn parse(input: &mut Parser,
|
||||||
expected_unit: CalcUnit) -> Result<CalcLengthOrPercentage, ()> {
|
expected_unit: CalcUnit) -> Result<CalcLengthOrPercentage, ()> {
|
||||||
let ast = try!(CalcLengthOrPercentage::parse_sum(input, expected_unit));
|
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, ()> {
|
pub fn parse_time(input: &mut Parser) -> Result<Time, ()> {
|
||||||
let ast = try!(CalcLengthOrPercentage::parse_sum(input, CalcUnit::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, ()> {
|
pub fn parse_angle(input: &mut Parser) -> Result<Angle, ()> {
|
||||||
let ast = try!(CalcLengthOrPercentage::parse_sum(input, CalcUnit::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)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[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 {
|
impl ToCss for Percentage {
|
||||||
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 {
|
||||||
|
@ -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)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum LengthOrPercentage {
|
pub enum LengthOrPercentage {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Percentage(Percentage),
|
Percentage(Percentage),
|
||||||
|
@ -790,6 +858,7 @@ impl ToCss for LengthOrPercentage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl LengthOrPercentage {
|
impl LengthOrPercentage {
|
||||||
|
/// Returns a `zero` length.
|
||||||
pub fn zero() -> LengthOrPercentage {
|
pub fn zero() -> LengthOrPercentage {
|
||||||
LengthOrPercentage::Length(Length::Absolute(Au(0)))
|
LengthOrPercentage::Length(Length::Absolute(Au(0)))
|
||||||
}
|
}
|
||||||
|
@ -812,6 +881,7 @@ impl LengthOrPercentage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a non-negative length.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_non_negative(input: &mut Parser) -> Result<LengthOrPercentage, ()> {
|
pub fn parse_non_negative(input: &mut Parser) -> Result<LengthOrPercentage, ()> {
|
||||||
LengthOrPercentage::parse_internal(input, AllowedNumericType::NonNegative)
|
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)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum LengthOrPercentageOrAuto {
|
pub enum LengthOrPercentageOrAuto {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Percentage(Percentage),
|
Percentage(Percentage),
|
||||||
|
@ -875,6 +948,8 @@ impl LengthOrPercentageOrAuto {
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a non-negative length, percentage, or auto.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_non_negative(input: &mut Parser) -> Result<LengthOrPercentageOrAuto, ()> {
|
pub fn parse_non_negative(input: &mut Parser) -> Result<LengthOrPercentageOrAuto, ()> {
|
||||||
LengthOrPercentageOrAuto::parse_internal(input, AllowedNumericType::NonNegative)
|
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)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum LengthOrPercentageOrNone {
|
pub enum LengthOrPercentageOrNone {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Percentage(Percentage),
|
Percentage(Percentage),
|
||||||
|
@ -937,6 +1015,7 @@ impl LengthOrPercentageOrNone {
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Parse a non-negative LengthOrPercentageOrNone.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_non_negative(input: &mut Parser) -> Result<LengthOrPercentageOrNone, ()> {
|
pub fn parse_non_negative(input: &mut Parser) -> Result<LengthOrPercentageOrNone, ()> {
|
||||||
LengthOrPercentageOrNone::parse_internal(input, AllowedNumericType::NonNegative)
|
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_>;
|
pub type LengthOrNone = Either<Length, None_>;
|
||||||
|
|
||||||
|
/// Either a `<length>` or the `normal` keyword.
|
||||||
pub type LengthOrNormal = Either<Length, Normal>;
|
pub type LengthOrNormal = Either<Length, Normal>;
|
||||||
|
|
||||||
|
/// Either a `<length>` or the `auto` keyword.
|
||||||
pub type LengthOrAuto = Either<Length, Auto>;
|
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)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub enum LengthOrPercentageOrAutoOrContent {
|
pub enum LengthOrPercentageOrAutoOrContent {
|
||||||
|
/// A `<length>`.
|
||||||
Length(Length),
|
Length(Length),
|
||||||
|
/// A percentage.
|
||||||
Percentage(Percentage),
|
Percentage(Percentage),
|
||||||
|
/// A `calc` node.
|
||||||
Calc(CalcLengthOrPercentage),
|
Calc(CalcLengthOrPercentage),
|
||||||
|
/// The `auto` keyword.
|
||||||
Auto,
|
Auto,
|
||||||
|
/// The `content` keyword.
|
||||||
Content
|
Content
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1011,9 +1102,11 @@ impl Parse for LengthOrPercentageOrAutoOrContent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Either a `<length>` or a `<number>`.
|
||||||
pub type LengthOrNumber = Either<Length, Number>;
|
pub type LengthOrNumber = Either<Length, Number>;
|
||||||
|
|
||||||
impl LengthOrNumber {
|
impl LengthOrNumber {
|
||||||
|
/// Parse a non-negative LengthOrNumber.
|
||||||
pub fn parse_non_negative(input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_non_negative(input: &mut Parser) -> Result<Self, ()> {
|
||||||
if let Ok(v) = input.try(Length::parse_non_negative) {
|
if let Ok(v) = input.try(Length::parse_non_negative) {
|
||||||
Ok(Either::First(v))
|
Ok(Either::First(v))
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
//! Specified values.
|
||||||
|
//!
|
||||||
|
//! TODO(emilio): Enhance docs.
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::{self, Parser, Token};
|
use cssparser::{self, Parser, Token};
|
||||||
use euclid::size::Size2D;
|
use euclid::size::Size2D;
|
||||||
|
@ -35,6 +39,7 @@ impl NoViewportPercentage for i32 {} // For PropertyDeclaration::Order
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct CSSColor {
|
pub struct CSSColor {
|
||||||
pub parsed: cssparser::Color,
|
pub parsed: cssparser::Color,
|
||||||
pub authored: Option<String>,
|
pub authored: Option<String>,
|
||||||
|
@ -68,6 +73,7 @@ impl ToCss for CSSColor {
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct CSSRGBA {
|
pub struct CSSRGBA {
|
||||||
pub parsed: cssparser::RGBA,
|
pub parsed: cssparser::RGBA,
|
||||||
pub authored: Option<String>,
|
pub authored: Option<String>,
|
||||||
|
@ -85,6 +91,7 @@ impl ToCss for CSSRGBA {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct SimplifiedSumNode {
|
pub struct SimplifiedSumNode {
|
||||||
values: Vec<SimplifiedValueNode>,
|
values: Vec<SimplifiedValueNode>,
|
||||||
}
|
}
|
||||||
|
@ -100,6 +107,7 @@ impl<'a> Mul<CSSFloat> for &'a SimplifiedSumNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum SimplifiedValueNode {
|
pub enum SimplifiedValueNode {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Angle(Angle),
|
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, ()> {
|
pub fn parse_integer(input: &mut Parser) -> Result<i32, ()> {
|
||||||
match try!(input.next()) {
|
match try!(input.next()) {
|
||||||
Token::Number(ref value) => value.int_value.ok_or(()),
|
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, ()> {
|
pub fn parse_number(input: &mut Parser) -> Result<f32, ()> {
|
||||||
match try!(input.next()) {
|
match try!(input.next()) {
|
||||||
Token::Number(ref value) => Ok(value.value),
|
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)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct BorderRadiusSize(pub Size2D<LengthOrPercentage>);
|
pub struct BorderRadiusSize(pub Size2D<LengthOrPercentage>);
|
||||||
|
|
||||||
impl NoViewportPercentage for BorderRadiusSize {}
|
impl NoViewportPercentage for BorderRadiusSize {}
|
||||||
|
|
||||||
impl BorderRadiusSize {
|
impl BorderRadiusSize {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn zero() -> BorderRadiusSize {
|
pub fn zero() -> BorderRadiusSize {
|
||||||
let zero = LengthOrPercentage::Length(Length::Absolute(Au(0)));
|
let zero = LengthOrPercentage::Length(Length::Absolute(Au(0)));
|
||||||
BorderRadiusSize(Size2D::new(zero, zero))
|
BorderRadiusSize(Size2D::new(zero, zero))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn new(width: LengthOrPercentage, height: LengthOrPercentage) -> BorderRadiusSize {
|
pub fn new(width: LengthOrPercentage, height: LengthOrPercentage) -> BorderRadiusSize {
|
||||||
BorderRadiusSize(Size2D::new(width, height))
|
BorderRadiusSize(Size2D::new(width, height))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn circle(radius: LengthOrPercentage) -> BorderRadiusSize {
|
pub fn circle(radius: LengthOrPercentage) -> BorderRadiusSize {
|
||||||
BorderRadiusSize(Size2D::new(radius, radius))
|
BorderRadiusSize(Size2D::new(radius, radius))
|
||||||
}
|
}
|
||||||
|
@ -228,11 +242,13 @@ impl ToCss for Angle {
|
||||||
|
|
||||||
impl Angle {
|
impl Angle {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn radians(self) -> f32 {
|
pub fn radians(self) -> f32 {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn from_radians(r: f32) -> Self {
|
pub fn from_radians(r: f32) -> Self {
|
||||||
Angle(r)
|
Angle(r)
|
||||||
}
|
}
|
||||||
|
@ -257,6 +273,7 @@ impl Parse for Angle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Angle {
|
impl Angle {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Angle, ()> {
|
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Angle, ()> {
|
||||||
match_ignore_ascii_case! { unit,
|
match_ignore_ascii_case! { unit,
|
||||||
"deg" => Ok(Angle(value * RAD_PER_DEG)),
|
"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, ()> {
|
pub fn parse_border_radius(context: &ParserContext, input: &mut Parser) -> Result<BorderRadiusSize, ()> {
|
||||||
input.try(|i| BorderRadiusSize::parse(context, i)).or_else(|()| {
|
input.try(|i| BorderRadiusSize::parse(context, i)).or_else(|_| {
|
||||||
match_ignore_ascii_case! { try!(input.expect_ident()),
|
match_ignore_ascii_case! { try!(input.expect_ident()),
|
||||||
"thin" => Ok(BorderRadiusSize::circle(
|
"thin" => Ok(BorderRadiusSize::circle(
|
||||||
LengthOrPercentage::Length(Length::from_px(1.)))),
|
LengthOrPercentage::Length(Length::from_px(1.)))),
|
||||||
"medium" => Ok(BorderRadiusSize::circle(
|
"medium" => Ok(BorderRadiusSize::circle(
|
||||||
LengthOrPercentage::Length(Length::from_px(3.)))),
|
LengthOrPercentage::Length(Length::from_px(3.)))),
|
||||||
"thick" => Ok(BorderRadiusSize::circle(
|
"thick" => Ok(BorderRadiusSize::circle(
|
||||||
LengthOrPercentage::Length(Length::from_px(5.)))),
|
LengthOrPercentage::Length(Length::from_px(5.)))),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn parse_border_width(input: &mut Parser) -> Result<Length, ()> {
|
pub fn parse_border_width(input: &mut Parser) -> Result<Length, ()> {
|
||||||
input.try(Length::parse_non_negative).or_else(|()| {
|
input.try(Length::parse_non_negative).or_else(|()| {
|
||||||
match_ignore_ascii_case! { try!(input.expect_ident()),
|
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)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum BorderWidth {
|
pub enum BorderWidth {
|
||||||
Thin,
|
Thin,
|
||||||
Medium,
|
Medium,
|
||||||
|
@ -317,6 +337,7 @@ impl Parse for BorderWidth {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BorderWidth {
|
impl BorderWidth {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn from_length(length: Length) -> Self {
|
pub fn from_length(length: Length) -> Self {
|
||||||
BorderWidth::Width(length)
|
BorderWidth::Width(length)
|
||||||
}
|
}
|
||||||
|
@ -382,6 +403,7 @@ define_numbered_css_keyword_enum! { BorderStyle:
|
||||||
impl NoViewportPercentage for BorderStyle {}
|
impl NoViewportPercentage for BorderStyle {}
|
||||||
|
|
||||||
impl BorderStyle {
|
impl BorderStyle {
|
||||||
|
/// Whether this border style is either none or hidden.
|
||||||
pub fn none_or_hidden(&self) -> bool {
|
pub fn none_or_hidden(&self) -> bool {
|
||||||
matches!(*self, BorderStyle::none | BorderStyle::hidden)
|
matches!(*self, BorderStyle::none | BorderStyle::hidden)
|
||||||
}
|
}
|
||||||
|
@ -435,6 +457,7 @@ impl ToCss for Time {
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
|
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct Number(pub CSSFloat);
|
pub struct Number(pub CSSFloat);
|
||||||
|
|
||||||
impl NoViewportPercentage for Number {}
|
impl NoViewportPercentage for Number {}
|
||||||
|
@ -453,10 +476,12 @@ impl Number {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn parse_non_negative(input: &mut Parser) -> Result<Number, ()> {
|
pub fn parse_non_negative(input: &mut Parser) -> Result<Number, ()> {
|
||||||
Number::parse_with_minimum(input, 0.0)
|
Number::parse_with_minimum(input, 0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn parse_at_least_one(input: &mut Parser) -> Result<Number, ()> {
|
pub fn parse_at_least_one(input: &mut Parser) -> Result<Number, ()> {
|
||||||
Number::parse_with_minimum(input, 1.0)
|
Number::parse_with_minimum(input, 1.0)
|
||||||
}
|
}
|
||||||
|
@ -482,6 +507,7 @@ impl ToCss for Number {
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
|
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct Opacity(pub CSSFloat);
|
pub struct Opacity(pub CSSFloat);
|
||||||
|
|
||||||
impl NoViewportPercentage for Opacity {}
|
impl NoViewportPercentage for Opacity {}
|
||||||
|
@ -518,10 +544,12 @@ impl ToCss for Opacity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub type UrlOrNone = Either<SpecifiedUrl, None_>;
|
pub type UrlOrNone = Either<SpecifiedUrl, None_>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct Shadow {
|
pub struct Shadow {
|
||||||
pub offset_x: Length,
|
pub offset_x: Length,
|
||||||
pub offset_y: Length,
|
pub offset_y: Length,
|
||||||
|
@ -573,6 +601,7 @@ impl ToComputedValue for Shadow {
|
||||||
|
|
||||||
impl Shadow {
|
impl Shadow {
|
||||||
// disable_spread_and_inset is for filter: drop-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, ()> {
|
pub fn parse(context: &ParserContext, input: &mut Parser, disable_spread_and_inset: bool) -> Result<Shadow, ()> {
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
let length_count = if disable_spread_and_inset { 3 } else { 4 };
|
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)]
|
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
/// A [position][pos].
|
||||||
|
///
|
||||||
|
/// [pos]: https://drafts.csswg.org/css-values/#position
|
||||||
pub struct Position {
|
pub struct Position {
|
||||||
|
/// The horizontal component.
|
||||||
pub horizontal: HorizontalPosition,
|
pub horizontal: HorizontalPosition,
|
||||||
|
/// The vertical component.
|
||||||
pub vertical: VerticalPosition,
|
pub vertical: VerticalPosition,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,9 +64,12 @@ impl HasViewportPercentage for Position {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Position {
|
impl Position {
|
||||||
pub fn new(mut first_position: Option<PositionComponent>, mut second_position: Option<PositionComponent>,
|
/// Create a new position value.
|
||||||
first_keyword: Option<PositionComponent>, second_keyword: Option<PositionComponent>)
|
pub fn new(mut first_position: Option<PositionComponent>,
|
||||||
-> Result<Position, ()> {
|
mut second_position: Option<PositionComponent>,
|
||||||
|
first_keyword: Option<PositionComponent>,
|
||||||
|
second_keyword: Option<PositionComponent>)
|
||||||
|
-> Result<Position, ()> {
|
||||||
// Unwrap for checking if values are at right place.
|
// Unwrap for checking if values are at right place.
|
||||||
let first_key = first_keyword.unwrap_or(PositionComponent::Keyword(Keyword::Left));
|
let first_key = first_keyword.unwrap_or(PositionComponent::Keyword(Keyword::Left));
|
||||||
let second_key = second_keyword.unwrap_or(PositionComponent::Keyword(Keyword::Top));
|
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 {
|
pub fn center() -> Position {
|
||||||
Position {
|
Position {
|
||||||
horizontal: HorizontalPosition {
|
horizontal: HorizontalPosition {
|
||||||
|
@ -242,6 +251,7 @@ impl ToComputedValue for Position {
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Copy)]
|
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct HorizontalPosition {
|
pub struct HorizontalPosition {
|
||||||
pub keyword: Option<Keyword>,
|
pub keyword: Option<Keyword>,
|
||||||
pub position: Option<LengthOrPercentage>,
|
pub position: Option<LengthOrPercentage>,
|
||||||
|
@ -249,11 +259,7 @@ pub struct HorizontalPosition {
|
||||||
|
|
||||||
impl HasViewportPercentage for HorizontalPosition {
|
impl HasViewportPercentage for HorizontalPosition {
|
||||||
fn has_viewport_percentage(&self) -> bool {
|
fn has_viewport_percentage(&self) -> bool {
|
||||||
if let Some(pos) = self.position {
|
self.position.map_or(false, |pos| pos.has_viewport_percentage())
|
||||||
pos.has_viewport_percentage()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,6 +377,7 @@ impl ToComputedValue for HorizontalPosition {
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Copy)]
|
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct VerticalPosition {
|
pub struct VerticalPosition {
|
||||||
pub keyword: Option<Keyword>,
|
pub keyword: Option<Keyword>,
|
||||||
pub position: Option<LengthOrPercentage>,
|
pub position: Option<LengthOrPercentage>,
|
||||||
|
@ -378,11 +385,7 @@ pub struct VerticalPosition {
|
||||||
|
|
||||||
impl HasViewportPercentage for VerticalPosition {
|
impl HasViewportPercentage for VerticalPosition {
|
||||||
fn has_viewport_percentage(&self) -> bool {
|
fn has_viewport_percentage(&self) -> bool {
|
||||||
if let Some(pos) = self.position {
|
self.position.map_or(false, |pos| pos.has_viewport_percentage())
|
||||||
pos.has_viewport_percentage()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,6 +513,7 @@ define_css_keyword_enum!(Keyword:
|
||||||
"y-end" => YEnd);
|
"y-end" => YEnd);
|
||||||
|
|
||||||
impl Keyword {
|
impl Keyword {
|
||||||
|
/// Convert the given keyword to a length or a percentage.
|
||||||
pub fn to_length_or_percentage(self) -> LengthOrPercentage {
|
pub fn to_length_or_percentage(self) -> LengthOrPercentage {
|
||||||
match self {
|
match self {
|
||||||
Keyword::Center => LengthOrPercentage::Percentage(Percentage(0.5)),
|
Keyword::Center => LengthOrPercentage::Percentage(Percentage(0.5)),
|
||||||
|
@ -532,10 +536,14 @@ enum PositionCategory {
|
||||||
LengthOrPercentage,
|
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)]
|
#[derive(Clone, PartialEq, Copy)]
|
||||||
pub enum PositionComponent {
|
pub enum PositionComponent {
|
||||||
|
/// A `<length>`
|
||||||
Length(LengthOrPercentage),
|
Length(LengthOrPercentage),
|
||||||
|
/// A position keyword.
|
||||||
Keyword(Keyword),
|
Keyword(Keyword),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,6 +576,7 @@ impl HasViewportPercentage for PositionComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PositionComponent {
|
impl PositionComponent {
|
||||||
|
/// Convert the given position component to a length or a percentage.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_length_or_percentage(self) -> LengthOrPercentage {
|
pub fn to_length_or_percentage(self) -> LengthOrPercentage {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -18,23 +18,29 @@ use style_traits::ToCss;
|
||||||
use values::NoViewportPercentage;
|
use values::NoViewportPercentage;
|
||||||
use values::computed::ComputedValueAsSpecified;
|
use values::computed::ComputedValueAsSpecified;
|
||||||
|
|
||||||
|
/// A set of data needed in Gecko to represent a URL.
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Serialize, Deserialize, Eq))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Serialize, Deserialize, Eq))]
|
||||||
pub struct UrlExtraData {
|
pub struct UrlExtraData {
|
||||||
|
/// The base URI.
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub base: GeckoArcURI,
|
pub base: GeckoArcURI,
|
||||||
|
/// The referrer.
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub referrer: GeckoArcURI,
|
pub referrer: GeckoArcURI,
|
||||||
|
/// The principal that originated this URI.
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub principal: GeckoArcPrincipal,
|
pub principal: GeckoArcPrincipal,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UrlExtraData {
|
impl UrlExtraData {
|
||||||
|
/// Constructs a `UrlExtraData`.
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
pub fn make_from(_: &ParserContext) -> Option<UrlExtraData> {
|
pub fn make_from(_: &ParserContext) -> Option<UrlExtraData> {
|
||||||
Some(UrlExtraData { })
|
Some(UrlExtraData { })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs a `UrlExtraData`.
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub fn make_from(context: &ParserContext) -> Option<UrlExtraData> {
|
pub fn make_from(context: &ParserContext) -> Option<UrlExtraData> {
|
||||||
match context.extra_data {
|
match context.extra_data {
|
||||||
|
@ -81,6 +87,11 @@ impl Parse for SpecifiedUrl {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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>,
|
pub fn parse_from_string<'a>(url: Cow<'a, str>,
|
||||||
context: &ParserContext)
|
context: &ParserContext)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ()> {
|
||||||
|
@ -104,14 +115,19 @@ impl SpecifiedUrl {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get this URL's extra data.
|
||||||
pub fn extra_data(&self) -> &UrlExtraData {
|
pub fn extra_data(&self) -> &UrlExtraData {
|
||||||
&self.extra_data
|
&self.extra_data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the resolved url if it was valid.
|
||||||
pub fn url(&self) -> Option<&ServoUrl> {
|
pub fn url(&self) -> Option<&ServoUrl> {
|
||||||
self.resolved.as_ref()
|
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 {
|
pub fn as_str(&self) -> &str {
|
||||||
match self.resolved {
|
match self.resolved {
|
||||||
Some(ref url) => url.as_str(),
|
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")]
|
#[cfg(feature = "servo")]
|
||||||
pub fn new_for_testing(url: &str) -> Self {
|
pub fn new_for_testing(url: &str) -> Self {
|
||||||
SpecifiedUrl {
|
SpecifiedUrl {
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
//! [at]: https://drafts.csswg.org/css-device-adapt/#atviewport-rule
|
//! [at]: https://drafts.csswg.org/css-device-adapt/#atviewport-rule
|
||||||
//! [meta]: https://drafts.csswg.org/css-device-adapt/#viewport-meta
|
//! [meta]: https://drafts.csswg.org/css-device-adapt/#viewport-meta
|
||||||
|
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important};
|
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important};
|
||||||
use cssparser::ToCss as ParserToCss;
|
use cssparser::ToCss as ParserToCss;
|
||||||
|
@ -60,6 +62,7 @@ macro_rules! declare_viewport_descriptor_inner {
|
||||||
) => {
|
) => {
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum ViewportDescriptor {
|
pub enum ViewportDescriptor {
|
||||||
$(
|
$(
|
||||||
$assigned_variant($assigned_data),
|
$assigned_variant($assigned_data),
|
||||||
|
@ -69,6 +72,7 @@ macro_rules! declare_viewport_descriptor_inner {
|
||||||
const VIEWPORT_DESCRIPTOR_VARIANTS: usize = $number_of_variants;
|
const VIEWPORT_DESCRIPTOR_VARIANTS: usize = $number_of_variants;
|
||||||
|
|
||||||
impl ViewportDescriptor {
|
impl ViewportDescriptor {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn discriminant_value(&self) -> usize {
|
pub fn discriminant_value(&self) -> usize {
|
||||||
match *self {
|
match *self {
|
||||||
$(
|
$(
|
||||||
|
@ -114,12 +118,13 @@ trait FromMeta: Sized {
|
||||||
fn from_meta(value: &str) -> Option<Self>;
|
fn from_meta(value: &str) -> Option<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ViewportLength is a length | percentage | auto | extend-to-zoom
|
/// ViewportLength is a length | percentage | auto | extend-to-zoom
|
||||||
// See:
|
/// See:
|
||||||
// * http://dev.w3.org/csswg/css-device-adapt/#min-max-width-desc
|
/// * http://dev.w3.org/csswg/css-device-adapt/#min-max-width-desc
|
||||||
// * http://dev.w3.org/csswg/css-device-adapt/#extend-to-zoom
|
/// * http://dev.w3.org/csswg/css-device-adapt/#extend-to-zoom
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum ViewportLength {
|
pub enum ViewportLength {
|
||||||
Specified(LengthOrPercentageOrAuto),
|
Specified(LengthOrPercentageOrAuto),
|
||||||
ExtendToZoom
|
ExtendToZoom
|
||||||
|
@ -127,7 +132,7 @@ pub enum ViewportLength {
|
||||||
|
|
||||||
impl ToCss for ViewportLength {
|
impl ToCss for ViewportLength {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||||
where W: fmt::Write
|
where W: fmt::Write,
|
||||||
{
|
{
|
||||||
match *self {
|
match *self {
|
||||||
ViewportLength::Specified(length) => length.to_css(dest),
|
ViewportLength::Specified(length) => length.to_css(dest),
|
||||||
|
@ -209,6 +214,7 @@ struct ViewportRuleParser<'a, 'b: 'a> {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct ViewportDescriptorDeclaration {
|
pub struct ViewportDescriptorDeclaration {
|
||||||
pub origin: Origin,
|
pub origin: Origin,
|
||||||
pub descriptor: ViewportDescriptor,
|
pub descriptor: ViewportDescriptor,
|
||||||
|
@ -216,6 +222,7 @@ pub struct ViewportDescriptorDeclaration {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ViewportDescriptorDeclaration {
|
impl ViewportDescriptorDeclaration {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn new(origin: Origin,
|
pub fn new(origin: Origin,
|
||||||
descriptor: ViewportDescriptor,
|
descriptor: ViewportDescriptor,
|
||||||
important: bool) -> ViewportDescriptorDeclaration
|
important: bool) -> ViewportDescriptorDeclaration
|
||||||
|
@ -313,9 +320,11 @@ impl<'a, 'b> DeclarationParser for ViewportRuleParser<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A `@viewport` rule.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct ViewportRule {
|
pub struct ViewportRule {
|
||||||
|
/// The declarations contained in this @viewport rule.
|
||||||
pub declarations: Vec<ViewportDescriptorDeclaration>
|
pub declarations: Vec<ViewportDescriptorDeclaration>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,6 +342,7 @@ fn is_whitespace_separator_or_equals(c: &char) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ViewportRule {
|
impl ViewportRule {
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn parse(input: &mut Parser, context: &ParserContext)
|
pub fn parse(input: &mut Parser, context: &ParserContext)
|
||||||
-> Result<ViewportRule, ()>
|
-> Result<ViewportRule, ()>
|
||||||
{
|
{
|
||||||
|
@ -358,6 +368,7 @@ impl ViewportRule {
|
||||||
Ok(ViewportRule { declarations: cascade.finish() })
|
Ok(ViewportRule { declarations: cascade.finish() })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub fn from_meta(content: &str) -> Option<ViewportRule> {
|
pub fn from_meta(content: &str) -> Option<ViewportRule> {
|
||||||
let mut declarations = vec![None; VIEWPORT_DESCRIPTOR_VARIANTS];
|
let mut declarations = vec![None; VIEWPORT_DESCRIPTOR_VARIANTS];
|
||||||
macro_rules! push_descriptor {
|
macro_rules! push_descriptor {
|
||||||
|
@ -531,11 +542,13 @@ impl ViewportDescriptorDeclaration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct Cascade {
|
pub struct Cascade {
|
||||||
declarations: Vec<Option<(usize, ViewportDescriptorDeclaration)>>,
|
declarations: Vec<Option<(usize, ViewportDescriptorDeclaration)>>,
|
||||||
count_so_far: usize,
|
count_so_far: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
impl Cascade {
|
impl Cascade {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Cascade {
|
Cascade {
|
||||||
|
@ -545,7 +558,9 @@ impl Cascade {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_stylesheets<'a, I>(stylesheets: I, device: &Device) -> Self
|
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();
|
let mut cascade = Self::new();
|
||||||
for stylesheet in stylesheets {
|
for stylesheet in stylesheets {
|
||||||
stylesheet.as_ref().effective_viewport_rules(device, |rule| {
|
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 {
|
pub trait MaybeNew {
|
||||||
|
/// Create a ViewportConstraints from a viewport size and a `@viewport`
|
||||||
|
/// rule.
|
||||||
fn maybe_new(initial_viewport: TypedSize2D<f32, ViewportPx>,
|
fn maybe_new(initial_viewport: TypedSize2D<f32, ViewportPx>,
|
||||||
rule: &ViewportRule)
|
rule: &ViewportRule)
|
||||||
-> Option<ViewportConstraints>;
|
-> Option<ViewportConstraints>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MaybeNew for ViewportConstraints {
|
impl MaybeNew for ViewportConstraints {
|
||||||
|
|
|
@ -8,14 +8,17 @@ use super::ToCss;
|
||||||
|
|
||||||
macro_rules! define_cursor {
|
macro_rules! define_cursor {
|
||||||
($( $css: expr => $variant: ident = $value: expr, )+) => {
|
($( $css: expr => $variant: ident = $value: expr, )+) => {
|
||||||
|
/// https://drafts.csswg.org/css-ui/#cursor
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize, HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize, HeapSizeOf))]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum Cursor {
|
pub enum Cursor {
|
||||||
$( $variant = $value ),+
|
$( $variant = $value ),+
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cursor {
|
impl Cursor {
|
||||||
|
/// Given a CSS keyword, get the corresponding cursor enum.
|
||||||
pub fn from_css_keyword(keyword: &str) -> Result<Cursor, ()> {
|
pub fn from_css_keyword(keyword: &str) -> Result<Cursor, ()> {
|
||||||
match_ignore_ascii_case! { keyword,
|
match_ignore_ascii_case! { keyword,
|
||||||
$( concat!($css) => Ok(Cursor::$variant), )+
|
$( concat!($css) => Ok(Cursor::$variant), )+
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#![crate_name = "style_traits"]
|
#![crate_name = "style_traits"]
|
||||||
#![crate_type = "rlib"]
|
#![crate_type = "rlib"]
|
||||||
|
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code, missing_docs)]
|
||||||
|
|
||||||
#![cfg_attr(feature = "servo", feature(plugin))]
|
#![cfg_attr(feature = "servo", feature(plugin))]
|
||||||
#![cfg_attr(feature = "servo", feature(proc_macro))]
|
#![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
|
* 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/. */
|
* 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 app_units::Au;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -78,13 +80,14 @@ macro_rules! __define_css_keyword_enum__add_optional_traits {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! __define_css_keyword_enum__actual {
|
macro_rules! __define_css_keyword_enum__actual {
|
||||||
($name: ident [ $( $derived_trait: ident),* ] [ $( $css: expr => $variant: ident ),+ ]) => {
|
($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 )* )]
|
#[derive(Clone, Eq, PartialEq, Copy, Hash, RustcEncodable, Debug $(, $derived_trait )* )]
|
||||||
pub enum $name {
|
pub enum $name {
|
||||||
$( $variant ),+
|
$( $variant ),+
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $name {
|
impl $name {
|
||||||
|
/// Parse this property from a CSS input stream.
|
||||||
pub fn parse(input: &mut ::cssparser::Parser) -> Result<$name, ()> {
|
pub fn parse(input: &mut ::cssparser::Parser) -> Result<$name, ()> {
|
||||||
match_ignore_ascii_case! { try!(input.expect_ident()),
|
match_ignore_ascii_case! { try!(input.expect_ident()),
|
||||||
$( $css => Ok($name::$variant), )+
|
$( $css => Ok($name::$variant), )+
|
||||||
|
@ -95,27 +98,33 @@ macro_rules! __define_css_keyword_enum__actual {
|
||||||
|
|
||||||
impl ToCss for $name {
|
impl ToCss for $name {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
|
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) ),+
|
match *self {
|
||||||
}
|
$( $name::$variant => dest.write_str($css) ),+
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper types for the handling of specified values.
|
||||||
pub mod specified {
|
pub mod specified {
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
|
|
||||||
|
/// Whether to allow negative values or not.
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum AllowedNumericType {
|
pub enum AllowedNumericType {
|
||||||
|
/// Allow all kind of numeric values.
|
||||||
All,
|
All,
|
||||||
|
/// Allow only non-negative values.
|
||||||
NonNegative
|
NonNegative
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AllowedNumericType {
|
impl AllowedNumericType {
|
||||||
|
/// Whether value is valid for this allowed numeric type.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_ok(&self, value: f32) -> bool {
|
pub fn is_ok(&self, value: f32) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -124,6 +133,7 @@ pub mod specified {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clamp the value following the rules of this numeric type.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn clamp(&self, val: Au) -> Au {
|
pub fn clamp(&self, val: Au) -> Au {
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
//! Helper types for the `@viewport` rule.
|
||||||
|
|
||||||
use {PagePx, ViewportPx};
|
use {PagePx, ViewportPx};
|
||||||
use cssparser::{Parser, ToCss};
|
use cssparser::{Parser, ToCss};
|
||||||
use euclid::scale_factor::ScaleFactor;
|
use euclid::scale_factor::ScaleFactor;
|
||||||
|
@ -20,16 +22,25 @@ define_css_keyword_enum!(Orientation:
|
||||||
"landscape" => Landscape);
|
"landscape" => Landscape);
|
||||||
|
|
||||||
|
|
||||||
|
/// A set of viewport descriptors:
|
||||||
|
///
|
||||||
|
/// https://drafts.csswg.org/css-device-adapt/#viewport-desc
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize, HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize, HeapSizeOf))]
|
||||||
pub struct ViewportConstraints {
|
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>,
|
pub size: TypedSize2D<f32, ViewportPx>,
|
||||||
|
/// https://drafts.csswg.org/css-device-adapt/#zoom-desc
|
||||||
pub initial_zoom: ScaleFactor<f32, PagePx, ViewportPx>,
|
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>>,
|
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>>,
|
pub max_zoom: Option<ScaleFactor<f32, PagePx, ViewportPx>>,
|
||||||
|
/// https://drafts.csswg.org/css-device-adapt/#user-zoom-desc
|
||||||
pub user_zoom: UserZoom,
|
pub user_zoom: UserZoom,
|
||||||
|
/// https://drafts.csswg.org/css-device-adapt/#orientation-desc
|
||||||
pub orientation: Orientation
|
pub orientation: Orientation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,19 +64,21 @@ impl ToCss for ViewportConstraints {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Zoom is a number | percentage | auto
|
/// https://drafts.csswg.org/css-device-adapt/#descdef-viewport-zoom
|
||||||
/// See http://dev.w3.org/csswg/css-device-adapt/#descdef-viewport-zoom
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub enum Zoom {
|
pub enum Zoom {
|
||||||
|
/// A number value.
|
||||||
Number(f32),
|
Number(f32),
|
||||||
|
/// A percentage value.
|
||||||
Percentage(f32),
|
Percentage(f32),
|
||||||
|
/// The `auto` keyword.
|
||||||
Auto,
|
Auto,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for Zoom {
|
impl ToCss for Zoom {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||||
where W: fmt::Write
|
where W: fmt::Write,
|
||||||
{
|
{
|
||||||
match *self {
|
match *self {
|
||||||
Zoom::Number(number) => write!(dest, "{}", number),
|
Zoom::Number(number) => write!(dest, "{}", number),
|
||||||
|
@ -76,6 +89,9 @@ impl ToCss for Zoom {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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, ()> {
|
pub fn parse(input: &mut Parser) -> Result<Zoom, ()> {
|
||||||
use cssparser::Token;
|
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]
|
#[inline]
|
||||||
pub fn to_f32(&self) -> Option<f32> {
|
pub fn to_f32(&self) -> Option<f32> {
|
||||||
match *self {
|
match *self {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue