Add iterators for vector types

MozReview-Commit-ID: I7oOpYhVP5S
This commit is contained in:
Manish Goregaokar 2017-05-02 21:58:21 -07:00 committed by Manish Goregaokar
parent 36f26148e6
commit c85aae4abd
3 changed files with 43 additions and 3 deletions

View file

@ -140,7 +140,7 @@ class Longhand(object):
need_clone=False, need_index=False, gecko_ffi_name=None, depend_on_viewport_size=False,
allowed_in_keyframe_block=True, complex_color=False, cast_type='u8',
has_uncacheable_values=False, logical=False, alias=None, extra_prefixes=None, boxed=False,
flags=None, allowed_in_page_rule=False, allow_quirks=False):
flags=None, allowed_in_page_rule=False, allow_quirks=False, vector=False):
self.name = name
if not spec:
raise TypeError("Spec should be specified for %s" % name)
@ -167,6 +167,7 @@ class Longhand(object):
self.flags = flags.split() if flags else []
self.allowed_in_page_rule = arg_to_bool(allowed_in_page_rule)
self.allow_quirks = allow_quirks
self.is_vector = vector
# https://drafts.csswg.org/css-animations/#keyframes
# > The <declaration-list> inside of <keyframe-block> accepts any CSS property

View file

@ -74,7 +74,7 @@
</%doc>
<%def name="vector_longhand(name, gecko_only=False, allow_empty=False,
delegate_animate=False, space_separated_allowed=False, **kwargs)">
<%call expr="longhand(name, **kwargs)">
<%call expr="longhand(name, vector=True, **kwargs)">
% if not gecko_only:
use smallvec::SmallVec;
use std::fmt;
@ -103,6 +103,8 @@
pub use super::single_value::computed_value as single_value;
pub use self::single_value::T as SingleComputedValue;
use smallvec::SmallVec;
use values::computed::ComputedVecIter;
/// The computed value, effectively a list of single values.
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -129,6 +131,8 @@
}
}
% endif
pub type Iter<'a, 'cx, 'cx_a> = ComputedVecIter<'a, 'cx, 'cx_a, super::single_value::SpecifiedValue>;
}
impl ToCss for computed_value::T {
@ -212,12 +216,18 @@
pub use self::single_value::SpecifiedValue as SingleSpecifiedValue;
impl SpecifiedValue {
pub fn compute_iter<'a, 'cx, 'cx_a>(&'a self, context: &'cx Context<'cx_a>) -> computed_value::Iter<'a, 'cx, 'cx_a> {
computed_value::Iter::new(context, &self.0)
}
}
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline]
fn to_computed_value(&self, context: &Context) -> computed_value::T {
computed_value::T(self.0.iter().map(|x| x.to_computed_value(context)).collect())
computed_value::T(self.compute_iter(context).collect())
}
#[inline]
fn from_computed_value(computed: &computed_value::T) -> Self {

View file

@ -100,6 +100,35 @@ impl<'a> Context<'a> {
pub fn mutate_style(&mut self) -> &mut StyleBuilder<'a> { &mut self.style }
}
/// An iterator over a slice of computed values
pub struct ComputedVecIter<'a, 'cx, 'cx_a: 'cx, S: ToComputedValue + 'a> {
cx: &'cx Context<'cx_a>,
values: &'a [S],
}
impl<'a, 'cx, 'cx_a: 'cx, S: ToComputedValue + 'a> ComputedVecIter<'a, 'cx, 'cx_a, S> {
/// Construct an iterator from a slice of specified values and a context
pub fn new(cx: &'cx Context<'cx_a>, values: &'a [S]) -> Self {
ComputedVecIter {
cx: cx,
values: values,
}
}
}
impl<'a, 'cx, 'cx_a: 'cx, S: ToComputedValue + 'a> Iterator for ComputedVecIter<'a, 'cx, 'cx_a, S> {
type Item = S::ComputedValue;
fn next(&mut self) -> Option<Self::Item> {
if let Some((next, rest)) = self.values.split_first() {
let ret = next.to_computed_value(self.cx);
self.values = rest;
Some(ret)
} else {
None
}
}
}
/// A trait to represent the conversion between computed and specified values.
pub trait ToComputedValue {
/// The computed value type we're going to be converted to.