Add full parsing/serialization for mask-repeat and background-repeat

This commit is contained in:
James Bendig 2017-03-24 15:31:16 -05:00
parent 9eb6bb78b0
commit 67282f9bee
8 changed files with 237 additions and 68 deletions

View file

@ -768,45 +768,45 @@ impl FragmentDisplayListBuilding for Fragment {
let mut stretch_size = image_size;
// Adjust origin and size based on background-repeat
match *get_cyclic(&background.background_repeat.0, index) {
background_repeat::single_value::T::no_repeat => {
let background_repeat = get_cyclic(&background.background_repeat.0, index);
match background_repeat.0 {
background_repeat::single_value::RepeatKeyword::NoRepeat => {
bounds.origin.x = anchor_origin_x;
bounds.origin.y = anchor_origin_y;
bounds.size.width = image_size.width;
bounds.size.height = image_size.height;
}
background_repeat::single_value::T::repeat_x => {
bounds.origin.y = anchor_origin_y;
bounds.size.height = image_size.height;
background_repeat::single_value::RepeatKeyword::Repeat => {
ImageFragmentInfo::tile_image(&mut bounds.origin.x,
&mut bounds.size.width,
anchor_origin_x,
image_size.width);
}
background_repeat::single_value::T::repeat_y => {
bounds.origin.x = anchor_origin_x;
bounds.size.width = image_size.width;
ImageFragmentInfo::tile_image(&mut bounds.origin.y,
&mut bounds.size.height,
anchor_origin_y,
image_size.height);
}
background_repeat::single_value::T::repeat => {
ImageFragmentInfo::tile_image(&mut bounds.origin.x,
&mut bounds.size.width,
anchor_origin_x,
image_size.width);
ImageFragmentInfo::tile_image(&mut bounds.origin.y,
&mut bounds.size.height,
anchor_origin_y,
image_size.height);
}
background_repeat::single_value::T::space => {
background_repeat::single_value::RepeatKeyword::Space => {
ImageFragmentInfo::tile_image_spaced(&mut bounds.origin.x,
&mut bounds.size.width,
&mut tile_spacing.width,
anchor_origin_x,
image_size.width);
}
background_repeat::single_value::RepeatKeyword::Round => {
ImageFragmentInfo::tile_image_round(&mut bounds.origin.x,
&mut bounds.size.width,
anchor_origin_x,
&mut stretch_size.width);
}
};
match background_repeat.1 {
background_repeat::single_value::RepeatKeyword::NoRepeat => {
bounds.origin.y = anchor_origin_y;
bounds.size.height = image_size.height;
}
background_repeat::single_value::RepeatKeyword::Repeat => {
ImageFragmentInfo::tile_image(&mut bounds.origin.y,
&mut bounds.size.height,
anchor_origin_y,
image_size.height);
}
background_repeat::single_value::RepeatKeyword::Space => {
ImageFragmentInfo::tile_image_spaced(&mut bounds.origin.y,
&mut bounds.size.height,
&mut tile_spacing.height,
@ -814,11 +814,7 @@ impl FragmentDisplayListBuilding for Fragment {
image_size.height);
}
background_repeat::single_value::T::round => {
ImageFragmentInfo::tile_image_round(&mut bounds.origin.x,
&mut bounds.size.width,
anchor_origin_x,
&mut stretch_size.width);
background_repeat::single_value::RepeatKeyword::Round => {
ImageFragmentInfo::tile_image_round(&mut bounds.origin.y,
&mut bounds.size.height,
anchor_origin_y,

View file

@ -2084,27 +2084,24 @@ fn static_assert() {
%>
<%self:simple_image_array_property name="repeat" shorthand="${shorthand}" field_name="mRepeat">
use properties::longhands::${shorthand}_repeat::single_value::computed_value::T;
use properties::longhands::${shorthand}_repeat::single_value::computed_value::RepeatKeyword;
use gecko_bindings::structs::nsStyleImageLayers_Repeat;
use gecko_bindings::structs::NS_STYLE_IMAGELAYER_REPEAT_REPEAT;
use gecko_bindings::structs::NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT;
use gecko_bindings::structs::NS_STYLE_IMAGELAYER_REPEAT_SPACE;
use gecko_bindings::structs::NS_STYLE_IMAGELAYER_REPEAT_ROUND;
let (repeat_x, repeat_y) = match servo {
T::repeat_x => (NS_STYLE_IMAGELAYER_REPEAT_REPEAT,
NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT),
T::repeat_y => (NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT,
NS_STYLE_IMAGELAYER_REPEAT_REPEAT),
T::repeat => (NS_STYLE_IMAGELAYER_REPEAT_REPEAT,
NS_STYLE_IMAGELAYER_REPEAT_REPEAT),
T::space => (NS_STYLE_IMAGELAYER_REPEAT_SPACE,
NS_STYLE_IMAGELAYER_REPEAT_SPACE),
T::round => (NS_STYLE_IMAGELAYER_REPEAT_ROUND,
NS_STYLE_IMAGELAYER_REPEAT_ROUND),
T::no_repeat => (NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT,
NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT),
};
fn to_ns(repeat: RepeatKeyword) -> u32 {
match repeat {
RepeatKeyword::Repeat => NS_STYLE_IMAGELAYER_REPEAT_REPEAT,
RepeatKeyword::Space => NS_STYLE_IMAGELAYER_REPEAT_SPACE,
RepeatKeyword::Round => NS_STYLE_IMAGELAYER_REPEAT_ROUND,
RepeatKeyword::NoRepeat => NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT,
}
}
let repeat_x = to_ns(servo.0);
let repeat_y = to_ns(servo.1);
nsStyleImageLayers_Repeat {
mXRepeat: repeat_x as u8,
mYRepeat: repeat_y as u8,

View file

@ -192,11 +192,117 @@ ${helpers.predefined_type("background-color", "CSSColor",
}
</%helpers:vector_longhand>
${helpers.single_keyword("background-repeat",
"repeat repeat-x repeat-y space round no-repeat",
vector=True,
spec="https://drafts.csswg.org/css-backgrounds/#the-background-repeat",
animatable=False)}
<%helpers:vector_longhand name="background-repeat" animatable="False"
spec="https://drafts.csswg.org/css-backgrounds/#the-background-repeat">
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
define_css_keyword_enum!(RepeatKeyword:
"repeat" => Repeat,
"space" => Space,
"round" => Round,
"no-repeat" => NoRepeat);
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum SpecifiedValue {
RepeatX,
RepeatY,
Other(RepeatKeyword, Option<RepeatKeyword>),
}
pub mod computed_value {
pub use super::RepeatKeyword;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct T(pub RepeatKeyword, pub RepeatKeyword);
}
no_viewport_percentage!(SpecifiedValue);
impl ToCss for computed_value::T {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match (self.0, self.1) {
(RepeatKeyword::Repeat, RepeatKeyword::NoRepeat) => dest.write_str("repeat-x"),
(RepeatKeyword::NoRepeat, RepeatKeyword::Repeat) => dest.write_str("repeat-y"),
(horizontal, vertical) => {
try!(horizontal.to_css(dest));
if horizontal != vertical {
try!(dest.write_str(" "));
try!(vertical.to_css(dest));
}
Ok(())
},
}
}
}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
SpecifiedValue::RepeatX => dest.write_str("repeat-x"),
SpecifiedValue::RepeatY => dest.write_str("repeat-y"),
SpecifiedValue::Other(horizontal, vertical) => {
try!(horizontal.to_css(dest));
if let Some(vertical) = vertical {
try!(dest.write_str(" "));
try!(vertical.to_css(dest));
}
Ok(())
}
}
}
}
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T(RepeatKeyword::Repeat, RepeatKeyword::Repeat)
}
#[inline]
pub fn get_initial_specified_value() -> SpecifiedValue {
SpecifiedValue::Other(RepeatKeyword::Repeat, None)
}
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline]
fn to_computed_value(&self, _context: &Context) -> computed_value::T {
match *self {
SpecifiedValue::RepeatX =>
computed_value::T(RepeatKeyword::Repeat, RepeatKeyword::NoRepeat),
SpecifiedValue::RepeatY =>
computed_value::T(RepeatKeyword::NoRepeat, RepeatKeyword::Repeat),
SpecifiedValue::Other(horizontal, vertical) =>
computed_value::T(horizontal, vertical.unwrap_or(horizontal))
}
}
#[inline]
fn from_computed_value(computed: &computed_value::T) -> Self {
match (computed.0, computed.1) {
(RepeatKeyword::Repeat, RepeatKeyword::NoRepeat) => SpecifiedValue::RepeatX,
(RepeatKeyword::NoRepeat, RepeatKeyword::Repeat) => SpecifiedValue::RepeatY,
(horizontal, vertical) => SpecifiedValue::Other(horizontal, Some(vertical)),
}
}
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
"repeat-x" => Ok(SpecifiedValue::RepeatX),
"repeat-y" => Ok(SpecifiedValue::RepeatY),
_ => {
let horizontal = try!(RepeatKeyword::from_ident(&ident));
let vertical = input.try(RepeatKeyword::parse).ok();
Ok(SpecifiedValue::Other(horizontal, vertical))
}
}
}
</%helpers:vector_longhand>
${helpers.single_keyword("background-attachment",
"scroll fixed" + (" local" if product == "gecko" else ""),

View file

@ -94,15 +94,24 @@ ${helpers.single_keyword("mask-mode",
animatable=False,
spec="https://drafts.fxtf.org/css-masking/#propdef-mask-mode")}
// TODO implement all of repeat-style for background and mask
// https://drafts.csswg.org/css-backgrounds-3/#repeat-style
${helpers.single_keyword("mask-repeat",
"repeat repeat-x repeat-y space round no-repeat",
vector=True,
products="gecko",
extra_prefixes="webkit",
animatable=False,
spec="https://drafts.fxtf.org/css-masking/#propdef-mask-repeat")}
<%helpers:vector_longhand name="mask-repeat" products="gecko" animatable="False" extra_prefixes="webkit"
spec="https://drafts.fxtf.org/css-masking/#propdef-mask-repeat">
pub use properties::longhands::background_repeat::single_value::parse;
pub use properties::longhands::background_repeat::single_value::SpecifiedValue;
pub use properties::longhands::background_repeat::single_value::computed_value;
pub use properties::longhands::background_repeat::single_value::RepeatKeyword;
use properties::longhands::background_repeat::single_value;
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T(RepeatKeyword::NoRepeat, RepeatKeyword::NoRepeat)
}
#[inline]
pub fn get_initial_specified_value() -> SpecifiedValue {
SpecifiedValue::Other(RepeatKeyword::NoRepeat, None)
}
</%helpers:vector_longhand>
<%helpers:vector_longhand name="mask-position-x" products="gecko" animatable="True" extra_prefixes="webkit"
spec="https://drafts.fxtf.org/css-masking/#propdef-mask-position">