Skip to content

Commit

Permalink
Auto merge of #16944 - upsuper:bug1345697, r=heycam
Browse files Browse the repository at this point in the history
Implement access to CSSKeyframesRule and CSSKeyframeRule for stylo

This is the Servo side change for [bug 1345697](https://bugzilla.mozilla.org/show_bug.cgi?id=1345697).

<!-- 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/16944)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed May 19, 2017
2 parents 486dac3 + f7c5e4b commit eda6430
Show file tree
Hide file tree
Showing 6 changed files with 284 additions and 36 deletions.
13 changes: 11 additions & 2 deletions components/style/gecko/arc_types.rs
Expand Up @@ -8,20 +8,23 @@

#![allow(non_snake_case, missing_docs)]

use gecko_bindings::bindings::{RawServoMediaList, RawServoMediaRule, RawServoNamespaceRule, RawServoPageRule};
use gecko_bindings::bindings::{RawServoKeyframe, RawServoKeyframesRule};
use gecko_bindings::bindings::{RawServoMediaList, RawServoMediaRule};
use gecko_bindings::bindings::{RawServoNamespaceRule, RawServoPageRule};
use gecko_bindings::bindings::{RawServoRuleNode, RawServoRuleNodeStrong, RawServoDocumentRule};
use gecko_bindings::bindings::{RawServoStyleSheet, RawServoImportRule, RawServoSupportsRule};
use gecko_bindings::bindings::{ServoComputedValues, ServoCssRules};
use gecko_bindings::structs::{RawServoDeclarationBlock, RawServoStyleRule};
use gecko_bindings::structs::RawServoAnimationValue;
use gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI};
use keyframes::Keyframe;
use media_queries::MediaList;
use properties::{ComputedValues, PropertyDeclarationBlock};
use properties::animated_properties::AnimationValue;
use rule_tree::StrongRuleNode;
use shared_lock::Locked;
use std::{mem, ptr};
use stylesheets::{CssRules, Stylesheet, StyleRule, ImportRule, MediaRule};
use stylesheets::{CssRules, Stylesheet, StyleRule, ImportRule, KeyframesRule, MediaRule};
use stylesheets::{NamespaceRule, PageRule, SupportsRule, DocumentRule};

macro_rules! impl_arc_ffi {
Expand Down Expand Up @@ -64,6 +67,12 @@ impl_arc_ffi!(Locked<ImportRule> => RawServoImportRule
impl_arc_ffi!(AnimationValue => RawServoAnimationValue
[Servo_AnimationValue_AddRef, Servo_AnimationValue_Release]);

impl_arc_ffi!(Locked<Keyframe> => RawServoKeyframe
[Servo_Keyframe_AddRef, Servo_Keyframe_Release]);

impl_arc_ffi!(Locked<KeyframesRule> => RawServoKeyframesRule
[Servo_KeyframesRule_AddRef, Servo_KeyframesRule_Release]);

impl_arc_ffi!(Locked<MediaList> => RawServoMediaList
[Servo_MediaList_AddRef, Servo_MediaList_Release]);

Expand Down
92 changes: 92 additions & 0 deletions components/style/gecko/generated/bindings.rs
Expand Up @@ -229,6 +229,16 @@ pub struct RawServoImportRule(RawServoImportRuleVoid);
pub type RawServoAnimationValueStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoAnimationValue>;
pub type RawServoAnimationValueBorrowed<'a> = &'a RawServoAnimationValue;
pub type RawServoAnimationValueBorrowedOrNull<'a> = Option<&'a RawServoAnimationValue>;
pub type RawServoKeyframeStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoKeyframe>;
pub type RawServoKeyframeBorrowed<'a> = &'a RawServoKeyframe;
pub type RawServoKeyframeBorrowedOrNull<'a> = Option<&'a RawServoKeyframe>;
enum RawServoKeyframeVoid { }
pub struct RawServoKeyframe(RawServoKeyframeVoid);
pub type RawServoKeyframesRuleStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoKeyframesRule>;
pub type RawServoKeyframesRuleBorrowed<'a> = &'a RawServoKeyframesRule;
pub type RawServoKeyframesRuleBorrowedOrNull<'a> = Option<&'a RawServoKeyframesRule>;
enum RawServoKeyframesRuleVoid { }
pub struct RawServoKeyframesRule(RawServoKeyframesRuleVoid);
pub type RawServoMediaListStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoMediaList>;
pub type RawServoMediaListBorrowed<'a> = &'a RawServoMediaList;
pub type RawServoMediaListBorrowedOrNull<'a> = Option<&'a RawServoMediaList>;
Expand Down Expand Up @@ -395,6 +405,18 @@ extern "C" {
extern "C" {
pub fn Servo_AnimationValue_Release(ptr: RawServoAnimationValueBorrowed);
}
extern "C" {
pub fn Servo_Keyframe_AddRef(ptr: RawServoKeyframeBorrowed);
}
extern "C" {
pub fn Servo_Keyframe_Release(ptr: RawServoKeyframeBorrowed);
}
extern "C" {
pub fn Servo_KeyframesRule_AddRef(ptr: RawServoKeyframesRuleBorrowed);
}
extern "C" {
pub fn Servo_KeyframesRule_Release(ptr: RawServoKeyframesRuleBorrowed);
}
extern "C" {
pub fn Servo_MediaList_AddRef(ptr: RawServoMediaListBorrowed);
}
Expand Down Expand Up @@ -1804,6 +1826,28 @@ extern "C" {
pub fn Servo_StyleRule_GetCssText(rule: RawServoStyleRuleBorrowed,
result: *mut nsAString);
}
extern "C" {
pub fn Servo_Keyframe_Debug(rule: RawServoKeyframeBorrowed,
result: *mut nsACString);
}
extern "C" {
pub fn Servo_Keyframe_GetCssText(rule: RawServoKeyframeBorrowed,
result: *mut nsAString);
}
extern "C" {
pub fn Servo_CssRules_GetKeyframesRuleAt(rules: ServoCssRulesBorrowed,
index: u32, line: *mut u32,
column: *mut u32)
-> RawServoKeyframesRuleStrong;
}
extern "C" {
pub fn Servo_KeyframesRule_Debug(rule: RawServoKeyframesRuleBorrowed,
result: *mut nsACString);
}
extern "C" {
pub fn Servo_KeyframesRule_GetCssText(rule: RawServoKeyframesRuleBorrowed,
result: *mut nsAString);
}
extern "C" {
pub fn Servo_CssRules_GetMediaRuleAt(rules: ServoCssRulesBorrowed,
index: u32, line: *mut u32,
Expand Down Expand Up @@ -1909,6 +1953,54 @@ extern "C" {
pub fn Servo_StyleRule_GetSelectorText(rule: RawServoStyleRuleBorrowed,
result: *mut nsAString);
}
extern "C" {
pub fn Servo_Keyframe_GetKeyText(keyframe: RawServoKeyframeBorrowed,
result: *mut nsAString);
}
extern "C" {
pub fn Servo_Keyframe_SetKeyText(keyframe: RawServoKeyframeBorrowed,
text: *const nsACString) -> bool;
}
extern "C" {
pub fn Servo_Keyframe_GetStyle(keyframe: RawServoKeyframeBorrowed)
-> RawServoDeclarationBlockStrong;
}
extern "C" {
pub fn Servo_Keyframe_SetStyle(keyframe: RawServoKeyframeBorrowed,
declarations:
RawServoDeclarationBlockBorrowed);
}
extern "C" {
pub fn Servo_KeyframesRule_GetName(rule: RawServoKeyframesRuleBorrowed)
-> *mut nsIAtom;
}
extern "C" {
pub fn Servo_KeyframesRule_SetName(rule: RawServoKeyframesRuleBorrowed,
name: *mut nsIAtom);
}
extern "C" {
pub fn Servo_KeyframesRule_GetCount(rule: RawServoKeyframesRuleBorrowed)
-> u32;
}
extern "C" {
pub fn Servo_KeyframesRule_GetKeyframe(rule:
RawServoKeyframesRuleBorrowed,
index: u32)
-> RawServoKeyframeStrong;
}
extern "C" {
pub fn Servo_KeyframesRule_FindRule(rule: RawServoKeyframesRuleBorrowed,
key: *const nsACString) -> u32;
}
extern "C" {
pub fn Servo_KeyframesRule_AppendRule(rule: RawServoKeyframesRuleBorrowed,
sheet: RawServoStyleSheetBorrowed,
css: *const nsACString) -> bool;
}
extern "C" {
pub fn Servo_KeyframesRule_DeleteRule(rule: RawServoKeyframesRuleBorrowed,
index: u32);
}
extern "C" {
pub fn Servo_MediaRule_GetMedia(rule: RawServoMediaRuleBorrowed)
-> RawServoMediaListStrong;
Expand Down
23 changes: 15 additions & 8 deletions components/style/keyframes.rs
Expand Up @@ -71,8 +71,21 @@ impl KeyframePercentage {

/// A keyframes selector is a list of percentages or from/to symbols, which are
/// converted at parse time to percentages.
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Eq)]
pub struct KeyframeSelector(Vec<KeyframePercentage>);

impl ToCss for KeyframeSelector {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
let mut iter = self.0.iter();
iter.next().unwrap().to_css(dest)?;
for percentage in iter {
write!(dest, ", ")?;
percentage.to_css(dest)?;
}
Ok(())
}
}

impl KeyframeSelector {
/// Return the list of percentages this selector contains.
#[inline]
Expand Down Expand Up @@ -108,20 +121,14 @@ pub struct Keyframe {
impl ToCssWithGuard for Keyframe {
fn to_css<W>(&self, guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
where W: fmt::Write {
let mut iter = self.selector.percentages().iter();
try!(iter.next().unwrap().to_css(dest));
for percentage in iter {
try!(write!(dest, ", "));
try!(percentage.to_css(dest));
}
self.selector.to_css(dest)?;
try!(dest.write_str(" { "));
try!(self.block.read_with(guard).to_css(dest));
try!(dest.write_str(" }"));
Ok(())
}
}


impl Keyframe {
/// Parse a CSS keyframe.
pub fn parse(css: &str, parent_stylesheet: &Stylesheet)
Expand Down
39 changes: 28 additions & 11 deletions components/style/stylesheets.rs
Expand Up @@ -25,7 +25,7 @@ pub use gecko::rules::{CounterStyleRule, FontFaceRule};
use gecko_bindings::structs::URLExtraData;
#[cfg(feature = "gecko")]
use gecko_bindings::sugar::refptr::RefPtr;
use keyframes::{Keyframe, parse_keyframe_list};
use keyframes::{Keyframe, KeyframeSelector, parse_keyframe_list};
use media_queries::{Device, MediaList, parse_media_query_list};
use parking_lot::RwLock;
use parser::{PARSING_MODE_DEFAULT, Parse, ParserContext, log_css_error};
Expand Down Expand Up @@ -565,6 +565,8 @@ pub struct KeyframesRule {
pub keyframes: Vec<Arc<Locked<Keyframe>>>,
/// Vendor prefix type the @keyframes has.
pub vendor_prefix: Option<VendorPrefix>,
/// The line and column of the rule's source code.
pub source_location: SourceLocation,
}

impl ToCssWithGuard for KeyframesRule {
Expand All @@ -573,18 +575,32 @@ impl ToCssWithGuard for KeyframesRule {
where W: fmt::Write {
try!(dest.write_str("@keyframes "));
try!(self.name.to_css(dest));
try!(dest.write_str(" { "));
try!(dest.write_str(" {"));
let iter = self.keyframes.iter();
let mut first = true;
for lock in iter {
if !first {
try!(dest.write_str(" "));
}
first = false;
try!(dest.write_str("\n"));
let keyframe = lock.read_with(&guard);
try!(keyframe.to_css(guard, dest));
}
dest.write_str(" }")
dest.write_str("\n}")
}
}

impl KeyframesRule {
/// Returns the index of the last keyframe that matches the given selector.
/// If the selector is not valid, or no keyframe is found, returns None.
///
/// Related spec:
/// https://drafts.csswg.org/css-animations-1/#interface-csskeyframesrule-findrule
pub fn find_rule(&self, guard: &SharedRwLockReadGuard, selector: &str) -> Option<usize> {
if let Ok(selector) = Parser::new(selector).parse_entirely(KeyframeSelector::parse) {
for (i, keyframe) in self.keyframes.iter().enumerate().rev() {
if keyframe.read_with(guard).selector == selector {
return Some(i);
}
}
}
None
}
}

Expand Down Expand Up @@ -1032,7 +1048,7 @@ enum AtRulePrelude {
/// A @viewport rule prelude.
Viewport,
/// A @keyframes rule, with its animation name and vendor prefix if exists.
Keyframes(KeyframesName, Option<VendorPrefix>),
Keyframes(KeyframesName, Option<VendorPrefix>, SourceLocation),
/// A @page rule prelude.
Page(SourceLocation),
/// A @document rule, with its conditional.
Expand Down Expand Up @@ -1257,7 +1273,7 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
}
let name = KeyframesName::parse(self.context, input)?;

Ok(AtRuleType::WithBlock(AtRulePrelude::Keyframes(name, prefix)))
Ok(AtRuleType::WithBlock(AtRulePrelude::Keyframes(name, prefix, location)))
},
"page" => {
if cfg!(feature = "gecko") {
Expand Down Expand Up @@ -1311,12 +1327,13 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
Ok(CssRule::Viewport(Arc::new(self.shared_lock.wrap(
try!(ViewportRule::parse(&context, input))))))
}
AtRulePrelude::Keyframes(name, prefix) => {
AtRulePrelude::Keyframes(name, prefix, location) => {
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Keyframes));
Ok(CssRule::Keyframes(Arc::new(self.shared_lock.wrap(KeyframesRule {
name: name,
keyframes: parse_keyframe_list(&context, input, self.shared_lock),
vendor_prefix: prefix,
source_location: location,
}))))
}
AtRulePrelude::Page(location) => {
Expand Down

0 comments on commit eda6430

Please sign in to comment.