/* 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/. */ <%namespace name="helpers" file="/helpers.mako.rs" /> <% from data import Keyword, Method, to_rust_ident %> <% data.new_style_struct("Box", inherited=False, gecko_name="Display") %> // TODO(SimonSapin): don't parse `inline-table`, since we don't support it <%helpers:longhand name="display" need_clone="True" animatable="False" custom_cascade="${product == 'servo'}"> <% values = """inline block inline-block table inline-table table-row-group table-header-group table-footer-group table-row table-column-group table-column table-cell table-caption list-item flex none """.split() if product == "gecko": values += "-moz-box -moz-inline-box".split() experimental_values = set("flex".split()) %> pub use self::computed_value::T as SpecifiedValue; use values::computed::ComputedValueAsSpecified; use values::NoViewportPercentage; impl NoViewportPercentage for SpecifiedValue {} pub mod computed_value { #[allow(non_camel_case_types)] #[derive(Clone, Eq, PartialEq, Copy, Hash, RustcEncodable, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] pub enum T { % for value in values: ${to_rust_ident(value)}, % endfor } impl ::cssparser::ToCss for T { fn to_css(&self, dest: &mut W) -> ::std::fmt::Result where W: ::std::fmt::Write { match *self { % for value in values: T::${to_rust_ident(value)} => dest.write_str("${value}"), % endfor } } } } #[inline] pub fn get_initial_value() -> computed_value::T { computed_value::T::${to_rust_ident(values[0])} } pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result { match_ignore_ascii_case! { try!(input.expect_ident()), % for value in values: "${value}" => { % if value in experimental_values: if !::util::prefs::PREFS.get("layout.${value}.enabled") .as_boolean().unwrap_or(false) { return Err(()) } % endif Ok(computed_value::T::${to_rust_ident(value)}) }, % endfor _ => Err(()) } } impl ComputedValueAsSpecified for SpecifiedValue {} % if product == "servo": fn cascade_property_custom(_declaration: &PropertyDeclaration, _inherited_style: &ComputedValues, context: &mut computed::Context, _seen: &mut PropertyBitField, _cacheable: &mut bool, _error_reporter: &mut StdBox) { longhands::_servo_display_for_hypothetical_box::derive_from_display(context); longhands::_servo_text_decorations_in_effect::derive_from_display(context); longhands::_servo_under_display_none::derive_from_display(context); } % endif ${helpers.single_keyword("position", "static absolute relative fixed", need_clone=True, extra_gecko_values="sticky", animatable=False)} <%helpers:single_keyword_computed name="float" values="none left right" animatable="False" need_clone="True" gecko_enum_prefix="StyleFloat" gecko_ffi_name="mFloat"> use values::NoViewportPercentage; impl NoViewportPercentage for SpecifiedValue {} impl ToComputedValue for SpecifiedValue { type ComputedValue = computed_value::T; #[inline] fn to_computed_value(&self, context: &Context) -> computed_value::T { let positioned = matches!(context.style().get_box().clone_position(), longhands::position::SpecifiedValue::absolute | longhands::position::SpecifiedValue::fixed); if positioned { SpecifiedValue::none } else { *self } } } ${helpers.single_keyword("clear", "none left right both", animatable=False, gecko_ffi_name="mBreakType", gecko_enum_prefix="StyleClear")} <%helpers:longhand name="-servo-display-for-hypothetical-box" animatable="False" derived_from="display" products="servo"> pub use super::display::{SpecifiedValue, get_initial_value}; pub use super::display::{parse}; pub mod computed_value { pub type T = super::SpecifiedValue; } #[inline] pub fn derive_from_display(context: &mut Context) { let d = context.style().get_box().clone_display(); context.mutate_style().mutate_box().set__servo_display_for_hypothetical_box(d); } <%helpers:longhand name="vertical-align" animatable="True"> use cssparser::ToCss; use std::fmt; <% vertical_align = data.longhands_by_name["vertical-align"] %> <% vertical_align.keyword = Keyword("vertical-align", "baseline sub super top text-top middle bottom text-bottom", extra_gecko_values="middle-with-baseline") %> <% vertical_align_keywords = vertical_align.keyword.values_for(product) %> use values::HasViewportPercentage; impl HasViewportPercentage for SpecifiedValue { fn has_viewport_percentage(&self) -> bool { match *self { SpecifiedValue::LengthOrPercentage(length) => length.has_viewport_percentage(), _ => false } } } #[allow(non_camel_case_types)] #[derive(Debug, Clone, PartialEq, Copy)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum SpecifiedValue { % for keyword in vertical_align_keywords: ${to_rust_ident(keyword)}, % endfor LengthOrPercentage(specified::LengthOrPercentage), } impl ToCss for SpecifiedValue { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match *self { % for keyword in vertical_align_keywords: SpecifiedValue::${to_rust_ident(keyword)} => dest.write_str("${keyword}"), % endfor SpecifiedValue::LengthOrPercentage(value) => value.to_css(dest), } } } /// baseline | sub | super | top | text-top | middle | bottom | text-bottom /// | | pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result { input.try(specified::LengthOrPercentage::parse) .map(SpecifiedValue::LengthOrPercentage) .or_else(|()| { match_ignore_ascii_case! { try!(input.expect_ident()), % for keyword in vertical_align_keywords: "${keyword}" => Ok(SpecifiedValue::${to_rust_ident(keyword)}), % endfor _ => Err(()) } }) } pub mod computed_value { use app_units::Au; use std::fmt; use values::LocalToCss; use values::{CSSFloat, computed}; #[allow(non_camel_case_types)] #[derive(PartialEq, Copy, Clone, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum T { % for keyword in vertical_align_keywords: ${to_rust_ident(keyword)}, % endfor LengthOrPercentage(computed::LengthOrPercentage), } impl ::cssparser::ToCss for T { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match *self { % for keyword in vertical_align_keywords: T::${to_rust_ident(keyword)} => dest.write_str("${keyword}"), % endfor T::LengthOrPercentage(value) => value.to_css(dest), } } } } #[inline] pub fn get_initial_value() -> computed_value::T { computed_value::T::baseline } impl ToComputedValue for SpecifiedValue { type ComputedValue = computed_value::T; #[inline] fn to_computed_value(&self, context: &Context) -> computed_value::T { match *self { % for keyword in vertical_align_keywords: SpecifiedValue::${to_rust_ident(keyword)} => { computed_value::T::${to_rust_ident(keyword)} } % endfor SpecifiedValue::LengthOrPercentage(value) => computed_value::T::LengthOrPercentage(value.to_computed_value(context)), } } } // CSS 2.1, Section 11 - Visual effects // Non-standard, see https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-clip-box#Specifications ${helpers.single_keyword("-servo-overflow-clip-box", "padding-box content-box", products="servo", animatable=False, internal=True)} ${helpers.single_keyword("overflow-clip-box", "padding-box content-box", products="gecko", animatable=False, internal=True)} // FIXME(pcwalton, #2742): Implement scrolling for `scroll` and `auto`. ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", need_clone=True, animatable=False, gecko_constant_prefix="NS_STYLE_OVERFLOW")} // FIXME(pcwalton, #2742): Implement scrolling for `scroll` and `auto`. <%helpers:longhand name="overflow-y" need_clone="True" animatable="False"> use super::overflow_x; use cssparser::ToCss; use std::fmt; pub use self::computed_value::T as SpecifiedValue; use values::NoViewportPercentage; impl NoViewportPercentage for SpecifiedValue {} impl ToCss for SpecifiedValue { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { self.0.to_css(dest) } } pub mod computed_value { #[derive(Debug, Clone, Copy, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct T(pub super::super::overflow_x::computed_value::T); } impl ToComputedValue for SpecifiedValue { type ComputedValue = computed_value::T; #[inline] fn to_computed_value(&self, context: &Context) -> computed_value::T { computed_value::T(self.0.to_computed_value(context)) } } pub fn get_initial_value() -> computed_value::T { computed_value::T(overflow_x::get_initial_value()) } pub fn parse(context: &ParserContext, input: &mut Parser) -> Result { overflow_x::parse(context, input).map(SpecifiedValue) } // TODO(pcwalton): Multiple transitions. <%helpers:longhand name="transition-duration" need_index="True" animatable="False"> use values::computed::ComputedValueAsSpecified; use values::specified::Time; pub use self::computed_value::T as SpecifiedValue; pub use values::specified::Time as SingleSpecifiedValue; use values::NoViewportPercentage; impl NoViewportPercentage for SpecifiedValue {} pub mod computed_value { use cssparser::ToCss; use std::fmt; use values::computed::{Context, ToComputedValue}; pub use values::computed::Time as SingleComputedValue; #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct T(pub Vec); impl ToCss for T { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { if self.0.is_empty() { return dest.write_str("none") } for (i, value) in self.0.iter().enumerate() { if i != 0 { try!(dest.write_str(", ")) } try!(value.to_css(dest)) } Ok(()) } } } impl ComputedValueAsSpecified for SpecifiedValue {} #[inline] pub fn parse_one(input: &mut Parser) -> Result { Time::parse(input) } #[inline] pub fn get_initial_value() -> computed_value::T { computed_value::T(vec![get_initial_single_value()]) } #[inline] pub fn get_initial_single_value() -> Time { Time(0.0) } pub fn parse(_: &ParserContext, input: &mut Parser) -> Result { Ok(SpecifiedValue(try!(input.parse_comma_separated(parse_one)))) } // TODO(pcwalton): Lots more timing functions. // TODO(pcwalton): Multiple transitions. <%helpers:longhand name="transition-timing-function" need_index="True" animatable="False"> use self::computed_value::{StartEnd, TransitionTimingFunction}; use euclid::point::{Point2D, TypedPoint2D}; use std::marker::PhantomData; pub use self::computed_value::SingleComputedValue as SingleSpecifiedValue; pub use self::computed_value::T as SpecifiedValue; // FIXME: This could use static variables and const functions when they are available. #[inline(always)] fn ease() -> TransitionTimingFunction { TransitionTimingFunction::CubicBezier(TypedPoint2D::new(0.25, 0.1), TypedPoint2D::new(0.25, 1.0)) } #[inline(always)] fn linear() -> TransitionTimingFunction { TransitionTimingFunction::CubicBezier(TypedPoint2D::new(0.0, 0.0), TypedPoint2D::new(1.0, 1.0)) } #[inline(always)] fn ease_in() -> TransitionTimingFunction { TransitionTimingFunction::CubicBezier(TypedPoint2D::new(0.42, 0.0), TypedPoint2D::new(1.0, 1.0)) } #[inline(always)] fn ease_out() -> TransitionTimingFunction { TransitionTimingFunction::CubicBezier(TypedPoint2D::new(0.0, 0.0), TypedPoint2D::new(0.58, 1.0)) } #[inline(always)] fn ease_in_out() -> TransitionTimingFunction { TransitionTimingFunction::CubicBezier(TypedPoint2D::new(0.42, 0.0), TypedPoint2D::new(0.58, 1.0)) } static STEP_START: TransitionTimingFunction = TransitionTimingFunction::Steps(1, StartEnd::Start); static STEP_END: TransitionTimingFunction = TransitionTimingFunction::Steps(1, StartEnd::End); pub mod computed_value { use cssparser::ToCss; use euclid::point::Point2D; use std::fmt; pub use self::TransitionTimingFunction as SingleComputedValue; #[derive(Copy, Clone, Debug, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum TransitionTimingFunction { CubicBezier(Point2D, Point2D), Steps(u32, StartEnd), } impl ToCss for TransitionTimingFunction { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match *self { TransitionTimingFunction::CubicBezier(p1, p2) => { try!(dest.write_str("cubic-bezier(")); try!(p1.x.to_css(dest)); try!(dest.write_str(", ")); try!(p1.y.to_css(dest)); try!(dest.write_str(", ")); try!(p2.x.to_css(dest)); try!(dest.write_str(", ")); try!(p2.y.to_css(dest)); dest.write_str(")") } TransitionTimingFunction::Steps(steps, start_end) => { try!(dest.write_str("steps(")); try!(steps.to_css(dest)); try!(dest.write_str(", ")); try!(start_end.to_css(dest)); dest.write_str(")") } } } } #[derive(Copy, Clone, Debug, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum StartEnd { Start, End, } impl ToCss for StartEnd { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match *self { StartEnd::Start => dest.write_str("start"), StartEnd::End => dest.write_str("end"), } } } #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct T(pub Vec); impl ToCss for T { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { if self.0.is_empty() { return dest.write_str("none") } for (i, value) in self.0.iter().enumerate() { if i != 0 { try!(dest.write_str(", ")) } try!(value.to_css(dest)) } Ok(()) } } } use values::NoViewportPercentage; impl NoViewportPercentage for SpecifiedValue {} impl ToComputedValue for SpecifiedValue { type ComputedValue = computed_value::T; #[inline] fn to_computed_value(&self, _: &Context) -> computed_value::T { (*self).clone() } } #[inline] pub fn get_initial_value() -> computed_value::T { computed_value::T(vec![get_initial_single_value()]) } #[inline] pub fn get_initial_single_value() -> TransitionTimingFunction { ease() } pub fn parse_one(input: &mut Parser) -> Result { if let Ok(function_name) = input.try(|input| input.expect_function()) { return match_ignore_ascii_case! { function_name, "cubic-bezier" => { let (mut p1x, mut p1y, mut p2x, mut p2y) = (0.0, 0.0, 0.0, 0.0); try!(input.parse_nested_block(|input| { p1x = try!(specified::parse_number(input)); try!(input.expect_comma()); p1y = try!(specified::parse_number(input)); try!(input.expect_comma()); p2x = try!(specified::parse_number(input)); try!(input.expect_comma()); p2y = try!(specified::parse_number(input)); Ok(()) })); let (p1, p2) = (Point2D::new(p1x, p1y), Point2D::new(p2x, p2y)); Ok(TransitionTimingFunction::CubicBezier(p1, p2)) }, "steps" => { let (mut step_count, mut start_end) = (0, computed_value::StartEnd::End); try!(input.parse_nested_block(|input| { step_count = try!(specified::parse_integer(input)); if input.try(|input| input.expect_comma()).is_ok() { start_end = try!(match_ignore_ascii_case! { try!(input.expect_ident()), "start" => Ok(computed_value::StartEnd::Start), "end" => Ok(computed_value::StartEnd::End), _ => Err(()) }); } Ok(()) })); Ok(TransitionTimingFunction::Steps(step_count as u32, start_end)) }, _ => Err(()) } } match_ignore_ascii_case! { try!(input.expect_ident()), "ease" => Ok(ease()), "linear" => Ok(linear()), "ease-in" => Ok(ease_in()), "ease-out" => Ok(ease_out()), "ease-in-out" => Ok(ease_in_out()), "step-start" => Ok(STEP_START), "step-end" => Ok(STEP_END), _ => Err(()) } } pub fn parse(_: &ParserContext, input: &mut Parser) -> Result { Ok(SpecifiedValue(try!(input.parse_comma_separated(parse_one)))) } <%helpers:longhand name="transition-property" need_index="True" animatable="False"> pub use self::computed_value::SingleComputedValue as SingleSpecifiedValue; pub use self::computed_value::T as SpecifiedValue; pub mod computed_value { use cssparser::ToCss; use std::fmt; // NB: Can't generate the type here because it needs all the longhands // generated beforehand. pub use properties::animated_properties::TransitionProperty; pub use properties::animated_properties::TransitionProperty as SingleComputedValue; #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct T(pub Vec); impl ToCss for T { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { if self.0.is_empty() { return dest.write_str("none") } for (i, value) in self.0.iter().enumerate() { if i != 0 { try!(dest.write_str(", ")) } try!(value.to_css(dest)) } Ok(()) } } } #[inline] pub fn get_initial_value() -> computed_value::T { computed_value::T(Vec::new()) } #[inline] pub fn parse_one(input: &mut Parser) -> Result { SingleSpecifiedValue::parse(input) } pub fn parse(_: &ParserContext, input: &mut Parser) -> Result { Ok(SpecifiedValue(try!(input.parse_comma_separated(SingleSpecifiedValue::parse)))) } use values::NoViewportPercentage; impl NoViewportPercentage for SpecifiedValue {} impl ToComputedValue for SpecifiedValue { type ComputedValue = computed_value::T; #[inline] fn to_computed_value(&self, _: &Context) -> computed_value::T { (*self).clone() } } <%helpers:longhand name="transition-delay" need_index="True" animatable="False"> pub use properties::longhands::transition_duration::{SingleSpecifiedValue, SpecifiedValue}; pub use properties::longhands::transition_duration::{computed_value}; pub use properties::longhands::transition_duration::{get_initial_single_value}; pub use properties::longhands::transition_duration::{get_initial_value, parse, parse_one}; <%helpers:longhand name="animation-name" need_index="True" animatable="False", allowed_in_keyframe_block="False"> use values::computed::ComputedValueAsSpecified; use values::NoViewportPercentage; pub mod computed_value { use cssparser::ToCss; use std::fmt; use string_cache::Atom; pub use string_cache::Atom as SingleComputedValue; #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct T(pub Vec); impl ToCss for T { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { if self.0.is_empty() { return dest.write_str("none") } for (i, name) in self.0.iter().enumerate() { if i != 0 { try!(dest.write_str(", ")); } // NB: to_string() needed due to geckolib backend. try!(dest.write_str(&*name.to_string())); } Ok(()) } } } pub use self::computed_value::T as SpecifiedValue; impl NoViewportPercentage for SpecifiedValue {} pub use string_cache::Atom as SingleSpecifiedValue; #[inline] pub fn parse_one(input: &mut Parser) -> Result { use cssparser::Token; Ok(match input.next() { Ok(Token::Ident(ref value)) if value != "none" => Atom::from(&**value), Ok(Token::QuotedString(value)) => Atom::from(&*value), _ => return Err(()), }) } #[inline] pub fn get_initial_value() -> computed_value::T { computed_value::T(vec![]) } pub fn parse(_: &ParserContext, input: &mut Parser) -> Result { use std::borrow::Cow; Ok(SpecifiedValue(try!(input.parse_comma_separated(parse_one)))) } impl ComputedValueAsSpecified for SpecifiedValue {} <%helpers:longhand name="animation-duration" need_index="True" animatable="False", allowed_in_keyframe_block="False"> pub use super::transition_duration::computed_value; pub use super::transition_duration::{get_initial_value, get_initial_single_value}; pub use super::transition_duration::{parse, parse_one}; pub use super::transition_duration::SpecifiedValue; pub use super::transition_duration::SingleSpecifiedValue; <%helpers:longhand name="animation-timing-function" need_index="True" animatable="False", allowed_in_keyframe_block="False"> pub use super::transition_timing_function::computed_value; pub use super::transition_timing_function::{get_initial_value, get_initial_single_value}; pub use super::transition_timing_function::{parse, parse_one}; pub use super::transition_timing_function::SpecifiedValue; pub use super::transition_timing_function::SingleSpecifiedValue; <%helpers:longhand name="animation-iteration-count" need_index="True" animatable="False", allowed_in_keyframe_block="False"> use values::computed::ComputedValueAsSpecified; use values::NoViewportPercentage; pub mod computed_value { use cssparser::ToCss; use std::fmt; pub use self::AnimationIterationCount as SingleComputedValue; #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum AnimationIterationCount { Number(u32), Infinite, } impl ToCss for AnimationIterationCount { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match *self { AnimationIterationCount::Number(n) => write!(dest, "{}", n), AnimationIterationCount::Infinite => dest.write_str("infinite"), } } } #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct T(pub Vec); impl ToCss for T { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { if self.0.is_empty() { return dest.write_str("none") } for (i, value) in self.0.iter().enumerate() { if i != 0 { try!(dest.write_str(", ")) } try!(value.to_css(dest)) } Ok(()) } } } pub use self::computed_value::AnimationIterationCount; pub use self::computed_value::AnimationIterationCount as SingleSpecifiedValue; pub use self::computed_value::T as SpecifiedValue; impl NoViewportPercentage for SpecifiedValue {} #[inline] pub fn get_initial_single_value() -> AnimationIterationCount { AnimationIterationCount::Number(1) } pub fn parse_one(input: &mut Parser) -> Result { if input.try(|input| input.expect_ident_matching("infinite")).is_ok() { Ok(AnimationIterationCount::Infinite) } else { let number = try!(input.expect_integer()); if number < 0 { return Err(()); } Ok(AnimationIterationCount::Number(number as u32)) } } #[inline] pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result { Ok(SpecifiedValue(try!(input.parse_comma_separated(parse_one)))) } #[inline] pub fn get_initial_value() -> computed_value::T { computed_value::T(vec![get_initial_single_value()]) } impl ComputedValueAsSpecified for SpecifiedValue {} ${helpers.keyword_list("animation-direction", "normal reverse alternate alternate-reverse", need_index=True, animatable=False, allowed_in_keyframe_block=False)} // animation-play-state is the exception to the rule for allowed_in_keyframe_block: // https://drafts.csswg.org/css-animations/#keyframes ${helpers.keyword_list("animation-play-state", "running paused", need_clone=True, need_index=True, animatable=False, allowed_in_keyframe_block=True)} ${helpers.keyword_list("animation-fill-mode", "none forwards backwards both", need_index=True, animatable=False, allowed_in_keyframe_block=False)} <%helpers:longhand name="animation-delay" need_index="True" animatable="False", allowed_in_keyframe_block="False"> pub use super::transition_duration::computed_value; pub use super::transition_duration::{get_initial_value, get_initial_single_value}; pub use super::transition_duration::{parse, parse_one}; pub use super::transition_duration::SpecifiedValue; pub use super::transition_duration::SingleSpecifiedValue; // CSSOM View Module // https://www.w3.org/TR/cssom-view-1/ ${helpers.single_keyword("scroll-behavior", "auto smooth", products="gecko", animatable=False)} // Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-type-x ${helpers.single_keyword("scroll-snap-type-x", "none mandatory proximity", products="gecko", gecko_constant_prefix="NS_STYLE_SCROLL_SNAP_TYPE", animatable=False)} // Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-type-y ${helpers.single_keyword("scroll-snap-type-y", "none mandatory proximity", products="gecko", gecko_constant_prefix="NS_STYLE_SCROLL_SNAP_TYPE", animatable=False)} // Compositing and Blending Level 1 // http://www.w3.org/TR/compositing-1/ ${helpers.single_keyword("isolation", "auto isolate", products="gecko", animatable=False)} ${helpers.single_keyword("page-break-after", "auto always avoid left right", products="gecko", animatable=False)} ${helpers.single_keyword("page-break-before", "auto always avoid left right", products="gecko", animatable=False)} ${helpers.single_keyword("page-break-inside", "auto avoid", products="gecko", gecko_ffi_name="mBreakInside", gecko_constant_prefix="NS_STYLE_PAGE_BREAK", animatable=False)} // CSS Basic User Interface Module Level 3 // http://dev.w3.org/csswg/css-ui/ ${helpers.single_keyword("resize", "none both horizontal vertical", products="gecko", animatable=False)} // Non-standard ${helpers.single_keyword("-moz-appearance", """none button button-arrow-down button-arrow-next button-arrow-previous button-arrow-up button-bevel button-focus caret checkbox checkbox-container checkbox-label checkmenuitem dualbutton groupbox listbox listitem menuarrow menubar menucheckbox menuimage menuitem menuitemtext menulist menulist-button menulist-text menulist-textfield menupopup menuradio menuseparator meterbar meterchunk progressbar progressbar-vertical progresschunk progresschunk-vertical radio radio-container radio-label radiomenuitem range range-thumb resizer resizerpanel scale-horizontal scalethumbend scalethumb-horizontal scalethumbstart scalethumbtick scalethumb-vertical scale-vertical scrollbarbutton-down scrollbarbutton-left scrollbarbutton-right scrollbarbutton-up scrollbarthumb-horizontal scrollbarthumb-vertical scrollbartrack-horizontal scrollbartrack-vertical searchfield separator spinner spinner-downbutton spinner-textfield spinner-upbutton splitter statusbar statusbarpanel tab tabpanel tabpanels tab-scroll-arrow-back tab-scroll-arrow-forward textfield textfield-multiline toolbar toolbarbutton toolbarbutton-dropdown toolbargripper toolbox tooltip treeheader treeheadercell treeheadersortarrow treeitem treeline treetwisty treetwistyopen treeview -moz-win-borderless-glass -moz-win-browsertabbar-toolbox -moz-win-communications-toolbox -moz-win-exclude-glass -moz-win-glass -moz-win-media-toolbox -moz-window-button-box -moz-window-button-box-maximized -moz-window-button-close -moz-window-button-maximize -moz-window-button-minimize -moz-window-button-restore -moz-window-frame-bottom -moz-window-frame-left -moz-window-frame-right -moz-window-titlebar -moz-window-titlebar-maximized """, gecko_ffi_name="mAppearance", gecko_constant_prefix="NS_THEME", products="gecko", animatable=False)} // Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-binding <%helpers:longhand name="-moz-binding" products="gecko" animatable="False"> use cssparser::{CssStringWriter, ToCss}; use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI}; use std::fmt::{self, Write}; use url::Url; use values::specified::UrlExtraData; use values::computed::ComputedValueAsSpecified; use values::NoViewportPercentage; #[derive(PartialEq, Clone, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum SpecifiedValue { Url(Url, UrlExtraData), None, } impl ComputedValueAsSpecified for SpecifiedValue {} impl NoViewportPercentage for SpecifiedValue {} impl ToCss for SpecifiedValue { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { use values::LocalToCss; match *self { SpecifiedValue::Url(ref url, _) => { url.to_css(dest) } SpecifiedValue::None => { try!(dest.write_str("none")); Ok(()) } } } } pub mod computed_value { pub type T = super::SpecifiedValue; } #[inline] pub fn get_initial_value() -> SpecifiedValue { SpecifiedValue::None } pub fn parse(context: &ParserContext, input: &mut Parser) -> Result { if input.try(|input| input.expect_ident_matching("none")).is_ok() { return Ok(SpecifiedValue::None); } let url = context.parse_url(&*try!(input.expect_url())); match context.extra_data { ParserContextExtraData { base: Some(ref base), referrer: Some(ref referrer), principal: Some(ref principal), } => { let extra_data = UrlExtraData { base: base.clone(), referrer: referrer.clone(), principal: principal.clone(), }; Ok(SpecifiedValue::Url(url, extra_data)) }, _ => { // FIXME(heycam) should ensure we always have a principal, etc., when parsing // style attributes and re-parsing due to CSS Variables. println!("stylo: skipping -moz-binding declaration without ParserContextExtraData"); Err(()) }, } }