mirror of
https://github.com/servo/servo.git
synced 2025-07-05 14:33:38 +01:00
Auto merge of #20751 - emilio:gecko-sync, r=emilio
style: Sync changes from mozilla-central. See each commit for details. <!-- 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/20751) <!-- Reviewable:end -->
This commit is contained in:
commit
719e4e37e9
29 changed files with 245 additions and 326 deletions
|
@ -39,14 +39,14 @@ where
|
||||||
let mut new_running_animations = vec![];
|
let mut new_running_animations = vec![];
|
||||||
while let Ok(animation) = new_animations_receiver.try_recv() {
|
while let Ok(animation) = new_animations_receiver.try_recv() {
|
||||||
let mut should_push = true;
|
let mut should_push = true;
|
||||||
if let Animation::Keyframes(ref node, ref name, ref state) = animation {
|
if let Animation::Keyframes(ref node, _, ref name, ref state) = animation {
|
||||||
// If the animation was already present in the list for the
|
// If the animation was already present in the list for the
|
||||||
// node, just update its state, else push the new animation to
|
// node, just update its state, else push the new animation to
|
||||||
// run.
|
// run.
|
||||||
if let Some(ref mut animations) = running_animations.get_mut(node) {
|
if let Some(ref mut animations) = running_animations.get_mut(node) {
|
||||||
// TODO: This being linear is probably not optimal.
|
// TODO: This being linear is probably not optimal.
|
||||||
for anim in animations.iter_mut() {
|
for anim in animations.iter_mut() {
|
||||||
if let Animation::Keyframes(_, ref anim_name, ref mut anim_state) = *anim {
|
if let Animation::Keyframes(_, _, ref anim_name, ref mut anim_state) = *anim {
|
||||||
if *name == *anim_name {
|
if *name == *anim_name {
|
||||||
debug!("update_animation_state: Found other animation {}", name);
|
debug!("update_animation_state: Found other animation {}", name);
|
||||||
anim_state.update_from_other(&state, timer);
|
anim_state.update_from_other(&state, timer);
|
||||||
|
@ -83,7 +83,7 @@ where
|
||||||
Animation::Transition(_, started_at, ref frame, _expired) => {
|
Animation::Transition(_, started_at, ref frame, _expired) => {
|
||||||
now < started_at + frame.duration
|
now < started_at + frame.duration
|
||||||
}
|
}
|
||||||
Animation::Keyframes(_, _, ref mut state) => {
|
Animation::Keyframes(_, _, _, ref mut state) => {
|
||||||
// This animation is still running, or we need to keep
|
// This animation is still running, or we need to keep
|
||||||
// iterating.
|
// iterating.
|
||||||
now < state.started_at + state.duration || state.tick()
|
now < state.started_at + state.duration || state.tick()
|
||||||
|
|
|
@ -272,27 +272,27 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> {
|
||||||
}
|
}
|
||||||
self.traversal.list_item.truncate_to_level(self.level);
|
self.traversal.list_item.truncate_to_level(self.level);
|
||||||
|
|
||||||
for &(ref counter_name, value) in &*fragment.style().get_counters().counter_reset {
|
for pair in &*fragment.style().get_counters().counter_reset {
|
||||||
let counter_name = &*counter_name.0;
|
let counter_name = &*pair.name.0;
|
||||||
if let Some(ref mut counter) = self.traversal.counters.get_mut(counter_name) {
|
if let Some(ref mut counter) = self.traversal.counters.get_mut(counter_name) {
|
||||||
counter.reset(self.level, value);
|
counter.reset(self.level, pair.value);
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut counter = Counter::new();
|
let mut counter = Counter::new();
|
||||||
counter.reset(self.level, value);
|
counter.reset(self.level, pair.value);
|
||||||
self.traversal.counters.insert(counter_name.to_owned(), counter);
|
self.traversal.counters.insert(counter_name.to_owned(), counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
for &(ref counter_name, value) in &*fragment.style().get_counters().counter_increment {
|
for pair in &*fragment.style().get_counters().counter_increment {
|
||||||
let counter_name = &*counter_name.0;
|
let counter_name = &*pair.name.0;
|
||||||
if let Some(ref mut counter) = self.traversal.counters.get_mut(counter_name) {
|
if let Some(ref mut counter) = self.traversal.counters.get_mut(counter_name) {
|
||||||
counter.increment(self.level, value);
|
counter.increment(self.level, pair.value);
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut counter = Counter::new();
|
let mut counter = Counter::new();
|
||||||
counter.increment(self.level, value);
|
counter.increment(self.level, pair.value);
|
||||||
self.traversal.counters.insert(counter_name.to_owned(), counter);
|
self.traversal.counters.insert(counter_name.to_owned(), counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -335,7 +335,7 @@ fn create_and_insert_some_stuff() {
|
||||||
|
|
||||||
let false_positives = (1001_usize..2000).filter(|i| bf.might_contain(i)).count();
|
let false_positives = (1001_usize..2000).filter(|i| bf.might_contain(i)).count();
|
||||||
|
|
||||||
assert!(false_positives < 150, "{} is not < 150", false_positives); // 15%.
|
assert!(false_positives < 160, "{} is not < 160", false_positives); // 16%.
|
||||||
|
|
||||||
for i in 0_usize..100 {
|
for i in 0_usize..100 {
|
||||||
bf.remove(&i);
|
bf.remove(&i);
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
* 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;
|
||||||
|
@ -16,8 +15,9 @@ use properties::longhands::animation_direction::computed_value::single_value::T
|
||||||
use properties::longhands::animation_play_state::computed_value::single_value::T as AnimationPlayState;
|
use properties::longhands::animation_play_state::computed_value::single_value::T as AnimationPlayState;
|
||||||
use rule_tree::CascadeLevel;
|
use rule_tree::CascadeLevel;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
use std::fmt;
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
use stylesheets::keyframes_rule::{KeyframesStep, KeyframesStepValue};
|
use stylesheets::keyframes_rule::{KeyframesAnimation, KeyframesStep, KeyframesStepValue};
|
||||||
use timer::Timer;
|
use timer::Timer;
|
||||||
use values::computed::Time;
|
use values::computed::Time;
|
||||||
use values::computed::transform::TimingFunction;
|
use values::computed::transform::TimingFunction;
|
||||||
|
@ -52,7 +52,7 @@ pub enum KeyframesRunningState {
|
||||||
/// duration, the current and maximum iteration count, and the state (either
|
/// duration, the current and maximum iteration count, and the state (either
|
||||||
/// playing or paused).
|
/// playing or paused).
|
||||||
// TODO: unify the use of f32/f64 in this file.
|
// TODO: unify the use of f32/f64 in this file.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone)]
|
||||||
pub struct KeyframesAnimationState {
|
pub struct KeyframesAnimationState {
|
||||||
/// The time this animation started at.
|
/// The time this animation started at.
|
||||||
pub started_at: f64,
|
pub started_at: f64,
|
||||||
|
@ -183,6 +183,22 @@ impl KeyframesAnimationState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for KeyframesAnimationState {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("KeyframesAnimationState")
|
||||||
|
.field("started_at", &self.started_at)
|
||||||
|
.field("duration", &self.duration)
|
||||||
|
.field("delay", &self.delay)
|
||||||
|
.field("iteration_state", &self.iteration_state)
|
||||||
|
.field("running_state", &self.running_state)
|
||||||
|
.field("direction", &self.direction)
|
||||||
|
.field("current_direction", &self.current_direction)
|
||||||
|
.field("expired", &self.expired)
|
||||||
|
.field("cascade_style", &())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// State relating to an animation.
|
/// State relating to an animation.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Animation {
|
pub enum Animation {
|
||||||
|
@ -194,7 +210,9 @@ pub enum Animation {
|
||||||
Transition(OpaqueNode, f64, AnimationFrame, bool),
|
Transition(OpaqueNode, f64, AnimationFrame, bool),
|
||||||
/// A keyframes animation is identified by a name, and can have a
|
/// A keyframes animation is identified by a name, and can have a
|
||||||
/// node-dependent state (i.e. iteration count, etc.).
|
/// node-dependent state (i.e. iteration count, etc.).
|
||||||
Keyframes(OpaqueNode, Atom, KeyframesAnimationState),
|
///
|
||||||
|
/// TODO(emilio): The animation object could be refcounted.
|
||||||
|
Keyframes(OpaqueNode, KeyframesAnimation, Atom, KeyframesAnimationState),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Animation {
|
impl Animation {
|
||||||
|
@ -204,7 +222,7 @@ impl Animation {
|
||||||
debug_assert!(!self.is_expired());
|
debug_assert!(!self.is_expired());
|
||||||
match *self {
|
match *self {
|
||||||
Animation::Transition(_, _, _, ref mut expired) => *expired = true,
|
Animation::Transition(_, _, _, ref mut expired) => *expired = true,
|
||||||
Animation::Keyframes(_, _, ref mut state) => state.expired = true,
|
Animation::Keyframes(_, _, _, ref mut state) => state.expired = true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +231,7 @@ impl Animation {
|
||||||
pub fn is_expired(&self) -> bool {
|
pub fn is_expired(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Animation::Transition(_, _, _, expired) => expired,
|
Animation::Transition(_, _, _, expired) => expired,
|
||||||
Animation::Keyframes(_, _, ref state) => state.expired,
|
Animation::Keyframes(_, _, _, ref state) => state.expired,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +240,7 @@ impl Animation {
|
||||||
pub fn node(&self) -> &OpaqueNode {
|
pub fn node(&self) -> &OpaqueNode {
|
||||||
match *self {
|
match *self {
|
||||||
Animation::Transition(ref node, _, _, _) => node,
|
Animation::Transition(ref node, _, _, _) => node,
|
||||||
Animation::Keyframes(ref node, _, _) => node,
|
Animation::Keyframes(ref node, _, _, _) => node,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +249,7 @@ impl Animation {
|
||||||
pub fn is_paused(&self) -> bool {
|
pub fn is_paused(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Animation::Transition(..) => false,
|
Animation::Transition(..) => false,
|
||||||
Animation::Keyframes(_, _, ref state) => state.is_paused(),
|
Animation::Keyframes(_, _, _, ref state) => state.is_paused(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,7 +408,6 @@ impl PropertyAnimation {
|
||||||
/// Inserts transitions into the queue of running animations as applicable for
|
/// Inserts transitions into the queue of running animations as applicable for
|
||||||
/// the given style difference. This is called from the layout worker threads.
|
/// the given style difference. This is called from the layout worker threads.
|
||||||
/// Returns true if any animations were kicked off and false otherwise.
|
/// Returns true if any animations were kicked off and false otherwise.
|
||||||
#[cfg(feature = "servo")]
|
|
||||||
pub fn start_transitions_if_applicable(
|
pub fn start_transitions_if_applicable(
|
||||||
new_animations_sender: &Sender<Animation>,
|
new_animations_sender: &Sender<Animation>,
|
||||||
opaque_node: OpaqueNode,
|
opaque_node: OpaqueNode,
|
||||||
|
@ -500,12 +517,16 @@ where
|
||||||
|
|
||||||
/// Triggers animations for a given node looking at the animation property
|
/// Triggers animations for a given node looking at the animation property
|
||||||
/// values.
|
/// values.
|
||||||
pub fn maybe_start_animations(
|
pub fn maybe_start_animations<E>(
|
||||||
|
element: E,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
new_animations_sender: &Sender<Animation>,
|
new_animations_sender: &Sender<Animation>,
|
||||||
node: OpaqueNode,
|
node: OpaqueNode,
|
||||||
new_style: &Arc<ComputedValues>,
|
new_style: &Arc<ComputedValues>,
|
||||||
) -> bool {
|
) -> bool
|
||||||
|
where
|
||||||
|
E: TElement,
|
||||||
|
{
|
||||||
let mut had_animations = false;
|
let mut had_animations = false;
|
||||||
|
|
||||||
let box_style = new_style.get_box();
|
let box_style = new_style.get_box();
|
||||||
|
@ -522,7 +543,7 @@ pub fn maybe_start_animations(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref anim) = context.stylist.get_animation(name) {
|
if let Some(anim) = context.stylist.get_animation(name, element) {
|
||||||
debug!("maybe_start_animations: animation {} found", name);
|
debug!("maybe_start_animations: animation {} found", name);
|
||||||
|
|
||||||
// If this animation doesn't have any keyframe, we can just continue
|
// If this animation doesn't have any keyframe, we can just continue
|
||||||
|
@ -561,6 +582,7 @@ pub fn maybe_start_animations(
|
||||||
new_animations_sender
|
new_animations_sender
|
||||||
.send(Animation::Keyframes(
|
.send(Animation::Keyframes(
|
||||||
node,
|
node,
|
||||||
|
anim.clone(),
|
||||||
name.clone(),
|
name.clone(),
|
||||||
KeyframesAnimationState {
|
KeyframesAnimationState {
|
||||||
started_at: animation_start,
|
started_at: animation_start,
|
||||||
|
@ -605,6 +627,7 @@ pub fn update_style_for_animation_frame(
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates a single animation and associated style based on the current time.
|
/// Updates a single animation and associated style based on the current time.
|
||||||
pub fn update_style_for_animation<E>(
|
pub fn update_style_for_animation<E>(
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
|
@ -628,7 +651,7 @@ pub fn update_style_for_animation<E>(
|
||||||
*style = new_style
|
*style = new_style
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Animation::Keyframes(_, ref name, ref state) => {
|
Animation::Keyframes(_, ref animation, ref name, ref state) => {
|
||||||
debug!(
|
debug!(
|
||||||
"update_style_for_animation: animation found: \"{}\", {:?}",
|
"update_style_for_animation: animation found: \"{}\", {:?}",
|
||||||
name, state
|
name, state
|
||||||
|
@ -641,14 +664,6 @@ pub fn update_style_for_animation<E>(
|
||||||
KeyframesRunningState::Paused(progress) => started_at + duration * progress,
|
KeyframesRunningState::Paused(progress) => started_at + duration * progress,
|
||||||
};
|
};
|
||||||
|
|
||||||
let animation = match context.stylist.get_animation(name) {
|
|
||||||
None => {
|
|
||||||
warn!("update_style_for_animation: Animation {:?} not found", name);
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
Some(animation) => animation,
|
|
||||||
};
|
|
||||||
|
|
||||||
debug_assert!(!animation.steps.is_empty());
|
debug_assert!(!animation.steps.is_empty());
|
||||||
|
|
||||||
let maybe_index = style
|
let maybe_index = style
|
||||||
|
|
|
@ -8,8 +8,8 @@ use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
||||||
use context::QuirksMode;
|
use context::QuirksMode;
|
||||||
use dom::TElement;
|
use dom::TElement;
|
||||||
use gecko_bindings::bindings::{self, RawServoStyleSet};
|
use gecko_bindings::bindings::{self, RawServoStyleSet};
|
||||||
use gecko_bindings::structs::{self, RawGeckoPresContextOwned, ServoStyleSetSizes, ServoStyleSheet};
|
use gecko_bindings::structs::{self, RawGeckoPresContextOwned, ServoStyleSetSizes, StyleSheet as DomStyleSheet};
|
||||||
use gecko_bindings::structs::{ServoStyleSheetInner, StyleSheetInfo, nsIDocument};
|
use gecko_bindings::structs::{StyleSheetInfo, nsIDocument};
|
||||||
use gecko_bindings::sugar::ownership::{HasArcFFI, HasBoxFFI, HasFFI, HasSimpleFFI};
|
use gecko_bindings::sugar::ownership::{HasArcFFI, HasBoxFFI, HasFFI, HasSimpleFFI};
|
||||||
use invalidation::media_queries::{MediaListKey, ToMediaListKey};
|
use invalidation::media_queries::{MediaListKey, ToMediaListKey};
|
||||||
use malloc_size_of::MallocSizeOfOps;
|
use malloc_size_of::MallocSizeOfOps;
|
||||||
|
@ -23,7 +23,7 @@ use stylist::Stylist;
|
||||||
|
|
||||||
/// Little wrapper to a Gecko style sheet.
|
/// Little wrapper to a Gecko style sheet.
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct GeckoStyleSheet(*const ServoStyleSheet);
|
pub struct GeckoStyleSheet(*const DomStyleSheet);
|
||||||
|
|
||||||
impl ToMediaListKey for ::gecko::data::GeckoStyleSheet {
|
impl ToMediaListKey for ::gecko::data::GeckoStyleSheet {
|
||||||
fn to_media_list_key(&self) -> MediaListKey {
|
fn to_media_list_key(&self) -> MediaListKey {
|
||||||
|
@ -33,30 +33,30 @@ impl ToMediaListKey for ::gecko::data::GeckoStyleSheet {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GeckoStyleSheet {
|
impl GeckoStyleSheet {
|
||||||
/// Create a `GeckoStyleSheet` from a raw `ServoStyleSheet` pointer.
|
/// Create a `GeckoStyleSheet` from a raw `DomStyleSheet` pointer.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn new(s: *const ServoStyleSheet) -> Self {
|
pub unsafe fn new(s: *const DomStyleSheet) -> Self {
|
||||||
debug_assert!(!s.is_null());
|
debug_assert!(!s.is_null());
|
||||||
bindings::Gecko_StyleSheet_AddRef(s);
|
bindings::Gecko_StyleSheet_AddRef(s);
|
||||||
Self::from_addrefed(s)
|
Self::from_addrefed(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `GeckoStyleSheet` from a raw `ServoStyleSheet` pointer that
|
/// Create a `GeckoStyleSheet` from a raw `DomStyleSheet` pointer that
|
||||||
/// already holds a strong reference.
|
/// already holds a strong reference.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn from_addrefed(s: *const ServoStyleSheet) -> Self {
|
pub unsafe fn from_addrefed(s: *const DomStyleSheet) -> Self {
|
||||||
debug_assert!(!s.is_null());
|
debug_assert!(!s.is_null());
|
||||||
GeckoStyleSheet(s)
|
GeckoStyleSheet(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the raw `ServoStyleSheet` that we're wrapping.
|
/// Get the raw `StyleSheet` that we're wrapping.
|
||||||
pub fn raw(&self) -> &ServoStyleSheet {
|
pub fn raw(&self) -> &DomStyleSheet {
|
||||||
unsafe { &*self.0 }
|
unsafe { &*self.0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inner(&self) -> &ServoStyleSheetInner {
|
fn inner(&self) -> &StyleSheetInfo {
|
||||||
unsafe {
|
unsafe {
|
||||||
&*(self.raw()._base.mInner as *const StyleSheetInfo as *const ServoStyleSheetInner)
|
&*(self.raw().mInner as *const StyleSheetInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ impl StylesheetInDocument for GeckoStyleSheet {
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let dom_media_list = self.raw()._base.mMedia.mRawPtr as *const DomMediaList;
|
let dom_media_list = self.raw().mMedia.mRawPtr as *const DomMediaList;
|
||||||
if dom_media_list.is_null() {
|
if dom_media_list.is_null() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ use euclid::TypedScale;
|
||||||
use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
|
use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
|
||||||
use gecko_bindings::bindings;
|
use gecko_bindings::bindings;
|
||||||
use gecko_bindings::structs;
|
use gecko_bindings::structs;
|
||||||
use gecko_bindings::structs::{nsCSSKeyword, nsCSSProps_KTableEntry, nsCSSUnit, nsCSSValue};
|
use gecko_bindings::structs::{nsCSSKTableEntry, nsCSSKeyword, nsCSSUnit, nsCSSValue};
|
||||||
use gecko_bindings::structs::{nsMediaFeature, nsMediaFeature_RangeType};
|
use gecko_bindings::structs::{nsMediaFeature, nsMediaFeature_RangeType};
|
||||||
use gecko_bindings::structs::{nsMediaFeature_ValueType, nsPresContext};
|
use gecko_bindings::structs::{nsMediaFeature_ValueType, nsPresContext};
|
||||||
use gecko_bindings::structs::RawGeckoPresContextOwned;
|
use gecko_bindings::structs::RawGeckoPresContextOwned;
|
||||||
|
@ -479,7 +479,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn find_in_table<F>(
|
unsafe fn find_in_table<F>(
|
||||||
mut current_entry: *const nsCSSProps_KTableEntry,
|
mut current_entry: *const nsCSSKTableEntry,
|
||||||
mut f: F,
|
mut f: F,
|
||||||
) -> Option<(nsCSSKeyword, i16)>
|
) -> Option<(nsCSSKeyword, i16)>
|
||||||
where
|
where
|
||||||
|
@ -544,7 +544,7 @@ fn parse_feature_value<'i, 't>(
|
||||||
bindings::Gecko_LookupCSSKeyword(keyword.as_bytes().as_ptr(), keyword.len() as u32)
|
bindings::Gecko_LookupCSSKeyword(keyword.as_bytes().as_ptr(), keyword.len() as u32)
|
||||||
};
|
};
|
||||||
|
|
||||||
let first_table_entry: *const nsCSSProps_KTableEntry =
|
let first_table_entry: *const nsCSSKTableEntry =
|
||||||
unsafe { *feature.mData.mKeywordTable.as_ref() };
|
unsafe { *feature.mData.mKeywordTable.as_ref() };
|
||||||
|
|
||||||
let value = match unsafe { find_in_table(first_table_entry, |kw, _| kw == keyword) } {
|
let value = match unsafe { find_in_table(first_table_entry, |kw, _| kw == keyword) } {
|
||||||
|
|
|
@ -103,7 +103,6 @@ extern crate void;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
#[cfg(feature = "servo")]
|
|
||||||
pub mod animation;
|
pub mod animation;
|
||||||
pub mod applicable_declarations;
|
pub mod applicable_declarations;
|
||||||
#[allow(missing_docs)] // TODO.
|
#[allow(missing_docs)] // TODO.
|
||||||
|
|
|
@ -425,6 +425,7 @@ trait PrivateMatchMethods: TElement {
|
||||||
let this_opaque = self.as_node().opaque();
|
let this_opaque = self.as_node().opaque();
|
||||||
// Trigger any present animations if necessary.
|
// Trigger any present animations if necessary.
|
||||||
animation::maybe_start_animations(
|
animation::maybe_start_animations(
|
||||||
|
*self,
|
||||||
&shared_context,
|
&shared_context,
|
||||||
new_animations_sender,
|
new_animations_sender,
|
||||||
this_opaque,
|
this_opaque,
|
||||||
|
|
|
@ -5697,9 +5697,9 @@ clip-path
|
||||||
) {
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
bindings::Gecko_ClearAndResizeCounter${counter_property}s(&mut self.gecko, v.len() as u32);
|
bindings::Gecko_ClearAndResizeCounter${counter_property}s(&mut self.gecko, v.len() as u32);
|
||||||
for (i, &(ref name, value)) in v.iter().enumerate() {
|
for (i, ref pair) in v.iter().enumerate() {
|
||||||
self.gecko.m${counter_property}s[i].mCounter.assign(name.0.as_slice());
|
self.gecko.m${counter_property}s[i].mCounter.assign(pair.name.0.as_slice());
|
||||||
self.gecko.m${counter_property}s[i].mValue = value;
|
self.gecko.m${counter_property}s[i].mValue = pair.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5717,12 +5717,16 @@ clip-path
|
||||||
pub fn clone_counter_${counter_property.lower()}(
|
pub fn clone_counter_${counter_property.lower()}(
|
||||||
&self
|
&self
|
||||||
) -> longhands::counter_${counter_property.lower()}::computed_value::T {
|
) -> longhands::counter_${counter_property.lower()}::computed_value::T {
|
||||||
|
use values::generics::counters::CounterPair;
|
||||||
use values::CustomIdent;
|
use values::CustomIdent;
|
||||||
use gecko_string_cache::Atom;
|
use gecko_string_cache::Atom;
|
||||||
|
|
||||||
longhands::counter_${counter_property.lower()}::computed_value::T::new(
|
longhands::counter_${counter_property.lower()}::computed_value::T::new(
|
||||||
self.gecko.m${counter_property}s.iter().map(|ref gecko_counter| {
|
self.gecko.m${counter_property}s.iter().map(|ref gecko_counter| {
|
||||||
(CustomIdent(Atom::from(gecko_counter.mCounter.to_string())), gecko_counter.mValue)
|
CounterPair {
|
||||||
|
name: CustomIdent(Atom::from(gecko_counter.mCounter.to_string())),
|
||||||
|
value: gecko_counter.mValue,
|
||||||
|
}
|
||||||
}).collect()
|
}).collect()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,7 +196,6 @@ pub fn nscsspropertyid_is_transitionable(property: nsCSSPropertyID) -> bool {
|
||||||
|
|
||||||
/// An animated property interpolation between two computed values for that
|
/// An animated property interpolation between two computed values for that
|
||||||
/// property.
|
/// property.
|
||||||
#[cfg(feature = "servo")]
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
||||||
pub enum AnimatedProperty {
|
pub enum AnimatedProperty {
|
||||||
|
@ -213,7 +212,6 @@ pub enum AnimatedProperty {
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "servo")]
|
|
||||||
impl AnimatedProperty {
|
impl AnimatedProperty {
|
||||||
/// Get the name of this property.
|
/// Get the name of this property.
|
||||||
pub fn name(&self) -> &'static str {
|
pub fn name(&self) -> &'static str {
|
||||||
|
@ -255,9 +253,12 @@ impl AnimatedProperty {
|
||||||
|
|
||||||
/// Update `style` with the proper computed style corresponding to this
|
/// Update `style` with the proper computed style corresponding to this
|
||||||
/// animation at `progress`.
|
/// animation at `progress`.
|
||||||
|
#[cfg_attr(feature = "gecko", allow(unused))]
|
||||||
pub fn update(&self, style: &mut ComputedValues, progress: f64) {
|
pub fn update(&self, style: &mut ComputedValues, progress: f64) {
|
||||||
match *self {
|
#[cfg(feature = "servo")]
|
||||||
% for prop in data.longhands:
|
{
|
||||||
|
match *self {
|
||||||
|
% for prop in data.longhands:
|
||||||
% if prop.animatable:
|
% if prop.animatable:
|
||||||
AnimatedProperty::${prop.camel_case}(ref from, ref to) => {
|
AnimatedProperty::${prop.camel_case}(ref from, ref to) => {
|
||||||
// https://drafts.csswg.org/web-animations/#discrete-animation-type
|
// https://drafts.csswg.org/web-animations/#discrete-animation-type
|
||||||
|
@ -276,7 +277,8 @@ impl AnimatedProperty {
|
||||||
style.mutate_${prop.style_struct.name_lower}().set_${prop.ident}(value);
|
style.mutate_${prop.style_struct.name_lower}().set_${prop.ident}(value);
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
% endfor
|
% endfor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1291,16 +1293,8 @@ impl Animate for ComputedTransformOperation {
|
||||||
&TransformOperation::Perspective(ref fd),
|
&TransformOperation::Perspective(ref fd),
|
||||||
&TransformOperation::Perspective(ref td),
|
&TransformOperation::Perspective(ref td),
|
||||||
) => {
|
) => {
|
||||||
let mut fd_matrix = Matrix3D::identity();
|
Ok(TransformOperation::Perspective(
|
||||||
let mut td_matrix = Matrix3D::identity();
|
fd.animate(td, procedure)?
|
||||||
if fd.px() > 0. {
|
|
||||||
fd_matrix.m34 = -1. / fd.px();
|
|
||||||
}
|
|
||||||
if td.px() > 0. {
|
|
||||||
td_matrix.m34 = -1. / td.px();
|
|
||||||
}
|
|
||||||
Ok(TransformOperation::Matrix3D(
|
|
||||||
fd_matrix.animate(&td_matrix, procedure)?,
|
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
_ if self.is_translate() && other.is_translate() => {
|
_ if self.is_translate() && other.is_translate() => {
|
||||||
|
@ -2640,16 +2634,7 @@ impl ComputeSquaredDistance for ComputedTransformOperation {
|
||||||
&TransformOperation::Perspective(ref fd),
|
&TransformOperation::Perspective(ref fd),
|
||||||
&TransformOperation::Perspective(ref td),
|
&TransformOperation::Perspective(ref td),
|
||||||
) => {
|
) => {
|
||||||
let mut fd_matrix = Matrix3D::identity();
|
fd.compute_squared_distance(td)
|
||||||
let mut td_matrix = Matrix3D::identity();
|
|
||||||
if fd.px() > 0. {
|
|
||||||
fd_matrix.m34 = -1. / fd.px();
|
|
||||||
}
|
|
||||||
|
|
||||||
if td.px() > 0. {
|
|
||||||
td_matrix.m34 = -1. / td.px();
|
|
||||||
}
|
|
||||||
fd_matrix.compute_squared_distance(&td_matrix)
|
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
&TransformOperation::Perspective(ref p),
|
&TransformOperation::Perspective(ref p),
|
||||||
|
@ -2658,6 +2643,8 @@ impl ComputeSquaredDistance for ComputedTransformOperation {
|
||||||
&TransformOperation::Matrix3D(ref m),
|
&TransformOperation::Matrix3D(ref m),
|
||||||
&TransformOperation::Perspective(ref p),
|
&TransformOperation::Perspective(ref p),
|
||||||
) => {
|
) => {
|
||||||
|
// FIXME(emilio): Is this right? Why interpolating this with
|
||||||
|
// Perspective but not with anything else?
|
||||||
let mut p_matrix = Matrix3D::identity();
|
let mut p_matrix = Matrix3D::identity();
|
||||||
if p.px() > 0. {
|
if p.px() > 0. {
|
||||||
p_matrix.m34 = -1. / p.px();
|
p_matrix.m34 = -1. / p.px();
|
||||||
|
|
|
@ -56,12 +56,6 @@ use style_adjuster::StyleAdjuster;
|
||||||
|
|
||||||
pub use self::declaration_block::*;
|
pub use self::declaration_block::*;
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! property_name {
|
|
||||||
($s: tt) => { atom!($s) }
|
|
||||||
}
|
|
||||||
|
|
||||||
<%!
|
<%!
|
||||||
from data import Method, Keyword, to_rust_ident, to_camel_case, SYSTEM_FONT_LONGHANDS
|
from data import Method, Keyword, to_rust_ident, to_camel_case, SYSTEM_FONT_LONGHANDS
|
||||||
import os.path
|
import os.path
|
||||||
|
|
|
@ -237,7 +237,7 @@ pub trait ToCssWithGuard {
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub struct DeepCloneParams {
|
pub struct DeepCloneParams {
|
||||||
/// The new sheet we're cloning rules into.
|
/// The new sheet we're cloning rules into.
|
||||||
pub reference_sheet: *const ::gecko_bindings::structs::ServoStyleSheet,
|
pub reference_sheet: *const ::gecko_bindings::structs::StyleSheet,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parameters needed for deep clones.
|
/// Parameters needed for deep clones.
|
||||||
|
|
|
@ -259,7 +259,7 @@ impl DeepCloneWithLock for Keyframe {
|
||||||
/// declarations to apply.
|
/// declarations to apply.
|
||||||
///
|
///
|
||||||
/// TODO: Find a better name for this?
|
/// TODO: Find a better name for this?
|
||||||
#[derive(Debug, MallocSizeOf)]
|
#[derive(Clone, Debug, MallocSizeOf)]
|
||||||
pub enum KeyframesStepValue {
|
pub enum KeyframesStepValue {
|
||||||
/// A step formed by a declaration block specified by the CSS.
|
/// A step formed by a declaration block specified by the CSS.
|
||||||
Declarations {
|
Declarations {
|
||||||
|
@ -275,7 +275,7 @@ pub enum KeyframesStepValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A single step from a keyframe animation.
|
/// A single step from a keyframe animation.
|
||||||
#[derive(Debug, MallocSizeOf)]
|
#[derive(Clone, Debug, MallocSizeOf)]
|
||||||
pub struct KeyframesStep {
|
pub struct KeyframesStep {
|
||||||
/// The percentage of the animation duration when this step starts.
|
/// The percentage of the animation duration when this step starts.
|
||||||
pub start_percentage: KeyframePercentage,
|
pub start_percentage: KeyframePercentage,
|
||||||
|
@ -352,7 +352,7 @@ impl KeyframesStep {
|
||||||
/// of keyframes, in order.
|
/// of keyframes, in order.
|
||||||
///
|
///
|
||||||
/// It only takes into account animable properties.
|
/// It only takes into account animable properties.
|
||||||
#[derive(Debug, MallocSizeOf)]
|
#[derive(Clone, Debug, MallocSizeOf)]
|
||||||
pub struct KeyframesAnimation {
|
pub struct KeyframesAnimation {
|
||||||
/// The difference steps of the animation.
|
/// The difference steps of the animation.
|
||||||
pub steps: Vec<KeyframesStep>,
|
pub steps: Vec<KeyframesStep>,
|
||||||
|
|
|
@ -1421,14 +1421,53 @@ impl Stylist {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the registered `@keyframes` animation for the specified name.
|
/// Returns the registered `@keyframes` animation for the specified name.
|
||||||
///
|
|
||||||
/// FIXME(emilio): This needs to account for the element rules.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_animation(&self, name: &Atom) -> Option<&KeyframesAnimation> {
|
pub fn get_animation<'a, E>(
|
||||||
self.cascade_data
|
&'a self,
|
||||||
.iter_origins()
|
name: &Atom,
|
||||||
.filter_map(|(d, _)| d.animations.get(name))
|
element: E,
|
||||||
.next()
|
) -> Option<&'a KeyframesAnimation>
|
||||||
|
where
|
||||||
|
E: TElement + 'a,
|
||||||
|
{
|
||||||
|
macro_rules! try_find_in {
|
||||||
|
($data:expr) => {
|
||||||
|
if let Some(animation) = $data.animations.get(name) {
|
||||||
|
return Some(animation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(emilio): We implement basically what Blink does for this case,
|
||||||
|
// which is [1] as of this writing.
|
||||||
|
//
|
||||||
|
// See [2] for the spec discussion about what to do about this. WebKit's
|
||||||
|
// behavior makes a bit more sense off-hand, but it's way more complex
|
||||||
|
// to implement, and it makes value computation having to thread around
|
||||||
|
// the cascade level, which is not great. Also, it breaks if you inherit
|
||||||
|
// animation-name from an element in a different tree.
|
||||||
|
//
|
||||||
|
// See [3] for the bug to implement whatever gets resolved, and related
|
||||||
|
// bugs for a bit more context.
|
||||||
|
//
|
||||||
|
// [1]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/
|
||||||
|
// core/css/resolver/style_resolver.cc?l=1267&rcl=90f9f8680ebb4a87d177f3b0833372ae4e0c88d8
|
||||||
|
// [2]: https://github.com/w3c/csswg-drafts/issues/1995
|
||||||
|
// [3]: https://bugzil.la/1458189
|
||||||
|
if let Some(shadow) = element.shadow_root() {
|
||||||
|
try_find_in!(shadow.style_data());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(shadow) = element.containing_shadow() {
|
||||||
|
try_find_in!(shadow.style_data());
|
||||||
|
} else {
|
||||||
|
try_find_in!(self.cascade_data.author);
|
||||||
|
}
|
||||||
|
|
||||||
|
try_find_in!(self.cascade_data.user);
|
||||||
|
try_find_in!(self.cascade_data.user_agent.cascade_data);
|
||||||
|
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the match results of a given element against the set of
|
/// Computes the match results of a given element against the set of
|
||||||
|
@ -1517,27 +1556,25 @@ impl Stylist {
|
||||||
E: TElement,
|
E: TElement,
|
||||||
{
|
{
|
||||||
use font_metrics::get_metrics_provider_for_product;
|
use font_metrics::get_metrics_provider_for_product;
|
||||||
use std::iter;
|
|
||||||
|
|
||||||
// FIXME(emilio): Why do we even need the rule node? We should probably
|
let block = declarations.read_with(guards.author);
|
||||||
// just avoid allocating it and calling `apply_declarations` directly,
|
let iter_declarations = || {
|
||||||
// maybe...
|
block.declaration_importance_iter().map(|(declaration, importance)| {
|
||||||
let rule_node = self.rule_tree.insert_ordered_rules(iter::once((
|
debug_assert!(!importance.important());
|
||||||
StyleSource::from_declarations(declarations),
|
(declaration, CascadeLevel::StyleAttributeNormal)
|
||||||
CascadeLevel::StyleAttributeNormal,
|
})
|
||||||
)));
|
};
|
||||||
|
|
||||||
// This currently ignores visited styles. It appears to be used for
|
|
||||||
// font styles in <canvas> via Servo_StyleSet_ResolveForDeclarations.
|
|
||||||
// It is unclear if visited styles are meaningful for this case.
|
|
||||||
let metrics = get_metrics_provider_for_product();
|
let metrics = get_metrics_provider_for_product();
|
||||||
|
|
||||||
// FIXME(emilio): the pseudo bit looks quite dubious!
|
// We don't bother inserting these declarations in the rule tree, since
|
||||||
properties::cascade::<E>(
|
// it'd be quite useless and slow.
|
||||||
|
properties::apply_declarations::<E, _, _>(
|
||||||
&self.device,
|
&self.device,
|
||||||
/* pseudo = */ None,
|
/* pseudo = */ None,
|
||||||
&rule_node,
|
self.rule_tree.root(),
|
||||||
guards,
|
guards,
|
||||||
|
iter_declarations,
|
||||||
Some(parent_style),
|
Some(parent_style),
|
||||||
Some(parent_style),
|
Some(parent_style),
|
||||||
Some(parent_style),
|
Some(parent_style),
|
||||||
|
|
|
@ -251,11 +251,11 @@ impl ToAnimatedZero for TransformOperation {
|
||||||
generic::TransformOperation::Rotate(_) => {
|
generic::TransformOperation::Rotate(_) => {
|
||||||
Ok(generic::TransformOperation::Rotate(Angle::zero()))
|
Ok(generic::TransformOperation::Rotate(Angle::zero()))
|
||||||
},
|
},
|
||||||
generic::TransformOperation::Perspective(..) |
|
generic::TransformOperation::Perspective(ref l) => {
|
||||||
|
Ok(generic::TransformOperation::Perspective(l.to_animated_zero()?))
|
||||||
|
},
|
||||||
generic::TransformOperation::AccumulateMatrix { .. } |
|
generic::TransformOperation::AccumulateMatrix { .. } |
|
||||||
generic::TransformOperation::InterpolateMatrix { .. } => {
|
generic::TransformOperation::InterpolateMatrix { .. } => {
|
||||||
// Perspective: We convert a perspective function into an equivalent
|
|
||||||
// ComputedMatrix, and then decompose/interpolate/recompose these matrices.
|
|
||||||
// AccumulateMatrix/InterpolateMatrix: We do interpolation on
|
// AccumulateMatrix/InterpolateMatrix: We do interpolation on
|
||||||
// AccumulateMatrix/InterpolateMatrix by reading it as a ComputedMatrix
|
// AccumulateMatrix/InterpolateMatrix by reading it as a ComputedMatrix
|
||||||
// (with layout information), and then do matrix interpolation.
|
// (with layout information), and then do matrix interpolation.
|
||||||
|
|
|
@ -23,12 +23,13 @@ pub enum BorderImageSideWidth<LengthOrPercentage, Number> {
|
||||||
|
|
||||||
/// A generic value for the `border-image-slice` property.
|
/// A generic value for the `border-image-slice` property.
|
||||||
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||||
ToComputedValue)]
|
ToComputedValue, ToCss)]
|
||||||
pub struct BorderImageSlice<NumberOrPercentage> {
|
pub struct BorderImageSlice<NumberOrPercentage> {
|
||||||
/// The offsets.
|
/// The offsets.
|
||||||
|
#[css(field_bound)]
|
||||||
pub offsets: Rect<NumberOrPercentage>,
|
pub offsets: Rect<NumberOrPercentage>,
|
||||||
/// Whether to fill the middle part.
|
/// Whether to fill the middle part.
|
||||||
#[value_info(represents_keyword)]
|
#[css(represents_keyword)]
|
||||||
pub fill: bool,
|
pub fill: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,22 +87,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N> ToCss for BorderImageSlice<N>
|
|
||||||
where
|
|
||||||
N: PartialEq + ToCss,
|
|
||||||
{
|
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
|
||||||
where
|
|
||||||
W: Write,
|
|
||||||
{
|
|
||||||
self.offsets.to_css(dest)?;
|
|
||||||
if self.fill {
|
|
||||||
dest.write_str(" fill")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<L> BorderRadius<L> {
|
impl<L> BorderRadius<L> {
|
||||||
/// Returns a new `BorderRadius<L>`.
|
/// Returns a new `BorderRadius<L>`.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -4,12 +4,19 @@
|
||||||
|
|
||||||
//! Generic types for counters-related CSS values.
|
//! Generic types for counters-related CSS values.
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
use std::fmt::Write;
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use style_traits::{CssWriter, ToCss};
|
|
||||||
use values::CustomIdent;
|
use values::CustomIdent;
|
||||||
|
|
||||||
|
/// A name / value pair for counters.
|
||||||
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||||
|
ToComputedValue, ToCss)]
|
||||||
|
pub struct CounterPair<Integer> {
|
||||||
|
/// The name of the counter.
|
||||||
|
pub name: CustomIdent,
|
||||||
|
/// The value of the counter / increment / etc.
|
||||||
|
pub value: Integer,
|
||||||
|
}
|
||||||
|
|
||||||
/// A generic value for the `counter-increment` property.
|
/// A generic value for the `counter-increment` property.
|
||||||
#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||||
ToComputedValue, ToCss)]
|
ToComputedValue, ToCss)]
|
||||||
|
@ -18,13 +25,13 @@ pub struct CounterIncrement<I>(Counters<I>);
|
||||||
impl<I> CounterIncrement<I> {
|
impl<I> CounterIncrement<I> {
|
||||||
/// Returns a new value for `counter-increment`.
|
/// Returns a new value for `counter-increment`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(counters: Vec<(CustomIdent, I)>) -> Self {
|
pub fn new(counters: Vec<CounterPair<I>>) -> Self {
|
||||||
CounterIncrement(Counters(counters.into_boxed_slice()))
|
CounterIncrement(Counters(counters.into_boxed_slice()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I> Deref for CounterIncrement<I> {
|
impl<I> Deref for CounterIncrement<I> {
|
||||||
type Target = [(CustomIdent, I)];
|
type Target = [CounterPair<I>];
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
|
@ -40,13 +47,13 @@ pub struct CounterReset<I>(Counters<I>);
|
||||||
impl<I> CounterReset<I> {
|
impl<I> CounterReset<I> {
|
||||||
/// Returns a new value for `counter-reset`.
|
/// Returns a new value for `counter-reset`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(counters: Vec<(CustomIdent, I)>) -> Self {
|
pub fn new(counters: Vec<CounterPair<I>>) -> Self {
|
||||||
CounterReset(Counters(counters.into_boxed_slice()))
|
CounterReset(Counters(counters.into_boxed_slice()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I> Deref for CounterReset<I> {
|
impl<I> Deref for CounterReset<I> {
|
||||||
type Target = [(CustomIdent, I)];
|
type Target = [CounterPair<I>];
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
|
@ -58,8 +65,8 @@ impl<I> Deref for CounterReset<I> {
|
||||||
///
|
///
|
||||||
/// Keyword `none` is represented by an empty vector.
|
/// Keyword `none` is represented by an empty vector.
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||||
ToComputedValue)]
|
ToComputedValue, ToCss)]
|
||||||
pub struct Counters<I>(#[css(if_empty = "none")] Box<[(CustomIdent, I)]>);
|
pub struct Counters<I>(#[css(iterable, if_empty = "none")] Box<[CounterPair<I>]>);
|
||||||
|
|
||||||
impl<I> Default for Counters<I> {
|
impl<I> Default for Counters<I> {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -67,30 +74,3 @@ impl<I> Default for Counters<I> {
|
||||||
Counters(vec![].into_boxed_slice())
|
Counters(vec![].into_boxed_slice())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I> ToCss for Counters<I>
|
|
||||||
where
|
|
||||||
I: ToCss,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
|
||||||
where
|
|
||||||
W: fmt::Write,
|
|
||||||
{
|
|
||||||
if self.0.is_empty() {
|
|
||||||
return dest.write_str("none");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut first = true;
|
|
||||||
for &(ref name, ref value) in &*self.0 {
|
|
||||||
if !first {
|
|
||||||
dest.write_str(" ")?;
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
name.to_css(dest)?;
|
|
||||||
dest.write_str(" ")?;
|
|
||||||
value.to_css(dest)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,14 +4,12 @@
|
||||||
|
|
||||||
//! Generic types for CSS values related to effects.
|
//! Generic types for CSS values related to effects.
|
||||||
|
|
||||||
use std::fmt::{self, Write};
|
|
||||||
use style_traits::values::{CssWriter, SequenceWriter, ToCss};
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use values::specified::url::SpecifiedUrl;
|
use values::specified::url::SpecifiedUrl;
|
||||||
|
|
||||||
/// A generic value for a single `box-shadow`.
|
/// A generic value for a single `box-shadow`.
|
||||||
#[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
#[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||||
ToAnimatedValue, ToAnimatedZero)]
|
ToAnimatedValue, ToAnimatedZero, ToCss)]
|
||||||
pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
|
pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
|
||||||
/// The base shadow.
|
/// The base shadow.
|
||||||
pub base: SimpleShadow<Color, SizeLength, BlurShapeLength>,
|
pub base: SimpleShadow<Color, SizeLength, BlurShapeLength>,
|
||||||
|
@ -19,7 +17,7 @@ pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
|
||||||
pub spread: ShapeLength,
|
pub spread: ShapeLength,
|
||||||
/// Whether this is an inset box shadow.
|
/// Whether this is an inset box shadow.
|
||||||
#[animation(constant)]
|
#[animation(constant)]
|
||||||
#[value_info(represents_keyword)]
|
#[css(represents_keyword)]
|
||||||
pub inset: bool,
|
pub inset: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,27 +78,3 @@ pub struct SimpleShadow<Color, SizeLength, ShapeLength> {
|
||||||
/// Blur radius.
|
/// Blur radius.
|
||||||
pub blur: ShapeLength,
|
pub blur: ShapeLength,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Color, SizeLength, BlurShapeLength, ShapeLength> ToCss
|
|
||||||
for BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength>
|
|
||||||
where
|
|
||||||
Color: ToCss,
|
|
||||||
SizeLength: ToCss,
|
|
||||||
BlurShapeLength: ToCss,
|
|
||||||
ShapeLength: ToCss,
|
|
||||||
{
|
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
|
||||||
where
|
|
||||||
W: Write,
|
|
||||||
{
|
|
||||||
{
|
|
||||||
let mut writer = SequenceWriter::new(&mut *dest, " ");
|
|
||||||
writer.item(&self.base)?;
|
|
||||||
writer.item(&self.spread)?;
|
|
||||||
}
|
|
||||||
if self.inset {
|
|
||||||
dest.write_str(" inset")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ use values::CustomIdent;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use values::generics::CounterStyleOrNone;
|
use values::generics::CounterStyleOrNone;
|
||||||
use values::generics::counters::CounterIncrement as GenericCounterIncrement;
|
use values::generics::counters::CounterIncrement as GenericCounterIncrement;
|
||||||
|
use values::generics::counters::CounterPair;
|
||||||
use values::generics::counters::CounterReset as GenericCounterReset;
|
use values::generics::counters::CounterReset as GenericCounterReset;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use values::specified::Attr;
|
use values::specified::Attr;
|
||||||
|
@ -48,7 +49,7 @@ fn parse_counters<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
default_value: i32,
|
default_value: i32,
|
||||||
) -> Result<Vec<(CustomIdent, Integer)>, ParseError<'i>> {
|
) -> Result<Vec<CounterPair<Integer>>, ParseError<'i>> {
|
||||||
if input
|
if input
|
||||||
.try(|input| input.expect_ident_matching("none"))
|
.try(|input| input.expect_ident_matching("none"))
|
||||||
.is_ok()
|
.is_ok()
|
||||||
|
@ -59,16 +60,16 @@ fn parse_counters<'i, 't>(
|
||||||
let mut counters = Vec::new();
|
let mut counters = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
let location = input.current_source_location();
|
let location = input.current_source_location();
|
||||||
let counter_name = match input.next() {
|
let name = match input.next() {
|
||||||
Ok(&Token::Ident(ref ident)) => CustomIdent::from_ident(location, ident, &["none"])?,
|
Ok(&Token::Ident(ref ident)) => CustomIdent::from_ident(location, ident, &["none"])?,
|
||||||
Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
|
Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
};
|
};
|
||||||
|
|
||||||
let counter_delta = input
|
let value = input
|
||||||
.try(|input| Integer::parse(context, input))
|
.try(|input| Integer::parse(context, input))
|
||||||
.unwrap_or(Integer::new(default_value));
|
.unwrap_or(Integer::new(default_value));
|
||||||
counters.push((counter_name, counter_delta))
|
counters.push(CounterPair { name, value });
|
||||||
}
|
}
|
||||||
|
|
||||||
if !counters.is_empty() {
|
if !counters.is_empty() {
|
||||||
|
|
|
@ -1947,11 +1947,11 @@ pub struct FontSynthesis {
|
||||||
/// If a `font-weight` is requested that the font family does not contain,
|
/// If a `font-weight` is requested that the font family does not contain,
|
||||||
/// the user agent may synthesize the requested weight from the weights
|
/// the user agent may synthesize the requested weight from the weights
|
||||||
/// that do exist in the font family.
|
/// that do exist in the font family.
|
||||||
#[value_info(represents_keyword)]
|
#[css(represents_keyword)]
|
||||||
pub weight: bool,
|
pub weight: bool,
|
||||||
/// If a font-style is requested that the font family does not contain,
|
/// If a font-style is requested that the font family does not contain,
|
||||||
/// the user agent may synthesize the requested style from the normal face in the font family.
|
/// the user agent may synthesize the requested style from the normal face in the font family.
|
||||||
#[value_info(represents_keyword)]
|
#[css(represents_keyword)]
|
||||||
pub style: bool,
|
pub style: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -424,14 +424,14 @@ pub enum AutoFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
|
||||||
ToComputedValue)]
|
ToComputedValue, ToCss)]
|
||||||
/// Controls how the auto-placement algorithm works
|
/// Controls how the auto-placement algorithm works
|
||||||
/// specifying exactly how auto-placed items get flowed into the grid
|
/// specifying exactly how auto-placed items get flowed into the grid
|
||||||
pub struct GridAutoFlow {
|
pub struct GridAutoFlow {
|
||||||
/// Specifiy how auto-placement algorithm fills each `row` or `column` in turn
|
/// Specifiy how auto-placement algorithm fills each `row` or `column` in turn
|
||||||
pub autoflow: AutoFlow,
|
pub autoflow: AutoFlow,
|
||||||
/// Specify use `dense` packing algorithm or not
|
/// Specify use `dense` packing algorithm or not
|
||||||
#[value_info(represents_keyword)]
|
#[css(represents_keyword)]
|
||||||
pub dense: bool,
|
pub dense: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,20 +446,6 @@ impl GridAutoFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for GridAutoFlow {
|
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
|
||||||
where
|
|
||||||
W: Write,
|
|
||||||
{
|
|
||||||
self.autoflow.to_css(dest)?;
|
|
||||||
|
|
||||||
if self.dense {
|
|
||||||
dest.write_str(" dense")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parse for GridAutoFlow {
|
impl Parse for GridAutoFlow {
|
||||||
/// [ row | column ] || dense
|
/// [ row | column ] || dense
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
|
|
|
@ -140,13 +140,13 @@ fn derive_struct_fields<'a>(
|
||||||
values.push(value.to_string());
|
values.push(value.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if info_attrs.represents_keyword {
|
let css_attrs = cg::parse_field_attrs::<CssFieldAttrs>(field);
|
||||||
|
if css_attrs.represents_keyword {
|
||||||
let ident = field.ident.as_ref()
|
let ident = field.ident.as_ref()
|
||||||
.expect("only named field should use represents_keyword");
|
.expect("only named field should use represents_keyword");
|
||||||
values.push(cg::to_css_identifier(ident.as_ref()));
|
values.push(cg::to_css_identifier(ident.as_ref()));
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let css_attrs = cg::parse_field_attrs::<CssFieldAttrs>(field);
|
|
||||||
if let Some(if_empty) = css_attrs.if_empty {
|
if let Some(if_empty) = css_attrs.if_empty {
|
||||||
values.push(if_empty);
|
values.push(if_empty);
|
||||||
}
|
}
|
||||||
|
@ -176,6 +176,5 @@ struct ValueInfoVariantAttrs {
|
||||||
#[darling(attributes(value_info), default)]
|
#[darling(attributes(value_info), default)]
|
||||||
#[derive(Default, FromField)]
|
#[derive(Default, FromField)]
|
||||||
struct ValueInfoFieldAttrs {
|
struct ValueInfoFieldAttrs {
|
||||||
represents_keyword: bool,
|
|
||||||
other_values: Option<String>,
|
other_values: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,7 +175,7 @@ fn derive_single_field_expr(
|
||||||
{
|
{
|
||||||
let mut iter = #field.iter().peekable();
|
let mut iter = #field.iter().peekable();
|
||||||
if iter.peek().is_none() {
|
if iter.peek().is_none() {
|
||||||
writer.item(&::style_traits::values::Verbatim(#if_empty))?;
|
writer.raw_item(#if_empty)?;
|
||||||
} else {
|
} else {
|
||||||
for item in iter {
|
for item in iter {
|
||||||
writer.item(&item)?;
|
writer.item(&item)?;
|
||||||
|
@ -189,6 +189,15 @@ fn derive_single_field_expr(
|
||||||
writer.item(&item)?;
|
writer.item(&item)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if attrs.represents_keyword {
|
||||||
|
let ident =
|
||||||
|
field.ast().ident.as_ref().expect("Unnamed field with represents_keyword?");
|
||||||
|
let ident = cg::to_css_identifier(ident.as_ref());
|
||||||
|
quote! {
|
||||||
|
if *#field {
|
||||||
|
writer.raw_item(#ident)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if attrs.field_bound {
|
if attrs.field_bound {
|
||||||
let ty = &field.ast().ty;
|
let ty = &field.ast().ty;
|
||||||
|
@ -236,5 +245,6 @@ pub struct CssFieldAttrs {
|
||||||
pub field_bound: bool,
|
pub field_bound: bool,
|
||||||
pub iterable: bool,
|
pub iterable: bool,
|
||||||
pub skip: bool,
|
pub skip: bool,
|
||||||
|
pub represents_keyword: bool,
|
||||||
pub skip_if: Option<Path>,
|
pub skip_if: Option<Path>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,8 +56,6 @@ pub type KeywordsCollectFn<'a> = &'a mut FnMut(&[&'static str]);
|
||||||
/// * `#[value_info(starts_with_keyword)]` can be used on variants to
|
/// * `#[value_info(starts_with_keyword)]` can be used on variants to
|
||||||
/// add the name of a non-unit variant (serialized like `ToCss`) into
|
/// add the name of a non-unit variant (serialized like `ToCss`) into
|
||||||
/// `collect_completion_keywords`.
|
/// `collect_completion_keywords`.
|
||||||
/// * `#[value_info(represents_keyword)]` can be used on fields into
|
|
||||||
/// `collect_completion_keywords`.
|
|
||||||
pub trait SpecifiedValueInfo {
|
pub trait SpecifiedValueInfo {
|
||||||
/// Supported CssTypes by the given value type.
|
/// Supported CssTypes by the given value type.
|
||||||
///
|
///
|
||||||
|
|
|
@ -37,6 +37,9 @@ use std::fmt::{self, Write};
|
||||||
/// * if `#[css(skip_if = "function")]` is found on a field, the `ToCss` call
|
/// * if `#[css(skip_if = "function")]` is found on a field, the `ToCss` call
|
||||||
/// for that field is skipped if `function` returns true. This function is
|
/// for that field is skipped if `function` returns true. This function is
|
||||||
/// provided the field as an argument;
|
/// provided the field as an argument;
|
||||||
|
/// * `#[css(represents_keyword)]` can be used on bool fields in order to
|
||||||
|
/// serialize the field name if the field is true, or nothing otherwise. It
|
||||||
|
/// also collects those keywords for `SpecifiedValueInfo`.
|
||||||
/// * finally, one can put `#[css(derive_debug)]` on the whole type, to
|
/// * finally, one can put `#[css(derive_debug)]` on the whole type, to
|
||||||
/// implement `Debug` by a single call to `ToCss::to_css`.
|
/// implement `Debug` by a single call to `ToCss::to_css`.
|
||||||
pub trait ToCss {
|
pub trait ToCss {
|
||||||
|
@ -232,21 +235,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper type that implements `ToCss` by printing its inner field.
|
|
||||||
pub struct Verbatim<'a, T>(pub &'a T)
|
|
||||||
where
|
|
||||||
T: ?Sized + 'a;
|
|
||||||
|
|
||||||
impl<'a, T> ToCss for Verbatim<'a, T>
|
|
||||||
where
|
|
||||||
T: AsRef<str> + ?Sized + 'a,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: Write {
|
|
||||||
dest.write_str(self.0.as_ref())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Type used as the associated type in the `OneOrMoreSeparated` trait on a
|
/// Type used as the associated type in the `OneOrMoreSeparated` trait on a
|
||||||
/// type to indicate that a serialized list of elements of this type is
|
/// type to indicate that a serialized list of elements of this type is
|
||||||
/// separated by commas.
|
/// separated by commas.
|
||||||
|
|
|
@ -14,7 +14,7 @@ use std::ptr;
|
||||||
use style::error_reporting::{ParseErrorReporter, ContextualParseError};
|
use style::error_reporting::{ParseErrorReporter, ContextualParseError};
|
||||||
use style::gecko_bindings::bindings::{Gecko_CreateCSSErrorReporter, Gecko_DestroyCSSErrorReporter};
|
use style::gecko_bindings::bindings::{Gecko_CreateCSSErrorReporter, Gecko_DestroyCSSErrorReporter};
|
||||||
use style::gecko_bindings::bindings::Gecko_ReportUnexpectedCSSError;
|
use style::gecko_bindings::bindings::Gecko_ReportUnexpectedCSSError;
|
||||||
use style::gecko_bindings::structs::{Loader, ServoStyleSheet, nsIURI};
|
use style::gecko_bindings::structs::{Loader, StyleSheet as DomStyleSheet, nsIURI};
|
||||||
use style::gecko_bindings::structs::ErrorReporter as GeckoErrorReporter;
|
use style::gecko_bindings::structs::ErrorReporter as GeckoErrorReporter;
|
||||||
use style::gecko_bindings::structs::URLExtraData as RawUrlExtraData;
|
use style::gecko_bindings::structs::URLExtraData as RawUrlExtraData;
|
||||||
use style::stylesheets::UrlExtraData;
|
use style::stylesheets::UrlExtraData;
|
||||||
|
@ -27,9 +27,11 @@ pub struct ErrorReporter(*mut GeckoErrorReporter);
|
||||||
|
|
||||||
impl ErrorReporter {
|
impl ErrorReporter {
|
||||||
/// Create a new instance of the Gecko error reporter.
|
/// Create a new instance of the Gecko error reporter.
|
||||||
pub fn new(sheet: *mut ServoStyleSheet,
|
pub fn new(
|
||||||
loader: *mut Loader,
|
sheet: *mut DomStyleSheet,
|
||||||
extra_data: *mut RawUrlExtraData) -> ErrorReporter {
|
loader: *mut Loader,
|
||||||
|
extra_data: *mut RawUrlExtraData,
|
||||||
|
) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
let url = extra_data.as_ref()
|
let url = extra_data.as_ref()
|
||||||
.map(|d| d.mBaseURI.raw::<nsIURI>())
|
.map(|d| d.mBaseURI.raw::<nsIURI>())
|
||||||
|
|
|
@ -73,7 +73,6 @@ use style::gecko_bindings::bindings::RawGeckoCSSPropertyIDListBorrowed;
|
||||||
use style::gecko_bindings::bindings::RawGeckoComputedKeyframeValuesListBorrowedMut;
|
use style::gecko_bindings::bindings::RawGeckoComputedKeyframeValuesListBorrowedMut;
|
||||||
use style::gecko_bindings::bindings::RawGeckoComputedTimingBorrowed;
|
use style::gecko_bindings::bindings::RawGeckoComputedTimingBorrowed;
|
||||||
use style::gecko_bindings::bindings::RawGeckoFontFaceRuleListBorrowedMut;
|
use style::gecko_bindings::bindings::RawGeckoFontFaceRuleListBorrowedMut;
|
||||||
use style::gecko_bindings::bindings::RawGeckoServoAnimationValueListBorrowed;
|
|
||||||
use style::gecko_bindings::bindings::RawGeckoServoAnimationValueListBorrowedMut;
|
use style::gecko_bindings::bindings::RawGeckoServoAnimationValueListBorrowedMut;
|
||||||
use style::gecko_bindings::bindings::RawGeckoServoStyleRuleListBorrowedMut;
|
use style::gecko_bindings::bindings::RawGeckoServoStyleRuleListBorrowedMut;
|
||||||
use style::gecko_bindings::bindings::RawServoAnimationValueBorrowed;
|
use style::gecko_bindings::bindings::RawServoAnimationValueBorrowed;
|
||||||
|
@ -92,8 +91,8 @@ use style::gecko_bindings::structs;
|
||||||
use style::gecko_bindings::structs::{CallerType, CSSPseudoElementType, CompositeOperation};
|
use style::gecko_bindings::structs::{CallerType, CSSPseudoElementType, CompositeOperation};
|
||||||
use style::gecko_bindings::structs::{Loader, LoaderReusableStyleSheets};
|
use style::gecko_bindings::structs::{Loader, LoaderReusableStyleSheets};
|
||||||
use style::gecko_bindings::structs::{RawServoStyleRule, ComputedStyleStrong, RustString};
|
use style::gecko_bindings::structs::{RawServoStyleRule, ComputedStyleStrong, RustString};
|
||||||
use style::gecko_bindings::structs::{ServoStyleSheet, SheetLoadData, SheetLoadDataHolder};
|
|
||||||
use style::gecko_bindings::structs::{SheetParsingMode, nsAtom, nsCSSPropertyID};
|
use style::gecko_bindings::structs::{SheetParsingMode, nsAtom, nsCSSPropertyID};
|
||||||
|
use style::gecko_bindings::structs::{StyleSheet as DomStyleSheet, SheetLoadData, SheetLoadDataHolder};
|
||||||
use style::gecko_bindings::structs::{nsCSSFontDesc, nsCSSCounterDesc};
|
use style::gecko_bindings::structs::{nsCSSFontDesc, nsCSSCounterDesc};
|
||||||
use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint, PropertyValuePair};
|
use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint, PropertyValuePair};
|
||||||
use style::gecko_bindings::structs::AtomArray;
|
use style::gecko_bindings::structs::AtomArray;
|
||||||
|
@ -129,7 +128,7 @@ use style::invalidation::element::restyle_hints;
|
||||||
use style::media_queries::{MediaList, parse_media_query_list};
|
use style::media_queries::{MediaList, parse_media_query_list};
|
||||||
use style::parser::{Parse, ParserContext, self};
|
use style::parser::{Parse, ParserContext, self};
|
||||||
use style::properties::{ComputedValues, DeclarationSource, Importance};
|
use style::properties::{ComputedValues, DeclarationSource, Importance};
|
||||||
use style::properties::{LonghandId, LonghandIdSet, PropertyDeclaration, PropertyDeclarationBlock, PropertyId};
|
use style::properties::{LonghandId, LonghandIdSet, PropertyDeclarationBlock, PropertyId};
|
||||||
use style::properties::{PropertyDeclarationId, ShorthandId};
|
use style::properties::{PropertyDeclarationId, ShorthandId};
|
||||||
use style::properties::{SourcePropertyDeclaration, StyleBuilder};
|
use style::properties::{SourcePropertyDeclaration, StyleBuilder};
|
||||||
use style::properties::{parse_one_declaration_into, parse_style_attribute};
|
use style::properties::{parse_one_declaration_into, parse_style_attribute};
|
||||||
|
@ -708,31 +707,6 @@ pub extern "C" fn Servo_AnimationValue_Serialize(
|
||||||
debug_assert!(rv.is_ok());
|
debug_assert!(rv.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn Servo_Shorthand_AnimationValues_Serialize(
|
|
||||||
shorthand_property: nsCSSPropertyID,
|
|
||||||
values: RawGeckoServoAnimationValueListBorrowed,
|
|
||||||
buffer: *mut nsAString,
|
|
||||||
) {
|
|
||||||
let property_id = get_property_id_from_nscsspropertyid!(shorthand_property, ());
|
|
||||||
let shorthand = match property_id.as_shorthand() {
|
|
||||||
Ok(shorthand) => shorthand,
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Convert RawServoAnimationValue(s) into a vector of PropertyDeclaration
|
|
||||||
// so that we can use reference of the PropertyDeclaration without worrying
|
|
||||||
// about its lifetime. (longhands_to_css() expects &PropertyDeclaration
|
|
||||||
// iterator.)
|
|
||||||
let declarations: Vec<PropertyDeclaration> =
|
|
||||||
values.iter().map(|v| AnimationValue::as_arc(&&*v.mRawPtr).uncompute()).collect();
|
|
||||||
|
|
||||||
let _ = shorthand.longhands_to_css(
|
|
||||||
declarations.iter(),
|
|
||||||
&mut CssWriter::new(&mut *buffer),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_AnimationValue_GetOpacity(
|
pub extern "C" fn Servo_AnimationValue_GetOpacity(
|
||||||
value: RawServoAnimationValueBorrowed,
|
value: RawServoAnimationValueBorrowed,
|
||||||
|
@ -1194,7 +1168,7 @@ fn mode_to_origin(mode: SheetParsingMode) -> Origin {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(
|
pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(
|
||||||
loader: *mut Loader,
|
loader: *mut Loader,
|
||||||
stylesheet: *mut ServoStyleSheet,
|
stylesheet: *mut DomStyleSheet,
|
||||||
load_data: *mut SheetLoadData,
|
load_data: *mut SheetLoadData,
|
||||||
bytes: *const nsACString,
|
bytes: *const nsACString,
|
||||||
mode: SheetParsingMode,
|
mode: SheetParsingMode,
|
||||||
|
@ -1263,7 +1237,7 @@ pub extern "C" fn Servo_StyleSheet_FromUTF8BytesAsync(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_StyleSet_AppendStyleSheet(
|
pub extern "C" fn Servo_StyleSet_AppendStyleSheet(
|
||||||
raw_data: RawServoStyleSetBorrowed,
|
raw_data: RawServoStyleSetBorrowed,
|
||||||
sheet: *const ServoStyleSheet,
|
sheet: *const DomStyleSheet,
|
||||||
) {
|
) {
|
||||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
||||||
|
@ -1288,7 +1262,7 @@ pub extern "C" fn Servo_AuthorStyles_Drop(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Servo_AuthorStyles_AppendStyleSheet(
|
pub unsafe extern "C" fn Servo_AuthorStyles_AppendStyleSheet(
|
||||||
styles: RawServoAuthorStylesBorrowedMut,
|
styles: RawServoAuthorStylesBorrowedMut,
|
||||||
sheet: *const ServoStyleSheet,
|
sheet: *const DomStyleSheet,
|
||||||
) {
|
) {
|
||||||
let styles = AuthorStyles::<GeckoStyleSheet>::from_ffi_mut(styles);
|
let styles = AuthorStyles::<GeckoStyleSheet>::from_ffi_mut(styles);
|
||||||
|
|
||||||
|
@ -1301,8 +1275,8 @@ pub unsafe extern "C" fn Servo_AuthorStyles_AppendStyleSheet(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Servo_AuthorStyles_InsertStyleSheetBefore(
|
pub unsafe extern "C" fn Servo_AuthorStyles_InsertStyleSheetBefore(
|
||||||
styles: RawServoAuthorStylesBorrowedMut,
|
styles: RawServoAuthorStylesBorrowedMut,
|
||||||
sheet: *const ServoStyleSheet,
|
sheet: *const DomStyleSheet,
|
||||||
before_sheet: *const ServoStyleSheet,
|
before_sheet: *const DomStyleSheet,
|
||||||
) {
|
) {
|
||||||
let styles = AuthorStyles::<GeckoStyleSheet>::from_ffi_mut(styles);
|
let styles = AuthorStyles::<GeckoStyleSheet>::from_ffi_mut(styles);
|
||||||
|
|
||||||
|
@ -1319,7 +1293,7 @@ pub unsafe extern "C" fn Servo_AuthorStyles_InsertStyleSheetBefore(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Servo_AuthorStyles_RemoveStyleSheet(
|
pub unsafe extern "C" fn Servo_AuthorStyles_RemoveStyleSheet(
|
||||||
styles: RawServoAuthorStylesBorrowedMut,
|
styles: RawServoAuthorStylesBorrowedMut,
|
||||||
sheet: *const ServoStyleSheet,
|
sheet: *const DomStyleSheet,
|
||||||
) {
|
) {
|
||||||
let styles = AuthorStyles::<GeckoStyleSheet>::from_ffi_mut(styles);
|
let styles = AuthorStyles::<GeckoStyleSheet>::from_ffi_mut(styles);
|
||||||
|
|
||||||
|
@ -1454,7 +1428,7 @@ pub unsafe extern "C" fn Servo_StyleSet_MediumFeaturesChanged(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_StyleSet_PrependStyleSheet(
|
pub extern "C" fn Servo_StyleSet_PrependStyleSheet(
|
||||||
raw_data: RawServoStyleSetBorrowed,
|
raw_data: RawServoStyleSetBorrowed,
|
||||||
sheet: *const ServoStyleSheet,
|
sheet: *const DomStyleSheet,
|
||||||
) {
|
) {
|
||||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
||||||
|
@ -1467,8 +1441,8 @@ pub extern "C" fn Servo_StyleSet_PrependStyleSheet(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_StyleSet_InsertStyleSheetBefore(
|
pub extern "C" fn Servo_StyleSet_InsertStyleSheetBefore(
|
||||||
raw_data: RawServoStyleSetBorrowed,
|
raw_data: RawServoStyleSetBorrowed,
|
||||||
sheet: *const ServoStyleSheet,
|
sheet: *const DomStyleSheet,
|
||||||
before_sheet: *const ServoStyleSheet
|
before_sheet: *const DomStyleSheet
|
||||||
) {
|
) {
|
||||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
||||||
|
@ -1485,7 +1459,7 @@ pub extern "C" fn Servo_StyleSet_InsertStyleSheetBefore(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_StyleSet_RemoveStyleSheet(
|
pub extern "C" fn Servo_StyleSet_RemoveStyleSheet(
|
||||||
raw_data: RawServoStyleSetBorrowed,
|
raw_data: RawServoStyleSetBorrowed,
|
||||||
sheet: *const ServoStyleSheet
|
sheet: *const DomStyleSheet
|
||||||
) {
|
) {
|
||||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
||||||
|
@ -1560,7 +1534,7 @@ pub extern "C" fn Servo_StyleSheet_GetRules(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_StyleSheet_Clone(
|
pub extern "C" fn Servo_StyleSheet_Clone(
|
||||||
raw_sheet: RawServoStyleSheetContentsBorrowed,
|
raw_sheet: RawServoStyleSheetContentsBorrowed,
|
||||||
reference_sheet: *const ServoStyleSheet,
|
reference_sheet: *const DomStyleSheet,
|
||||||
) -> RawServoStyleSheetContentsStrong {
|
) -> RawServoStyleSheetContentsStrong {
|
||||||
use style::shared_lock::{DeepCloneParams, DeepCloneWithLock};
|
use style::shared_lock::{DeepCloneParams, DeepCloneWithLock};
|
||||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
|
@ -1681,7 +1655,7 @@ pub extern "C" fn Servo_CssRules_InsertRule(
|
||||||
index: u32,
|
index: u32,
|
||||||
nested: bool,
|
nested: bool,
|
||||||
loader: *mut Loader,
|
loader: *mut Loader,
|
||||||
gecko_stylesheet: *mut ServoStyleSheet,
|
gecko_stylesheet: *mut DomStyleSheet,
|
||||||
rule_type: *mut u16,
|
rule_type: *mut u16,
|
||||||
) -> nsresult {
|
) -> nsresult {
|
||||||
let loader = if loader.is_null() {
|
let loader = if loader.is_null() {
|
||||||
|
@ -2136,16 +2110,16 @@ pub extern "C" fn Servo_ImportRule_GetHref(rule: RawServoImportRuleBorrowed, res
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_ImportRule_GetSheet(
|
pub extern "C" fn Servo_ImportRule_GetSheet(
|
||||||
rule: RawServoImportRuleBorrowed,
|
rule: RawServoImportRuleBorrowed,
|
||||||
) -> *const ServoStyleSheet {
|
) -> *const DomStyleSheet {
|
||||||
read_locked_arc(rule, |rule: &ImportRule| {
|
read_locked_arc(rule, |rule: &ImportRule| {
|
||||||
rule.stylesheet.as_sheet().unwrap().raw() as *const ServoStyleSheet
|
rule.stylesheet.as_sheet().unwrap().raw() as *const DomStyleSheet
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_ImportRule_SetSheet(
|
pub extern "C" fn Servo_ImportRule_SetSheet(
|
||||||
rule: RawServoImportRuleBorrowed,
|
rule: RawServoImportRuleBorrowed,
|
||||||
sheet: *mut ServoStyleSheet,
|
sheet: *mut DomStyleSheet,
|
||||||
) {
|
) {
|
||||||
write_locked_arc(rule, |rule: &mut ImportRule| {
|
write_locked_arc(rule, |rule: &mut ImportRule| {
|
||||||
let sheet = unsafe { GeckoStyleSheet::new(sheet) };
|
let sheet = unsafe { GeckoStyleSheet::new(sheet) };
|
||||||
|
@ -3609,6 +3583,20 @@ pub unsafe extern "C" fn Servo_DeclarationBlock_SetProperty(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Servo_DeclarationBlock_SetPropertyToAnimationValue(
|
||||||
|
declarations: RawServoDeclarationBlockBorrowed,
|
||||||
|
animation_value: RawServoAnimationValueBorrowed,
|
||||||
|
) -> bool {
|
||||||
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
||||||
|
decls.push(
|
||||||
|
AnimationValue::as_arc(&animation_value).uncompute(),
|
||||||
|
Importance::Normal,
|
||||||
|
DeclarationSource::CssOm,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Servo_DeclarationBlock_SetPropertyById(
|
pub unsafe extern "C" fn Servo_DeclarationBlock_SetPropertyById(
|
||||||
declarations: RawServoDeclarationBlockBorrowed,
|
declarations: RawServoDeclarationBlockBorrowed,
|
||||||
|
@ -4506,7 +4494,6 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(
|
||||||
raw_data: RawServoStyleSetBorrowed,
|
raw_data: RawServoStyleSetBorrowed,
|
||||||
computed_keyframes: RawGeckoComputedKeyframeValuesListBorrowedMut
|
computed_keyframes: RawGeckoComputedKeyframeValuesListBorrowedMut
|
||||||
) {
|
) {
|
||||||
use std::mem;
|
|
||||||
use style::properties::LonghandIdSet;
|
use style::properties::LonghandIdSet;
|
||||||
|
|
||||||
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
||||||
|
@ -4567,10 +4554,6 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(
|
||||||
// This is safe since we immediately write to the uninitialized values.
|
// This is safe since we immediately write to the uninitialized values.
|
||||||
unsafe { animation_values.set_len((property_index + 1) as u32) };
|
unsafe { animation_values.set_len((property_index + 1) as u32) };
|
||||||
animation_values[property_index].mProperty = property.to_nscsspropertyid();
|
animation_values[property_index].mProperty = property.to_nscsspropertyid();
|
||||||
// We only make sure we have enough space for this variable,
|
|
||||||
// but didn't construct a default value for StyleAnimationValue,
|
|
||||||
// so we should zero it to avoid getting undefined behaviors.
|
|
||||||
animation_values[property_index].mValue.mGecko = unsafe { mem::zeroed() };
|
|
||||||
match value {
|
match value {
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
animation_values[property_index].mValue.mServo.set_arc_leaky(Arc::new(v));
|
animation_values[property_index].mValue.mServo.set_arc_leaky(Arc::new(v));
|
||||||
|
@ -4768,17 +4751,18 @@ fn fill_in_missing_keyframe_values(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn Servo_StyleSet_GetKeyframesForName(
|
pub unsafe extern "C" fn Servo_StyleSet_GetKeyframesForName(
|
||||||
raw_data: RawServoStyleSetBorrowed,
|
raw_data: RawServoStyleSetBorrowed,
|
||||||
|
element: RawGeckoElementBorrowed,
|
||||||
name: *mut nsAtom,
|
name: *mut nsAtom,
|
||||||
inherited_timing_function: nsTimingFunctionBorrowed,
|
inherited_timing_function: nsTimingFunctionBorrowed,
|
||||||
keyframes: RawGeckoKeyframeListBorrowedMut,
|
keyframes: RawGeckoKeyframeListBorrowedMut,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
debug_assert!(keyframes.len() == 0,
|
debug_assert!(keyframes.len() == 0, "keyframes should be initially empty");
|
||||||
"keyframes should be initially empty");
|
|
||||||
|
|
||||||
|
let element = GeckoElement(element);
|
||||||
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
||||||
let name = Atom::from_raw(name);
|
let name = Atom::from_raw(name);
|
||||||
|
|
||||||
let animation = match data.stylist.get_animation(&name) {
|
let animation = match data.stylist.get_animation(&name, element) {
|
||||||
Some(animation) => animation,
|
Some(animation) => animation,
|
||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,7 @@ use style::gecko::global_style_data::GLOBAL_STYLE_DATA;
|
||||||
use style::gecko_bindings::bindings;
|
use style::gecko_bindings::bindings;
|
||||||
use style::gecko_bindings::bindings::Gecko_LoadStyleSheet;
|
use style::gecko_bindings::bindings::Gecko_LoadStyleSheet;
|
||||||
use style::gecko_bindings::structs::{Loader, LoaderReusableStyleSheets};
|
use style::gecko_bindings::structs::{Loader, LoaderReusableStyleSheets};
|
||||||
use style::gecko_bindings::structs::{ServoStyleSheet, SheetLoadData, SheetLoadDataHolder};
|
use style::gecko_bindings::structs::{StyleSheet as DomStyleSheet, SheetLoadData, SheetLoadDataHolder};
|
||||||
use style::gecko_bindings::structs::URLExtraData;
|
use style::gecko_bindings::structs::URLExtraData;
|
||||||
use style::gecko_bindings::sugar::ownership::FFIArcHelpers;
|
use style::gecko_bindings::sugar::ownership::FFIArcHelpers;
|
||||||
use style::gecko_bindings::sugar::refptr::RefPtr;
|
use style::gecko_bindings::sugar::refptr::RefPtr;
|
||||||
|
@ -24,13 +24,15 @@ use style::stylesheets::StylesheetContents;
|
||||||
use style::stylesheets::import_rule::ImportSheet;
|
use style::stylesheets::import_rule::ImportSheet;
|
||||||
use style::values::CssUrl;
|
use style::values::CssUrl;
|
||||||
|
|
||||||
pub struct StylesheetLoader(*mut Loader, *mut ServoStyleSheet, *mut SheetLoadData, *mut LoaderReusableStyleSheets);
|
pub struct StylesheetLoader(*mut Loader, *mut DomStyleSheet, *mut SheetLoadData, *mut LoaderReusableStyleSheets);
|
||||||
|
|
||||||
impl StylesheetLoader {
|
impl StylesheetLoader {
|
||||||
pub fn new(loader: *mut Loader,
|
pub fn new(
|
||||||
parent: *mut ServoStyleSheet,
|
loader: *mut Loader,
|
||||||
parent_load_data: *mut SheetLoadData,
|
parent: *mut DomStyleSheet,
|
||||||
reusable_sheets: *mut LoaderReusableStyleSheets) -> Self {
|
parent_load_data: *mut SheetLoadData,
|
||||||
|
reusable_sheets: *mut LoaderReusableStyleSheets,
|
||||||
|
) -> Self {
|
||||||
StylesheetLoader(loader, parent, parent_load_data, reusable_sheets)
|
StylesheetLoader(loader, parent, parent_load_data, reusable_sheets)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use style::computed_values::display::T as Display;
|
||||||
use style::properties::{PropertyDeclaration, Importance};
|
use style::properties::{PropertyDeclaration, Importance};
|
||||||
use style::properties::declaration_block::PropertyDeclarationBlock;
|
use style::properties::declaration_block::PropertyDeclarationBlock;
|
||||||
use style::properties::parse_property_declaration_list;
|
use style::properties::parse_property_declaration_list;
|
||||||
use style::values::{CustomIdent, RGBA};
|
use style::values::RGBA;
|
||||||
use style::values::specified::{BorderStyle, BorderSideWidth, Color};
|
use style::values::specified::{BorderStyle, BorderSideWidth, Color};
|
||||||
use style::values::specified::{Length, LengthOrPercentage, LengthOrPercentageOrAuto};
|
use style::values::specified::{Length, LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||||
use style::values::specified::NoCalcLength;
|
use style::values::specified::NoCalcLength;
|
||||||
|
@ -890,31 +890,4 @@ mod shorthand_serialization {
|
||||||
assert_eq!(shadow.to_css_string(), shadow_css);
|
assert_eq!(shadow.to_css_string(), shadow_css);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod counter_increment {
|
|
||||||
pub use super::*;
|
|
||||||
pub use style::properties::longhands::counter_increment::SpecifiedValue as CounterIncrement;
|
|
||||||
use style::values::specified::Integer;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn counter_increment_with_properties_should_serialize_correctly() {
|
|
||||||
let mut properties = Vec::new();
|
|
||||||
|
|
||||||
properties.push((CustomIdent("counter1".into()), Integer::new(1)));
|
|
||||||
properties.push((CustomIdent("counter2".into()), Integer::new(-4)));
|
|
||||||
|
|
||||||
let counter_increment = CounterIncrement::new(properties);
|
|
||||||
let counter_increment_css = "counter1 1 counter2 -4";
|
|
||||||
|
|
||||||
assert_eq!(counter_increment.to_css_string(), counter_increment_css);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn counter_increment_without_properties_should_serialize_correctly() {
|
|
||||||
let counter_increment = CounterIncrement::new(Vec::new());
|
|
||||||
let counter_increment_css = "none";
|
|
||||||
|
|
||||||
assert_eq!(counter_increment.to_css_string(), counter_increment_css);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue