Auto merge of #20786 - emilio:gecko-sync, r=emilio

style: Sync changes from mozilla-central.

See individual commits for details.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20786)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2018-05-19 07:48:36 -04:00 committed by GitHub
commit b536774fbf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 718 additions and 523 deletions

View file

@ -54,7 +54,7 @@ use style::logical_geometry::Direction;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::selector_parser::{PseudoElement, RestyleDamage}; use style::selector_parser::{PseudoElement, RestyleDamage};
use style::servo::restyle_damage::ServoRestyleDamage; use style::servo::restyle_damage::ServoRestyleDamage;
use style::values::computed::counters::ContentItem; use style::values::generics::counters::ContentItem;
use style::values::generics::url::UrlOrNone as ImageUrlOrNone; use style::values::generics::url::UrlOrNone as ImageUrlOrNone;
use table::TableFlow; use table::TableFlow;
use table_caption::TableCaptionFlow; use table_caption::TableCaptionFlow;

View file

@ -66,7 +66,7 @@ use style::values::computed::Gradient;
use style::values::computed::effects::SimpleShadow; use style::values::computed::effects::SimpleShadow;
use style::values::generics::background::BackgroundSize; use style::values::generics::background::BackgroundSize;
use style::values::generics::image::{GradientKind, Image, PaintWorklet}; use style::values::generics::image::{GradientKind, Image, PaintWorklet};
use style::values::generics::pointing::Cursor; use style::values::generics::ui::Cursor;
use style_traits::CSSPixel; use style_traits::CSSPixel;
use style_traits::ToCss; use style_traits::ToCss;
use style_traits::cursor::CursorKind; use style_traits::cursor::CursorKind;
@ -3012,8 +3012,8 @@ impl ComputedValuesCursorUtility for ComputedValues {
#[inline] #[inline]
fn get_cursor(&self, default_cursor: CursorKind) -> Option<CursorKind> { fn get_cursor(&self, default_cursor: CursorKind) -> Option<CursorKind> {
match ( match (
self.get_pointing().pointer_events, self.get_inheritedui().pointer_events,
&self.get_pointing().cursor, &self.get_inheritedui().cursor,
) { ) {
(PointerEvents::None, _) => None, (PointerEvents::None, _) => None,
(PointerEvents::Auto, &Cursor { keyword: CursorKind::Auto, .. }) => Some(default_cursor), (PointerEvents::Auto, &Cursor { keyword: CursorKind::Auto, .. }) => Some(default_cursor),

View file

@ -51,6 +51,8 @@ impl ToLayout for Filter {
GenericFilter::Sepia(amount) => wr::FilterOp::Sepia(amount.0), GenericFilter::Sepia(amount) => wr::FilterOp::Sepia(amount.0),
// Statically check that DropShadow is impossible. // Statically check that DropShadow is impossible.
GenericFilter::DropShadow(ref shadow) => match *shadow {}, GenericFilter::DropShadow(ref shadow) => match *shadow {},
// Statically check that Url is impossible.
GenericFilter::Url(ref url) => match *url {},
} }
} }
} }

View file

@ -20,7 +20,7 @@ use style::computed_values::list_style_type::T as ListStyleType;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::selector_parser::RestyleDamage; use style::selector_parser::RestyleDamage;
use style::servo::restyle_damage::ServoRestyleDamage; use style::servo::restyle_damage::ServoRestyleDamage;
use style::values::computed::counters::ContentItem; use style::values::generics::counters::ContentItem;
use text::TextRunScanner; use text::TextRunScanner;
use traversal::InorderFlowTraversal; use traversal::InorderFlowTraversal;
@ -240,6 +240,9 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> {
self.traversal.quote -= 1 self.traversal.quote -= 1
} }
} }
GeneratedContentInfo::ContentItem(ContentItem::Url(..)) => {
unreachable!("Servo doesn't parse content: url(..) yet")
}
} }
}; };

View file

@ -36,7 +36,8 @@ use script_layout_interface::wrapper_traits::{ThreadSafeLayoutElement, ThreadSaf
use script_layout_interface::wrapper_traits::GetLayoutData; use script_layout_interface::wrapper_traits::GetLayoutData;
use style::dom::{NodeInfo, TNode}; use style::dom::{NodeInfo, TNode};
use style::selector_parser::RestyleDamage; use style::selector_parser::RestyleDamage;
use style::values::computed::counters::{Content, ContentItem}; use style::values::computed::counters::ContentItem;
use style::values::generics::counters::Content;
pub trait LayoutNodeLayoutData { pub trait LayoutNodeLayoutData {
/// Similar to borrow_data*, but returns the full PersistentLayoutData rather /// Similar to borrow_data*, but returns the full PersistentLayoutData rather
@ -113,12 +114,12 @@ impl<T: ThreadSafeLayoutNode> ThreadSafeLayoutNodeHelpers for T {
if self.get_pseudo_element_type().is_replaced_content() { if self.get_pseudo_element_type().is_replaced_content() {
let style = self.as_element().unwrap().resolved_style(); let style = self.as_element().unwrap().resolved_style();
return match style.as_ref().get_counters().content { return TextContent::GeneratedContent(
Content::Items(ref value) if !value.is_empty() => { match style.as_ref().get_counters().content {
TextContent::GeneratedContent((*value).to_vec()) Content::Items(ref value) => value.to_vec(),
_ => vec![],
} }
_ => TextContent::GeneratedContent(vec![]), );
};
} }
TextContent::Text(self.node_text_content().into_boxed_str()) TextContent::Text(self.node_text_content().into_boxed_str())

View file

@ -145,11 +145,11 @@ impl nsStyleImage {
match image { match image {
GenericImage::Gradient(boxed_gradient) => self.set_gradient(*boxed_gradient), GenericImage::Gradient(boxed_gradient) => self.set_gradient(*boxed_gradient),
GenericImage::Url(ref url) => unsafe { GenericImage::Url(ref url) => unsafe {
bindings::Gecko_SetLayerImageImageValue(self, url.image_value.get()); bindings::Gecko_SetLayerImageImageValue(self, url.0.image_value.get());
}, },
GenericImage::Rect(ref image_rect) => { GenericImage::Rect(ref image_rect) => {
unsafe { unsafe {
bindings::Gecko_SetLayerImageImageValue(self, image_rect.url.image_value.get()); bindings::Gecko_SetLayerImageImageValue(self, image_rect.url.0.image_value.get());
bindings::Gecko_InitializeImageCropRect(self); bindings::Gecko_InitializeImageCropRect(self);
// Set CropRect // Set CropRect

View file

@ -7,7 +7,7 @@
use app_units::AU_PER_PX; use app_units::AU_PER_PX;
use app_units::Au; use app_units::Au;
use context::QuirksMode; use context::QuirksMode;
use cssparser::{BasicParseErrorKind, Parser, Token, RGBA}; use cssparser::{BasicParseErrorKind, Parser, RGBA};
use euclid::Size2D; use euclid::Size2D;
use euclid::TypedScale; use euclid::TypedScale;
use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor}; use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
@ -32,7 +32,7 @@ use stylesheets::Origin;
use values::{serialize_atom_identifier, CSSFloat, CustomIdent, KeyframesName}; use values::{serialize_atom_identifier, CSSFloat, CustomIdent, KeyframesName};
use values::computed::{self, ToComputedValue}; use values::computed::{self, ToComputedValue};
use values::computed::font::FontSize; use values::computed::font::FontSize;
use values::specified::{Integer, Length, Number}; use values::specified::{Integer, Length, Number, Resolution};
/// The `Device` in Gecko wraps a pres context, has a default values computed, /// The `Device` in Gecko wraps a pres context, has a default values computed,
/// and contains all the viewport rule state. /// and contains all the viewport rule state.
@ -286,53 +286,6 @@ impl PartialEq for Expression {
} }
} }
/// A resolution.
#[derive(Clone, Debug, PartialEq, ToCss)]
pub enum Resolution {
/// Dots per inch.
#[css(dimension)]
Dpi(CSSFloat),
/// Dots per pixel.
#[css(dimension)]
Dppx(CSSFloat),
/// Dots per centimeter.
#[css(dimension)]
Dpcm(CSSFloat),
}
impl Resolution {
fn to_dpi(&self) -> CSSFloat {
match *self {
Resolution::Dpi(f) => f,
Resolution::Dppx(f) => f * 96.0,
Resolution::Dpcm(f) => f * 2.54,
}
}
fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let location = input.current_source_location();
let (value, unit) = match *input.next()? {
Token::Dimension {
value, ref unit, ..
} => (value, unit),
ref t => return Err(location.new_unexpected_token_error(t.clone())),
};
if value <= 0. {
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
(match_ignore_ascii_case! { &unit,
"dpi" => Ok(Resolution::Dpi(value)),
"dppx" => Ok(Resolution::Dppx(value)),
"dpcm" => Ok(Resolution::Dpcm(value)),
_ => Err(())
}).map_err(|()| {
location.new_custom_error(StyleParseErrorKind::UnexpectedDimension(unit.clone()))
})
}
}
/// A value found or expected in a media expression. /// A value found or expected in a media expression.
/// ///
/// FIXME(emilio): How should calc() serialize in the Number / Integer / /// FIXME(emilio): How should calc() serialize in the Number / Integer /
@ -535,7 +488,7 @@ fn parse_feature_value<'i, 't>(
MediaExpressionValue::IntRatio(a.value() as u32, b.value() as u32) MediaExpressionValue::IntRatio(a.value() as u32, b.value() as u32)
}, },
nsMediaFeature_ValueType::eResolution => { nsMediaFeature_ValueType::eResolution => {
MediaExpressionValue::Resolution(Resolution::parse(input)?) MediaExpressionValue::Resolution(Resolution::parse(context, input)?)
}, },
nsMediaFeature_ValueType::eEnumerated => { nsMediaFeature_ValueType::eEnumerated => {
let location = input.current_source_location(); let location = input.current_source_location();

View file

@ -216,11 +216,7 @@ impl PseudoElement {
None None
} }
/// Constructs an atom from a string of text, and whether we're in a /// Constructs a pseudo-element from a string of text.
/// user-agent stylesheet.
///
/// If we're not in a user-agent stylesheet, we will never parse anonymous
/// box pseudo-elements.
/// ///
/// Returns `None` if the pseudo-element is not recognised. /// Returns `None` if the pseudo-element is not recognised.
#[inline] #[inline]
@ -234,6 +230,10 @@ impl PseudoElement {
return Some(${pseudo_element_variant(pseudo)}) return Some(${pseudo_element_variant(pseudo)})
} }
% endfor % endfor
// Alias "-moz-selection" to "selection" at parse time.
"-moz-selection" => {
return Some(PseudoElement::Selection);
}
_ => { _ => {
// FIXME: -moz-tree check should probably be // FIXME: -moz-tree check should probably be
// ascii-case-insensitive. // ascii-case-insensitive.

View file

@ -12,10 +12,13 @@ use gecko_bindings::structs::root::{RustString, nsStyleImageRequest};
use gecko_bindings::structs::root::mozilla::css::{ImageValue, URLValue}; use gecko_bindings::structs::root::mozilla::css::{ImageValue, URLValue};
use gecko_bindings::sugar::refptr::RefPtr; use gecko_bindings::sugar::refptr::RefPtr;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use nsstring::nsCString;
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use servo_arc::{Arc, RawOffsetArc}; use servo_arc::{Arc, RawOffsetArc};
use std::fmt::{self, Write};
use std::mem; use std::mem;
use style_traits::ParseError; use style_traits::{CssWriter, ParseError, ToCss};
use values::computed::{Context, ToComputedValue};
/// A CSS url() value for gecko. /// A CSS url() value for gecko.
#[css(function = "url")] #[css(function = "url")]
@ -70,10 +73,8 @@ impl CssUrl {
self.as_str().chars().next().map_or(false, |c| c == '#') self.as_str().chars().next().map_or(false, |c| c == '#')
} }
/// Return the resolved url as string, or the empty string if it's invalid. /// Return the unresolved url as string, or the empty string if it's
/// /// invalid.
/// FIXME(bholley): This returns the unresolved URL while the servo version
/// returns the resolved URL.
pub fn as_str(&self) -> &str { pub fn as_str(&self) -> &str {
&*self.serialization &*self.serialization
} }
@ -121,7 +122,7 @@ impl MallocSizeOf for CssUrl {
} }
/// A specified url() value for general usage. /// A specified url() value for general usage.
#[derive(Clone, Debug, SpecifiedValueInfo, ToComputedValue, ToCss)] #[derive(Clone, Debug, SpecifiedValueInfo, ToCss)]
pub struct SpecifiedUrl { pub struct SpecifiedUrl {
/// The specified url value. /// The specified url value.
pub url: CssUrl, pub url: CssUrl,
@ -139,15 +140,11 @@ impl SpecifiedUrl {
debug_assert!(!ptr.is_null()); debug_assert!(!ptr.is_null());
RefPtr::from_addrefed(ptr) RefPtr::from_addrefed(ptr)
}; };
SpecifiedUrl { url, url_value } Self { url, url_value }
}
/// Convert from URLValueData to SpecifiedUrl.
pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
CssUrl::from_url_value_data(url).map(Self::from_css_url)
} }
} }
impl PartialEq for SpecifiedUrl { impl PartialEq for SpecifiedUrl {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.url.eq(&other.url) self.url.eq(&other.url)
@ -179,7 +176,7 @@ impl MallocSizeOf for SpecifiedUrl {
/// A specified url() value for image. /// A specified url() value for image.
/// ///
/// This exists so that we can construct `ImageValue` and reuse it. /// This exists so that we can construct `ImageValue` and reuse it.
#[derive(Clone, Debug, SpecifiedValueInfo, ToComputedValue, ToCss)] #[derive(Clone, Debug, SpecifiedValueInfo, ToCss)]
pub struct SpecifiedImageUrl { pub struct SpecifiedImageUrl {
/// The specified url value. /// The specified url value.
pub url: CssUrl, pub url: CssUrl,
@ -190,16 +187,6 @@ pub struct SpecifiedImageUrl {
} }
impl SpecifiedImageUrl { impl SpecifiedImageUrl {
fn from_css_url(url: CssUrl) -> Self {
let image_value = unsafe {
let ptr = bindings::Gecko_ImageValue_Create(url.for_ffi());
// We do not expect Gecko_ImageValue_Create returns null.
debug_assert!(!ptr.is_null());
RefPtr::from_addrefed(ptr)
};
SpecifiedImageUrl { url, image_value }
}
/// Parse a URL from a string value. See SpecifiedUrl::parse_from_string. /// Parse a URL from a string value. See SpecifiedUrl::parse_from_string.
pub fn parse_from_string<'a>( pub fn parse_from_string<'a>(
url: String, url: String,
@ -208,20 +195,14 @@ impl SpecifiedImageUrl {
CssUrl::parse_from_string(url, context).map(Self::from_css_url) CssUrl::parse_from_string(url, context).map(Self::from_css_url)
} }
/// Convert from URLValueData to SpecifiedUrl. fn from_css_url(url: CssUrl) -> Self {
pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> { let image_value = unsafe {
CssUrl::from_url_value_data(url).map(Self::from_css_url) let ptr = bindings::Gecko_ImageValue_Create(url.for_ffi());
} // We do not expect Gecko_ImageValue_Create returns null.
debug_assert!(!ptr.is_null());
/// Convert from nsStyleImageRequest to SpecifiedUrl. RefPtr::from_addrefed(ptr)
pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Result<Self, ()> { };
if image_request.mImageValue.mRawPtr.is_null() { Self { url, image_value }
return Err(());
}
let image_value = image_request.mImageValue.mRawPtr.as_ref().unwrap();
let url_value_data = &image_value._base;
Self::from_url_value_data(url_value_data)
} }
} }
@ -253,7 +234,104 @@ impl MallocSizeOf for SpecifiedImageUrl {
} }
} }
impl ToComputedValue for SpecifiedUrl {
type ComputedValue = ComputedUrl;
#[inline]
fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
ComputedUrl(self.clone())
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
computed.0.clone()
}
}
impl ToComputedValue for SpecifiedImageUrl {
type ComputedValue = ComputedImageUrl;
#[inline]
fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
ComputedImageUrl(self.clone())
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
computed.0.clone()
}
}
fn serialize_computed_url<W>(
url_value_data: &URLValueData,
dest: &mut CssWriter<W>,
) -> fmt::Result
where
W: Write,
{
dest.write_str("url(")?;
unsafe {
let mut string = nsCString::new();
bindings::Gecko_GetComputedURLSpec(url_value_data, &mut string);
string.as_str_unchecked().to_css(dest)?;
}
dest.write_char(')')
}
/// The computed value of a CSS `url()`. /// The computed value of a CSS `url()`.
pub type ComputedUrl = SpecifiedUrl; ///
/// The only difference between specified and computed URLs is the
/// serialization.
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)]
pub struct ComputedUrl(pub SpecifiedUrl);
impl ToCss for ComputedUrl {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write
{
serialize_computed_url(&self.0.url_value._base, dest)
}
}
impl ComputedUrl {
/// Convert from URLValueData to ComputedUrl.
pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
Ok(ComputedUrl(
SpecifiedUrl::from_css_url(CssUrl::from_url_value_data(url)?)
))
}
}
/// The computed value of a CSS `url()` for image. /// The computed value of a CSS `url()` for image.
pub type ComputedImageUrl = SpecifiedImageUrl; #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)]
pub struct ComputedImageUrl(pub SpecifiedImageUrl);
impl ToCss for ComputedImageUrl {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write
{
serialize_computed_url(&self.0.image_value._base, dest)
}
}
impl ComputedImageUrl {
/// Convert from URLValueData to SpecifiedUrl.
pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
Ok(ComputedImageUrl(
SpecifiedImageUrl::from_css_url(CssUrl::from_url_value_data(url)?)
))
}
/// Convert from nsStyleImageReques to ComputedImageUrl.
pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Result<Self, ()> {
if image_request.mImageValue.mRawPtr.is_null() {
return Err(());
}
let image_value = image_request.mImageValue.mRawPtr.as_ref().unwrap();
let url_value_data = &image_value._base;
Self::from_url_value_data(url_value_data)
}
}

View file

@ -7,7 +7,7 @@
use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor}; use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
use gecko_bindings::structs::{nscolor, StyleComplexColor}; use gecko_bindings::structs::{nscolor, StyleComplexColor};
use values::computed::Color as ComputedColor; use values::computed::Color as ComputedColor;
use values::generics::pointing::CaretColor; use values::generics::ui::CaretColor;
impl From<nscolor> for StyleComplexColor { impl From<nscolor> for StyleComplexColor {
fn from(other: nscolor) -> Self { fn from(other: nscolor) -> Self {

View file

@ -4,7 +4,7 @@
import re import re
PHYSICAL_SIDES = ["top", "left", "bottom", "right"] PHYSICAL_SIDES = ["top", "right", "bottom", "left"]
LOGICAL_SIDES = ["block-start", "block-end", "inline-start", "inline-end"] LOGICAL_SIDES = ["block-start", "block-end", "inline-start", "inline-end"]
PHYSICAL_SIZES = ["width", "height"] PHYSICAL_SIZES = ["width", "height"]
LOGICAL_SIZES = ["block-size", "inline-size"] LOGICAL_SIZES = ["block-size", "inline-size"]

View file

@ -10,6 +10,7 @@
%> %>
<%namespace name="helpers" file="/helpers.mako.rs" /> <%namespace name="helpers" file="/helpers.mako.rs" />
use Atom;
use app_units::Au; use app_units::Au;
use custom_properties::CustomPropertiesMap; use custom_properties::CustomPropertiesMap;
use gecko_bindings::bindings; use gecko_bindings::bindings;
@ -60,7 +61,7 @@ use std::mem::{forget, uninitialized, transmute, zeroed};
use std::{cmp, ops, ptr}; use std::{cmp, ops, ptr};
use values::{self, CustomIdent, Either, KeyframesName, None_}; use values::{self, CustomIdent, Either, KeyframesName, None_};
use values::computed::{NonNegativeLength, ToComputedValue, Percentage}; use values::computed::{NonNegativeLength, ToComputedValue, Percentage};
use values::computed::font::{FontSize, SingleFontFamily}; use values::computed::font::FontSize;
use values::computed::effects::{BoxShadow, Filter, SimpleShadow}; use values::computed::effects::{BoxShadow, Filter, SimpleShadow};
use values::computed::outline::OutlineStyle; use values::computed::outline::OutlineStyle;
use values::generics::column::ColumnCount; use values::generics::column::ColumnCount;
@ -126,8 +127,6 @@ impl ComputedValues {
} }
pub fn pseudo(&self) -> Option<PseudoElement> { pub fn pseudo(&self) -> Option<PseudoElement> {
use string_cache::Atom;
let atom = (self.0).mPseudoTag.mRawPtr; let atom = (self.0).mPseudoTag.mRawPtr;
if atom.is_null() { if atom.is_null() {
return None; return None;
@ -698,7 +697,7 @@ def set_gecko_property(ffi_name, expr):
} }
SVGPaintKind::PaintServer(url) => { SVGPaintKind::PaintServer(url) => {
unsafe { unsafe {
bindings::Gecko_nsStyleSVGPaint_SetURLValue(paint, url.url_value.get()); bindings::Gecko_nsStyleSVGPaint_SetURLValue(paint, url.0.url_value.get());
} }
} }
SVGPaintKind::Color(color) => { SVGPaintKind::Color(color) => {
@ -738,8 +737,8 @@ def set_gecko_property(ffi_name, expr):
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
use values::computed::url::ComputedUrl;
use values::generics::svg::{SVGPaint, SVGPaintKind}; use values::generics::svg::{SVGPaint, SVGPaintKind};
use values::specified::url::SpecifiedUrl;
use self::structs::nsStyleSVGPaintType; use self::structs::nsStyleSVGPaintType;
use self::structs::nsStyleSVGFallbackType; use self::structs::nsStyleSVGFallbackType;
let ref paint = ${get_gecko_property(gecko_ffi_name)}; let ref paint = ${get_gecko_property(gecko_ffi_name)};
@ -761,7 +760,7 @@ def set_gecko_property(ffi_name, expr):
nsStyleSVGPaintType::eStyleSVGPaintType_Server => { nsStyleSVGPaintType::eStyleSVGPaintType_Server => {
unsafe { unsafe {
SVGPaintKind::PaintServer( SVGPaintKind::PaintServer(
SpecifiedUrl::from_url_value_data( ComputedUrl::from_url_value_data(
&(**paint.mPaint.mPaintServer.as_ref())._base &(**paint.mPaint.mPaintServer.as_ref())._base
).unwrap() ).unwrap()
) )
@ -940,7 +939,7 @@ def set_gecko_property(ffi_name, expr):
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
match v { match v {
UrlOrNone::Url(ref url) => { UrlOrNone::Url(ref url) => {
self.gecko.${gecko_ffi_name}.set_move(url.url_value.clone()) self.gecko.${gecko_ffi_name}.set_move(url.0.url_value.clone())
} }
UrlOrNone::None => { UrlOrNone::None => {
unsafe { unsafe {
@ -962,16 +961,18 @@ def set_gecko_property(ffi_name, expr):
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
use values::specified::url::SpecifiedUrl; use values::computed::url::ComputedUrl;
if self.gecko.${gecko_ffi_name}.mRawPtr.is_null() { if self.gecko.${gecko_ffi_name}.mRawPtr.is_null() {
UrlOrNone::none() return UrlOrNone::none()
} else {
unsafe {
let ref gecko_url_value = *self.gecko.${gecko_ffi_name}.mRawPtr;
UrlOrNone::Url(SpecifiedUrl::from_url_value_data(&gecko_url_value._base)
.expect("${gecko_ffi_name} could not convert to SpecifiedUrl"))
} }
unsafe {
let gecko_url_value = &*self.gecko.${gecko_ffi_name}.mRawPtr;
UrlOrNone::Url(
ComputedUrl::from_url_value_data(&gecko_url_value._base)
.expect("${gecko_ffi_name} could not convert to ComputedUrl")
)
} }
} }
</%def> </%def>
@ -1861,7 +1862,6 @@ fn static_assert() {
pub fn clone_${value.name}(&self) -> longhands::${value.name}::computed_value::T { pub fn clone_${value.name}(&self) -> longhands::${value.name}::computed_value::T {
use gecko_bindings::structs::{nsStyleGridLine_kMinLine, nsStyleGridLine_kMaxLine}; use gecko_bindings::structs::{nsStyleGridLine_kMinLine, nsStyleGridLine_kMaxLine};
use string_cache::Atom;
longhands::${value.name}::computed_value::T { longhands::${value.name}::computed_value::T {
is_span: self.gecko.${value.gecko}.mHasSpan, is_span: self.gecko.${value.gecko}.mHasSpan,
@ -2034,7 +2034,6 @@ fn static_assert() {
pub fn clone_grid_template_${kind}(&self) -> longhands::grid_template_${kind}::computed_value::T { pub fn clone_grid_template_${kind}(&self) -> longhands::grid_template_${kind}::computed_value::T {
<% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %> <% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %>
use Atom;
use gecko_bindings::structs::nsTArray; use gecko_bindings::structs::nsTArray;
use nsstring::nsStringRepr; use nsstring::nsStringRepr;
use values::CustomIdent; use values::CustomIdent;
@ -2309,14 +2308,6 @@ fn static_assert() {
self.gecko.mFont.fontlist.mFontlist.mBasePtr.set_move((v.0).0.clone()); self.gecko.mFont.fontlist.mFontlist.mBasePtr.set_move((v.0).0.clone());
} }
pub fn font_family_count(&self) -> usize {
0
}
pub fn font_family_at(&self, _: usize) -> SingleFontFamily {
unimplemented!()
}
pub fn copy_font_family_from(&mut self, other: &Self) { pub fn copy_font_family_from(&mut self, other: &Self) {
unsafe { Gecko_CopyFontFamilyFrom(&mut self.gecko.mFont, &other.gecko.mFont); } unsafe { Gecko_CopyFontFamilyFrom(&mut self.gecko.mFont, &other.gecko.mFont); }
self.gecko.mGenericID = other.gecko.mGenericID; self.gecko.mGenericID = other.gecko.mGenericID;
@ -2335,14 +2326,25 @@ fn static_assert() {
let shared_fontlist = unsafe { fontlist.mFontlist.mBasePtr.to_safe() }; let shared_fontlist = unsafe { fontlist.mFontlist.mBasePtr.to_safe() };
if shared_fontlist.mNames.is_empty() { if shared_fontlist.mNames.is_empty() {
let default = match fontlist.mDefaultFontType { let default = fontlist.mDefaultFontType;
let default = match default {
FontFamilyType::eFamily_serif => { FontFamilyType::eFamily_serif => {
SingleFontFamily::Generic(atom!("serif")) SingleFontFamily::Generic(atom!("serif"))
} }
FontFamilyType::eFamily_sans_serif => { _ => {
// This can break with some combinations of user prefs, see
// bug 1442195 for example. It doesn't really matter in this
// case...
//
// FIXME(emilio): Probably should be storing the whole
// default font name instead though.
debug_assert_eq!(
default,
FontFamilyType::eFamily_sans_serif,
"Default generic should be serif or sans-serif"
);
SingleFontFamily::Generic(atom!("sans-serif")) SingleFontFamily::Generic(atom!("sans-serif"))
} }
_ => panic!("Default generic must be serif or sans-serif"),
}; };
FontFamily(FontFamilyList::new(Box::new([default]))) FontFamily(FontFamilyList::new(Box::new([default])))
} else { } else {
@ -2683,6 +2685,18 @@ fn static_assert() {
} }
} }
#[allow(non_snake_case)]
pub fn reset__x_lang(&mut self, other: &Self) {
self.copy__x_lang_from(other)
}
#[allow(non_snake_case)]
pub fn clone__x_lang(&self) -> longhands::_x_lang::computed_value::T {
longhands::_x_lang::computed_value::T(unsafe {
Atom::from_raw(self.gecko.mLanguage.mRawPtr)
})
}
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn set__x_text_zoom(&mut self, v: longhands::_x_text_zoom::computed_value::T) { pub fn set__x_text_zoom(&mut self, v: longhands::_x_text_zoom::computed_value::T) {
self.gecko.mAllowZoom = v.0; self.gecko.mAllowZoom = v.0;
@ -2699,8 +2713,8 @@ fn static_assert() {
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn reset__x_lang(&mut self, other: &Self) { pub fn clone__x_text_zoom(&self) -> longhands::_x_text_zoom::computed_value::T {
self.copy__x_lang_from(other) longhands::_x_text_zoom::computed_value::T(self.gecko.mAllowZoom)
} }
${impl_simple("_moz_script_level", "mScriptLevel")} ${impl_simple("_moz_script_level", "mScriptLevel")}
@ -2777,7 +2791,6 @@ fn static_assert() {
} }
pub fn clone_font_variant_alternates(&self) -> values::computed::font::FontVariantAlternates { pub fn clone_font_variant_alternates(&self) -> values::computed::font::FontVariantAlternates {
use Atom;
% for value in "normal swash stylistic ornaments annotation styleset character_variant historical".split(): % for value in "normal swash stylistic ornaments annotation styleset character_variant historical".split():
use gecko_bindings::structs::NS_FONT_VARIANT_ALTERNATES_${value.upper()}; use gecko_bindings::structs::NS_FONT_VARIANT_ALTERNATES_${value.upper()};
% endfor % endfor
@ -2833,6 +2846,13 @@ fn static_assert() {
${impl_simple_type_with_conversion("font_variant_east_asian", "mFont.variantEastAsian")} ${impl_simple_type_with_conversion("font_variant_east_asian", "mFont.variantEastAsian")}
${impl_simple_type_with_conversion("font_variant_numeric", "mFont.variantNumeric")} ${impl_simple_type_with_conversion("font_variant_numeric", "mFont.variantNumeric")}
#[allow(non_snake_case)]
pub fn clone__moz_min_font_size_ratio(
&self,
) -> longhands::_moz_min_font_size_ratio::computed_value::T {
Percentage(self.gecko.mMinFontSizeRatio as f32 / 100.)
}
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn set__moz_min_font_size_ratio(&mut self, v: longhands::_moz_min_font_size_ratio::computed_value::T) { pub fn set__moz_min_font_size_ratio(&mut self, v: longhands::_moz_min_font_size_ratio::computed_value::T) {
let scaled = v.0 * 100.; let scaled = v.0 * 100.;
@ -3286,7 +3306,6 @@ fn static_assert() {
use gecko_bindings::structs::nsCSSPropertyID::eCSSPropertyExtra_no_properties; use gecko_bindings::structs::nsCSSPropertyID::eCSSPropertyExtra_no_properties;
use gecko_bindings::structs::nsCSSPropertyID::eCSSPropertyExtra_variable; use gecko_bindings::structs::nsCSSPropertyID::eCSSPropertyExtra_variable;
use gecko_bindings::structs::nsCSSPropertyID::eCSSProperty_UNKNOWN; use gecko_bindings::structs::nsCSSPropertyID::eCSSProperty_UNKNOWN;
use Atom;
let property = self.gecko.mTransitions[index].mProperty; let property = self.gecko.mTransitions[index].mProperty;
if property == eCSSProperty_UNKNOWN || property == eCSSPropertyExtra_variable { if property == eCSSProperty_UNKNOWN || property == eCSSPropertyExtra_variable {
@ -3384,7 +3403,6 @@ fn static_assert() {
pub fn animation_name_at(&self, index: usize) pub fn animation_name_at(&self, index: usize)
-> longhands::animation_name::computed_value::SingleComputedValue { -> longhands::animation_name::computed_value::SingleComputedValue {
use properties::longhands::animation_name::single_value::SpecifiedValue as AnimationName; use properties::longhands::animation_name::single_value::SpecifiedValue as AnimationName;
use Atom;
let atom = self.gecko.mAnimations[index].mName.mRawPtr; let atom = self.gecko.mAnimations[index].mName.mRawPtr;
if atom == atom!("").as_ptr() { if atom == atom!("").as_ptr() {
@ -3590,7 +3608,6 @@ fn static_assert() {
use properties::longhands::will_change::computed_value::T; use properties::longhands::will_change::computed_value::T;
use gecko_bindings::structs::nsAtom; use gecko_bindings::structs::nsAtom;
use values::CustomIdent; use values::CustomIdent;
use Atom;
if self.gecko.mWillChange.len() == 0 { if self.gecko.mWillChange.len() == 0 {
return T::Auto return T::Auto
@ -4106,12 +4123,8 @@ fn static_assert() {
} }
UrlOrNone::Url(ref url) => { UrlOrNone::Url(ref url) => {
unsafe { unsafe {
Gecko_SetListStyleImageImageValue(&mut self.gecko, url.image_value.get()); Gecko_SetListStyleImageImageValue(&mut self.gecko, url.0.image_value.get());
} }
// We don't need to record this struct as uncacheable, like when setting
// background-image to a url() value, since only properties in reset structs
// are re-used from the applicable declaration cache, and the List struct
// is an inherited struct.
} }
} }
} }
@ -4125,7 +4138,7 @@ fn static_assert() {
} }
pub fn clone_list_style_image(&self) -> longhands::list_style_image::computed_value::T { pub fn clone_list_style_image(&self) -> longhands::list_style_image::computed_value::T {
use values::specified::url::SpecifiedImageUrl; use values::computed::url::ComputedImageUrl;
if self.gecko.mListStyleImage.mRawPtr.is_null() { if self.gecko.mListStyleImage.mRawPtr.is_null() {
return UrlOrNone::None; return UrlOrNone::None;
@ -4133,8 +4146,9 @@ fn static_assert() {
unsafe { unsafe {
let ref gecko_image_request = *self.gecko.mListStyleImage.mRawPtr; let ref gecko_image_request = *self.gecko.mListStyleImage.mRawPtr;
UrlOrNone::Url(SpecifiedImageUrl::from_image_request(gecko_image_request) UrlOrNone::Url(ComputedImageUrl::from_image_request(
.expect("mListStyleImage could not convert to SpecifiedImageUrl")) gecko_image_request
).expect("mListStyleImage could not convert to ComputedImageUrl"))
} }
} }
@ -4269,6 +4283,13 @@ fn static_assert() {
self.gecko.mSpan = v.0 self.gecko.mSpan = v.0
} }
#[allow(non_snake_case)]
pub fn clone__x_span(&self) -> longhands::_x_span::computed_value::T {
longhands::_x_span::computed_value::T(
self.gecko.mSpan
)
}
${impl_simple_copy('_x_span', 'mSpan')} ${impl_simple_copy('_x_span', 'mSpan')}
</%self:impl_trait> </%self:impl_trait>
@ -4473,7 +4494,7 @@ fn static_assert() {
}, },
Url(ref url) => { Url(ref url) => {
unsafe { unsafe {
bindings::Gecko_nsStyleFilter_SetURLValue(gecko_filter, url.url_value.get()); bindings::Gecko_nsStyleFilter_SetURLValue(gecko_filter, url.0.url_value.get());
} }
}, },
} }
@ -4492,7 +4513,7 @@ fn static_assert() {
pub fn clone_filter(&self) -> longhands::filter::computed_value::T { pub fn clone_filter(&self) -> longhands::filter::computed_value::T {
use values::generics::effects::Filter; use values::generics::effects::Filter;
use values::specified::url::SpecifiedUrl; use values::computed::url::ComputedUrl;
use gecko_bindings::structs::NS_STYLE_FILTER_BLUR; use gecko_bindings::structs::NS_STYLE_FILTER_BLUR;
use gecko_bindings::structs::NS_STYLE_FILTER_BRIGHTNESS; use gecko_bindings::structs::NS_STYLE_FILTER_BRIGHTNESS;
use gecko_bindings::structs::NS_STYLE_FILTER_CONTRAST; use gecko_bindings::structs::NS_STYLE_FILTER_CONTRAST;
@ -4534,7 +4555,7 @@ fn static_assert() {
NS_STYLE_FILTER_URL => { NS_STYLE_FILTER_URL => {
filters.push(unsafe { filters.push(unsafe {
Filter::Url( Filter::Url(
SpecifiedUrl::from_url_value_data(&(**filter.__bindgen_anon_1.mURL.as_ref())._base).unwrap() ComputedUrl::from_url_value_data(&(**filter.__bindgen_anon_1.mURL.as_ref())._base).unwrap()
) )
}); });
} }
@ -5000,7 +5021,7 @@ fn static_assert() {
% if ident == "clip_path": % if ident == "clip_path":
ShapeSource::ImageOrUrl(ref url) => { ShapeSource::ImageOrUrl(ref url) => {
unsafe { unsafe {
bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.url_value.get()) bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.0.url_value.get())
} }
} }
% elif ident == "shape_outside": % elif ident == "shape_outside":
@ -5213,9 +5234,27 @@ clip-path
SVGStrokeDashArray::Values(vec) SVGStrokeDashArray::Values(vec)
} }
#[allow(non_snake_case)]
pub fn _moz_context_properties_count(&self) -> usize {
self.gecko.mContextProps.len()
}
#[allow(non_snake_case)]
pub fn _moz_context_properties_at(
&self,
index: usize,
) -> longhands::_moz_context_properties::computed_value::single_value::T {
longhands::_moz_context_properties::computed_value::single_value::T(
CustomIdent(unsafe {
Atom::from_raw(self.gecko.mContextProps[index].mRawPtr)
})
)
}
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn set__moz_context_properties<I>(&mut self, v: I) pub fn set__moz_context_properties<I>(&mut self, v: I)
where I: IntoIterator<Item = longhands::_moz_context_properties::computed_value::single_value::T>, where
I: IntoIterator<Item = longhands::_moz_context_properties::computed_value::single_value::T>,
I::IntoIter: ExactSizeIterator I::IntoIter: ExactSizeIterator
{ {
let v = v.into_iter(); let v = v.into_iter();
@ -5266,7 +5305,7 @@ clip-path
} }
</%self:impl_trait> </%self:impl_trait>
<%self:impl_trait style_struct_name="Pointing" <%self:impl_trait style_struct_name="InheritedUI"
skip_longhands="cursor caret-color"> skip_longhands="cursor caret-color">
pub fn set_cursor(&mut self, v: longhands::cursor::computed_value::T) { pub fn set_cursor(&mut self, v: longhands::cursor::computed_value::T) {
use style_traits::cursor::CursorKind; use style_traits::cursor::CursorKind;
@ -5322,15 +5361,10 @@ clip-path
unsafe { unsafe {
Gecko_SetCursorImageValue( Gecko_SetCursorImageValue(
&mut self.gecko.mCursorImages[i], &mut self.gecko.mCursorImages[i],
v.images[i].url.image_value.get(), v.images[i].url.0.image_value.get(),
); );
} }
// We don't need to record this struct as uncacheable, like when setting
// background-image to a url() value, since only properties in reset structs
// are re-used from the applicable declaration cache, and the Pointing struct
// is an inherited struct.
match v.images[i].hotspot { match v.images[i].hotspot {
Some((x, y)) => { Some((x, y)) => {
self.gecko.mCursorImages[i].mHaveHotspot = true; self.gecko.mCursorImages[i].mHaveHotspot = true;
@ -5356,9 +5390,9 @@ clip-path
} }
pub fn clone_cursor(&self) -> longhands::cursor::computed_value::T { pub fn clone_cursor(&self) -> longhands::cursor::computed_value::T {
use values::computed::pointing::CursorImage; use values::computed::ui::CursorImage;
use values::computed::url::ComputedImageUrl;
use style_traits::cursor::CursorKind; use style_traits::cursor::CursorKind;
use values::specified::url::SpecifiedImageUrl;
let keyword = match self.gecko.mCursor as u32 { let keyword = match self.gecko.mCursor as u32 {
structs::NS_STYLE_CURSOR_AUTO => CursorKind::Auto, structs::NS_STYLE_CURSOR_AUTO => CursorKind::Auto,
@ -5403,8 +5437,8 @@ clip-path
let images = self.gecko.mCursorImages.iter().map(|gecko_cursor_image| { let images = self.gecko.mCursorImages.iter().map(|gecko_cursor_image| {
let url = unsafe { let url = unsafe {
let gecko_image_request = gecko_cursor_image.mImage.mRawPtr.as_ref().unwrap(); let gecko_image_request = gecko_cursor_image.mImage.mRawPtr.as_ref().unwrap();
SpecifiedImageUrl::from_image_request(&gecko_image_request) ComputedImageUrl::from_image_request(&gecko_image_request)
.expect("mCursorImages.mImage could not convert to SpecifiedImageUrl") .expect("mCursorImages.mImage could not convert to ComputedImageUrl")
}; };
let hotspot = let hotspot =
@ -5463,7 +5497,7 @@ clip-path
pub fn set_content(&mut self, v: longhands::content::computed_value::T, device: &Device) { pub fn set_content(&mut self, v: longhands::content::computed_value::T, device: &Device) {
use values::CustomIdent; use values::CustomIdent;
use values::computed::counters::{Content, ContentItem}; use values::generics::counters::{Content, ContentItem};
use values::generics::CounterStyleOrNone; use values::generics::CounterStyleOrNone;
use gecko_bindings::structs::nsStyleContentData; use gecko_bindings::structs::nsStyleContentData;
use gecko_bindings::structs::nsStyleContentAttr; use gecko_bindings::structs::nsStyleContentAttr;
@ -5590,7 +5624,7 @@ clip-path
unsafe { unsafe {
bindings::Gecko_SetContentDataImageValue( bindings::Gecko_SetContentDataImageValue(
&mut self.gecko.mContents[i], &mut self.gecko.mContents[i],
url.image_value.get(), url.0.image_value.get(),
) )
} }
} }
@ -5615,10 +5649,10 @@ clip-path
use {Atom, Namespace}; use {Atom, Namespace};
use gecko::conversions::string_from_chars_pointer; use gecko::conversions::string_from_chars_pointer;
use gecko_bindings::structs::nsStyleContentType::*; use gecko_bindings::structs::nsStyleContentType::*;
use values::computed::counters::{Content, ContentItem}; use values::generics::counters::{Content, ContentItem};
use values::computed::url::ComputedImageUrl;
use values::{CustomIdent, Either}; use values::{CustomIdent, Either};
use values::generics::CounterStyleOrNone; use values::generics::CounterStyleOrNone;
use values::specified::url::SpecifiedImageUrl;
use values::specified::Attr; use values::specified::Attr;
if self.gecko.mContents.is_empty() { if self.gecko.mContents.is_empty() {
@ -5679,8 +5713,8 @@ clip-path
let gecko_image_request = let gecko_image_request =
&**gecko_content.mContent.mImage.as_ref(); &**gecko_content.mContent.mImage.as_ref();
ContentItem::Url( ContentItem::Url(
SpecifiedImageUrl::from_image_request(gecko_image_request) ComputedImageUrl::from_image_request(gecko_image_request)
.expect("mContent could not convert to SpecifiedImageUrl") .expect("mContent could not convert to ComputedImageUrl")
) )
} }
}, },
@ -5719,7 +5753,6 @@ clip-path
) -> longhands::counter_${counter_property.lower()}::computed_value::T { ) -> longhands::counter_${counter_property.lower()}::computed_value::T {
use values::generics::counters::CounterPair; use values::generics::counters::CounterPair;
use values::CustomIdent; use values::CustomIdent;
use gecko_string_cache::Atom;
longhands::counter_${counter_property.lower()}::computed_value::T::new( longhands::counter_${counter_property.lower()}::computed_value::T::new(
self.gecko.m${counter_property}s.iter().map(|ref gecko_counter| { self.gecko.m${counter_property}s.iter().map(|ref gecko_counter| {

View file

@ -759,7 +759,7 @@
<%def name="four_sides_shorthand(name, sub_property_pattern, parser_function, <%def name="four_sides_shorthand(name, sub_property_pattern, parser_function,
needs_context=True, allow_quirks=False, **kwargs)"> needs_context=True, allow_quirks=False, **kwargs)">
<% sub_properties=' '.join(sub_property_pattern % side for side in ['top', 'right', 'bottom', 'left']) %> <% sub_properties=' '.join(sub_property_pattern % side for side in PHYSICAL_SIDES) %>
<%call expr="self.shorthand(name, sub_properties=sub_properties, **kwargs)"> <%call expr="self.shorthand(name, sub_properties=sub_properties, **kwargs)">
#[allow(unused_imports)] #[allow(unused_imports)]
use parser::Parse; use parser::Parse;

View file

@ -54,7 +54,7 @@ ${helpers.predefined_type(
${helpers.single_keyword("background-attachment", ${helpers.single_keyword("background-attachment",
"scroll fixed" + (" local" if product == "gecko" else ""), "scroll fixed" + (" local" if product == "gecko" else ""),
vector=True, vector=True,
gecko_constant_prefix="NS_STYLE_IMAGELAYER_ATTACHMENT", gecko_enum_prefix="StyleImageLayerAttachment",
spec="https://drafts.csswg.org/css-backgrounds/#the-background-attachment", spec="https://drafts.csswg.org/css-backgrounds/#the-background-attachment",
animation_value_type="discrete", animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER")} flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER")}

View file

@ -136,6 +136,7 @@ ${helpers.predefined_type("-moz-context-properties",
"MozContextProperties", "MozContextProperties",
initial_value=None, initial_value=None,
vector=True, vector=True,
need_index=True,
animation_value_type="none", animation_value_type="none",
products="gecko", products="gecko",
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-context-properties)", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-context-properties)",

View file

@ -4,7 +4,7 @@
<%namespace name="helpers" file="/helpers.mako.rs" /> <%namespace name="helpers" file="/helpers.mako.rs" />
<% data.new_style_struct("Pointing", inherited=True, gecko_name="UserInterface") %> <% data.new_style_struct("InheritedUI", inherited=True, gecko_name="UserInterface") %>
${helpers.predefined_type("cursor", ${helpers.predefined_type("cursor",
"Cursor", "Cursor",
@ -44,7 +44,7 @@ ${helpers.single_keyword("-moz-user-focus",
${helpers.predefined_type( ${helpers.predefined_type(
"caret-color", "caret-color",
"CaretColor", "CaretColor",
"generics::pointing::CaretColor::Auto", "generics::ui::CaretColor::Auto",
spec="https://drafts.csswg.org/css-ui/#caret-color", spec="https://drafts.csswg.org/css-ui/#caret-color",
animation_value_type="AnimatedCaretColor", animation_value_type="AnimatedCaretColor",
ignored_when_colors_disabled=True, ignored_when_colors_disabled=True,

View file

@ -109,11 +109,11 @@ pub mod longhands {
<%include file="/longhand/inherited_box.mako.rs" /> <%include file="/longhand/inherited_box.mako.rs" />
<%include file="/longhand/inherited_table.mako.rs" /> <%include file="/longhand/inherited_table.mako.rs" />
<%include file="/longhand/inherited_text.mako.rs" /> <%include file="/longhand/inherited_text.mako.rs" />
<%include file="/longhand/inherited_ui.mako.rs" />
<%include file="/longhand/list.mako.rs" /> <%include file="/longhand/list.mako.rs" />
<%include file="/longhand/margin.mako.rs" /> <%include file="/longhand/margin.mako.rs" />
<%include file="/longhand/outline.mako.rs" /> <%include file="/longhand/outline.mako.rs" />
<%include file="/longhand/padding.mako.rs" /> <%include file="/longhand/padding.mako.rs" />
<%include file="/longhand/pointing.mako.rs" />
<%include file="/longhand/position.mako.rs" /> <%include file="/longhand/position.mako.rs" />
<%include file="/longhand/table.mako.rs" /> <%include file="/longhand/table.mako.rs" />
<%include file="/longhand/text.mako.rs" /> <%include file="/longhand/text.mako.rs" />
@ -2399,6 +2399,18 @@ pub mod style_structs {
-> longhands::${longhand.ident}::computed_value::SingleComputedValue { -> longhands::${longhand.ident}::computed_value::SingleComputedValue {
self.${longhand.ident}_at(index % self.${longhand.ident}_count()) self.${longhand.ident}_at(index % self.${longhand.ident}_count())
} }
/// Clone the computed value for the property.
#[allow(non_snake_case)]
#[inline]
#[cfg(feature = "gecko")]
pub fn clone_${longhand.ident}(
&self,
) -> longhands::${longhand.ident}::computed_value::T {
longhands::${longhand.ident}::computed_value::T(
self.${longhand.ident}_iter().collect()
)
}
% endif % endif
% endfor % endfor
@ -2631,10 +2643,10 @@ impl ComputedValuesInner {
/// ineffective, and would yield an empty `::before` or `::after` /// ineffective, and would yield an empty `::before` or `::after`
/// pseudo-element. /// pseudo-element.
pub fn ineffective_content_property(&self) -> bool { pub fn ineffective_content_property(&self) -> bool {
use properties::longhands::content::computed_value::T; use values::generics::counters::Content;
match self.get_counters().content { match self.get_counters().content {
T::Normal | T::None => true, Content::Normal | Content::None => true,
T::Items(ref items) => items.is_empty(), Content::Items(ref items) => items.is_empty(),
} }
} }

View file

@ -14,6 +14,8 @@ use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
use values::animated::color::RGBA; use values::animated::color::RGBA;
use values::computed::{Angle, Number}; use values::computed::{Angle, Number};
use values::computed::length::Length; use values::computed::length::Length;
#[cfg(feature = "gecko")]
use values::computed::url::ComputedUrl;
use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::distance::{ComputeSquaredDistance, SquaredDistance};
use values::generics::effects::BoxShadow as GenericBoxShadow; use values::generics::effects::BoxShadow as GenericBoxShadow;
use values::generics::effects::Filter as GenericFilter; use values::generics::effects::Filter as GenericFilter;
@ -42,11 +44,11 @@ pub struct FilterList(pub Vec<Filter>);
/// An animated value for a single `filter`. /// An animated value for a single `filter`.
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub type Filter = GenericFilter<Angle, Number, Length, SimpleShadow>; pub type Filter = GenericFilter<Angle, Number, Length, SimpleShadow, ComputedUrl>;
/// An animated value for a single `filter`. /// An animated value for a single `filter`.
#[cfg(not(feature = "gecko"))] #[cfg(not(feature = "gecko"))]
pub type Filter = GenericFilter<Angle, Number, Length, Impossible>; pub type Filter = GenericFilter<Angle, Number, Length, Impossible, Impossible>;
/// An animated value for the `drop-shadow()` filter. /// An animated value for the `drop-shadow()` filter.
pub type SimpleShadow = GenericSimpleShadow<Option<RGBA>, Length, Length>; pub type SimpleShadow = GenericSimpleShadow<Option<RGBA>, Length, Length>;

View file

@ -15,9 +15,7 @@ use values::computed::Angle as ComputedAngle;
use values::computed::BorderCornerRadius as ComputedBorderCornerRadius; use values::computed::BorderCornerRadius as ComputedBorderCornerRadius;
use values::computed::MaxLength as ComputedMaxLength; use values::computed::MaxLength as ComputedMaxLength;
use values::computed::MozLength as ComputedMozLength; use values::computed::MozLength as ComputedMozLength;
#[cfg(feature = "servo")]
use values::computed::url::ComputedUrl; use values::computed::url::ComputedUrl;
use values::specified::url::SpecifiedUrl;
pub mod color; pub mod color;
pub mod effects; pub mod effects;
@ -260,8 +258,6 @@ macro_rules! trivial_to_animated_value {
trivial_to_animated_value!(Au); trivial_to_animated_value!(Au);
trivial_to_animated_value!(ComputedAngle); trivial_to_animated_value!(ComputedAngle);
trivial_to_animated_value!(SpecifiedUrl);
#[cfg(feature = "servo")]
trivial_to_animated_value!(ComputedUrl); trivial_to_animated_value!(ComputedUrl);
trivial_to_animated_value!(bool); trivial_to_animated_value!(bool);
trivial_to_animated_value!(f32); trivial_to_animated_value!(f32);

View file

@ -4,22 +4,10 @@
//! Computed values for counter properties //! Computed values for counter properties
#[cfg(feature = "servo")] use values::computed::url::ComputedImageUrl;
use computed_values::list_style_type::T as ListStyleType; use values::generics::counters as generics;
use cssparser::{Parser, Token};
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseErrorKind;
use style_traits::{ParseError, StyleParseErrorKind};
use values::CustomIdent;
#[cfg(feature = "gecko")]
use values::generics::CounterStyleOrNone;
use values::generics::counters::CounterIncrement as GenericCounterIncrement; use values::generics::counters::CounterIncrement as GenericCounterIncrement;
use values::generics::counters::CounterReset as GenericCounterReset; use values::generics::counters::CounterReset as GenericCounterReset;
#[cfg(feature = "gecko")]
use values::specified::Attr;
#[cfg(feature = "gecko")]
use values::specified::url::SpecifiedImageUrl;
pub use values::specified::{Content, ContentItem};
/// A computed value for the `counter-increment` property. /// A computed value for the `counter-increment` property.
pub type CounterIncrement = GenericCounterIncrement<i32>; pub type CounterIncrement = GenericCounterIncrement<i32>;
@ -27,134 +15,9 @@ pub type CounterIncrement = GenericCounterIncrement<i32>;
/// A computed value for the `counter-increment` property. /// A computed value for the `counter-increment` property.
pub type CounterReset = GenericCounterReset<i32>; pub type CounterReset = GenericCounterReset<i32>;
impl Content { /// A computed value for the `content` property.
/// Set `content` property to `normal`. pub type Content = generics::Content<ComputedImageUrl>;
#[inline]
pub fn normal() -> Self {
Content::Normal
}
#[cfg(feature = "servo")] /// A computed content item.
fn parse_counter_style(input: &mut Parser) -> ListStyleType { pub type ContentItem = generics::ContentItem<ComputedImageUrl>;
input
.try(|input| {
input.expect_comma()?;
ListStyleType::parse(input)
})
.unwrap_or(ListStyleType::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())
}
}
impl Parse for Content {
// normal | none | [ <string> | <counter> | open-quote | close-quote | no-open-quote |
// no-close-quote ]+
// TODO: <uri>, attr(<identifier>)
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if input
.try(|input| input.expect_ident_matching("normal"))
.is_ok()
{
return Ok(Content::Normal);
}
if input
.try(|input| input.expect_ident_matching("none"))
.is_ok()
{
return Ok(Content::None);
}
#[cfg(feature = "gecko")]
{
if input
.try(|input| input.expect_ident_matching("-moz-alt-content"))
.is_ok()
{
return Ok(Content::MozAltContent);
}
}
let mut content = vec![];
loop {
#[cfg(feature = "gecko")]
{
if let Ok(url) = input.try(|i| SpecifiedImageUrl::parse(_context, i)) {
content.push(ContentItem::Url(url));
continue;
}
}
// FIXME: remove clone() when lifetimes are non-lexical
match input.next().map(|t| t.clone()) {
Ok(Token::QuotedString(ref value)) => {
content.push(ContentItem::String(
value.as_ref().to_owned().into_boxed_str(),
));
},
Ok(Token::Function(ref name)) => {
let result = match_ignore_ascii_case! { &name,
"counter" => Some(input.parse_nested_block(|input| {
let location = input.current_source_location();
let name = CustomIdent::from_ident(location, input.expect_ident()?, &[])?;
#[cfg(feature = "servo")]
let style = Content::parse_counter_style(input);
#[cfg(feature = "gecko")]
let style = Content::parse_counter_style(_context, input);
Ok(ContentItem::Counter(name, style))
})),
"counters" => Some(input.parse_nested_block(|input| {
let location = input.current_source_location();
let name = CustomIdent::from_ident(location, input.expect_ident()?, &[])?;
input.expect_comma()?;
let separator = input.expect_string()?.as_ref().to_owned().into_boxed_str();
#[cfg(feature = "servo")]
let style = Content::parse_counter_style(input);
#[cfg(feature = "gecko")]
let style = Content::parse_counter_style(_context, input);
Ok(ContentItem::Counters(name, separator, style))
})),
#[cfg(feature = "gecko")]
"attr" => Some(input.parse_nested_block(|input| {
Ok(ContentItem::Attr(Attr::parse_function(_context, input)?))
})),
_ => None
};
match result {
Some(result) => content.push(result?),
None => {
return Err(input.new_custom_error(
StyleParseErrorKind::UnexpectedFunction(name.clone()),
))
},
}
},
Ok(Token::Ident(ref ident)) => {
content.push(match_ignore_ascii_case! { &ident,
"open-quote" => ContentItem::OpenQuote,
"close-quote" => ContentItem::CloseQuote,
"no-open-quote" => ContentItem::NoOpenQuote,
"no-close-quote" => ContentItem::NoCloseQuote,
_ => return Err(input.new_custom_error(
SelectorParseErrorKind::UnexpectedIdent(ident.clone())))
});
},
Err(_) => break,
Ok(t) => return Err(input.new_unexpected_token_error(t)),
}
}
if content.is_empty() {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
Ok(Content::Items(content.into_boxed_slice()))
}
}

View file

@ -9,6 +9,8 @@ use values::Impossible;
use values::computed::{Angle, NonNegativeNumber}; use values::computed::{Angle, NonNegativeNumber};
use values::computed::color::RGBAColor; use values::computed::color::RGBAColor;
use values::computed::length::{Length, NonNegativeLength}; use values::computed::length::{Length, NonNegativeLength};
#[cfg(feature = "gecko")]
use values::computed::url::ComputedUrl;
use values::generics::effects::BoxShadow as GenericBoxShadow; use values::generics::effects::BoxShadow as GenericBoxShadow;
use values::generics::effects::Filter as GenericFilter; use values::generics::effects::Filter as GenericFilter;
use values::generics::effects::SimpleShadow as GenericSimpleShadow; use values::generics::effects::SimpleShadow as GenericSimpleShadow;
@ -18,11 +20,11 @@ pub type BoxShadow = GenericBoxShadow<Option<RGBAColor>, Length, NonNegativeLeng
/// A computed value for a single `filter`. /// A computed value for a single `filter`.
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, SimpleShadow>; pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, SimpleShadow, ComputedUrl>;
/// A computed value for a single `filter`. /// A computed value for a single `filter`.
#[cfg(not(feature = "gecko"))] #[cfg(not(feature = "gecko"))]
pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, Impossible>; pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, Impossible, Impossible>;
/// A computed value for the `drop-shadow()` filter. /// A computed value for the `drop-shadow()` filter.
pub type SimpleShadow = GenericSimpleShadow<Option<RGBAColor>, Length, NonNegativeLength>; pub type SimpleShadow = GenericSimpleShadow<Option<RGBAColor>, Length, NonNegativeLength>;

View file

@ -56,6 +56,7 @@ pub use self::inherited_box::{ImageOrientation, Orientation};
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub use self::gecko::ScrollSnapPoint; pub use self::gecko::ScrollSnapPoint;
pub use self::rect::LengthOrNumberRect; pub use self::rect::LengthOrNumberRect;
pub use self::resolution::Resolution;
pub use super::{Auto, Either, None_}; pub use super::{Auto, Either, None_};
pub use super::specified::{BorderStyle, TextDecorationLine}; pub use super::specified::{BorderStyle, TextDecorationLine};
pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrPercentage}; pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrPercentage};
@ -67,9 +68,6 @@ pub use self::list::Quotes;
pub use self::list::ListStyleType; pub use self::list::ListStyleType;
pub use self::outline::OutlineStyle; pub use self::outline::OutlineStyle;
pub use self::percentage::{Percentage, NonNegativePercentage}; pub use self::percentage::{Percentage, NonNegativePercentage};
pub use self::pointing::{CaretColor, Cursor};
#[cfg(feature = "gecko")]
pub use self::pointing::CursorImage;
pub use self::position::{GridAutoFlow, GridTemplateAreas, Position, ZIndex}; pub use self::position::{GridAutoFlow, GridTemplateAreas, Position, ZIndex};
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind}; pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind};
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth}; pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
@ -80,7 +78,9 @@ pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle, TextOve
pub use self::time::Time; pub use self::time::Time;
pub use self::transform::{Rotate, Scale, TimingFunction, Transform, TransformOperation}; pub use self::transform::{Rotate, Scale, TimingFunction, Transform, TransformOperation};
pub use self::transform::{TransformOrigin, TransformStyle, Translate}; pub use self::transform::{TransformOrigin, TransformStyle, Translate};
pub use self::ui::MozForceBrokenImageIcon; pub use self::ui::{CaretColor, Cursor, MozForceBrokenImageIcon};
#[cfg(feature = "gecko")]
pub use self::ui::CursorImage;
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub mod align; pub mod align;
@ -104,9 +104,9 @@ pub mod length;
pub mod list; pub mod list;
pub mod outline; pub mod outline;
pub mod percentage; pub mod percentage;
pub mod pointing;
pub mod position; pub mod position;
pub mod rect; pub mod rect;
pub mod resolution;
pub mod svg; pub mod svg;
pub mod table; pub mod table;
pub mod text; pub mod text;

View file

@ -1,21 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Computed values for Pointing properties.
//!
//! https://drafts.csswg.org/css-ui/#pointing-keyboard
use values::computed::Number;
use values::computed::color::Color;
use values::computed::url::ComputedImageUrl;
use values::generics::pointing as generics;
/// A computed value for the `caret-color` property.
pub type CaretColor = generics::CaretColor<Color>;
/// A computed value for the `cursor` property.
pub type Cursor = generics::Cursor<CursorImage>;
/// A computed value for item of `image cursors`.
pub type CursorImage = generics::CursorImage<ComputedImageUrl, Number>;

View file

@ -0,0 +1,48 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Resolution values:
//!
//! https://drafts.csswg.org/css-values/#resolution
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
use values::CSSFloat;
use values::computed::{Context, ToComputedValue};
use values::specified;
/// A computed `<resolution>`.
pub struct Resolution(CSSFloat);
impl Resolution {
/// Returns this resolution value as dppx.
#[inline]
pub fn dppx(&self) -> CSSFloat {
self.0
}
}
impl ToComputedValue for specified::Resolution {
type ComputedValue = Resolution;
#[inline]
fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
Resolution(self.to_dppx())
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
specified::Resolution::Dppx(computed.dppx())
}
}
impl ToCss for Resolution {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: fmt::Write,
{
self.dppx().to_css(dest)?;
dest.write_str("dppx")
}
}

View file

@ -4,4 +4,18 @@
//! Computed values for UI properties //! Computed values for UI properties
use values::computed::Number;
use values::computed::color::Color;
use values::computed::url::ComputedImageUrl;
use values::generics::ui as generics;
pub use values::specified::ui::MozForceBrokenImageIcon; pub use values::specified::ui::MozForceBrokenImageIcon;
/// A computed value for the `caret-color` property.
pub type CaretColor = generics::CaretColor<Color>;
/// A computed value for the `cursor` property.
pub type Cursor = generics::Cursor<CursorImage>;
/// A computed value for item of `image cursors`.
pub type CursorImage = generics::CursorImage<ComputedImageUrl, Number>;

View file

@ -4,8 +4,14 @@
//! Generic types for counters-related CSS values. //! Generic types for counters-related CSS values.
#[cfg(feature = "servo")]
use computed_values::list_style_type::T as ListStyleType;
use std::ops::Deref; use std::ops::Deref;
use values::CustomIdent; use values::CustomIdent;
#[cfg(feature = "gecko")]
use values::generics::CounterStyleOrNone;
#[cfg(feature = "gecko")]
use values::specified::Attr;
/// A name / value pair for counters. /// A name / value pair for counters.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, #[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
@ -74,3 +80,78 @@ impl<I> Default for Counters<I> {
Counters(vec![].into_boxed_slice()) Counters(vec![].into_boxed_slice())
} }
} }
#[cfg(feature = "servo")]
type CounterStyleType = ListStyleType;
#[cfg(feature = "gecko")]
type CounterStyleType = CounterStyleOrNone;
#[cfg(feature = "servo")]
#[inline]
fn is_decimal(counter_type: &CounterStyleType) -> bool {
*counter_type == ListStyleType::Decimal
}
#[cfg(feature = "gecko")]
#[inline]
fn is_decimal(counter_type: &CounterStyleType) -> bool {
*counter_type == CounterStyleOrNone::decimal()
}
/// The specified value for the `content` property.
///
/// https://drafts.csswg.org/css-content/#propdef-content
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum Content<ImageUrl> {
/// `normal` reserved keyword.
Normal,
/// `none` reserved keyword.
None,
/// `-moz-alt-content`.
#[cfg(feature = "gecko")]
MozAltContent,
/// Content items.
Items(#[css(iterable)] Box<[ContentItem<ImageUrl>]>),
}
impl<ImageUrl> Content<ImageUrl> {
/// Set `content` property to `normal`.
#[inline]
pub fn normal() -> Self {
Content::Normal
}
}
/// Items for the `content` property.
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum ContentItem<ImageUrl> {
/// Literal string content.
String(Box<str>),
/// `counter(name, style)`.
#[css(comma, function)]
Counter(CustomIdent, #[css(skip_if = "is_decimal")] CounterStyleType),
/// `counters(name, separator, style)`.
#[css(comma, function)]
Counters(
CustomIdent,
Box<str>,
#[css(skip_if = "is_decimal")] CounterStyleType,
),
/// `open-quote`.
OpenQuote,
/// `close-quote`.
CloseQuote,
/// `no-open-quote`.
NoOpenQuote,
/// `no-close-quote`.
NoCloseQuote,
/// `attr([namespace? `|`]? ident)`
#[cfg(feature = "gecko")]
Attr(Attr),
/// `url(url)`
Url(ImageUrl),
}

View file

@ -4,9 +4,6 @@
//! Generic types for CSS values related to effects. //! Generic types for CSS values related to effects.
#[cfg(feature = "gecko")]
use values::specified::url::SpecifiedUrl;
/// A generic value for a single `box-shadow`. /// A generic value for a single `box-shadow`.
#[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, #[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToAnimatedValue, ToAnimatedZero, ToCss)] ToAnimatedValue, ToAnimatedZero, ToCss)]
@ -23,9 +20,10 @@ pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
/// A generic value for a single `filter`. /// A generic value for a single `filter`.
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[animation(no_bound(Url))]
#[derive(Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, #[derive(Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss)] SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss)]
pub enum Filter<Angle, Factor, Length, DropShadow> { pub enum Filter<Angle, Factor, Length, DropShadow, Url> {
/// `blur(<length>)` /// `blur(<length>)`
#[css(function)] #[css(function)]
Blur(Length), Blur(Length),
@ -58,8 +56,7 @@ pub enum Filter<Angle, Factor, Length, DropShadow> {
DropShadow(DropShadow), DropShadow(DropShadow),
/// `<url>` /// `<url>`
#[animation(error)] #[animation(error)]
#[cfg(feature = "gecko")] Url(Url),
Url(SpecifiedUrl),
} }
/// A generic value for the `drop-shadow()` filter and the `text-shadow` property. /// A generic value for the `drop-shadow()` filter and the `text-shadow` property.

View file

@ -26,13 +26,13 @@ pub mod font;
pub mod gecko; pub mod gecko;
pub mod grid; pub mod grid;
pub mod image; pub mod image;
pub mod pointing;
pub mod position; pub mod position;
pub mod rect; pub mod rect;
pub mod size; pub mod size;
pub mod svg; pub mod svg;
pub mod text; pub mod text;
pub mod transform; pub mod transform;
pub mod ui;
pub mod url; pub mod url;
// https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type // https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type

View file

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Generic values for pointing properties. //! Generic values for UI properties.
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss}; use style_traits::{CssWriter, ToCss};

View file

@ -8,17 +8,18 @@
use computed_values::list_style_type::T as ListStyleType; use computed_values::list_style_type::T as ListStyleType;
use cssparser::{Parser, Token}; use cssparser::{Parser, Token};
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseErrorKind;
use style_traits::{ParseError, StyleParseErrorKind}; use style_traits::{ParseError, StyleParseErrorKind};
use values::CustomIdent; use values::CustomIdent;
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
use values::generics::CounterStyleOrNone; use values::generics::CounterStyleOrNone;
use values::generics::counters as generics;
use values::generics::counters::CounterIncrement as GenericCounterIncrement; use values::generics::counters::CounterIncrement as GenericCounterIncrement;
use values::generics::counters::CounterPair; use values::generics::counters::CounterPair;
use values::generics::counters::CounterReset as GenericCounterReset; use values::generics::counters::CounterReset as GenericCounterReset;
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
use values::specified::Attr; use values::specified::Attr;
use values::specified::Integer; use values::specified::Integer;
#[cfg(feature = "gecko")]
use values::specified::url::SpecifiedImageUrl; use values::specified::url::SpecifiedImageUrl;
/// A specified value for the `counter-increment` property. /// A specified value for the `counter-increment` property.
@ -79,69 +80,129 @@ fn parse_counters<'i, 't>(
} }
} }
#[cfg(feature = "servo")]
type CounterStyleType = ListStyleType;
#[cfg(feature = "gecko")]
type CounterStyleType = CounterStyleOrNone;
#[cfg(feature = "servo")]
#[inline]
fn is_decimal(counter_type: &CounterStyleType) -> bool {
*counter_type == ListStyleType::Decimal
}
#[cfg(feature = "gecko")]
#[inline]
fn is_decimal(counter_type: &CounterStyleType) -> bool {
*counter_type == CounterStyleOrNone::decimal()
}
/// The specified value for the `content` property. /// The specified value for the `content` property.
/// pub type Content = generics::Content<SpecifiedImageUrl>;
/// https://drafts.csswg.org/css-content/#propdef-content
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, /// The specified value for a content item in the `content` property.
ToComputedValue, ToCss)] pub type ContentItem = generics::ContentItem<SpecifiedImageUrl>;
pub enum Content {
/// `normal` reserved keyword. impl Content {
Normal, #[cfg(feature = "servo")]
/// `none` reserved keyword. fn parse_counter_style(_: &ParserContext, input: &mut Parser) -> ListStyleType {
None, input
/// `-moz-alt-content`. .try(|input| {
input.expect_comma()?;
ListStyleType::parse(input)
})
.unwrap_or(ListStyleType::Decimal)
}
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
MozAltContent, fn parse_counter_style(context: &ParserContext, input: &mut Parser) -> CounterStyleOrNone {
/// Content items. input
Items(#[css(iterable)] Box<[ContentItem]>), .try(|input| {
input.expect_comma()?;
CounterStyleOrNone::parse(context, input)
})
.unwrap_or(CounterStyleOrNone::decimal())
}
} }
/// Items for the `content` property. impl Parse for Content {
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, // normal | none | [ <string> | <counter> | open-quote | close-quote | no-open-quote |
ToComputedValue, ToCss)] // no-close-quote ]+
pub enum ContentItem { // TODO: <uri>, attr(<identifier>)
/// Literal string content. fn parse<'i, 't>(
String(Box<str>), context: &ParserContext,
/// `counter(name, style)`. input: &mut Parser<'i, 't>,
#[css(comma, function)] ) -> Result<Self, ParseError<'i>> {
Counter(CustomIdent, #[css(skip_if = "is_decimal")] CounterStyleType), if input
/// `counters(name, separator, style)`. .try(|input| input.expect_ident_matching("normal"))
#[css(comma, function)] .is_ok()
Counters( {
CustomIdent, return Ok(generics::Content::Normal);
Box<str>, }
#[css(skip_if = "is_decimal")] CounterStyleType, if input
), .try(|input| input.expect_ident_matching("none"))
/// `open-quote`. .is_ok()
OpenQuote, {
/// `close-quote`. return Ok(generics::Content::None);
CloseQuote, }
/// `no-open-quote`.
NoOpenQuote,
/// `no-close-quote`.
NoCloseQuote,
/// `attr([namespace? `|`]? ident)`
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
Attr(Attr), {
/// `url(url)` if input
.try(|input| input.expect_ident_matching("-moz-alt-content"))
.is_ok()
{
return Ok(generics::Content::MozAltContent);
}
}
let mut content = vec![];
loop {
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
Url(SpecifiedImageUrl), {
if let Ok(url) = input.try(|i| SpecifiedImageUrl::parse(context, i)) {
content.push(generics::ContentItem::Url(url));
continue;
}
}
// FIXME: remove clone() when lifetimes are non-lexical
match input.next().map(|t| t.clone()) {
Ok(Token::QuotedString(ref value)) => {
content.push(generics::ContentItem::String(
value.as_ref().to_owned().into_boxed_str(),
));
},
Ok(Token::Function(ref name)) => {
let result = match_ignore_ascii_case! { &name,
"counter" => Some(input.parse_nested_block(|input| {
let location = input.current_source_location();
let name = CustomIdent::from_ident(location, input.expect_ident()?, &[])?;
let style = Content::parse_counter_style(context, input);
Ok(generics::ContentItem::Counter(name, style))
})),
"counters" => Some(input.parse_nested_block(|input| {
let location = input.current_source_location();
let name = CustomIdent::from_ident(location, input.expect_ident()?, &[])?;
input.expect_comma()?;
let separator = input.expect_string()?.as_ref().to_owned().into_boxed_str();
let style = Content::parse_counter_style(context, input);
Ok(generics::ContentItem::Counters(name, separator, style))
})),
#[cfg(feature = "gecko")]
"attr" => Some(input.parse_nested_block(|input| {
Ok(generics::ContentItem::Attr(Attr::parse_function(context, input)?))
})),
_ => None
};
match result {
Some(result) => content.push(result?),
None => {
return Err(input.new_custom_error(
StyleParseErrorKind::UnexpectedFunction(name.clone()),
))
},
}
},
Ok(Token::Ident(ref ident)) => {
content.push(match_ignore_ascii_case! { &ident,
"open-quote" => generics::ContentItem::OpenQuote,
"close-quote" => generics::ContentItem::CloseQuote,
"no-open-quote" => generics::ContentItem::NoOpenQuote,
"no-close-quote" => generics::ContentItem::NoCloseQuote,
_ => return Err(input.new_custom_error(
SelectorParseErrorKind::UnexpectedIdent(ident.clone())
))
});
},
Err(_) => break,
Ok(t) => return Err(input.new_unexpected_token_error(t)),
}
}
if content.is_empty() {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
Ok(generics::Content::Items(content.into_boxed_slice()))
}
} }

View file

@ -28,11 +28,11 @@ pub type BoxShadow =
/// A specified value for a single `filter`. /// A specified value for a single `filter`.
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, SimpleShadow>; pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, SimpleShadow, SpecifiedUrl>;
/// A specified value for a single `filter`. /// A specified value for a single `filter`.
#[cfg(not(feature = "gecko"))] #[cfg(not(feature = "gecko"))]
pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, Impossible>; pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, Impossible, Impossible>;
/// A value for the `<factor>` parts in `Filter`. /// A value for the `<factor>` parts in `Filter`.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]

View file

@ -61,10 +61,8 @@ pub use self::list::Quotes;
pub use self::list::ListStyleType; pub use self::list::ListStyleType;
pub use self::outline::OutlineStyle; pub use self::outline::OutlineStyle;
pub use self::rect::LengthOrNumberRect; pub use self::rect::LengthOrNumberRect;
pub use self::resolution::Resolution;
pub use self::percentage::Percentage; pub use self::percentage::Percentage;
pub use self::pointing::{CaretColor, Cursor};
#[cfg(feature = "gecko")]
pub use self::pointing::CursorImage;
pub use self::position::{GridAutoFlow, GridTemplateAreas, Position}; pub use self::position::{GridAutoFlow, GridTemplateAreas, Position};
pub use self::position::{PositionComponent, ZIndex}; pub use self::position::{PositionComponent, ZIndex};
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind}; pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind};
@ -77,7 +75,9 @@ pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpa
pub use self::time::Time; pub use self::time::Time;
pub use self::transform::{Rotate, Scale, TimingFunction, Transform}; pub use self::transform::{Rotate, Scale, TimingFunction, Transform};
pub use self::transform::{TransformOrigin, TransformStyle, Translate}; pub use self::transform::{TransformOrigin, TransformStyle, Translate};
pub use self::ui::MozForceBrokenImageIcon; pub use self::ui::{CaretColor, Cursor, MozForceBrokenImageIcon};
#[cfg(feature = "gecko")]
pub use self::ui::CursorImage;
pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent; pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent;
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
@ -104,9 +104,9 @@ pub mod length;
pub mod list; pub mod list;
pub mod outline; pub mod outline;
pub mod percentage; pub mod percentage;
pub mod pointing;
pub mod position; pub mod position;
pub mod rect; pub mod rect;
pub mod resolution;
pub mod source_size_list; pub mod source_size_list;
pub mod svg; pub mod svg;
pub mod table; pub mod table;

View file

@ -1,86 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Specified values for Pointing properties.
//!
//! https://drafts.csswg.org/css-ui/#pointing-keyboard
use cssparser::Parser;
use parser::{Parse, ParserContext};
use style_traits::{ParseError, StyleParseErrorKind};
use style_traits::cursor::CursorKind;
use values::generics::pointing as generics;
use values::specified::Number;
use values::specified::color::Color;
use values::specified::url::SpecifiedImageUrl;
/// A specified value for the `caret-color` property.
pub type CaretColor = generics::CaretColor<Color>;
impl Parse for CaretColor {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
return Ok(generics::CaretColor::Auto);
}
Ok(generics::CaretColor::Color(Color::parse(context, input)?))
}
}
/// A specified value for the `cursor` property.
pub type Cursor = generics::Cursor<CursorImage>;
/// A specified value for item of `image cursors`.
pub type CursorImage = generics::CursorImage<SpecifiedImageUrl, Number>;
impl Parse for Cursor {
/// cursor: [<url> [<number> <number>]?]# [auto | default | ...]
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let mut images = vec![];
loop {
match input.try(|input| CursorImage::parse(context, input)) {
Ok(image) => images.push(image),
Err(_) => break,
}
input.expect_comma()?;
}
Ok(Self {
images: images.into_boxed_slice(),
keyword: CursorKind::parse(context, input)?,
})
}
}
impl Parse for CursorKind {
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let location = input.current_source_location();
let ident = input.expect_ident()?;
CursorKind::from_css_keyword(&ident).map_err(|_| {
location.new_custom_error(StyleParseErrorKind::UnspecifiedError)
})
}
}
impl Parse for CursorImage {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Ok(Self {
url: SpecifiedImageUrl::parse(context, input)?,
hotspot: match input.try(|input| Number::parse(context, input)) {
Ok(number) => Some((number, Number::parse(context, input)?)),
Err(_) => None,
},
})
}
}

View file

@ -0,0 +1,79 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Resolution values:
//!
//! https://drafts.csswg.org/css-values/#resolution
use cssparser::{Parser, Token};
use parser::{Parse, ParserContext};
use style_traits::{ParseError, StyleParseErrorKind};
use values::CSSFloat;
/// A specified resolution.
#[derive(Clone, Debug, PartialEq, ToCss)]
pub enum Resolution {
/// Dots per inch.
#[css(dimension)]
Dpi(CSSFloat),
/// An alias unit for dots per pixel.
#[css(dimension)]
X(CSSFloat),
/// Dots per pixel.
#[css(dimension)]
Dppx(CSSFloat),
/// Dots per centimeter.
#[css(dimension)]
Dpcm(CSSFloat),
}
impl Resolution {
/// Convert this resolution value to dppx units.
pub fn to_dppx(&self) -> CSSFloat {
match *self {
Resolution::X(f) |
Resolution::Dppx(f) => f,
_ => self.to_dpi() / 96.0,
}
}
/// Convert this resolution value to dpi units.
pub fn to_dpi(&self) -> CSSFloat {
match *self {
Resolution::Dpi(f) => f,
Resolution::X(f) |
Resolution::Dppx(f) => f * 96.0,
Resolution::Dpcm(f) => f * 2.54,
}
}
}
impl Parse for Resolution {
fn parse<'i, 't>(
_: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let location = input.current_source_location();
let (value, unit) = match *input.next()? {
Token::Dimension {
value, ref unit, ..
} => (value, unit),
ref t => return Err(location.new_unexpected_token_error(t.clone())),
};
if value <= 0. {
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
match_ignore_ascii_case! { &unit,
"dpi" => Ok(Resolution::Dpi(value)),
"dppx" => Ok(Resolution::Dppx(value)),
"dpcm" => Ok(Resolution::Dpcm(value)),
"x" => Ok(Resolution::X(value)),
_ => Err(location.new_custom_error(
StyleParseErrorKind::UnexpectedDimension(unit.clone())
)),
}
}
}

View file

@ -8,6 +8,81 @@ use cssparser::Parser;
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
use style_traits::cursor::CursorKind;
use values::generics::ui as generics;
use values::specified::Number;
use values::specified::color::Color;
use values::specified::url::SpecifiedImageUrl;
/// A specified value for the `caret-color` property.
pub type CaretColor = generics::CaretColor<Color>;
impl Parse for CaretColor {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
return Ok(generics::CaretColor::Auto);
}
Ok(generics::CaretColor::Color(Color::parse(context, input)?))
}
}
/// A specified value for the `cursor` property.
pub type Cursor = generics::Cursor<CursorImage>;
/// A specified value for item of `image cursors`.
pub type CursorImage = generics::CursorImage<SpecifiedImageUrl, Number>;
impl Parse for Cursor {
/// cursor: [<url> [<number> <number>]?]# [auto | default | ...]
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let mut images = vec![];
loop {
match input.try(|input| CursorImage::parse(context, input)) {
Ok(image) => images.push(image),
Err(_) => break,
}
input.expect_comma()?;
}
Ok(Self {
images: images.into_boxed_slice(),
keyword: CursorKind::parse(context, input)?,
})
}
}
impl Parse for CursorKind {
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let location = input.current_source_location();
let ident = input.expect_ident()?;
CursorKind::from_css_keyword(&ident).map_err(|_| {
location.new_custom_error(StyleParseErrorKind::UnspecifiedError)
})
}
}
impl Parse for CursorImage {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Ok(Self {
url: SpecifiedImageUrl::parse(context, input)?,
hotspot: match input.try(|input| Number::parse(context, input)) {
Ok(number) => Some((number, Number::parse(context, input)?)),
Err(_) => None,
},
})
}
}
/// Specified value of `-moz-force-broken-image-icon` /// Specified value of `-moz-force-broken-image-icon`
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,

View file

@ -401,6 +401,7 @@ macro_rules! impl_to_css_for_predefined_type {
} }
impl_to_css_for_predefined_type!(f32); impl_to_css_for_predefined_type!(f32);
impl_to_css_for_predefined_type!(i8);
impl_to_css_for_predefined_type!(i32); impl_to_css_for_predefined_type!(i32);
impl_to_css_for_predefined_type!(u16); impl_to_css_for_predefined_type!(u16);
impl_to_css_for_predefined_type!(u32); impl_to_css_for_predefined_type!(u32);