servo: Merge #16888 - Implement @counter-style for stylo (from upsuper:bug1328319); r=heycam,Manishearth,SimonSapin

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

Source-Repo: https://github.com/servo/servo
Source-Revision: 1afc89e944c7ea7e4510b4b678a95a8faaa309b1

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : c05b40bd3b03187aa1ea82629385669156bd9cf4
This commit is contained in:
Xidorn Quan 2017-05-16 01:17:07 -05:00
Родитель 267a890b22
Коммит fc0ebbbaff
22 изменённых файлов: 1522 добавлений и 938 удалений

Просмотреть файл

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

Просмотреть файл

@ -49,9 +49,9 @@ pub fn parse_counter_style_name(input: &mut Parser) -> Result<CustomIdent, ()> {
/// Parse the body (inside `{}`) of an @counter-style rule
pub fn parse_counter_style_body(name: CustomIdent, context: &ParserContext, input: &mut Parser)
-> Result<CounterStyleRule, ()> {
-> Result<CounterStyleRuleData, ()> {
let start = input.position();
let mut rule = CounterStyleRule::empty(name);
let mut rule = CounterStyleRuleData::empty(name);
{
let parser = CounterStyleRuleParser {
context: context,
@ -108,7 +108,7 @@ pub fn parse_counter_style_body(name: CustomIdent, context: &ParserContext, inpu
struct CounterStyleRuleParser<'a, 'b: 'a> {
context: &'a ParserContext<'b>,
rule: &'a mut CounterStyleRule,
rule: &'a mut CounterStyleRuleData,
}
/// Default methods reject all at rules.
@ -143,7 +143,7 @@ macro_rules! counter_style_descriptors {
) => {
/// An @counter-style rule
#[derive(Debug)]
pub struct CounterStyleRule {
pub struct CounterStyleRuleData {
name: CustomIdent,
$(
#[$doc]
@ -151,9 +151,9 @@ macro_rules! counter_style_descriptors {
)+
}
impl CounterStyleRule {
impl CounterStyleRuleData {
fn empty(name: CustomIdent) -> Self {
CounterStyleRule {
CounterStyleRuleData {
name: name,
$(
$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);
)+
/// Convert to Gecko types
#[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)
}
)*
@ -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
where W: fmt::Write {
dest.write_str("@counter-style ")?;
@ -531,7 +536,7 @@ impl Parse for AdditiveSymbols {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
let tuples = Vec::<AdditiveTuple>::parse(context, input)?;
// 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(())
}
Ok(AdditiveSymbols(tuples))
@ -547,8 +552,10 @@ impl ToCss for AdditiveSymbols {
/// <integer> && <symbol>
#[derive(Debug, Clone)]
pub struct AdditiveTuple {
value: u32,
symbol: Symbol,
/// <integer>
pub weight: u32,
/// <symbol>
pub symbol: Symbol,
}
impl OneOrMoreCommaSeparated for AdditiveTuple {}
@ -556,13 +563,13 @@ impl OneOrMoreCommaSeparated for AdditiveTuple {}
impl Parse for AdditiveTuple {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
let symbol = input.try(|input| Symbol::parse(context, input));
let value = input.expect_integer()?;
if value < 0 {
let weight = input.expect_integer()?;
if weight < 0 {
return Err(())
}
let symbol = symbol.or_else(|()| Symbol::parse(context, input))?;
Ok(AdditiveTuple {
value: value as u32,
weight: weight as u32,
symbol: symbol,
})
}
@ -570,7 +577,7 @@ impl Parse for AdditiveTuple {
impl ToCss for AdditiveTuple {
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)
}
}

Просмотреть файл

@ -208,9 +208,9 @@ macro_rules! font_face_descriptors_common {
/// Convert to Gecko types
#[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)
}
)*

Просмотреть файл

@ -4,9 +4,11 @@
//! Data needed to style a Gecko document.
use Atom;
use animation::Animation;
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
use dom::OpaqueNode;
use gecko::rules::{CounterStyleRule, FontFaceRule};
use gecko_bindings::bindings::RawServoStyleSet;
use gecko_bindings::structs::RawGeckoPresContextOwned;
use gecko_bindings::structs::nsIDocument;
@ -19,7 +21,7 @@ use std::collections::HashMap;
use std::sync::mpsc::{Receiver, Sender, channel};
use stylearc::Arc;
use stylesheet_set::StylesheetSet;
use stylesheets::{FontFaceRule, Origin};
use stylesheets::Origin;
use stylist::{ExtraStyleData, Stylist};
/// 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.
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
@ -71,6 +75,7 @@ impl PerDocumentStyleData {
running_animations: Arc::new(RwLock::new(HashMap::new())),
expired_animations: Arc::new(RwLock::new(HashMap::new())),
font_faces: vec![],
counter_styles: HashMap::new(),
}))
}
@ -103,6 +108,7 @@ impl PerDocumentStyleDataImpl {
let mut extra_data = ExtraStyleData {
font_faces: &mut self.font_faces,
counter_styles: &mut self.counter_styles,
};
let author_style_disabled = self.stylesheets.author_style_disabled();

Просмотреть файл

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

Просмотреть файл

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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -10,7 +10,8 @@ use counter_style;
use cssparser::UnicodeRange;
use font_face::{FontFaceRuleData, Source};
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::refptr::{RefPtr, UniqueRefPtr};
use shared_lock::{ToCssWithGuard, SharedRwLockReadGuard};
@ -20,14 +21,14 @@ use std::fmt;
pub type FontFaceRule = RefPtr<nsCSSFontFaceRule>;
impl ToNsCssValue for FamilyName {
fn convert(&self, nscssvalue: &mut nsCSSValue) {
fn convert(self, nscssvalue: &mut nsCSSValue) {
nscssvalue.set_string_from_atom(&self.name)
}
}
impl ToNsCssValue for font_weight::T {
fn convert(&self, nscssvalue: &mut nsCSSValue) {
nscssvalue.set_integer(*self as i32)
fn convert(self, nscssvalue: &mut nsCSSValue) {
nscssvalue.set_integer(self as i32)
}
}
@ -41,8 +42,8 @@ macro_rules! map_enum {
) => {
$(
impl ToNsCssValue for $prop::T {
fn convert(&self, nscssvalue: &mut nsCSSValue) {
nscssvalue.set_enum(match *self {
fn convert(self, nscssvalue: &mut nsCSSValue) {
nscssvalue.set_enum(match self {
$( $prop::T::$servo => structs::$gecko as i32, )+
})
}
@ -72,7 +73,7 @@ map_enum! {
}
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| {
acc + match *src {
// Each format hint takes one position in the array of mSrc.
@ -85,15 +86,15 @@ impl ToNsCssValue for Vec<Source> {
macro_rules! next { () => {
target_srcs.next().expect("Length of target_srcs should be enough")
} }
for src in self.iter() {
match *src {
Source::Url(ref url) => {
for src in self.into_iter() {
match src {
Source::Url(url) => {
next!().set_url(&url.url);
for hint in url.format_hints.iter() {
next!().set_font_format(&hint);
}
}
Source::Local(ref family) => {
Source::Local(family) => {
next!().set_local_font(&family.name);
}
}
@ -103,7 +104,7 @@ impl ToNsCssValue for Vec<Source> {
}
impl ToNsCssValue for Vec<UnicodeRange> {
fn convert(&self, nscssvalue: &mut nsCSSValue) {
fn convert(self, nscssvalue: &mut nsCSSValue) {
let target_ranges = nscssvalue
.set_array((self.len() * 2) as i32)
.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
pub type CounterStyleDescriptors = [nsCSSValue; nsCSSCounterDesc::eCSSCounterDesc_COUNT as usize];
impl ToNsCssValue for counter_style::System {
fn convert(&self, nscssvalue: &mut nsCSSValue) {
fn convert(self, nscssvalue: &mut nsCSSValue) {
use counter_style::System::*;
match *self {
match self {
Cyclic => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_CYCLIC 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),
@ -154,48 +180,48 @@ impl ToNsCssValue for counter_style::System {
let mut b = nsCSSValue::null();
a.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_FIXED as i32);
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 b = nsCSSValue::null();
a.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_EXTENDS as i32);
b.set_string_from_atom(&other.0);
//nscssvalue.set_pair(a, b); // FIXME: add bindings for nsCSSValue::SetPairValue
b.set_atom_ident(other.0);
nscssvalue.set_pair(&a, &b);
}
}
}
}
impl ToNsCssValue for counter_style::Negative {
fn convert(&self, nscssvalue: &mut nsCSSValue) {
if let Some(ref second) = self.1 {
fn convert(self, nscssvalue: &mut nsCSSValue) {
if let Some(second) = self.1 {
let mut a = nsCSSValue::null();
let mut b = nsCSSValue::null();
a.set_from(&self.0);
a.set_from(self.0);
b.set_from(second);
//nscssvalue.set_pair(a, b); // FIXME: add bindings for nsCSSValue::SetPairValue
nscssvalue.set_pair(&a, &b);
} else {
nscssvalue.set_from(&self.0)
nscssvalue.set_from(self.0)
}
}
}
impl ToNsCssValue for counter_style::Symbol {
fn convert(&self, nscssvalue: &mut nsCSSValue) {
match *self {
counter_style::Symbol::String(ref s) => nscssvalue.set_string(s),
counter_style::Symbol::Ident(ref s) => nscssvalue.set_ident(s),
fn convert(self, nscssvalue: &mut nsCSSValue) {
match self {
counter_style::Symbol::String(s) => nscssvalue.set_string(&s),
counter_style::Symbol::Ident(s) => nscssvalue.set_ident(&s),
}
}
}
impl ToNsCssValue for counter_style::Ranges {
fn convert(&self, _nscssvalue: &mut nsCSSValue) {
fn convert(self, nscssvalue: &mut nsCSSValue) {
if self.0.is_empty() {
//nscssvalue.set_auto(); // FIXME: add bindings for nsCSSValue::SetAutoValue
nscssvalue.set_auto();
} 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) {
if let Some(finite) = bound {
nscssvalue.set_integer(finite)
@ -207,52 +233,59 @@ impl ToNsCssValue for counter_style::Ranges {
let mut end = nsCSSValue::null();
set_bound(range.start, &mut start);
set_bound(range.end, &mut end);
// FIXME: add bindings for nsCSSValuePairList
}
(start, end)
}));
}
}
}
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 pad_with = nsCSSValue::null();
min_length.set_integer(self.0 as i32);
pad_with.set_from(&self.1);
// FIXME: add bindings for nsCSSValue::SetPairValue
//nscssvalue.set_pair(min_length, pad_with);
pad_with.set_from(self.1);
nscssvalue.set_pair(&min_length, &pad_with);
}
}
impl ToNsCssValue for counter_style::Fallback {
fn convert(&self, nscssvalue: &mut nsCSSValue) {
nscssvalue.set_ident_from_atom(&self.0 .0)
fn convert(self, nscssvalue: &mut nsCSSValue) {
nscssvalue.set_atom_ident(self.0 .0)
}
}
impl ToNsCssValue for counter_style::Symbols {
fn convert(&self, _nscssvalue: &mut nsCSSValue) {
debug_assert!(!self.0.is_empty());
// FIXME: add bindings for nsCSSValueList
fn convert(self, nscssvalue: &mut nsCSSValue) {
nscssvalue.set_list(self.0.into_iter().map(|item| {
let mut value = nsCSSValue::null();
value.set_from(item);
value
}));
}
}
impl ToNsCssValue for counter_style::AdditiveSymbols {
fn convert(&self, _nscssvalue: &mut nsCSSValue) {
debug_assert!(!self.0.is_empty());
// FIXME: add bindings for nsCSSValuePairList
fn convert(self, nscssvalue: &mut nsCSSValue) {
nscssvalue.set_pair_list(self.0.into_iter().map(|tuple| {
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 {
fn convert(&self, nscssvalue: &mut nsCSSValue) {
fn convert(self, nscssvalue: &mut nsCSSValue) {
use counter_style::SpeakAs::*;
match *self {
Auto => {} //nscssvalue.set_auto(), // FIXME: add bindings for nsCSSValue::SetAutoValue
match self {
Auto => nscssvalue.set_auto(),
Bullets => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SPEAKAS_BULLETS 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),
Other(ref other) => nscssvalue.set_ident_from_atom(&other.0),
Other(other) => nscssvalue.set_atom_ident(other.0),
}
}
}

Просмотреть файл

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

Просмотреть файл

@ -6,6 +6,7 @@
use app_units::Au;
use gecko_bindings::bindings;
use gecko_bindings::structs;
use gecko_bindings::structs::{nsCSSValue, nsCSSUnit};
use gecko_bindings::structs::{nsCSSValue_Array, nscolor};
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
///
/// This method requires the current value to be null.
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) {
@ -175,7 +191,7 @@ impl nsCSSValue {
}
/// 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)
}
@ -198,6 +214,52 @@ impl nsCSSValue {
*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 {
@ -249,5 +311,5 @@ impl IndexMut<usize> for nsCSSValue_Array {
/// Generic conversion to nsCSSValue
pub trait ToNsCssValue {
/// Convert
fn convert(&self, nscssvalue: &mut nsCSSValue);
fn convert(self, nscssvalue: &mut nsCSSValue);
}

Просмотреть файл

@ -255,6 +255,8 @@ macro_rules! impl_refcount {
impl_refcount!(::gecko_bindings::structs::nsCSSFontFaceRule,
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.
//

Просмотреть файл

@ -198,7 +198,7 @@ impl fmt::Display for WeakAtom {
impl Atom {
/// 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 ret = callback(&atom);
mem::forget(atom);

Просмотреть файл

@ -2987,29 +2987,12 @@ fn static_assert() {
}
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;
<%
keyword = data.longhands_by_name["list-style-type"].keyword
# The first four are @counter-styles
# 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
use values::generics::CounterStyleOrNone;
let name = match v.0 {
CounterStyleOrNone::None_ => atom!("none"),
CounterStyleOrNone::Name(name) => name.0,
};
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) {
use properties::longhands::content::computed_value::T;
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::bindings::Gecko_ClearAndResizeStyleContents;
@ -4086,6 +4070,13 @@ clip-path
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 {
T::none |
T::normal => {
@ -4147,8 +4138,7 @@ clip-path
}
let mut array = unsafe { &mut **self.gecko.mContents[i].mContent.mCounters.as_mut() };
array[0].set_string(&name);
// When we support <custom-ident> values for list-style-type this will need to be updated
array[1].set_atom_ident(style.to_css_string().into());
set_counter_style(style, &mut array[1]);
}
ContentItem::Counters(name, sep, style) => {
unsafe {
@ -4158,8 +4148,7 @@ clip-path
let mut array = unsafe { &mut **self.gecko.mContents[i].mContent.mCounters.as_mut() };
array[0].set_string(&name);
array[1].set_string(&sep);
// When we support <custom-ident> values for list-style-type this will need to be updated
array[2].set_atom_ident(style.to_css_string().into());
set_counter_style(style, &mut array[2]);
}
ContentItem::Url(ref url) => {
unsafe {

Просмотреть файл

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

Просмотреть файл

@ -721,7 +721,7 @@ ${helpers.single_keyword_system("font-variant-caps",
// XXXManishearth handle quirks mode
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
}) };

Просмотреть файл

@ -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.
//
// [1]: http://dev.w3.org/csswg/css-counter-styles/
${helpers.single_keyword("list-style-type", """
disc none circle square decimal disclosure-open disclosure-closed lower-alpha upper-alpha
""", extra_servo_values="""arabic-indic bengali cambodian cjk-decimal devanagari
gujarati gurmukhi kannada khmer lao malayalam mongolian
myanmar oriya persian telugu thai tibetan cjk-earthly-branch
cjk-heavenly-stem lower-greek hiragana hiragana-iroha katakana
katakana-iroha""",
extra_gecko_values="""japanese-informal japanese-formal korean-hangul-formal
korean-hanja-formal korean-hanja-informal simp-chinese-informal simp-chinese-formal
trad-chinese-informal trad-chinese-formal ethiopic-numeric upper-roman lower-roman
""",
gecko_constant_prefix="NS_STYLE_LIST_STYLE",
needs_conversion="True",
animation_value_type="none",
spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type")}
% if product == "servo":
${helpers.single_keyword("list-style-type", """
disc none circle square decimal disclosure-open disclosure-closed lower-alpha upper-alpha
arabic-indic bengali cambodian cjk-decimal devanagari gujarati gurmukhi kannada khmer lao
malayalam mongolian myanmar oriya persian telugu thai tibetan cjk-earthly-branch
cjk-heavenly-stem lower-greek hiragana hiragana-iroha katakana katakana-iroha""",
needs_conversion="True",
animation_value_type="none",
spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type")}
% else:
<%helpers:longhand name="list-style-type" animation_value_type="none"
spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type">
use std::fmt;
use style_traits::ToCss;
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"
boxed="${product == 'gecko'}"

Просмотреть файл

@ -25,14 +25,6 @@
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 let Ok(value) = input.try(|input| list_style_image::parse(context, input)) {
image = Some(value);
@ -48,11 +40,31 @@
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
}
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`,
// 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.
@ -61,14 +73,14 @@
Ok(Longhands {
list_style_position: position,
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)) => {
Ok(Longhands {
list_style_position: position,
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) => {
@ -82,7 +94,7 @@
Ok(Longhands {
list_style_position: position,
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) => {

Просмотреть файл

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

Просмотреть файл

@ -14,6 +14,8 @@ use dom::{AnimationRules, TElement};
use element_state::ElementState;
use error_reporting::RustLogReporter;
use font_metrics::FontMetricsProvider;
#[cfg(feature = "gecko")]
use gecko_bindings::structs::nsIAtom;
use keyframes::KeyframesAnimation;
use media_queries::Device;
use pdqsort::sort_by;
@ -41,7 +43,10 @@ use std::hash::Hash;
use std::marker::PhantomData;
use style_traits::viewport::ViewportConstraints;
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")]
use stylesheets::NestedRulesResult;
use thread_state;
@ -168,33 +173,44 @@ pub struct Stylist {
/// This struct holds data which user of Stylist may want to extract
/// from stylesheets which can be done at the same time as updating.
#[cfg(feature = "gecko")]
pub struct ExtraStyleData<'a> {
/// A list of effective font-face rules and their origin.
#[cfg(feature = "gecko")]
pub font_faces: &'a mut Vec<(Arc<Locked<FontFaceRule>>, Origin)>,
#[allow(missing_docs)]
#[cfg(feature = "servo")]
pub marker: PhantomData<&'a usize>,
/// A map of effective counter-style rules.
pub counter_styles: &'a mut HashMap<Atom, Arc<Locked<CounterStyleRule>>>,
}
#[cfg(feature = "gecko")]
impl<'a> ExtraStyleData<'a> {
/// Clear the internal @font-face rule list.
fn clear_font_faces(&mut self) {
/// Clear the internal data.
fn clear(&mut self) {
self.font_faces.clear();
self.counter_styles.clear();
}
/// Add the given @font-face rule.
fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, origin: 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")]
impl<'a> ExtraStyleData<'a> {
fn clear_font_faces(&mut self) {}
fn add_font_face(&mut self, _: &Arc<Locked<FontFaceRule>>, _: Origin) {}
fn clear(&mut self) {}
}
impl Stylist {
@ -343,7 +359,7 @@ impl Stylist {
self.pseudos_map.insert(pseudo, PerPseudoElementSelectorMap::new());
});
extra_data.clear_font_faces();
extra_data.clear();
if let Some(ua_stylesheets) = ua_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);
}
}
#[cfg(feature = "gecko")]
CssRule::FontFace(ref rule) => {
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.
_ => {}
}

Просмотреть файл

@ -5,9 +5,13 @@
//! Generic types that share their serialization implementations
//! for both specified and computed values.
use counter_style::parse_counter_style_name;
use cssparser::Parser;
use euclid::size::Size2D;
use parser::{Parse, ParserContext};
use std::fmt;
use style_traits::ToCss;
use super::CustomIdent;
use super::HasViewportPercentage;
use super::computed::{Context, ToComputedValue};
@ -75,3 +79,49 @@ impl<L: ToComputedValue> ToComputedValue for BorderRadiusSize<L> {
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),
}
}
}

Просмотреть файл

@ -61,7 +61,8 @@ use style::gecko_bindings::structs;
use style::gecko_bindings::structs::{CSSPseudoElementType, CompositeOperation};
use style::gecko_bindings::structs::{RawServoStyleRule, ServoStyleSheet};
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::RawGeckoPresContextOwned;
use style::gecko_bindings::structs::ServoElementSnapshotTable;
@ -871,19 +872,28 @@ impl_group_rule_funcs! { (Document, DocumentRule, RawServoDocumentRule),
to_css: Servo_DocumentRule_GetCssText,
}
#[no_mangle]
pub extern "C" fn Servo_CssRules_GetFontFaceRuleAt(rules: ServoCssRulesBorrowed, index: u32)
-> *mut nsCSSFontFaceRule
{
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let rules = Locked::<CssRules>::as_arc(&rules).read_with(&guard);
match rules.0[index as usize] {
CssRule::FontFace(ref rule) => rule.read_with(&guard).get(),
_ => unreachable!("Servo_CssRules_GetFontFaceRuleAt should only be called on a FontFace rule"),
macro_rules! impl_getter_for_embedded_rule {
($getter:ident: $name:ident -> $ty:ty) => {
#[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 rules = Locked::<CssRules>::as_arc(&rules).read_with(&guard);
match rules.0[index as usize] {
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]
pub extern "C" fn Servo_StyleRule_GetStyle(rule: RawServoStyleRuleBorrowed) -> RawServoDeclarationBlockStrong {
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]
pub extern "C" fn Servo_StyleSet_ResolveForDeclarations(raw_data: RawServoStyleSetBorrowed,
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,
local_name: *mut nsIAtom) -> bool {
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]