Auto merge of #16888 - upsuper:bug1328319, r=heycam,Manishearth,SimonSapin

Implement @counter-style for stylo

Servo side change of [bug 1328319](https://bugzilla.mozilla.org/show_bug.cgi?id=1328319).

<!-- 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/16888)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-05-16 01:17:07 -05:00 committed by GitHub
commit 1afc89e944
22 changed files with 1522 additions and 938 deletions

View file

@ -319,6 +319,7 @@ mod bindings {
.include(add_include("mozilla/dom/NameSpaceConstants.h")) .include(add_include("mozilla/dom/NameSpaceConstants.h"))
.include(add_include("mozilla/LookAndFeel.h")) .include(add_include("mozilla/LookAndFeel.h"))
.include(add_include("mozilla/ServoBindings.h")) .include(add_include("mozilla/ServoBindings.h"))
.include(add_include("nsCSSCounterStyleRule.h"))
.include(add_include("nsCSSFontFaceRule.h")) .include(add_include("nsCSSFontFaceRule.h"))
.include(add_include("nsMediaFeatures.h")) .include(add_include("nsMediaFeatures.h"))
.include(add_include("nsMediaList.h")) .include(add_include("nsMediaList.h"))
@ -402,6 +403,7 @@ mod bindings {
"nsBorderColors", "nsBorderColors",
"nscolor", "nscolor",
"nsChangeHint", "nsChangeHint",
"nsCSSCounterStyleRule",
"nsCSSFontFaceRule", "nsCSSFontFaceRule",
"nsCSSKeyword", "nsCSSKeyword",
"nsCSSPropertyID", "nsCSSPropertyID",
@ -691,6 +693,7 @@ mod bindings {
"StyleBasicShapeType", "StyleBasicShapeType",
"StyleShapeSource", "StyleShapeSource",
"StyleTransition", "StyleTransition",
"nsCSSCounterStyleRule",
"nsCSSFontFaceRule", "nsCSSFontFaceRule",
"nsCSSKeyword", "nsCSSKeyword",
"nsCSSPropertyID", "nsCSSPropertyID",

View file

@ -49,9 +49,9 @@ pub fn parse_counter_style_name(input: &mut Parser) -> Result<CustomIdent, ()> {
/// Parse the body (inside `{}`) of an @counter-style rule /// Parse the body (inside `{}`) of an @counter-style rule
pub fn parse_counter_style_body(name: CustomIdent, context: &ParserContext, input: &mut Parser) pub fn parse_counter_style_body(name: CustomIdent, context: &ParserContext, input: &mut Parser)
-> Result<CounterStyleRule, ()> { -> Result<CounterStyleRuleData, ()> {
let start = input.position(); let start = input.position();
let mut rule = CounterStyleRule::empty(name); let mut rule = CounterStyleRuleData::empty(name);
{ {
let parser = CounterStyleRuleParser { let parser = CounterStyleRuleParser {
context: context, context: context,
@ -108,7 +108,7 @@ pub fn parse_counter_style_body(name: CustomIdent, context: &ParserContext, inpu
struct CounterStyleRuleParser<'a, 'b: 'a> { struct CounterStyleRuleParser<'a, 'b: 'a> {
context: &'a ParserContext<'b>, context: &'a ParserContext<'b>,
rule: &'a mut CounterStyleRule, rule: &'a mut CounterStyleRuleData,
} }
/// Default methods reject all at rules. /// Default methods reject all at rules.
@ -143,7 +143,7 @@ macro_rules! counter_style_descriptors {
) => { ) => {
/// An @counter-style rule /// An @counter-style rule
#[derive(Debug)] #[derive(Debug)]
pub struct CounterStyleRule { pub struct CounterStyleRuleData {
name: CustomIdent, name: CustomIdent,
$( $(
#[$doc] #[$doc]
@ -151,9 +151,9 @@ macro_rules! counter_style_descriptors {
)+ )+
} }
impl CounterStyleRule { impl CounterStyleRuleData {
fn empty(name: CustomIdent) -> Self { fn empty(name: CustomIdent) -> Self {
CounterStyleRule { CounterStyleRuleData {
name: name, name: name,
$( $(
$ident: None, $ident: None,
@ -161,15 +161,20 @@ macro_rules! counter_style_descriptors {
} }
} }
/// Get the name of the counter style rule.
pub fn name(&self) -> &CustomIdent {
&self.name
}
$( $(
accessor!(#[$doc] $name $ident: $ty = $initial); accessor!(#[$doc] $name $ident: $ty = $initial);
)+ )+
/// Convert to Gecko types /// Convert to Gecko types
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub fn set_descriptors(&self, descriptors: &mut CounterStyleDescriptors) { pub fn set_descriptors(self, descriptors: &mut CounterStyleDescriptors) {
$( $(
if let Some(ref value) = self.$ident { if let Some(value) = self.$ident {
descriptors[nsCSSCounterDesc::$gecko_ident as usize].set_from(value) descriptors[nsCSSCounterDesc::$gecko_ident as usize].set_from(value)
} }
)* )*
@ -197,7 +202,7 @@ macro_rules! counter_style_descriptors {
} }
} }
impl ToCssWithGuard for CounterStyleRule { impl ToCssWithGuard for CounterStyleRuleData {
fn to_css<W>(&self, _guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result fn to_css<W>(&self, _guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
where W: fmt::Write { where W: fmt::Write {
dest.write_str("@counter-style ")?; dest.write_str("@counter-style ")?;
@ -531,7 +536,7 @@ impl Parse for AdditiveSymbols {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
let tuples = Vec::<AdditiveTuple>::parse(context, input)?; let tuples = Vec::<AdditiveTuple>::parse(context, input)?;
// FIXME maybe? https://github.com/w3c/csswg-drafts/issues/1220 // FIXME maybe? https://github.com/w3c/csswg-drafts/issues/1220
if tuples.windows(2).any(|window| window[0].value <= window[1].value) { if tuples.windows(2).any(|window| window[0].weight <= window[1].weight) {
return Err(()) return Err(())
} }
Ok(AdditiveSymbols(tuples)) Ok(AdditiveSymbols(tuples))
@ -547,8 +552,10 @@ impl ToCss for AdditiveSymbols {
/// <integer> && <symbol> /// <integer> && <symbol>
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct AdditiveTuple { pub struct AdditiveTuple {
value: u32, /// <integer>
symbol: Symbol, pub weight: u32,
/// <symbol>
pub symbol: Symbol,
} }
impl OneOrMoreCommaSeparated for AdditiveTuple {} impl OneOrMoreCommaSeparated for AdditiveTuple {}
@ -556,13 +563,13 @@ impl OneOrMoreCommaSeparated for AdditiveTuple {}
impl Parse for AdditiveTuple { impl Parse for AdditiveTuple {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
let symbol = input.try(|input| Symbol::parse(context, input)); let symbol = input.try(|input| Symbol::parse(context, input));
let value = input.expect_integer()?; let weight = input.expect_integer()?;
if value < 0 { if weight < 0 {
return Err(()) return Err(())
} }
let symbol = symbol.or_else(|()| Symbol::parse(context, input))?; let symbol = symbol.or_else(|()| Symbol::parse(context, input))?;
Ok(AdditiveTuple { Ok(AdditiveTuple {
value: value as u32, weight: weight as u32,
symbol: symbol, symbol: symbol,
}) })
} }
@ -570,7 +577,7 @@ impl Parse for AdditiveTuple {
impl ToCss for AdditiveTuple { impl ToCss for AdditiveTuple {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
write!(dest, "{} ", self.value)?; write!(dest, "{} ", self.weight)?;
self.symbol.to_css(dest) self.symbol.to_css(dest)
} }
} }

View file

@ -208,9 +208,9 @@ macro_rules! font_face_descriptors_common {
/// Convert to Gecko types /// Convert to Gecko types
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub fn set_descriptors(&self, descriptors: &mut CSSFontFaceDescriptors) { pub fn set_descriptors(self, descriptors: &mut CSSFontFaceDescriptors) {
$( $(
if let Some(ref value) = self.$ident { if let Some(value) = self.$ident {
descriptors.$gecko_ident.set_from(value) descriptors.$gecko_ident.set_from(value)
} }
)* )*

View file

@ -4,9 +4,11 @@
//! Data needed to style a Gecko document. //! Data needed to style a Gecko document.
use Atom;
use animation::Animation; use animation::Animation;
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
use dom::OpaqueNode; use dom::OpaqueNode;
use gecko::rules::{CounterStyleRule, FontFaceRule};
use gecko_bindings::bindings::RawServoStyleSet; use gecko_bindings::bindings::RawServoStyleSet;
use gecko_bindings::structs::RawGeckoPresContextOwned; use gecko_bindings::structs::RawGeckoPresContextOwned;
use gecko_bindings::structs::nsIDocument; use gecko_bindings::structs::nsIDocument;
@ -19,7 +21,7 @@ use std::collections::HashMap;
use std::sync::mpsc::{Receiver, Sender, channel}; use std::sync::mpsc::{Receiver, Sender, channel};
use stylearc::Arc; use stylearc::Arc;
use stylesheet_set::StylesheetSet; use stylesheet_set::StylesheetSet;
use stylesheets::{FontFaceRule, Origin}; use stylesheets::Origin;
use stylist::{ExtraStyleData, Stylist}; use stylist::{ExtraStyleData, Stylist};
/// The container for data that a Servo-backed Gecko document needs to style /// The container for data that a Servo-backed Gecko document needs to style
@ -47,6 +49,8 @@ pub struct PerDocumentStyleDataImpl {
/// List of effective font face rules. /// List of effective font face rules.
pub font_faces: Vec<(Arc<Locked<FontFaceRule>>, Origin)>, pub font_faces: Vec<(Arc<Locked<FontFaceRule>>, Origin)>,
/// Map for effective counter style rules.
pub counter_styles: HashMap<Atom, Arc<Locked<CounterStyleRule>>>,
} }
/// The data itself is an `AtomicRefCell`, which guarantees the proper semantics /// The data itself is an `AtomicRefCell`, which guarantees the proper semantics
@ -71,6 +75,7 @@ impl PerDocumentStyleData {
running_animations: Arc::new(RwLock::new(HashMap::new())), running_animations: Arc::new(RwLock::new(HashMap::new())),
expired_animations: Arc::new(RwLock::new(HashMap::new())), expired_animations: Arc::new(RwLock::new(HashMap::new())),
font_faces: vec![], font_faces: vec![],
counter_styles: HashMap::new(),
})) }))
} }
@ -103,6 +108,7 @@ impl PerDocumentStyleDataImpl {
let mut extra_data = ExtraStyleData { let mut extra_data = ExtraStyleData {
font_faces: &mut self.font_faces, font_faces: &mut self.font_faces,
counter_styles: &mut self.counter_styles,
}; };
let author_style_disabled = self.stylesheets.author_style_disabled(); let author_style_disabled = self.stylesheets.author_style_disabled();

View file

@ -2382,6 +2382,8 @@ cfg_if! {
pub static nsGkAtoms_splitter: *mut nsIAtom; pub static nsGkAtoms_splitter: *mut nsIAtom;
#[link_name = "_ZN9nsGkAtoms6springE"] #[link_name = "_ZN9nsGkAtoms6springE"]
pub static nsGkAtoms_spring: *mut nsIAtom; pub static nsGkAtoms_spring: *mut nsIAtom;
#[link_name = "_ZN9nsGkAtoms6squareE"]
pub static nsGkAtoms_square: *mut nsIAtom;
#[link_name = "_ZN9nsGkAtoms3srcE"] #[link_name = "_ZN9nsGkAtoms3srcE"]
pub static nsGkAtoms_src: *mut nsIAtom; pub static nsGkAtoms_src: *mut nsIAtom;
#[link_name = "_ZN9nsGkAtoms6srcdocE"] #[link_name = "_ZN9nsGkAtoms6srcdocE"]
@ -7395,6 +7397,8 @@ cfg_if! {
pub static nsGkAtoms_splitter: *mut nsIAtom; pub static nsGkAtoms_splitter: *mut nsIAtom;
#[link_name = "?spring@nsGkAtoms@@2PEAVnsIAtom@@EA"] #[link_name = "?spring@nsGkAtoms@@2PEAVnsIAtom@@EA"]
pub static nsGkAtoms_spring: *mut nsIAtom; pub static nsGkAtoms_spring: *mut nsIAtom;
#[link_name = "?square@nsGkAtoms@@2PEAVnsIAtom@@EA"]
pub static nsGkAtoms_square: *mut nsIAtom;
#[link_name = "?src@nsGkAtoms@@2PEAVnsIAtom@@EA"] #[link_name = "?src@nsGkAtoms@@2PEAVnsIAtom@@EA"]
pub static nsGkAtoms_src: *mut nsIAtom; pub static nsGkAtoms_src: *mut nsIAtom;
#[link_name = "?srcdoc@nsGkAtoms@@2PEAVnsIAtom@@EA"] #[link_name = "?srcdoc@nsGkAtoms@@2PEAVnsIAtom@@EA"]
@ -12408,6 +12412,8 @@ cfg_if! {
pub static nsGkAtoms_splitter: *mut nsIAtom; pub static nsGkAtoms_splitter: *mut nsIAtom;
#[link_name = "\x01?spring@nsGkAtoms@@2PAVnsIAtom@@A"] #[link_name = "\x01?spring@nsGkAtoms@@2PAVnsIAtom@@A"]
pub static nsGkAtoms_spring: *mut nsIAtom; pub static nsGkAtoms_spring: *mut nsIAtom;
#[link_name = "\x01?square@nsGkAtoms@@2PAVnsIAtom@@A"]
pub static nsGkAtoms_square: *mut nsIAtom;
#[link_name = "\x01?src@nsGkAtoms@@2PAVnsIAtom@@A"] #[link_name = "\x01?src@nsGkAtoms@@2PAVnsIAtom@@A"]
pub static nsGkAtoms_src: *mut nsIAtom; pub static nsGkAtoms_src: *mut nsIAtom;
#[link_name = "\x01?srcdoc@nsGkAtoms@@2PAVnsIAtom@@A"] #[link_name = "\x01?srcdoc@nsGkAtoms@@2PAVnsIAtom@@A"]
@ -17424,6 +17430,8 @@ macro_rules! atom {
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_splitter as *mut _) } }; { unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_splitter as *mut _) } };
("spring") => ("spring") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_spring as *mut _) } }; { unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_spring as *mut _) } };
("square") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_square as *mut _) } };
("src") => ("src") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_src as *mut _) } }; { unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_src as *mut _) } };
("srcdoc") => ("srcdoc") =>

View file

@ -43,6 +43,7 @@ use gecko_bindings::structs::StyleBasicShape;
use gecko_bindings::structs::StyleBasicShapeType; use gecko_bindings::structs::StyleBasicShapeType;
use gecko_bindings::structs::StyleShapeSource; use gecko_bindings::structs::StyleShapeSource;
use gecko_bindings::structs::StyleTransition; use gecko_bindings::structs::StyleTransition;
use gecko_bindings::structs::nsCSSCounterStyleRule;
use gecko_bindings::structs::nsCSSFontFaceRule; use gecko_bindings::structs::nsCSSFontFaceRule;
use gecko_bindings::structs::nsCSSKeyword; use gecko_bindings::structs::nsCSSKeyword;
use gecko_bindings::structs::nsCSSPropertyID; use gecko_bindings::structs::nsCSSPropertyID;
@ -813,7 +814,8 @@ extern "C" {
aSrc: *const nsStyleVisibility); aSrc: *const nsStyleVisibility);
} }
extern "C" { extern "C" {
pub fn Gecko_SetListStyleType(style_struct: *mut nsStyleList, type_: u32); pub fn Gecko_SetListStyleType(style_struct: *mut nsStyleList,
name: *mut nsIAtom);
} }
extern "C" { extern "C" {
pub fn Gecko_CopyListStyleTypeFrom(dst: *mut nsStyleList, pub fn Gecko_CopyListStyleTypeFrom(dst: *mut nsStyleList,
@ -833,11 +835,15 @@ extern "C" {
pub fn Gecko_ReleaseImageValueArbitraryThread(aPtr: *mut ImageValue); pub fn Gecko_ReleaseImageValueArbitraryThread(aPtr: *mut ImageValue);
} }
extern "C" { extern "C" {
pub fn Gecko_ImageValue_Create(uri: ServoBundledURI) -> *mut ImageValue; pub fn Gecko_ImageValue_Create(aURI: ServoBundledURI) -> *mut ImageValue;
} }
extern "C" { extern "C" {
pub fn Gecko_SetLayerImageImageValue(image: *mut nsStyleImage, pub fn Gecko_SetLayerImageImageValue(image: *mut nsStyleImage,
imageValue: *mut ImageValue); aImageValue: *mut ImageValue);
}
extern "C" {
pub fn Gecko_SetUrlImageValue(image: *mut nsStyleImage,
uri: ServoBundledURI);
} }
extern "C" { extern "C" {
pub fn Gecko_SetImageElement(image: *mut nsStyleImage, pub fn Gecko_SetImageElement(image: *mut nsStyleImage,
@ -860,7 +866,11 @@ extern "C" {
} }
extern "C" { extern "C" {
pub fn Gecko_SetListStyleImageImageValue(style_struct: *mut nsStyleList, pub fn Gecko_SetListStyleImageImageValue(style_struct: *mut nsStyleList,
imageValue: *mut ImageValue); aImageValue: *mut ImageValue);
}
extern "C" {
pub fn Gecko_SetListStyleImage(style_struct: *mut nsStyleList,
uri: ServoBundledURI);
} }
extern "C" { extern "C" {
pub fn Gecko_CopyListStyleImageFrom(dest: *mut nsStyleList, pub fn Gecko_CopyListStyleImageFrom(dest: *mut nsStyleList,
@ -871,16 +881,24 @@ extern "C" {
len: usize); len: usize);
} }
extern "C" { extern "C" {
pub fn Gecko_SetCursorImageValue(cursor: *mut nsCursorImage, pub fn Gecko_SetCursorImageValue(aCursor: *mut nsCursorImage,
imageValue: *mut ImageValue); aImageValue: *mut ImageValue);
}
extern "C" {
pub fn Gecko_SetCursorImage(cursor: *mut nsCursorImage,
uri: ServoBundledURI);
} }
extern "C" { extern "C" {
pub fn Gecko_CopyCursorArrayFrom(dest: *mut nsStyleUserInterface, pub fn Gecko_CopyCursorArrayFrom(dest: *mut nsStyleUserInterface,
src: *const nsStyleUserInterface); src: *const nsStyleUserInterface);
} }
extern "C" { extern "C" {
pub fn Gecko_SetContentDataImageValue(content_data: *mut nsStyleContentData, pub fn Gecko_SetContentDataImageValue(aList: *mut nsStyleContentData,
imageValue: *mut ImageValue); aImageValue: *mut ImageValue);
}
extern "C" {
pub fn Gecko_SetContentDataImage(content_data: *mut nsStyleContentData,
uri: ServoBundledURI);
} }
extern "C" { extern "C" {
pub fn Gecko_SetContentDataArray(content_data: *mut nsStyleContentData, pub fn Gecko_SetContentDataArray(content_data: *mut nsStyleContentData,
@ -1157,9 +1175,6 @@ extern "C" {
pub fn Gecko_CSSValue_SetAbsoluteLength(css_value: nsCSSValueBorrowedMut, pub fn Gecko_CSSValue_SetAbsoluteLength(css_value: nsCSSValueBorrowedMut,
len: nscoord); len: nscoord);
} }
extern "C" {
pub fn Gecko_CSSValue_SetNormal(css_value: nsCSSValueBorrowedMut);
}
extern "C" { extern "C" {
pub fn Gecko_CSSValue_SetNumber(css_value: nsCSSValueBorrowedMut, pub fn Gecko_CSSValue_SetNumber(css_value: nsCSSValueBorrowedMut,
number: f32); number: f32);
@ -1206,6 +1221,18 @@ extern "C" {
pub fn Gecko_CSSValue_SetInt(css_value: nsCSSValueBorrowedMut, pub fn Gecko_CSSValue_SetInt(css_value: nsCSSValueBorrowedMut,
integer: i32, unit: nsCSSUnit); integer: i32, unit: nsCSSUnit);
} }
extern "C" {
pub fn Gecko_CSSValue_SetPair(css_value: nsCSSValueBorrowedMut,
xvalue: nsCSSValueBorrowed,
yvalue: nsCSSValueBorrowed);
}
extern "C" {
pub fn Gecko_CSSValue_SetList(css_value: nsCSSValueBorrowedMut, len: u32);
}
extern "C" {
pub fn Gecko_CSSValue_SetPairList(css_value: nsCSSValueBorrowedMut,
len: u32);
}
extern "C" { extern "C" {
pub fn Gecko_CSSValue_Drop(css_value: nsCSSValueBorrowedMut); pub fn Gecko_CSSValue_Drop(css_value: nsCSSValueBorrowedMut);
} }
@ -1272,6 +1299,22 @@ extern "C" {
extern "C" { extern "C" {
pub fn Gecko_CSSFontFaceRule_Release(aPtr: *mut nsCSSFontFaceRule); pub fn Gecko_CSSFontFaceRule_Release(aPtr: *mut nsCSSFontFaceRule);
} }
extern "C" {
pub fn Gecko_CSSCounterStyle_Create(name: *mut nsIAtom)
-> *mut nsCSSCounterStyleRule;
}
extern "C" {
pub fn Gecko_CSSCounterStyle_GetCssText(rule:
*const nsCSSCounterStyleRule,
result: *mut nsAString);
}
extern "C" {
pub fn Gecko_CSSCounterStyleRule_AddRef(aPtr: *mut nsCSSCounterStyleRule);
}
extern "C" {
pub fn Gecko_CSSCounterStyleRule_Release(aPtr:
*mut nsCSSCounterStyleRule);
}
extern "C" { extern "C" {
pub fn Gecko_GetBody(pres_context: RawGeckoPresContextBorrowed) pub fn Gecko_GetBody(pres_context: RawGeckoPresContextBorrowed)
-> RawGeckoElementBorrowedOrNull; -> RawGeckoElementBorrowedOrNull;
@ -1706,6 +1749,11 @@ extern "C" {
list: list:
RawGeckoFontFaceRuleListBorrowedMut); RawGeckoFontFaceRuleListBorrowedMut);
} }
extern "C" {
pub fn Servo_StyleSet_GetCounterStyleRule(set: RawServoStyleSetBorrowed,
name: *mut nsIAtom)
-> *mut nsCSSCounterStyleRule;
}
extern "C" { extern "C" {
pub fn Servo_StyleSet_ResolveForDeclarations(set: pub fn Servo_StyleSet_ResolveForDeclarations(set:
RawServoStyleSetBorrowed, RawServoStyleSetBorrowed,
@ -1832,6 +1880,11 @@ extern "C" {
index: u32) index: u32)
-> *mut nsCSSFontFaceRule; -> *mut nsCSSFontFaceRule;
} }
extern "C" {
pub fn Servo_CssRules_GetCounterStyleRuleAt(rules: ServoCssRulesBorrowed,
index: u32)
-> *mut nsCSSCounterStyleRule;
}
extern "C" { extern "C" {
pub fn Servo_StyleRule_GetStyle(rule: RawServoStyleRuleBorrowed) pub fn Servo_StyleRule_GetStyle(rule: RawServoStyleRuleBorrowed)
-> RawServoDeclarationBlockStrong; -> RawServoDeclarationBlockStrong;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,8 @@ use counter_style;
use cssparser::UnicodeRange; use cssparser::UnicodeRange;
use font_face::{FontFaceRuleData, Source}; use font_face::{FontFaceRuleData, Source};
use gecko_bindings::bindings; use gecko_bindings::bindings;
use gecko_bindings::structs::{self, nsCSSFontFaceRule, nsCSSValue, nsCSSCounterDesc}; use gecko_bindings::structs::{self, nsCSSFontFaceRule, nsCSSValue};
use gecko_bindings::structs::{nsCSSCounterDesc, nsCSSCounterStyleRule};
use gecko_bindings::sugar::ns_css_value::ToNsCssValue; use gecko_bindings::sugar::ns_css_value::ToNsCssValue;
use gecko_bindings::sugar::refptr::{RefPtr, UniqueRefPtr}; use gecko_bindings::sugar::refptr::{RefPtr, UniqueRefPtr};
use shared_lock::{ToCssWithGuard, SharedRwLockReadGuard}; use shared_lock::{ToCssWithGuard, SharedRwLockReadGuard};
@ -20,14 +21,14 @@ use std::fmt;
pub type FontFaceRule = RefPtr<nsCSSFontFaceRule>; pub type FontFaceRule = RefPtr<nsCSSFontFaceRule>;
impl ToNsCssValue for FamilyName { impl ToNsCssValue for FamilyName {
fn convert(&self, nscssvalue: &mut nsCSSValue) { fn convert(self, nscssvalue: &mut nsCSSValue) {
nscssvalue.set_string_from_atom(&self.name) nscssvalue.set_string_from_atom(&self.name)
} }
} }
impl ToNsCssValue for font_weight::T { impl ToNsCssValue for font_weight::T {
fn convert(&self, nscssvalue: &mut nsCSSValue) { fn convert(self, nscssvalue: &mut nsCSSValue) {
nscssvalue.set_integer(*self as i32) nscssvalue.set_integer(self as i32)
} }
} }
@ -41,8 +42,8 @@ macro_rules! map_enum {
) => { ) => {
$( $(
impl ToNsCssValue for $prop::T { impl ToNsCssValue for $prop::T {
fn convert(&self, nscssvalue: &mut nsCSSValue) { fn convert(self, nscssvalue: &mut nsCSSValue) {
nscssvalue.set_enum(match *self { nscssvalue.set_enum(match self {
$( $prop::T::$servo => structs::$gecko as i32, )+ $( $prop::T::$servo => structs::$gecko as i32, )+
}) })
} }
@ -72,7 +73,7 @@ map_enum! {
} }
impl ToNsCssValue for Vec<Source> { impl ToNsCssValue for Vec<Source> {
fn convert(&self, nscssvalue: &mut nsCSSValue) { fn convert(self, nscssvalue: &mut nsCSSValue) {
let src_len = self.iter().fold(0, |acc, src| { let src_len = self.iter().fold(0, |acc, src| {
acc + match *src { acc + match *src {
// Each format hint takes one position in the array of mSrc. // Each format hint takes one position in the array of mSrc.
@ -85,15 +86,15 @@ impl ToNsCssValue for Vec<Source> {
macro_rules! next { () => { macro_rules! next { () => {
target_srcs.next().expect("Length of target_srcs should be enough") target_srcs.next().expect("Length of target_srcs should be enough")
} } } }
for src in self.iter() { for src in self.into_iter() {
match *src { match src {
Source::Url(ref url) => { Source::Url(url) => {
next!().set_url(&url.url); next!().set_url(&url.url);
for hint in url.format_hints.iter() { for hint in url.format_hints.iter() {
next!().set_font_format(&hint); next!().set_font_format(&hint);
} }
} }
Source::Local(ref family) => { Source::Local(family) => {
next!().set_local_font(&family.name); next!().set_local_font(&family.name);
} }
} }
@ -103,7 +104,7 @@ impl ToNsCssValue for Vec<Source> {
} }
impl ToNsCssValue for Vec<UnicodeRange> { impl ToNsCssValue for Vec<UnicodeRange> {
fn convert(&self, nscssvalue: &mut nsCSSValue) { fn convert(self, nscssvalue: &mut nsCSSValue) {
let target_ranges = nscssvalue let target_ranges = nscssvalue
.set_array((self.len() * 2) as i32) .set_array((self.len() * 2) as i32)
.as_mut_slice().chunks_mut(2); .as_mut_slice().chunks_mut(2);
@ -137,13 +138,38 @@ impl ToCssWithGuard for FontFaceRule {
} }
} }
/// A @counter-style rule
pub type CounterStyleRule = RefPtr<nsCSSCounterStyleRule>;
impl From<counter_style::CounterStyleRuleData> for CounterStyleRule {
fn from(data: counter_style::CounterStyleRuleData) -> CounterStyleRule {
let mut result = unsafe {
UniqueRefPtr::from_addrefed(
bindings::Gecko_CSSCounterStyle_Create(data.name().0.as_ptr()))
};
data.set_descriptors(&mut result.mValues);
result.get()
}
}
impl ToCssWithGuard for CounterStyleRule {
fn to_css<W>(&self, _guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
where W: fmt::Write {
ns_auto_string!(css_text);
unsafe {
bindings::Gecko_CSSCounterStyle_GetCssText(self.get(), &mut *css_text);
}
write!(dest, "{}", css_text)
}
}
/// The type of nsCSSCounterStyleRule::mValues /// The type of nsCSSCounterStyleRule::mValues
pub type CounterStyleDescriptors = [nsCSSValue; nsCSSCounterDesc::eCSSCounterDesc_COUNT as usize]; pub type CounterStyleDescriptors = [nsCSSValue; nsCSSCounterDesc::eCSSCounterDesc_COUNT as usize];
impl ToNsCssValue for counter_style::System { impl ToNsCssValue for counter_style::System {
fn convert(&self, nscssvalue: &mut nsCSSValue) { fn convert(self, nscssvalue: &mut nsCSSValue) {
use counter_style::System::*; use counter_style::System::*;
match *self { match self {
Cyclic => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_CYCLIC as i32), Cyclic => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_CYCLIC as i32),
Numeric => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_NUMERIC as i32), Numeric => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_NUMERIC as i32),
Alphabetic => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_ALPHABETIC as i32), Alphabetic => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_ALPHABETIC as i32),
@ -154,48 +180,48 @@ impl ToNsCssValue for counter_style::System {
let mut b = nsCSSValue::null(); let mut b = nsCSSValue::null();
a.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_FIXED as i32); a.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_FIXED as i32);
b.set_integer(first_symbol_value.unwrap_or(1)); b.set_integer(first_symbol_value.unwrap_or(1));
//nscssvalue.set_pair(a, b); // FIXME: add bindings for nsCSSValue::SetPairValue nscssvalue.set_pair(&a, &b);
} }
Extends(ref other) => { Extends(other) => {
let mut a = nsCSSValue::null(); let mut a = nsCSSValue::null();
let mut b = nsCSSValue::null(); let mut b = nsCSSValue::null();
a.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_EXTENDS as i32); a.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_EXTENDS as i32);
b.set_string_from_atom(&other.0); b.set_atom_ident(other.0);
//nscssvalue.set_pair(a, b); // FIXME: add bindings for nsCSSValue::SetPairValue nscssvalue.set_pair(&a, &b);
} }
} }
} }
} }
impl ToNsCssValue for counter_style::Negative { impl ToNsCssValue for counter_style::Negative {
fn convert(&self, nscssvalue: &mut nsCSSValue) { fn convert(self, nscssvalue: &mut nsCSSValue) {
if let Some(ref second) = self.1 { if let Some(second) = self.1 {
let mut a = nsCSSValue::null(); let mut a = nsCSSValue::null();
let mut b = nsCSSValue::null(); let mut b = nsCSSValue::null();
a.set_from(&self.0); a.set_from(self.0);
b.set_from(second); b.set_from(second);
//nscssvalue.set_pair(a, b); // FIXME: add bindings for nsCSSValue::SetPairValue nscssvalue.set_pair(&a, &b);
} else { } else {
nscssvalue.set_from(&self.0) nscssvalue.set_from(self.0)
} }
} }
} }
impl ToNsCssValue for counter_style::Symbol { impl ToNsCssValue for counter_style::Symbol {
fn convert(&self, nscssvalue: &mut nsCSSValue) { fn convert(self, nscssvalue: &mut nsCSSValue) {
match *self { match self {
counter_style::Symbol::String(ref s) => nscssvalue.set_string(s), counter_style::Symbol::String(s) => nscssvalue.set_string(&s),
counter_style::Symbol::Ident(ref s) => nscssvalue.set_ident(s), counter_style::Symbol::Ident(s) => nscssvalue.set_ident(&s),
} }
} }
} }
impl ToNsCssValue for counter_style::Ranges { impl ToNsCssValue for counter_style::Ranges {
fn convert(&self, _nscssvalue: &mut nsCSSValue) { fn convert(self, nscssvalue: &mut nsCSSValue) {
if self.0.is_empty() { if self.0.is_empty() {
//nscssvalue.set_auto(); // FIXME: add bindings for nsCSSValue::SetAutoValue nscssvalue.set_auto();
} else { } else {
for range in &self.0 { nscssvalue.set_pair_list(self.0.into_iter().map(|range| {
fn set_bound(bound: Option<i32>, nscssvalue: &mut nsCSSValue) { fn set_bound(bound: Option<i32>, nscssvalue: &mut nsCSSValue) {
if let Some(finite) = bound { if let Some(finite) = bound {
nscssvalue.set_integer(finite) nscssvalue.set_integer(finite)
@ -207,52 +233,59 @@ impl ToNsCssValue for counter_style::Ranges {
let mut end = nsCSSValue::null(); let mut end = nsCSSValue::null();
set_bound(range.start, &mut start); set_bound(range.start, &mut start);
set_bound(range.end, &mut end); set_bound(range.end, &mut end);
// FIXME: add bindings for nsCSSValuePairList (start, end)
} }));
} }
} }
} }
impl ToNsCssValue for counter_style::Pad { impl ToNsCssValue for counter_style::Pad {
fn convert(&self, _nscssvalue: &mut nsCSSValue) { fn convert(self, nscssvalue: &mut nsCSSValue) {
let mut min_length = nsCSSValue::null(); let mut min_length = nsCSSValue::null();
let mut pad_with = nsCSSValue::null(); let mut pad_with = nsCSSValue::null();
min_length.set_integer(self.0 as i32); min_length.set_integer(self.0 as i32);
pad_with.set_from(&self.1); pad_with.set_from(self.1);
// FIXME: add bindings for nsCSSValue::SetPairValue nscssvalue.set_pair(&min_length, &pad_with);
//nscssvalue.set_pair(min_length, pad_with);
} }
} }
impl ToNsCssValue for counter_style::Fallback { impl ToNsCssValue for counter_style::Fallback {
fn convert(&self, nscssvalue: &mut nsCSSValue) { fn convert(self, nscssvalue: &mut nsCSSValue) {
nscssvalue.set_ident_from_atom(&self.0 .0) nscssvalue.set_atom_ident(self.0 .0)
} }
} }
impl ToNsCssValue for counter_style::Symbols { impl ToNsCssValue for counter_style::Symbols {
fn convert(&self, _nscssvalue: &mut nsCSSValue) { fn convert(self, nscssvalue: &mut nsCSSValue) {
debug_assert!(!self.0.is_empty()); nscssvalue.set_list(self.0.into_iter().map(|item| {
// FIXME: add bindings for nsCSSValueList let mut value = nsCSSValue::null();
value.set_from(item);
value
}));
} }
} }
impl ToNsCssValue for counter_style::AdditiveSymbols { impl ToNsCssValue for counter_style::AdditiveSymbols {
fn convert(&self, _nscssvalue: &mut nsCSSValue) { fn convert(self, nscssvalue: &mut nsCSSValue) {
debug_assert!(!self.0.is_empty()); nscssvalue.set_pair_list(self.0.into_iter().map(|tuple| {
// FIXME: add bindings for nsCSSValuePairList let mut weight = nsCSSValue::null();
let mut symbol = nsCSSValue::null();
weight.set_integer(tuple.weight as i32);
symbol.set_from(tuple.symbol);
(weight, symbol)
}));
} }
} }
impl ToNsCssValue for counter_style::SpeakAs { impl ToNsCssValue for counter_style::SpeakAs {
fn convert(&self, nscssvalue: &mut nsCSSValue) { fn convert(self, nscssvalue: &mut nsCSSValue) {
use counter_style::SpeakAs::*; use counter_style::SpeakAs::*;
match *self { match self {
Auto => {} //nscssvalue.set_auto(), // FIXME: add bindings for nsCSSValue::SetAutoValue Auto => nscssvalue.set_auto(),
Bullets => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SPEAKAS_BULLETS as i32), Bullets => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SPEAKAS_BULLETS as i32),
Numbers => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SPEAKAS_NUMBERS as i32), Numbers => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SPEAKAS_NUMBERS as i32),
Words => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SPEAKAS_WORDS as i32), Words => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SPEAKAS_WORDS as i32),
Other(ref other) => nscssvalue.set_ident_from_atom(&other.0), Other(other) => nscssvalue.set_atom_ident(other.0),
} }
} }
} }

View file

@ -47,7 +47,7 @@ pub fn each_class<F, T>(item: T,
let length = getter(item, &mut class, &mut list); let length = getter(item, &mut class, &mut list);
match length { match length {
0 => {} 0 => {}
1 => Atom::with(class, &mut callback), 1 => Atom::with(class, callback),
n => { n => {
let classes = slice::from_raw_parts(list, n as usize); let classes = slice::from_raw_parts(list, n as usize);
for c in classes { for c in classes {

View file

@ -6,6 +6,7 @@
use app_units::Au; use app_units::Au;
use gecko_bindings::bindings; use gecko_bindings::bindings;
use gecko_bindings::structs;
use gecko_bindings::structs::{nsCSSValue, nsCSSUnit}; use gecko_bindings::structs::{nsCSSValue, nsCSSUnit};
use gecko_bindings::structs::{nsCSSValue_Array, nscolor}; use gecko_bindings::structs::{nsCSSValue_Array, nscolor};
use gecko_string_cache::Atom; use gecko_string_cache::Atom;
@ -101,9 +102,24 @@ impl nsCSSValue {
} }
} }
fn set_valueless_unit(&mut self, unit: nsCSSUnit) {
debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_Null);
debug_assert!(unit as u32 <= nsCSSUnit::eCSSUnit_DummyInherit as u32, "Not a valueless unit");
self.mUnit = unit;
}
/// Set to an auto value
///
/// This method requires the current value to be null.
pub fn set_auto(&mut self) {
self.set_valueless_unit(nsCSSUnit::eCSSUnit_Auto);
}
/// Set to a normal value /// Set to a normal value
///
/// This method requires the current value to be null.
pub fn set_normal(&mut self) { pub fn set_normal(&mut self) {
unsafe { bindings::Gecko_CSSValue_SetNormal(self) } self.set_valueless_unit(nsCSSUnit::eCSSUnit_Normal);
} }
fn set_string_internal(&mut self, s: &str, unit: nsCSSUnit) { fn set_string_internal(&mut self, s: &str, unit: nsCSSUnit) {
@ -175,7 +191,7 @@ impl nsCSSValue {
} }
/// Generic set from any value that implements the ToNsCssValue trait. /// Generic set from any value that implements the ToNsCssValue trait.
pub fn set_from<T: ToNsCssValue>(&mut self, value: &T) { pub fn set_from<T: ToNsCssValue>(&mut self, value: T) {
value.convert(self) value.convert(self)
} }
@ -198,6 +214,52 @@ impl nsCSSValue {
*self.mValue.mFloat.as_mut() = value; *self.mValue.mFloat.as_mut() = value;
} }
} }
/// Set to a pair value
///
/// This is only supported on the main thread.
pub fn set_pair(&mut self, x: &nsCSSValue, y: &nsCSSValue) {
unsafe { bindings::Gecko_CSSValue_SetPair(self, x, y) }
}
/// Set to a list value
///
/// This is only supported on the main thread.
pub fn set_list<I>(&mut self, mut values: I) where I: ExactSizeIterator<Item=nsCSSValue> {
debug_assert!(values.len() > 0, "Empty list is not supported");
unsafe { bindings::Gecko_CSSValue_SetList(self, values.len() as u32); }
debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_List);
let mut item_ptr = &mut unsafe {
self.mValue.mList.as_ref() // &*nsCSSValueList_heap
.as_mut().expect("List pointer should be non-null")
}._base as *mut structs::nsCSSValueList;
while let Some(item) = unsafe { item_ptr.as_mut() } {
item.mValue = values.next().expect("Values shouldn't have been exhausted");
item_ptr = item.mNext;
}
debug_assert!(values.next().is_none(), "Values should have been exhausted");
}
/// Set to a pair list value
///
/// This is only supported on the main thread.
pub fn set_pair_list<I>(&mut self, mut values: I)
where I: ExactSizeIterator<Item=(nsCSSValue, nsCSSValue)> {
debug_assert!(values.len() > 0, "Empty list is not supported");
unsafe { bindings::Gecko_CSSValue_SetPairList(self, values.len() as u32); }
debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_PairList);
let mut item_ptr = &mut unsafe {
self.mValue.mPairList.as_ref() // &*nsCSSValuePairList_heap
.as_mut().expect("List pointer should be non-null")
}._base as *mut structs::nsCSSValuePairList;
while let Some(item) = unsafe { item_ptr.as_mut() } {
let value = values.next().expect("Values shouldn't have been exhausted");
item.mXValue = value.0;
item.mYValue = value.1;
item_ptr = item.mNext;
}
debug_assert!(values.next().is_none(), "Values should have been exhausted");
}
} }
impl Drop for nsCSSValue { impl Drop for nsCSSValue {
@ -249,5 +311,5 @@ impl IndexMut<usize> for nsCSSValue_Array {
/// Generic conversion to nsCSSValue /// Generic conversion to nsCSSValue
pub trait ToNsCssValue { pub trait ToNsCssValue {
/// Convert /// Convert
fn convert(&self, nscssvalue: &mut nsCSSValue); fn convert(self, nscssvalue: &mut nsCSSValue);
} }

View file

@ -255,6 +255,8 @@ macro_rules! impl_refcount {
impl_refcount!(::gecko_bindings::structs::nsCSSFontFaceRule, impl_refcount!(::gecko_bindings::structs::nsCSSFontFaceRule,
Gecko_CSSFontFaceRule_AddRef, Gecko_CSSFontFaceRule_Release); Gecko_CSSFontFaceRule_AddRef, Gecko_CSSFontFaceRule_Release);
impl_refcount!(::gecko_bindings::structs::nsCSSCounterStyleRule,
Gecko_CSSCounterStyleRule_AddRef, Gecko_CSSCounterStyleRule_Release);
// Companion of NS_DECL_THREADSAFE_FFI_REFCOUNTING. // Companion of NS_DECL_THREADSAFE_FFI_REFCOUNTING.
// //

View file

@ -198,7 +198,7 @@ impl fmt::Display for WeakAtom {
impl Atom { impl Atom {
/// Execute a callback with the atom represented by `ptr`. /// Execute a callback with the atom represented by `ptr`.
pub unsafe fn with<F, R: 'static>(ptr: *mut nsIAtom, callback: &mut F) -> R where F: FnMut(&Atom) -> R { pub unsafe fn with<F, R>(ptr: *mut nsIAtom, callback: F) -> R where F: FnOnce(&Atom) -> R {
let atom = Atom(WeakAtom::new(ptr)); let atom = Atom(WeakAtom::new(ptr));
let ret = callback(&atom); let ret = callback(&atom);
mem::forget(atom); mem::forget(atom);

View file

@ -2987,29 +2987,12 @@ fn static_assert() {
} }
pub fn set_list_style_type(&mut self, v: longhands::list_style_type::computed_value::T) { pub fn set_list_style_type(&mut self, v: longhands::list_style_type::computed_value::T) {
use properties::longhands::list_style_type::computed_value::T as Keyword; use values::generics::CounterStyleOrNone;
<% let name = match v.0 {
keyword = data.longhands_by_name["list-style-type"].keyword CounterStyleOrNone::None_ => atom!("none"),
# The first four are @counter-styles CounterStyleOrNone::Name(name) => name.0,
# The rest have special fallback behavior
special = """upper-roman lower-roman upper-alpha lower-alpha
japanese-informal japanese-formal korean-hangul-formal korean-hanja-informal
korean-hanja-formal simp-chinese-informal simp-chinese-formal
trad-chinese-informal trad-chinese-formal""".split()
%>
let result = match v {
% for value in keyword.values_for('gecko'):
% if value in special:
// Special keywords are implemented as @counter-styles
// and need to be manually set as strings
Keyword::${to_rust_ident(value)} => structs::${keyword.gecko_constant("none")},
% else:
Keyword::${to_rust_ident(value)} =>
structs::${keyword.gecko_constant(value)},
% endif
% endfor
}; };
unsafe { Gecko_SetListStyleType(&mut self.gecko, result as u32); } unsafe { Gecko_SetListStyleType(&mut self.gecko, name.as_ptr()); }
} }
@ -4072,7 +4055,8 @@ clip-path
pub fn set_content(&mut self, v: longhands::content::computed_value::T) { pub fn set_content(&mut self, v: longhands::content::computed_value::T) {
use properties::longhands::content::computed_value::T; use properties::longhands::content::computed_value::T;
use properties::longhands::content::computed_value::ContentItem; use properties::longhands::content::computed_value::ContentItem;
use style_traits::ToCss; use values::generics::CounterStyleOrNone;
use gecko_bindings::structs::nsCSSValue;
use gecko_bindings::structs::nsStyleContentType::*; use gecko_bindings::structs::nsStyleContentType::*;
use gecko_bindings::bindings::Gecko_ClearAndResizeStyleContents; use gecko_bindings::bindings::Gecko_ClearAndResizeStyleContents;
@ -4086,6 +4070,13 @@ clip-path
ptr ptr
} }
fn set_counter_style(style: CounterStyleOrNone, dest: &mut nsCSSValue) {
dest.set_atom_ident(match style {
CounterStyleOrNone::None_ => atom!("none"),
CounterStyleOrNone::Name(name) => name.0,
});
}
match v { match v {
T::none | T::none |
T::normal => { T::normal => {
@ -4147,8 +4138,7 @@ clip-path
} }
let mut array = unsafe { &mut **self.gecko.mContents[i].mContent.mCounters.as_mut() }; let mut array = unsafe { &mut **self.gecko.mContents[i].mContent.mCounters.as_mut() };
array[0].set_string(&name); array[0].set_string(&name);
// When we support <custom-ident> values for list-style-type this will need to be updated set_counter_style(style, &mut array[1]);
array[1].set_atom_ident(style.to_css_string().into());
} }
ContentItem::Counters(name, sep, style) => { ContentItem::Counters(name, sep, style) => {
unsafe { unsafe {
@ -4158,8 +4148,7 @@ clip-path
let mut array = unsafe { &mut **self.gecko.mContents[i].mContent.mCounters.as_mut() }; let mut array = unsafe { &mut **self.gecko.mContents[i].mContent.mCounters.as_mut() };
array[0].set_string(&name); array[0].set_string(&name);
array[1].set_string(&sep); array[1].set_string(&sep);
// When we support <custom-ident> values for list-style-type this will need to be updated set_counter_style(style, &mut array[2]);
array[2].set_atom_ident(style.to_css_string().into());
} }
ContentItem::Url(ref url) => { ContentItem::Url(ref url) => {
unsafe { unsafe {

View file

@ -11,9 +11,12 @@
use cssparser::Token; use cssparser::Token;
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
#[cfg(feature = "gecko")]
use values::generics::CounterStyleOrNone;
use values::specified::url::SpecifiedUrl; use values::specified::url::SpecifiedUrl;
use values::HasViewportPercentage; use values::HasViewportPercentage;
#[cfg(feature = "servo")]
use super::list_style_type; use super::list_style_type;
pub use self::computed_value::T as SpecifiedValue; pub use self::computed_value::T as SpecifiedValue;
@ -23,22 +26,25 @@
no_viewport_percentage!(SpecifiedValue); no_viewport_percentage!(SpecifiedValue);
pub mod computed_value { pub mod computed_value {
use super::super::list_style_type;
use cssparser; use cssparser;
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::specified::url::SpecifiedUrl; use values::specified::url::SpecifiedUrl;
#[cfg(feature = "servo")]
type CounterStyleType = super::super::list_style_type::computed_value::T;
#[cfg(feature = "gecko")]
type CounterStyleType = ::values::generics::CounterStyleOrNone;
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum ContentItem { pub enum ContentItem {
/// Literal string content. /// Literal string content.
String(String), String(String),
/// `counter(name, style)`. /// `counter(name, style)`.
Counter(String, list_style_type::computed_value::T), Counter(String, CounterStyleType),
/// `counters(name, separator, style)`. /// `counters(name, separator, style)`.
Counters(String, String, list_style_type::computed_value::T), Counters(String, String, CounterStyleType),
/// `open-quote`. /// `open-quote`.
OpenQuote, OpenQuote,
/// `close-quote`. /// `close-quote`.
@ -64,20 +70,20 @@
ContentItem::String(ref s) => { ContentItem::String(ref s) => {
cssparser::serialize_string(&**s, dest) cssparser::serialize_string(&**s, dest)
} }
ContentItem::Counter(ref s, ref list_style_type) => { ContentItem::Counter(ref s, ref counter_style) => {
try!(dest.write_str("counter(")); try!(dest.write_str("counter("));
try!(cssparser::serialize_identifier(&**s, dest)); try!(cssparser::serialize_identifier(&**s, dest));
try!(dest.write_str(", ")); try!(dest.write_str(", "));
try!(list_style_type.to_css(dest)); try!(counter_style.to_css(dest));
dest.write_str(")") dest.write_str(")")
} }
ContentItem::Counters(ref s, ref separator, ref list_style_type) => { ContentItem::Counters(ref s, ref separator, ref counter_style) => {
try!(dest.write_str("counters(")); try!(dest.write_str("counters("));
try!(cssparser::serialize_identifier(&**s, dest)); try!(cssparser::serialize_identifier(&**s, dest));
try!(dest.write_str(", ")); try!(dest.write_str(", "));
try!(cssparser::serialize_string(&**separator, dest)); try!(cssparser::serialize_string(&**separator, dest));
try!(dest.write_str(", ")); try!(dest.write_str(", "));
try!(list_style_type.to_css(dest)); try!(counter_style.to_css(dest));
dest.write_str(")") dest.write_str(")")
} }
ContentItem::OpenQuote => dest.write_str("open-quote"), ContentItem::OpenQuote => dest.write_str("open-quote"),
@ -134,6 +140,22 @@
computed_value::T::normal computed_value::T::normal
} }
#[cfg(feature = "servo")]
fn parse_counter_style(context: &ParserContext, input: &mut Parser) -> list_style_type::computed_value::T {
input.try(|input| {
input.expect_comma()?;
list_style_type::parse(context, input)
}).unwrap_or(list_style_type::computed_value::T::decimal)
}
#[cfg(feature = "gecko")]
fn parse_counter_style(context: &ParserContext, input: &mut Parser) -> CounterStyleOrNone {
input.try(|input| {
input.expect_comma()?;
CounterStyleOrNone::parse(context, input)
}).unwrap_or(CounterStyleOrNone::decimal())
}
// normal | none | [ <string> | <counter> | open-quote | close-quote | no-open-quote | // normal | none | [ <string> | <counter> | open-quote | close-quote | no-open-quote |
// no-close-quote ]+ // no-close-quote ]+
// TODO: <uri>, attr(<identifier>) // TODO: <uri>, attr(<identifier>)
@ -162,20 +184,14 @@
content.push(try!(match_ignore_ascii_case! { &name, content.push(try!(match_ignore_ascii_case! { &name,
"counter" => input.parse_nested_block(|input| { "counter" => input.parse_nested_block(|input| {
let name = try!(input.expect_ident()).into_owned(); let name = try!(input.expect_ident()).into_owned();
let style = input.try(|input| { let style = parse_counter_style(context, input);
try!(input.expect_comma());
list_style_type::parse(context, input)
}).unwrap_or(list_style_type::computed_value::T::decimal);
Ok(ContentItem::Counter(name, style)) Ok(ContentItem::Counter(name, style))
}), }),
"counters" => input.parse_nested_block(|input| { "counters" => input.parse_nested_block(|input| {
let name = try!(input.expect_ident()).into_owned(); let name = try!(input.expect_ident()).into_owned();
try!(input.expect_comma()); try!(input.expect_comma());
let separator = try!(input.expect_string()).into_owned(); let separator = try!(input.expect_string()).into_owned();
let style = input.try(|input| { let style = parse_counter_style(context, input);
try!(input.expect_comma());
list_style_type::parse(context, input)
}).unwrap_or(list_style_type::computed_value::T::decimal);
Ok(ContentItem::Counters(name, separator, style)) Ok(ContentItem::Counters(name, separator, style))
}), }),
% if product == "gecko": % if product == "gecko":

View file

@ -721,7 +721,7 @@ ${helpers.single_keyword_system("font-variant-caps",
// XXXManishearth handle quirks mode // XXXManishearth handle quirks mode
let ref gecko_font = cx.style().get_font().gecko(); let ref gecko_font = cx.style().get_font().gecko();
let base_size = unsafe { Atom::with(gecko_font.mLanguage.raw::<nsIAtom>(), &mut |atom| { let base_size = unsafe { Atom::with(gecko_font.mLanguage.raw::<nsIAtom>(), |atom| {
cx.font_metrics_provider.get_size(atom, gecko_font.mGenericID).0 cx.font_metrics_provider.get_size(atom, gecko_font.mGenericID).0
}) }; }) };

View file

@ -21,21 +21,85 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
// we may need to look into this and handle these differently. // we may need to look into this and handle these differently.
// //
// [1]: http://dev.w3.org/csswg/css-counter-styles/ // [1]: http://dev.w3.org/csswg/css-counter-styles/
${helpers.single_keyword("list-style-type", """ % if product == "servo":
disc none circle square decimal disclosure-open disclosure-closed lower-alpha upper-alpha ${helpers.single_keyword("list-style-type", """
""", extra_servo_values="""arabic-indic bengali cambodian cjk-decimal devanagari disc none circle square decimal disclosure-open disclosure-closed lower-alpha upper-alpha
gujarati gurmukhi kannada khmer lao malayalam mongolian arabic-indic bengali cambodian cjk-decimal devanagari gujarati gurmukhi kannada khmer lao
myanmar oriya persian telugu thai tibetan cjk-earthly-branch malayalam mongolian myanmar oriya persian telugu thai tibetan cjk-earthly-branch
cjk-heavenly-stem lower-greek hiragana hiragana-iroha katakana cjk-heavenly-stem lower-greek hiragana hiragana-iroha katakana katakana-iroha""",
katakana-iroha""", needs_conversion="True",
extra_gecko_values="""japanese-informal japanese-formal korean-hangul-formal animation_value_type="none",
korean-hanja-formal korean-hanja-informal simp-chinese-informal simp-chinese-formal spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type")}
trad-chinese-informal trad-chinese-formal ethiopic-numeric upper-roman lower-roman % else:
""", <%helpers:longhand name="list-style-type" animation_value_type="none"
gecko_constant_prefix="NS_STYLE_LIST_STYLE", spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type">
needs_conversion="True", use std::fmt;
animation_value_type="none", use style_traits::ToCss;
spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type")} use values::CustomIdent;
use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified;
use values::generics::CounterStyleOrNone;
pub use self::computed_value::T as SpecifiedValue;
pub mod computed_value {
use values::generics::CounterStyleOrNone;
/// <counter-style> | none
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct T(pub CounterStyleOrNone);
}
impl ComputedValueAsSpecified for SpecifiedValue {}
no_viewport_percentage!(SpecifiedValue);
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
self.0.to_css(dest)
}
}
#[cfg(feature = "gecko")]
impl SpecifiedValue {
/// Convert from gecko keyword to list-style-type.
///
/// This should only be used for mapping type attribute to
/// list-style-type, and thus only values possible in that
/// attribute is considered here.
pub fn from_gecko_keyword(value: u32) -> Self {
use gecko_bindings::structs;
SpecifiedValue(if value == structs::NS_STYLE_LIST_STYLE_NONE {
CounterStyleOrNone::None_
} else {
<%
values = """disc circle square decimal lower-roman
upper-roman lower-alpha upper-alpha""".split()
%>
CounterStyleOrNone::Name(CustomIdent(match value {
% for style in values:
structs::NS_STYLE_LIST_STYLE_${style.replace('-', '_').upper()} => atom!("${style}"),
% endfor
_ => unreachable!("Unknown counter style keyword value"),
}))
})
}
}
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T(CounterStyleOrNone::disc())
}
#[inline]
pub fn get_initial_specified_value() -> SpecifiedValue {
SpecifiedValue(CounterStyleOrNone::disc())
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
CounterStyleOrNone::parse(context, input).map(SpecifiedValue)
}
</%helpers:longhand>
% endif
<%helpers:longhand name="list-style-image" animation_value_type="none" <%helpers:longhand name="list-style-image" animation_value_type="none"
boxed="${product == 'gecko'}" boxed="${product == 'gecko'}"

View file

@ -25,14 +25,6 @@
continue continue
} }
if list_style_type.is_none() {
if let Ok(value) = input.try(|input| list_style_type::parse(context, input)) {
list_style_type = Some(value);
any = true;
continue
}
}
if image.is_none() { if image.is_none() {
if let Ok(value) = input.try(|input| list_style_image::parse(context, input)) { if let Ok(value) = input.try(|input| list_style_image::parse(context, input)) {
image = Some(value); image = Some(value);
@ -48,11 +40,31 @@
continue continue
} }
} }
// list-style-type must be checked the last, because it accepts
// arbitrary identifier for custom counter style, and thus may
// affect values of list-style-position.
if list_style_type.is_none() {
if let Ok(value) = input.try(|input| list_style_type::parse(context, input)) {
list_style_type = Some(value);
any = true;
continue
}
}
break break
} }
let position = unwrap_or_initial!(list_style_position, position); let position = unwrap_or_initial!(list_style_position, position);
fn list_style_type_none() -> list_style_type::SpecifiedValue {
% if product == "servo":
list_style_type::SpecifiedValue::none
% else:
use values::generics::CounterStyleOrNone;
list_style_type::SpecifiedValue(CounterStyleOrNone::None_)
% endif
}
// If there are two `none`s, then we can't have a type or image; if there is one `none`, // If there are two `none`s, then we can't have a type or image; if there is one `none`,
// then we can't have both a type *and* an image; if there is no `none` then we're fine as // then we can't have both a type *and* an image; if there is no `none` then we're fine as
// long as we parsed something. // long as we parsed something.
@ -61,14 +73,14 @@
Ok(Longhands { Ok(Longhands {
list_style_position: position, list_style_position: position,
list_style_image: list_style_image::SpecifiedValue(Either::Second(None_)), list_style_image: list_style_image::SpecifiedValue(Either::Second(None_)),
list_style_type: list_style_type::SpecifiedValue::none, list_style_type: list_style_type_none(),
}) })
} }
(true, 1, None, Some(image)) => { (true, 1, None, Some(image)) => {
Ok(Longhands { Ok(Longhands {
list_style_position: position, list_style_position: position,
list_style_image: image, list_style_image: image,
list_style_type: list_style_type::SpecifiedValue::none, list_style_type: list_style_type_none(),
}) })
} }
(true, 1, Some(list_style_type), None) => { (true, 1, Some(list_style_type), None) => {
@ -82,7 +94,7 @@
Ok(Longhands { Ok(Longhands {
list_style_position: position, list_style_position: position,
list_style_image: list_style_image::SpecifiedValue(Either::Second(None_)), list_style_image: list_style_image::SpecifiedValue(Either::Second(None_)),
list_style_type: list_style_type::SpecifiedValue::none, list_style_type: list_style_type_none(),
}) })
} }
(true, 0, list_style_type, image) => { (true, 0, list_style_type, image) => {

View file

@ -8,7 +8,9 @@
use {Atom, Prefix, Namespace}; use {Atom, Prefix, Namespace};
use context::QuirksMode; use context::QuirksMode;
use counter_style::{CounterStyleRule, parse_counter_style_name, parse_counter_style_body}; use counter_style::{parse_counter_style_name, parse_counter_style_body};
#[cfg(feature = "servo")]
use counter_style::CounterStyleRuleData;
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser}; use cssparser::{AtRuleParser, Parser, QualifiedRuleParser};
use cssparser::{AtRuleType, RuleListParser, parse_one_rule, SourceLocation}; use cssparser::{AtRuleType, RuleListParser, parse_one_rule, SourceLocation};
use cssparser::ToCss as ParserToCss; use cssparser::ToCss as ParserToCss;
@ -18,7 +20,7 @@ use error_reporting::{ParseErrorReporter, NullReporter};
use font_face::FontFaceRuleData; use font_face::FontFaceRuleData;
use font_face::parse_font_face_block; use font_face::parse_font_face_block;
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub use gecko::rules::FontFaceRule; pub use gecko::rules::{CounterStyleRule, FontFaceRule};
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
use gecko_bindings::structs::URLExtraData; use gecko_bindings::structs::URLExtraData;
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
@ -697,6 +699,10 @@ impl ToCssWithGuard for StyleRule {
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
pub type FontFaceRule = FontFaceRuleData; pub type FontFaceRule = FontFaceRuleData;
/// A @counter-style rule
#[cfg(feature = "servo")]
pub type CounterStyleRule = CounterStyleRuleData;
#[derive(Debug)] #[derive(Debug)]
/// A @-moz-document rule /// A @-moz-document rule
pub struct DocumentRule { pub struct DocumentRule {
@ -1282,7 +1288,7 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
AtRulePrelude::CounterStyle(name) => { AtRulePrelude::CounterStyle(name) => {
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::CounterStyle)); let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::CounterStyle));
Ok(CssRule::CounterStyle(Arc::new(self.shared_lock.wrap( Ok(CssRule::CounterStyle(Arc::new(self.shared_lock.wrap(
parse_counter_style_body(name, &context, input)?)))) parse_counter_style_body(name, &context, input)?.into()))))
} }
AtRulePrelude::Media(media_queries, location) => { AtRulePrelude::Media(media_queries, location) => {
Ok(CssRule::Media(Arc::new(self.shared_lock.wrap(MediaRule { Ok(CssRule::Media(Arc::new(self.shared_lock.wrap(MediaRule {

View file

@ -14,6 +14,8 @@ use dom::{AnimationRules, TElement};
use element_state::ElementState; use element_state::ElementState;
use error_reporting::RustLogReporter; use error_reporting::RustLogReporter;
use font_metrics::FontMetricsProvider; use font_metrics::FontMetricsProvider;
#[cfg(feature = "gecko")]
use gecko_bindings::structs::nsIAtom;
use keyframes::KeyframesAnimation; use keyframes::KeyframesAnimation;
use media_queries::Device; use media_queries::Device;
use pdqsort::sort_by; use pdqsort::sort_by;
@ -41,7 +43,10 @@ use std::hash::Hash;
use std::marker::PhantomData; use std::marker::PhantomData;
use style_traits::viewport::ViewportConstraints; use style_traits::viewport::ViewportConstraints;
use stylearc::Arc; use stylearc::Arc;
use stylesheets::{CssRule, FontFaceRule, Origin, StyleRule, Stylesheet, UserAgentStylesheets}; #[cfg(feature = "gecko")]
use stylesheets::{CounterStyleRule, FontFaceRule};
use stylesheets::{CssRule, Origin};
use stylesheets::{StyleRule, Stylesheet, UserAgentStylesheets};
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
use stylesheets::NestedRulesResult; use stylesheets::NestedRulesResult;
use thread_state; use thread_state;
@ -168,33 +173,44 @@ pub struct Stylist {
/// This struct holds data which user of Stylist may want to extract /// This struct holds data which user of Stylist may want to extract
/// from stylesheets which can be done at the same time as updating. /// from stylesheets which can be done at the same time as updating.
#[cfg(feature = "gecko")]
pub struct ExtraStyleData<'a> { pub struct ExtraStyleData<'a> {
/// A list of effective font-face rules and their origin. /// A list of effective font-face rules and their origin.
#[cfg(feature = "gecko")]
pub font_faces: &'a mut Vec<(Arc<Locked<FontFaceRule>>, Origin)>, pub font_faces: &'a mut Vec<(Arc<Locked<FontFaceRule>>, Origin)>,
/// A map of effective counter-style rules.
#[allow(missing_docs)] pub counter_styles: &'a mut HashMap<Atom, Arc<Locked<CounterStyleRule>>>,
#[cfg(feature = "servo")]
pub marker: PhantomData<&'a usize>,
} }
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
impl<'a> ExtraStyleData<'a> { impl<'a> ExtraStyleData<'a> {
/// Clear the internal @font-face rule list. /// Clear the internal data.
fn clear_font_faces(&mut self) { fn clear(&mut self) {
self.font_faces.clear(); self.font_faces.clear();
self.counter_styles.clear();
} }
/// Add the given @font-face rule. /// Add the given @font-face rule.
fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, origin: Origin) { fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, origin: Origin) {
self.font_faces.push((rule.clone(), origin)); self.font_faces.push((rule.clone(), origin));
} }
/// Add the given @counter-style rule.
fn add_counter_style(&mut self, guard: &SharedRwLockReadGuard,
rule: &Arc<Locked<CounterStyleRule>>) {
let name = rule.read_with(guard).mName.raw::<nsIAtom>().into();
self.counter_styles.insert(name, rule.clone());
}
}
#[allow(missing_docs)]
#[cfg(feature = "servo")]
pub struct ExtraStyleData<'a> {
pub marker: PhantomData<&'a usize>,
} }
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
impl<'a> ExtraStyleData<'a> { impl<'a> ExtraStyleData<'a> {
fn clear_font_faces(&mut self) {} fn clear(&mut self) {}
fn add_font_face(&mut self, _: &Arc<Locked<FontFaceRule>>, _: Origin) {}
} }
impl Stylist { impl Stylist {
@ -343,7 +359,7 @@ impl Stylist {
self.pseudos_map.insert(pseudo, PerPseudoElementSelectorMap::new()); self.pseudos_map.insert(pseudo, PerPseudoElementSelectorMap::new());
}); });
extra_data.clear_font_faces(); extra_data.clear();
if let Some(ua_stylesheets) = ua_stylesheets { if let Some(ua_stylesheets) = ua_stylesheets {
for stylesheet in &ua_stylesheets.user_or_user_agent_stylesheets { for stylesheet in &ua_stylesheets.user_or_user_agent_stylesheets {
@ -443,9 +459,14 @@ impl Stylist {
self.animations.insert(keyframes_rule.name.as_atom().clone(), animation); self.animations.insert(keyframes_rule.name.as_atom().clone(), animation);
} }
} }
#[cfg(feature = "gecko")]
CssRule::FontFace(ref rule) => { CssRule::FontFace(ref rule) => {
extra_data.add_font_face(&rule, stylesheet.origin); extra_data.add_font_face(&rule, stylesheet.origin);
} }
#[cfg(feature = "gecko")]
CssRule::CounterStyle(ref rule) => {
extra_data.add_counter_style(guard, &rule);
}
// We don't care about any other rule. // We don't care about any other rule.
_ => {} _ => {}
} }

View file

@ -5,9 +5,13 @@
//! Generic types that share their serialization implementations //! Generic types that share their serialization implementations
//! for both specified and computed values. //! for both specified and computed values.
use counter_style::parse_counter_style_name;
use cssparser::Parser;
use euclid::size::Size2D; use euclid::size::Size2D;
use parser::{Parse, ParserContext};
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use super::CustomIdent;
use super::HasViewportPercentage; use super::HasViewportPercentage;
use super::computed::{Context, ToComputedValue}; use super::computed::{Context, ToComputedValue};
@ -75,3 +79,49 @@ impl<L: ToComputedValue> ToComputedValue for BorderRadiusSize<L> {
BorderRadiusSize(Size2D::new(w, h)) BorderRadiusSize(Size2D::new(w, h))
} }
} }
/// https://drafts.csswg.org/css-counter-styles/#typedef-counter-style
///
/// Since wherever <counter-style> is used, 'none' is a valid value as
/// well, we combine them into one type to make code simpler.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum CounterStyleOrNone {
/// none
None_,
/// <counter-style-name>
Name(CustomIdent),
}
impl CounterStyleOrNone {
/// disc value
pub fn disc() -> Self {
CounterStyleOrNone::Name(CustomIdent(atom!("disc")))
}
/// decimal value
pub fn decimal() -> Self {
CounterStyleOrNone::Name(CustomIdent(atom!("decimal")))
}
}
no_viewport_percentage!(CounterStyleOrNone);
impl Parse for CounterStyleOrNone {
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
input.try(|input| {
parse_counter_style_name(input).map(CounterStyleOrNone::Name)
}).or_else(|_| {
input.expect_ident_matching("none").map(|_| CounterStyleOrNone::None_)
})
}
}
impl ToCss for CounterStyleOrNone {
#[inline]
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match self {
&CounterStyleOrNone::None_ => dest.write_str("none"),
&CounterStyleOrNone::Name(ref name) => name.to_css(dest),
}
}
}

View file

@ -61,7 +61,8 @@ use style::gecko_bindings::structs;
use style::gecko_bindings::structs::{CSSPseudoElementType, CompositeOperation}; use style::gecko_bindings::structs::{CSSPseudoElementType, CompositeOperation};
use style::gecko_bindings::structs::{RawServoStyleRule, ServoStyleSheet}; use style::gecko_bindings::structs::{RawServoStyleRule, ServoStyleSheet};
use style::gecko_bindings::structs::{SheetParsingMode, nsIAtom, nsCSSPropertyID}; use style::gecko_bindings::structs::{SheetParsingMode, nsIAtom, nsCSSPropertyID};
use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint, nsCSSFontFaceRule}; use style::gecko_bindings::structs::{nsCSSFontFaceRule, nsCSSCounterStyleRule};
use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint};
use style::gecko_bindings::structs::Loader; use style::gecko_bindings::structs::Loader;
use style::gecko_bindings::structs::RawGeckoPresContextOwned; use style::gecko_bindings::structs::RawGeckoPresContextOwned;
use style::gecko_bindings::structs::ServoElementSnapshotTable; use style::gecko_bindings::structs::ServoElementSnapshotTable;
@ -871,19 +872,28 @@ impl_group_rule_funcs! { (Document, DocumentRule, RawServoDocumentRule),
to_css: Servo_DocumentRule_GetCssText, to_css: Servo_DocumentRule_GetCssText,
} }
#[no_mangle] macro_rules! impl_getter_for_embedded_rule {
pub extern "C" fn Servo_CssRules_GetFontFaceRuleAt(rules: ServoCssRulesBorrowed, index: u32) ($getter:ident: $name:ident -> $ty:ty) => {
-> *mut nsCSSFontFaceRule #[no_mangle]
{ pub extern "C" fn $getter(rules: ServoCssRulesBorrowed, index: u32) -> *mut $ty
let global_style_data = &*GLOBAL_STYLE_DATA; {
let guard = global_style_data.shared_lock.read(); let global_style_data = &*GLOBAL_STYLE_DATA;
let rules = Locked::<CssRules>::as_arc(&rules).read_with(&guard); let guard = global_style_data.shared_lock.read();
match rules.0[index as usize] { let rules = Locked::<CssRules>::as_arc(&rules).read_with(&guard);
CssRule::FontFace(ref rule) => rule.read_with(&guard).get(), match rules.0[index as usize] {
_ => unreachable!("Servo_CssRules_GetFontFaceRuleAt should only be called on a FontFace rule"), CssRule::$name(ref rule) => rule.read_with(&guard).get(),
_ => unreachable!(concat!(stringify!($getter), " should only be called on a ",
stringify!($name), " rule")),
}
}
} }
} }
impl_getter_for_embedded_rule!(Servo_CssRules_GetFontFaceRuleAt:
FontFace -> nsCSSFontFaceRule);
impl_getter_for_embedded_rule!(Servo_CssRules_GetCounterStyleRuleAt:
CounterStyle -> nsCSSCounterStyleRule);
#[no_mangle] #[no_mangle]
pub extern "C" fn Servo_StyleRule_GetStyle(rule: RawServoStyleRuleBorrowed) -> RawServoDeclarationBlockStrong { pub extern "C" fn Servo_StyleRule_GetStyle(rule: RawServoStyleRuleBorrowed) -> RawServoDeclarationBlockStrong {
read_locked_arc(rule, |rule: &StyleRule| { read_locked_arc(rule, |rule: &StyleRule| {
@ -2374,6 +2384,19 @@ pub extern "C" fn Servo_StyleSet_GetFontFaceRules(raw_data: RawServoStyleSetBorr
} }
} }
#[no_mangle]
pub extern "C" fn Servo_StyleSet_GetCounterStyleRule(raw_data: RawServoStyleSetBorrowed,
name: *mut nsIAtom) -> *mut nsCSSCounterStyleRule {
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
unsafe {
Atom::with(name, |name| data.counter_styles.get(name))
}.map(|rule| {
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
rule.read_with(&guard).get()
}).unwrap_or(ptr::null_mut())
}
#[no_mangle] #[no_mangle]
pub extern "C" fn Servo_StyleSet_ResolveForDeclarations(raw_data: RawServoStyleSetBorrowed, pub extern "C" fn Servo_StyleSet_ResolveForDeclarations(raw_data: RawServoStyleSetBorrowed,
parent_style_or_null: ServoComputedValuesBorrowedOrNull, parent_style_or_null: ServoComputedValuesBorrowedOrNull,
@ -2401,7 +2424,7 @@ pub extern "C" fn Servo_StyleSet_ResolveForDeclarations(raw_data: RawServoStyleS
pub extern "C" fn Servo_StyleSet_MightHaveAttributeDependency(raw_data: RawServoStyleSetBorrowed, pub extern "C" fn Servo_StyleSet_MightHaveAttributeDependency(raw_data: RawServoStyleSetBorrowed,
local_name: *mut nsIAtom) -> bool { local_name: *mut nsIAtom) -> bool {
let data = PerDocumentStyleData::from_ffi(raw_data).borrow(); let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
unsafe { Atom::with(local_name, &mut |atom| data.stylist.might_have_attribute_dependency(atom)) } unsafe { Atom::with(local_name, |atom| data.stylist.might_have_attribute_dependency(atom)) }
} }
#[no_mangle] #[no_mangle]