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::selector_parser::{PseudoElement, RestyleDamage};
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 table::TableFlow;
use table_caption::TableCaptionFlow;

View file

@ -66,7 +66,7 @@ use style::values::computed::Gradient;
use style::values::computed::effects::SimpleShadow;
use style::values::generics::background::BackgroundSize;
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::ToCss;
use style_traits::cursor::CursorKind;
@ -3012,8 +3012,8 @@ impl ComputedValuesCursorUtility for ComputedValues {
#[inline]
fn get_cursor(&self, default_cursor: CursorKind) -> Option<CursorKind> {
match (
self.get_pointing().pointer_events,
&self.get_pointing().cursor,
self.get_inheritedui().pointer_events,
&self.get_inheritedui().cursor,
) {
(PointerEvents::None, _) => None,
(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),
// Statically check that DropShadow is impossible.
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::selector_parser::RestyleDamage;
use style::servo::restyle_damage::ServoRestyleDamage;
use style::values::computed::counters::ContentItem;
use style::values::generics::counters::ContentItem;
use text::TextRunScanner;
use traversal::InorderFlowTraversal;
@ -240,6 +240,9 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> {
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 style::dom::{NodeInfo, TNode};
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 {
/// 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() {
let style = self.as_element().unwrap().resolved_style();
return match style.as_ref().get_counters().content {
Content::Items(ref value) if !value.is_empty() => {
TextContent::GeneratedContent((*value).to_vec())
return TextContent::GeneratedContent(
match style.as_ref().get_counters().content {
Content::Items(ref value) => value.to_vec(),
_ => vec![],
}
_ => TextContent::GeneratedContent(vec![]),
};
);
}
TextContent::Text(self.node_text_content().into_boxed_str())

View file

@ -145,11 +145,11 @@ impl nsStyleImage {
match image {
GenericImage::Gradient(boxed_gradient) => self.set_gradient(*boxed_gradient),
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) => {
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);
// Set CropRect

View file

@ -7,7 +7,7 @@
use app_units::AU_PER_PX;
use app_units::Au;
use context::QuirksMode;
use cssparser::{BasicParseErrorKind, Parser, Token, RGBA};
use cssparser::{BasicParseErrorKind, Parser, RGBA};
use euclid::Size2D;
use euclid::TypedScale;
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::computed::{self, ToComputedValue};
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,
/// 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.
///
/// 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)
},
nsMediaFeature_ValueType::eResolution => {
MediaExpressionValue::Resolution(Resolution::parse(input)?)
MediaExpressionValue::Resolution(Resolution::parse(context, input)?)
},
nsMediaFeature_ValueType::eEnumerated => {
let location = input.current_source_location();

View file

@ -216,11 +216,7 @@ impl PseudoElement {
None
}
/// Constructs an atom from a string of text, and whether we're in a
/// user-agent stylesheet.
///
/// If we're not in a user-agent stylesheet, we will never parse anonymous
/// box pseudo-elements.
/// Constructs a pseudo-element from a string of text.
///
/// Returns `None` if the pseudo-element is not recognised.
#[inline]
@ -234,6 +230,10 @@ impl PseudoElement {
return Some(${pseudo_element_variant(pseudo)})
}
% endfor
// Alias "-moz-selection" to "selection" at parse time.
"-moz-selection" => {
return Some(PseudoElement::Selection);
}
_ => {
// FIXME: -moz-tree check should probably be
// 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::sugar::refptr::RefPtr;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use nsstring::nsCString;
use parser::{Parse, ParserContext};
use servo_arc::{Arc, RawOffsetArc};
use std::fmt::{self, Write};
use std::mem;
use style_traits::ParseError;
use style_traits::{CssWriter, ParseError, ToCss};
use values::computed::{Context, ToComputedValue};
/// A CSS url() value for gecko.
#[css(function = "url")]
@ -70,10 +73,8 @@ impl CssUrl {
self.as_str().chars().next().map_or(false, |c| c == '#')
}
/// Return the resolved 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.
/// Return the unresolved url as string, or the empty string if it's
/// invalid.
pub fn as_str(&self) -> &str {
&*self.serialization
}
@ -121,7 +122,7 @@ impl MallocSizeOf for CssUrl {
}
/// A specified url() value for general usage.
#[derive(Clone, Debug, SpecifiedValueInfo, ToComputedValue, ToCss)]
#[derive(Clone, Debug, SpecifiedValueInfo, ToCss)]
pub struct SpecifiedUrl {
/// The specified url value.
pub url: CssUrl,
@ -139,15 +140,11 @@ impl SpecifiedUrl {
debug_assert!(!ptr.is_null());
RefPtr::from_addrefed(ptr)
};
SpecifiedUrl { 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)
Self { url, url_value }
}
}
impl PartialEq for SpecifiedUrl {
fn eq(&self, other: &Self) -> bool {
self.url.eq(&other.url)
@ -179,7 +176,7 @@ impl MallocSizeOf for SpecifiedUrl {
/// A specified url() value for image.
///
/// 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 {
/// The specified url value.
pub url: CssUrl,
@ -190,16 +187,6 @@ pub struct 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.
pub fn parse_from_string<'a>(
url: String,
@ -208,20 +195,14 @@ impl SpecifiedImageUrl {
CssUrl::parse_from_string(url, context).map(Self::from_css_url)
}
/// 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)
}
/// Convert from nsStyleImageRequest to SpecifiedUrl.
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)
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)
};
Self { url, image_value }
}
}
@ -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()`.
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.
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_bindings::structs::{nscolor, StyleComplexColor};
use values::computed::Color as ComputedColor;
use values::generics::pointing::CaretColor;
use values::generics::ui::CaretColor;
impl From<nscolor> for StyleComplexColor {
fn from(other: nscolor) -> Self {

View file

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

View file

@ -10,6 +10,7 @@
%>
<%namespace name="helpers" file="/helpers.mako.rs" />
use Atom;
use app_units::Au;
use custom_properties::CustomPropertiesMap;
use gecko_bindings::bindings;
@ -60,7 +61,7 @@ use std::mem::{forget, uninitialized, transmute, zeroed};
use std::{cmp, ops, ptr};
use values::{self, CustomIdent, Either, KeyframesName, None_};
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::outline::OutlineStyle;
use values::generics::column::ColumnCount;
@ -126,8 +127,6 @@ impl ComputedValues {
}
pub fn pseudo(&self) -> Option<PseudoElement> {
use string_cache::Atom;
let atom = (self.0).mPseudoTag.mRawPtr;
if atom.is_null() {
return None;
@ -698,7 +697,7 @@ def set_gecko_property(ffi_name, expr):
}
SVGPaintKind::PaintServer(url) => {
unsafe {
bindings::Gecko_nsStyleSVGPaint_SetURLValue(paint, url.url_value.get());
bindings::Gecko_nsStyleSVGPaint_SetURLValue(paint, url.0.url_value.get());
}
}
SVGPaintKind::Color(color) => {
@ -738,8 +737,8 @@ def set_gecko_property(ffi_name, expr):
#[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
use values::computed::url::ComputedUrl;
use values::generics::svg::{SVGPaint, SVGPaintKind};
use values::specified::url::SpecifiedUrl;
use self::structs::nsStyleSVGPaintType;
use self::structs::nsStyleSVGFallbackType;
let ref paint = ${get_gecko_property(gecko_ffi_name)};
@ -761,7 +760,7 @@ def set_gecko_property(ffi_name, expr):
nsStyleSVGPaintType::eStyleSVGPaintType_Server => {
unsafe {
SVGPaintKind::PaintServer(
SpecifiedUrl::from_url_value_data(
ComputedUrl::from_url_value_data(
&(**paint.mPaint.mPaintServer.as_ref())._base
).unwrap()
)
@ -940,7 +939,7 @@ def set_gecko_property(ffi_name, expr):
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
match v {
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 => {
unsafe {
@ -962,16 +961,18 @@ def set_gecko_property(ffi_name, expr):
#[allow(non_snake_case)]
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() {
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"))
}
return UrlOrNone::none()
}
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>
@ -1861,7 +1862,6 @@ fn static_assert() {
pub fn clone_${value.name}(&self) -> longhands::${value.name}::computed_value::T {
use gecko_bindings::structs::{nsStyleGridLine_kMinLine, nsStyleGridLine_kMaxLine};
use string_cache::Atom;
longhands::${value.name}::computed_value::T {
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 {
<% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %>
use Atom;
use gecko_bindings::structs::nsTArray;
use nsstring::nsStringRepr;
use values::CustomIdent;
@ -2309,14 +2308,6 @@ fn static_assert() {
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) {
unsafe { Gecko_CopyFontFamilyFrom(&mut self.gecko.mFont, &other.gecko.mFont); }
self.gecko.mGenericID = other.gecko.mGenericID;
@ -2335,14 +2326,25 @@ fn static_assert() {
let shared_fontlist = unsafe { fontlist.mFontlist.mBasePtr.to_safe() };
if shared_fontlist.mNames.is_empty() {
let default = match fontlist.mDefaultFontType {
let default = fontlist.mDefaultFontType;
let default = match default {
FontFamilyType::eFamily_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"))
}
_ => panic!("Default generic must be serif or sans-serif"),
};
FontFamily(FontFamilyList::new(Box::new([default])))
} 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)]
pub fn set__x_text_zoom(&mut self, v: longhands::_x_text_zoom::computed_value::T) {
self.gecko.mAllowZoom = v.0;
@ -2699,8 +2713,8 @@ fn static_assert() {
}
#[allow(non_snake_case)]
pub fn reset__x_lang(&mut self, other: &Self) {
self.copy__x_lang_from(other)
pub fn clone__x_text_zoom(&self) -> longhands::_x_text_zoom::computed_value::T {
longhands::_x_text_zoom::computed_value::T(self.gecko.mAllowZoom)
}
${impl_simple("_moz_script_level", "mScriptLevel")}
@ -2777,7 +2791,6 @@ fn static_assert() {
}
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():
use gecko_bindings::structs::NS_FONT_VARIANT_ALTERNATES_${value.upper()};
% 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_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)]
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.;
@ -3286,7 +3306,6 @@ fn static_assert() {
use gecko_bindings::structs::nsCSSPropertyID::eCSSPropertyExtra_no_properties;
use gecko_bindings::structs::nsCSSPropertyID::eCSSPropertyExtra_variable;
use gecko_bindings::structs::nsCSSPropertyID::eCSSProperty_UNKNOWN;
use Atom;
let property = self.gecko.mTransitions[index].mProperty;
if property == eCSSProperty_UNKNOWN || property == eCSSPropertyExtra_variable {
@ -3384,7 +3403,6 @@ fn static_assert() {
pub fn animation_name_at(&self, index: usize)
-> longhands::animation_name::computed_value::SingleComputedValue {
use properties::longhands::animation_name::single_value::SpecifiedValue as AnimationName;
use Atom;
let atom = self.gecko.mAnimations[index].mName.mRawPtr;
if atom == atom!("").as_ptr() {
@ -3590,7 +3608,6 @@ fn static_assert() {
use properties::longhands::will_change::computed_value::T;
use gecko_bindings::structs::nsAtom;
use values::CustomIdent;
use Atom;
if self.gecko.mWillChange.len() == 0 {
return T::Auto
@ -4106,12 +4123,8 @@ fn static_assert() {
}
UrlOrNone::Url(ref url) => {
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 {
use values::specified::url::SpecifiedImageUrl;
use values::computed::url::ComputedImageUrl;
if self.gecko.mListStyleImage.mRawPtr.is_null() {
return UrlOrNone::None;
@ -4133,8 +4146,9 @@ fn static_assert() {
unsafe {
let ref gecko_image_request = *self.gecko.mListStyleImage.mRawPtr;
UrlOrNone::Url(SpecifiedImageUrl::from_image_request(gecko_image_request)
.expect("mListStyleImage could not convert to SpecifiedImageUrl"))
UrlOrNone::Url(ComputedImageUrl::from_image_request(
gecko_image_request
).expect("mListStyleImage could not convert to ComputedImageUrl"))
}
}
@ -4269,6 +4283,13 @@ fn static_assert() {
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')}
</%self:impl_trait>
@ -4473,7 +4494,7 @@ fn static_assert() {
},
Url(ref url) => {
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 {
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_BRIGHTNESS;
use gecko_bindings::structs::NS_STYLE_FILTER_CONTRAST;
@ -4534,7 +4555,7 @@ fn static_assert() {
NS_STYLE_FILTER_URL => {
filters.push(unsafe {
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":
ShapeSource::ImageOrUrl(ref url) => {
unsafe {
bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.url_value.get())
bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.0.url_value.get())
}
}
% elif ident == "shape_outside":
@ -5213,10 +5234,28 @@ clip-path
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)]
pub fn set__moz_context_properties<I>(&mut self, v: I)
where I: IntoIterator<Item = longhands::_moz_context_properties::computed_value::single_value::T>,
I::IntoIter: ExactSizeIterator
where
I: IntoIterator<Item = longhands::_moz_context_properties::computed_value::single_value::T>,
I::IntoIter: ExactSizeIterator
{
let v = v.into_iter();
unsafe {
@ -5266,7 +5305,7 @@ clip-path
}
</%self:impl_trait>
<%self:impl_trait style_struct_name="Pointing"
<%self:impl_trait style_struct_name="InheritedUI"
skip_longhands="cursor caret-color">
pub fn set_cursor(&mut self, v: longhands::cursor::computed_value::T) {
use style_traits::cursor::CursorKind;
@ -5322,15 +5361,10 @@ clip-path
unsafe {
Gecko_SetCursorImageValue(
&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 {
Some((x, y)) => {
self.gecko.mCursorImages[i].mHaveHotspot = true;
@ -5356,9 +5390,9 @@ clip-path
}
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 values::specified::url::SpecifiedImageUrl;
let keyword = match self.gecko.mCursor as u32 {
structs::NS_STYLE_CURSOR_AUTO => CursorKind::Auto,
@ -5403,8 +5437,8 @@ clip-path
let images = self.gecko.mCursorImages.iter().map(|gecko_cursor_image| {
let url = unsafe {
let gecko_image_request = gecko_cursor_image.mImage.mRawPtr.as_ref().unwrap();
SpecifiedImageUrl::from_image_request(&gecko_image_request)
.expect("mCursorImages.mImage could not convert to SpecifiedImageUrl")
ComputedImageUrl::from_image_request(&gecko_image_request)
.expect("mCursorImages.mImage could not convert to ComputedImageUrl")
};
let hotspot =
@ -5463,7 +5497,7 @@ clip-path
pub fn set_content(&mut self, v: longhands::content::computed_value::T, device: &Device) {
use values::CustomIdent;
use values::computed::counters::{Content, ContentItem};
use values::generics::counters::{Content, ContentItem};
use values::generics::CounterStyleOrNone;
use gecko_bindings::structs::nsStyleContentData;
use gecko_bindings::structs::nsStyleContentAttr;
@ -5590,7 +5624,7 @@ clip-path
unsafe {
bindings::Gecko_SetContentDataImageValue(
&mut self.gecko.mContents[i],
url.image_value.get(),
url.0.image_value.get(),
)
}
}
@ -5615,10 +5649,10 @@ clip-path
use {Atom, Namespace};
use gecko::conversions::string_from_chars_pointer;
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::generics::CounterStyleOrNone;
use values::specified::url::SpecifiedImageUrl;
use values::specified::Attr;
if self.gecko.mContents.is_empty() {
@ -5679,8 +5713,8 @@ clip-path
let gecko_image_request =
&**gecko_content.mContent.mImage.as_ref();
ContentItem::Url(
SpecifiedImageUrl::from_image_request(gecko_image_request)
.expect("mContent could not convert to SpecifiedImageUrl")
ComputedImageUrl::from_image_request(gecko_image_request)
.expect("mContent could not convert to ComputedImageUrl")
)
}
},
@ -5719,7 +5753,6 @@ clip-path
) -> longhands::counter_${counter_property.lower()}::computed_value::T {
use values::generics::counters::CounterPair;
use values::CustomIdent;
use gecko_string_cache::Atom;
longhands::counter_${counter_property.lower()}::computed_value::T::new(
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,
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)">
#[allow(unused_imports)]
use parser::Parse;

View file

@ -54,7 +54,7 @@ ${helpers.predefined_type(
${helpers.single_keyword("background-attachment",
"scroll fixed" + (" local" if product == "gecko" else ""),
vector=True,
gecko_constant_prefix="NS_STYLE_IMAGELAYER_ATTACHMENT",
gecko_enum_prefix="StyleImageLayerAttachment",
spec="https://drafts.csswg.org/css-backgrounds/#the-background-attachment",
animation_value_type="discrete",
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",
initial_value=None,
vector=True,
need_index=True,
animation_value_type="none",
products="gecko",
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" />
<% data.new_style_struct("Pointing", inherited=True, gecko_name="UserInterface") %>
<% data.new_style_struct("InheritedUI", inherited=True, gecko_name="UserInterface") %>
${helpers.predefined_type("cursor",
"Cursor",
@ -44,7 +44,7 @@ ${helpers.single_keyword("-moz-user-focus",
${helpers.predefined_type(
"caret-color",
"CaretColor",
"generics::pointing::CaretColor::Auto",
"generics::ui::CaretColor::Auto",
spec="https://drafts.csswg.org/css-ui/#caret-color",
animation_value_type="AnimatedCaretColor",
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_table.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/margin.mako.rs" />
<%include file="/longhand/outline.mako.rs" />
<%include file="/longhand/padding.mako.rs" />
<%include file="/longhand/pointing.mako.rs" />
<%include file="/longhand/position.mako.rs" />
<%include file="/longhand/table.mako.rs" />
<%include file="/longhand/text.mako.rs" />
@ -2399,6 +2399,18 @@ pub mod style_structs {
-> longhands::${longhand.ident}::computed_value::SingleComputedValue {
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
% endfor
@ -2631,10 +2643,10 @@ impl ComputedValuesInner {
/// ineffective, and would yield an empty `::before` or `::after`
/// pseudo-element.
pub fn ineffective_content_property(&self) -> bool {
use properties::longhands::content::computed_value::T;
use values::generics::counters::Content;
match self.get_counters().content {
T::Normal | T::None => true,
T::Items(ref items) => items.is_empty(),
Content::Normal | Content::None => true,
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::computed::{Angle, Number};
use values::computed::length::Length;
#[cfg(feature = "gecko")]
use values::computed::url::ComputedUrl;
use values::distance::{ComputeSquaredDistance, SquaredDistance};
use values::generics::effects::BoxShadow as GenericBoxShadow;
use values::generics::effects::Filter as GenericFilter;
@ -42,11 +44,11 @@ pub struct FilterList(pub Vec<Filter>);
/// An animated value for a single `filter`.
#[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`.
#[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.
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::MaxLength as ComputedMaxLength;
use values::computed::MozLength as ComputedMozLength;
#[cfg(feature = "servo")]
use values::computed::url::ComputedUrl;
use values::specified::url::SpecifiedUrl;
pub mod color;
pub mod effects;
@ -260,8 +258,6 @@ macro_rules! trivial_to_animated_value {
trivial_to_animated_value!(Au);
trivial_to_animated_value!(ComputedAngle);
trivial_to_animated_value!(SpecifiedUrl);
#[cfg(feature = "servo")]
trivial_to_animated_value!(ComputedUrl);
trivial_to_animated_value!(bool);
trivial_to_animated_value!(f32);

View file

@ -4,22 +4,10 @@
//! Computed values for counter properties
#[cfg(feature = "servo")]
use computed_values::list_style_type::T as ListStyleType;
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::computed::url::ComputedImageUrl;
use values::generics::counters as generics;
use values::generics::counters::CounterIncrement as GenericCounterIncrement;
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.
pub type CounterIncrement = GenericCounterIncrement<i32>;
@ -27,134 +15,9 @@ pub type CounterIncrement = GenericCounterIncrement<i32>;
/// A computed value for the `counter-increment` property.
pub type CounterReset = GenericCounterReset<i32>;
impl Content {
/// Set `content` property to `normal`.
#[inline]
pub fn normal() -> Self {
Content::Normal
}
/// A computed value for the `content` property.
pub type Content = generics::Content<ComputedImageUrl>;
#[cfg(feature = "servo")]
fn parse_counter_style(input: &mut Parser) -> ListStyleType {
input
.try(|input| {
input.expect_comma()?;
ListStyleType::parse(input)
})
.unwrap_or(ListStyleType::Decimal)
}
/// A computed content item.
pub type ContentItem = generics::ContentItem<ComputedImageUrl>;
#[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::color::RGBAColor;
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::Filter as GenericFilter;
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`.
#[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`.
#[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.
pub type SimpleShadow = GenericSimpleShadow<Option<RGBAColor>, Length, NonNegativeLength>;

View file

@ -56,6 +56,7 @@ pub use self::inherited_box::{ImageOrientation, Orientation};
#[cfg(feature = "gecko")]
pub use self::gecko::ScrollSnapPoint;
pub use self::rect::LengthOrNumberRect;
pub use self::resolution::Resolution;
pub use super::{Auto, Either, None_};
pub use super::specified::{BorderStyle, TextDecorationLine};
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::outline::OutlineStyle;
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::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind};
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::transform::{Rotate, Scale, TimingFunction, Transform, TransformOperation};
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")]
pub mod align;
@ -104,9 +104,9 @@ pub mod length;
pub mod list;
pub mod outline;
pub mod percentage;
pub mod pointing;
pub mod position;
pub mod rect;
pub mod resolution;
pub mod svg;
pub mod table;
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
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;
/// 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.
#[cfg(feature = "servo")]
use computed_values::list_style_type::T as ListStyleType;
use std::ops::Deref;
use values::CustomIdent;
#[cfg(feature = "gecko")]
use values::generics::CounterStyleOrNone;
#[cfg(feature = "gecko")]
use values::specified::Attr;
/// A name / value pair for counters.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
@ -74,3 +80,78 @@ impl<I> Default for Counters<I> {
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.
#[cfg(feature = "gecko")]
use values::specified::url::SpecifiedUrl;
/// A generic value for a single `box-shadow`.
#[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToAnimatedValue, ToAnimatedZero, ToCss)]
@ -23,9 +20,10 @@ pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
/// A generic value for a single `filter`.
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[animation(no_bound(Url))]
#[derive(Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss)]
pub enum Filter<Angle, Factor, Length, DropShadow> {
pub enum Filter<Angle, Factor, Length, DropShadow, Url> {
/// `blur(<length>)`
#[css(function)]
Blur(Length),
@ -58,8 +56,7 @@ pub enum Filter<Angle, Factor, Length, DropShadow> {
DropShadow(DropShadow),
/// `<url>`
#[animation(error)]
#[cfg(feature = "gecko")]
Url(SpecifiedUrl),
Url(Url),
}
/// 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 grid;
pub mod image;
pub mod pointing;
pub mod position;
pub mod rect;
pub mod size;
pub mod svg;
pub mod text;
pub mod transform;
pub mod ui;
pub mod url;
// 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
* 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 style_traits::{CssWriter, ToCss};

View file

@ -8,17 +8,18 @@
use computed_values::list_style_type::T as ListStyleType;
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 as generics;
use values::generics::counters::CounterIncrement as GenericCounterIncrement;
use values::generics::counters::CounterPair;
use values::generics::counters::CounterReset as GenericCounterReset;
#[cfg(feature = "gecko")]
use values::specified::Attr;
use values::specified::Integer;
#[cfg(feature = "gecko")]
use values::specified::url::SpecifiedImageUrl;
/// 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.
///
/// https://drafts.csswg.org/css-content/#propdef-content
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum Content {
/// `normal` reserved keyword.
Normal,
/// `none` reserved keyword.
None,
/// `-moz-alt-content`.
pub type Content = generics::Content<SpecifiedImageUrl>;
/// The specified value for a content item in the `content` property.
pub type ContentItem = generics::ContentItem<SpecifiedImageUrl>;
impl Content {
#[cfg(feature = "servo")]
fn parse_counter_style(_: &ParserContext, input: &mut Parser) -> ListStyleType {
input
.try(|input| {
input.expect_comma()?;
ListStyleType::parse(input)
})
.unwrap_or(ListStyleType::Decimal)
}
#[cfg(feature = "gecko")]
MozAltContent,
/// Content items.
Items(#[css(iterable)] Box<[ContentItem]>),
fn parse_counter_style(context: &ParserContext, input: &mut Parser) -> CounterStyleOrNone {
input
.try(|input| {
input.expect_comma()?;
CounterStyleOrNone::parse(context, input)
})
.unwrap_or(CounterStyleOrNone::decimal())
}
}
/// Items for the `content` property.
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
ToComputedValue, ToCss)]
pub enum ContentItem {
/// 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)`
#[cfg(feature = "gecko")]
Url(SpecifiedImageUrl),
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(generics::Content::Normal);
}
if input
.try(|input| input.expect_ident_matching("none"))
.is_ok()
{
return Ok(generics::Content::None);
}
#[cfg(feature = "gecko")]
{
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")]
{
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`.
#[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`.
#[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`.
#[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::outline::OutlineStyle;
pub use self::rect::LengthOrNumberRect;
pub use self::resolution::Resolution;
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::{PositionComponent, ZIndex};
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::transform::{Rotate, Scale, TimingFunction, Transform};
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;
#[cfg(feature = "gecko")]
@ -104,9 +104,9 @@ pub mod length;
pub mod list;
pub mod outline;
pub mod percentage;
pub mod pointing;
pub mod position;
pub mod rect;
pub mod resolution;
pub mod source_size_list;
pub mod svg;
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 std::fmt::{self, Write};
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`
#[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!(i8);
impl_to_css_for_predefined_type!(i32);
impl_to_css_for_predefined_type!(u16);
impl_to_css_for_predefined_type!(u32);