diff options
author | Patrick Walton <pcwalton@mimiga.net> | 2014-12-13 19:09:06 -0800 |
---|---|---|
committer | Simon Sapin <simon.sapin@exyr.org> | 2015-03-03 17:54:12 +0100 |
commit | 09c53f461dadf0c1f2896754c329ee6ad3e9359e (patch) | |
tree | e7ff2e7cd5e29034ad3914ddeb231447ff883e1a | |
parent | 6fcc02e92f4c519239a834dc37a2965a4993322a (diff) | |
download | servo-09c53f461dadf0c1f2896754c329ee6ad3e9359e.tar.gz servo-09c53f461dadf0c1f2896754c329ee6ad3e9359e.zip |
layout: Implement `image-rendering` per CSS-IMAGES-3 § 5.3 and
`background-size` per CSS-BACKGROUNDS § 3.9.
Nearest neighbor interpolation is used for `crisp-edges`, like Firefox.
A note has been added that we could do better if we wanted to.
Multiple backgrounds are not yet supported.
-rw-r--r-- | components/gfx/display_list/mod.rs | 11 | ||||
-rw-r--r-- | components/gfx/paint_context.rs | 19 | ||||
-rw-r--r-- | components/layout/display_list_builder.rs | 122 | ||||
-rw-r--r-- | components/script/dom/webidls/CSSStyleDeclaration.webidl | 3 | ||||
-rw-r--r-- | components/style/properties.mako.rs | 193 | ||||
-rw-r--r-- | tests/ref/2x4.png | bin | 0 -> 171 bytes | |||
-rw-r--r-- | tests/ref/4x2.png | bin | 0 -> 180 bytes | |||
-rw-r--r-- | tests/ref/background_size.png | bin | 0 -> 510 bytes | |||
-rw-r--r-- | tests/ref/background_size_a.html | 62 | ||||
-rw-r--r-- | tests/ref/background_size_ref.html | 19 | ||||
-rw-r--r-- | tests/ref/background_size_shorthand_a.html | 28 | ||||
-rw-r--r-- | tests/ref/background_size_shorthand_ref.html | 23 | ||||
-rw-r--r-- | tests/ref/basic.list | 4 | ||||
-rw-r--r-- | tests/ref/image_rendering_auto_a.html | 11 | ||||
-rw-r--r-- | tests/ref/image_rendering_pixelated_a.html | 20 | ||||
-rw-r--r-- | tests/ref/image_rendering_pixelated_ref.html | 40 |
16 files changed, 521 insertions, 34 deletions
diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 9ba4d93e9e9..fde17c0aed5 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -42,8 +42,9 @@ use util::smallvec::{SmallVec, SmallVec8}; use std::fmt; use std::slice::Iter; use std::sync::Arc; +use style::computed_values::{border_style, cursor, filter, image_rendering, mix_blend_mode}; +use style::computed_values::{pointer_events}; use style::properties::ComputedValues; -use style::computed_values::{border_style, cursor, filter, mix_blend_mode, pointer_events}; // It seems cleaner to have layout code not mention Azure directly, so let's just reexport this for // layout to use. @@ -763,6 +764,10 @@ pub struct ImageDisplayItem { /// the bounds of this display item, then the image will be repeated in the appropriate /// direction to tile the entire bounds. pub stretch_size: Size2D<Au>, + + /// The algorithm we should use to stretch the image. See `image_rendering` in CSS-IMAGES-3 § + /// 5.3. + pub image_rendering: image_rendering::T, } /// Paints a gradient. @@ -937,7 +942,9 @@ impl DisplayItem { bounds.origin.y = bounds.origin.y + y_offset; bounds.size = image_item.stretch_size; - paint_context.draw_image(&bounds, image_item.image.clone()); + paint_context.draw_image(&bounds, + image_item.image.clone(), + image_item.image_rendering.clone()); x_offset = x_offset + image_item.stretch_size.width; } diff --git a/components/gfx/paint_context.rs b/components/gfx/paint_context.rs index 82184bf06de..442e13f7333 100644 --- a/components/gfx/paint_context.rs +++ b/components/gfx/paint_context.rs @@ -37,7 +37,7 @@ use std::mem; use std::num::Float; use std::ptr; use std::sync::Arc; -use style::computed_values::{border_style, filter, mix_blend_mode}; +use style::computed_values::{border_style, filter, image_rendering, mix_blend_mode}; use util::geometry::{self, Au, MAX_RECT, ZERO_RECT}; use util::opts; use util::range::Range; @@ -127,7 +127,10 @@ impl<'a> PaintContext<'a> { self.draw_target.pop_clip(); } - pub fn draw_image(&self, bounds: &Rect<Au>, image: Arc<Box<Image>>) { + pub fn draw_image(&self, + bounds: &Rect<Au>, + image: Arc<Box<Image>>, + image_rendering: image_rendering::T) { let size = Size2D(image.width as i32, image.height as i32); let (pixel_width, pixels, source_format) = match image.pixels { PixelsByColorType::RGBA8(ref pixels) => (4, pixels.as_slice(), SurfaceFormat::B8G8R8A8), @@ -146,7 +149,17 @@ impl<'a> PaintContext<'a> { let source_rect = Rect(Point2D(0.0, 0.0), Size2D(image.width as AzFloat, image.height as AzFloat)); let dest_rect = bounds.to_azure_rect(); - let draw_surface_options = DrawSurfaceOptions::new(Filter::Linear, true); + + // TODO(pcwalton): According to CSS-IMAGES-3 § 5.3, nearest-neighbor interpolation is a + // conforming implementation of `crisp-edges`, but it is not the best we could do. + // Something like Scale2x would be ideal. + let draw_surface_options = match image_rendering { + image_rendering::T::Auto => DrawSurfaceOptions::new(Filter::Linear, true), + image_rendering::T::CrispEdges | image_rendering::T::Pixelated => { + DrawSurfaceOptions::new(Filter::Point, true) + } + }; + let draw_options = DrawOptions::new(1.0, 0); draw_target_ref.draw_surface(azure_surface, dest_rect, diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index e20ade0ce19..e61e8728eb6 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -18,7 +18,7 @@ use fragment::{CoordinateSystem, Fragment, IframeFragmentInfo, ImageFragmentInfo use fragment::{ScannedTextFragmentInfo, SpecificFragmentInfo}; use inline::InlineFlow; use list_item::ListItemFlow; -use model; +use model::{self, MaybeAuto}; use util::{OpaqueNodeMethods, ToGfxColor}; use geom::{Point2D, Rect, Size2D, SideOffsets2D}; @@ -31,8 +31,7 @@ use gfx::display_list::{GradientStop, ImageDisplayItem, LineDisplayItem}; use gfx::display_list::{OpaqueNode, SolidColorDisplayItem}; use gfx::display_list::{StackingContext, TextDisplayItem, TextOrientation}; use gfx::paint_task::{PaintLayer, THREAD_TINT_COLORS}; -use png; -use png::PixelsByColorType; +use png::{self, PixelsByColorType}; use msg::compositor_msg::ScrollPolicy; use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::ConstellationChan; @@ -46,11 +45,11 @@ use std::default::Default; use std::iter::repeat; use std::num::Float; use style::values::specified::{AngleOrCorner, HorizontalDirection, VerticalDirection}; -use style::values::computed::{Image, LinearGradient, LengthOrPercentage}; +use style::values::computed::{Image, LinearGradient, LengthOrPercentage, LengthOrPercentageOrAuto}; use style::values::RGBA; use style::computed_values::filter::Filter; -use style::computed_values::{background_attachment, background_repeat, border_style, overflow_x}; -use style::computed_values::{position, visibility}; +use style::computed_values::{background_attachment, background_repeat, background_size}; +use style::computed_values::{border_style, image_rendering, overflow_x, position, visibility}; use style::properties::style_structs::Border; use style::properties::ComputedValues; use std::num::ToPrimitive; @@ -93,6 +92,14 @@ pub trait FragmentDisplayListBuilding { absolute_bounds: &Rect<Au>, clip: &ClippingRegion); + /// Computes the background size for an image with the given background area according to the + /// rules in CSS-BACKGROUNDS § 3.9. + fn compute_background_image_size(&self, + style: &ComputedValues, + bounds: &Rect<Au>, + image: &png::Image) + -> Size2D<Au>; + /// Adds the display items necessary to paint the background image of this fragment to the /// display list at the appropriate stacking level. fn build_display_list_for_background_image(&self, @@ -326,6 +333,59 @@ impl FragmentDisplayListBuilding for Fragment { } } + fn compute_background_image_size(&self, + style: &ComputedValues, + bounds: &Rect<Au>, + image: &png::Image) + -> Size2D<Au> { + // If `image_aspect_ratio` < `bounds_aspect_ratio`, the image is tall; otherwise, it is + // wide. + let image_aspect_ratio = (image.width as f64) / (image.height as f64); + let bounds_aspect_ratio = bounds.size.width.to_subpx() / bounds.size.height.to_subpx(); + let intrinsic_size = Size2D(Au::from_px(image.width as int), + Au::from_px(image.height as int)); + match (style.get_background().background_size.clone(), + image_aspect_ratio < bounds_aspect_ratio) { + (background_size::T::Contain, false) | (background_size::T::Cover, true) => { + Size2D(bounds.size.width, + Au::from_frac_px(bounds.size.width.to_subpx() / image_aspect_ratio)) + } + + (background_size::T::Contain, true) | (background_size::T::Cover, false) => { + Size2D(Au::from_frac_px(bounds.size.height.to_subpx() * image_aspect_ratio), + bounds.size.height) + } + + (background_size::T::Explicit(background_size::ExplicitSize { + width, + height: LengthOrPercentageOrAuto::Auto, + }), _) => { + let width = MaybeAuto::from_style(width, bounds.size.width) + .specified_or_default(intrinsic_size.width); + Size2D(width, Au::from_frac_px(width.to_subpx() / image_aspect_ratio)) + } + + (background_size::T::Explicit(background_size::ExplicitSize { + width: LengthOrPercentageOrAuto::Auto, + height + }), _) => { + let height = MaybeAuto::from_style(height, bounds.size.height) + .specified_or_default(intrinsic_size.height); + Size2D(Au::from_frac_px(height.to_subpx() * image_aspect_ratio), height) + } + + (background_size::T::Explicit(background_size::ExplicitSize { + width, + height + }), _) => { + Size2D(MaybeAuto::from_style(width, bounds.size.width) + .specified_or_default(intrinsic_size.width), + MaybeAuto::from_style(height, bounds.size.height) + .specified_or_default(intrinsic_size.height)) + } + } + } + fn build_display_list_for_background_image(&self, style: &ComputedValues, display_list: &mut DisplayList, @@ -349,16 +409,16 @@ impl FragmentDisplayListBuilding for Fragment { }; debug!("(building display list) building background image"); - let image_width = Au::from_px(image.width as int); - let image_height = Au::from_px(image.height as int); + // Use `background-size` to get the size. let mut bounds = *absolute_bounds; + let image_size = self.compute_background_image_size(style, &bounds, &**image); // Clip. // // TODO: Check the bounds to see if a clip item is actually required. let clip = clip.clone().intersect_rect(&bounds); - // Use background-attachment to get the initial virtual origin + // Use `background-attachment` to get the initial virtual origin let (virtual_origin_x, virtual_origin_y) = match background.background_attachment { background_attachment::T::scroll => { (absolute_bounds.origin.x, absolute_bounds.origin.y) @@ -368,11 +428,11 @@ impl FragmentDisplayListBuilding for Fragment { } }; - // Use background-position to get the offset + // Use `background-position` to get the offset. let horizontal_position = model::specified(background.background_position.horizontal, - bounds.size.width - image_width); + bounds.size.width - image_size.width); let vertical_position = model::specified(background.background_position.vertical, - bounds.size.height - image_height); + bounds.size.height - image_size.height); let abs_x = virtual_origin_x + horizontal_position; let abs_y = virtual_origin_y + vertical_position; @@ -382,26 +442,34 @@ impl FragmentDisplayListBuilding for Fragment { background_repeat::T::no_repeat => { bounds.origin.x = abs_x; bounds.origin.y = abs_y; - bounds.size.width = image_width; - bounds.size.height = image_height; + bounds.size.width = image_size.width; + bounds.size.height = image_size.height; } background_repeat::T::repeat_x => { bounds.origin.y = abs_y; - bounds.size.height = image_height; - ImageFragmentInfo::tile_image(&mut bounds.origin.x, &mut bounds.size.width, - abs_x, image.width); + bounds.size.height = image_size.height; + ImageFragmentInfo::tile_image(&mut bounds.origin.x, + &mut bounds.size.width, + abs_x, + image_size.width.to_nearest_px() as u32); } background_repeat::T::repeat_y => { bounds.origin.x = abs_x; - bounds.size.width = image_width; - ImageFragmentInfo::tile_image(&mut bounds.origin.y, &mut bounds.size.height, - abs_y, image.height); + bounds.size.width = image_size.width; + ImageFragmentInfo::tile_image(&mut bounds.origin.y, + &mut bounds.size.height, + abs_y, + image_size.height.to_nearest_px() as u32); } background_repeat::T::repeat => { - ImageFragmentInfo::tile_image(&mut bounds.origin.x, &mut bounds.size.width, - abs_x, image.width); - ImageFragmentInfo::tile_image(&mut bounds.origin.y, &mut bounds.size.height, - abs_y, image.height); + ImageFragmentInfo::tile_image(&mut bounds.origin.x, + &mut bounds.size.width, + abs_x, + image_size.width.to_nearest_px() as u32); + ImageFragmentInfo::tile_image(&mut bounds.origin.y, + &mut bounds.size.height, + abs_y, + image_size.height.to_nearest_px() as u32); } }; @@ -413,8 +481,8 @@ impl FragmentDisplayListBuilding for Fragment { Cursor::DefaultCursor), clip), image: image.clone(), - stretch_size: Size2D(Au::from_px(image.width as int), - Au::from_px(image.height as int)), + stretch_size: Size2D(image_size.width, image_size.height), + image_rendering: style.get_effects().image_rendering.clone(), }), level); } @@ -912,6 +980,7 @@ impl FragmentDisplayListBuilding for Fragment { (*clip).clone()), image: image.clone(), stretch_size: stacking_relative_content_box.size, + image_rendering: self.style.get_effects().image_rendering.clone(), })); } else { // No image data at all? Do nothing. @@ -947,6 +1016,7 @@ impl FragmentDisplayListBuilding for Fragment { pixels: PixelsByColorType::RGBA8(canvas_data), }), stretch_size: stacking_relative_content_box.size, + image_rendering: image_rendering::T::Auto, }; display_list.content.push_back(DisplayItem::ImageClass(canvas_display_item)); diff --git a/components/script/dom/webidls/CSSStyleDeclaration.webidl b/components/script/dom/webidls/CSSStyleDeclaration.webidl index d6a4420b2a9..46ca8424b70 100644 --- a/components/script/dom/webidls/CSSStyleDeclaration.webidl +++ b/components/script/dom/webidls/CSSStyleDeclaration.webidl @@ -38,6 +38,7 @@ partial interface CSSStyleDeclaration { [TreatNullAs=EmptyString] attribute DOMString backgroundRepeat; [TreatNullAs=EmptyString] attribute DOMString backgroundImage; [TreatNullAs=EmptyString] attribute DOMString backgroundAttachment; + [TreatNullAs=EmptyString] attribute DOMString backgroundSize; [TreatNullAs=EmptyString] attribute DOMString border; [TreatNullAs=EmptyString] attribute DOMString borderColor; @@ -173,4 +174,6 @@ partial interface CSSStyleDeclaration { [TreatNullAs=EmptyString] attribute DOMString maxWidth; [TreatNullAs=EmptyString] attribute DOMString zIndex; + + [TreatNullAs=EmptyString] attribute DOMString imageRendering; }; diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs index 83d6570a800..5330de59a93 100644 --- a/components/style/properties.mako.rs +++ b/components/style/properties.mako.rs @@ -1073,6 +1073,126 @@ pub mod longhands { ${single_keyword("background-attachment", "scroll fixed")} + <%self:longhand name="background-size"> + use cssparser::{ToCss, Token}; + use std::ascii::AsciiExt; + use text_writer::{self, TextWriter}; + use values::computed::{Context, ToComputedValue}; + + pub mod computed_value { + use values::computed::LengthOrPercentageOrAuto; + + #[derive(PartialEq, Clone, Debug)] + pub struct ExplicitSize { + pub width: LengthOrPercentageOrAuto, + pub height: LengthOrPercentageOrAuto, + } + + #[derive(PartialEq, Clone, Debug)] + pub enum T { + Explicit(ExplicitSize), + Cover, + Contain, + } + } + + #[derive(Clone, PartialEq, Debug)] + pub struct SpecifiedExplicitSize { + pub width: specified::LengthOrPercentageOrAuto, + pub height: specified::LengthOrPercentageOrAuto, + } + + impl ToCss for SpecifiedExplicitSize { + fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter { + try!(self.width.to_css(dest)); + try!(dest.write_str(" ")); + self.height.to_css(dest) + } + } + + #[derive(Clone, PartialEq, Debug)] + pub enum SpecifiedValue { + Explicit(SpecifiedExplicitSize), + Cover, + Contain, + } + + impl ToCss for SpecifiedValue { + fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter { + match *self { + SpecifiedValue::Explicit(ref size) => size.to_css(dest), + SpecifiedValue::Cover => dest.write_str("cover"), + SpecifiedValue::Contain => dest.write_str("contain"), + } + } + } + + impl ToComputedValue for SpecifiedValue { + type ComputedValue = computed_value::T; + + #[inline] + fn to_computed_value(&self, context: &computed::Context) -> computed_value::T { + match *self { + SpecifiedValue::Explicit(ref size) => { + computed_value::T::Explicit(computed_value::ExplicitSize { + width: size.width.to_computed_value(context), + height: size.height.to_computed_value(context), + }) + } + SpecifiedValue::Cover => computed_value::T::Cover, + SpecifiedValue::Contain => computed_value::T::Contain, + } + } + } + + #[inline] + pub fn get_initial_value() -> computed_value::T { + computed_value::T::Explicit(computed_value::ExplicitSize { + width: computed::LengthOrPercentageOrAuto::Auto, + height: computed::LengthOrPercentageOrAuto::Auto, + }) + } + + pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> { + let width; + if let Ok(value) = input.try(|input| { + match input.next() { + Err(_) => Err(()), + Ok(Token::Ident(ref ident)) if ident.as_slice() + .eq_ignore_ascii_case("cover") => { + Ok(SpecifiedValue::Cover) + } + Ok(Token::Ident(ref ident)) if ident.as_slice() + .eq_ignore_ascii_case("contain") => { + Ok(SpecifiedValue::Contain) + } + Ok(_) => Err(()), + } + }) { + return Ok(value) + } else { + width = try!(specified::LengthOrPercentageOrAuto::parse(input)) + } + + let height; + if let Ok(value) = input.try(|input| { + match input.next() { + Err(_) => Ok(specified::LengthOrPercentageOrAuto::Auto), + Ok(_) => Err(()), + } + }) { + height = value + } else { + height = try!(specified::LengthOrPercentageOrAuto::parse(input)); + } + + Ok(SpecifiedValue::Explicit(SpecifiedExplicitSize { + width: width, + height: height, + })) + } + </%self:longhand> + ${new_style_struct("Color", is_inherited=True)} <%self:raw_longhand name="color"> @@ -2415,6 +2535,62 @@ pub mod longhands { """normal multiply screen overlay darken lighten color-dodge color-burn hard-light soft-light difference exclusion hue saturation color luminosity""")} + + <%self:longhand name="image-rendering"> + use values::computed::{Context, ToComputedValue}; + + pub mod computed_value { + use cssparser::ToCss; + use text_writer::{self, TextWriter}; + + #[derive(Copy, Clone, Debug, PartialEq)] + pub enum T { + Auto, + CrispEdges, + Pixelated, + } + + impl ToCss for T { + fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter { + match *self { + T::Auto => dest.write_str("auto"), + T::CrispEdges => dest.write_str("crisp-edges"), + T::Pixelated => dest.write_str("pixelated"), + } + } + } + } + + pub type SpecifiedValue = computed_value::T; + + #[inline] + pub fn get_initial_value() -> computed_value::T { + computed_value::T::Auto + } + + pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> { + // According to to CSS-IMAGES-3, `optimizespeed` and `optimizequality` are synonyms for + // `auto`. + match_ignore_ascii_case! { + try!(input.expect_ident()), + "auto" => Ok(computed_value::T::Auto), + "optimizespeed" => Ok(computed_value::T::Auto), + "optimizequality" => Ok(computed_value::T::Auto), + "crisp-edges" => Ok(computed_value::T::CrispEdges), + "pixelated" => Ok(computed_value::T::Pixelated) + _ => Err(()) + } + } + + impl ToComputedValue for SpecifiedValue { + type ComputedValue = computed_value::T; + + #[inline] + fn to_computed_value(&self, _: &Context) -> computed_value::T { + *self + } + } + </%self:longhand> } @@ -2507,14 +2683,17 @@ pub mod shorthands { // TODO: other background-* properties <%self:shorthand name="background" - sub_properties="background-color background-position background-repeat background-attachment background-image"> - use properties::longhands::{background_color, background_position, background_repeat, - background_attachment, background_image}; + sub_properties="background-color background-position background-repeat background-attachment background-image background-size"> + use properties::longhands::{background_color, background_position, background_repeat}; + use properties::longhands::{background_attachment, background_image, background_size}; + + use cssparser::Token; let mut color = None; let mut image = None; let mut position = None; let mut repeat = None; + let mut size = None; let mut attachment = None; let mut any = false; @@ -2523,6 +2702,13 @@ pub mod shorthands { if let Ok(value) = input.try(|input| background_position::parse(context, input)) { position = Some(value); any = true; + + // Parse background size, if applicable. + size = input.try(|input| { + try!(input.expect_delim('/')); + background_size::parse(context, input) + }).ok(); + continue } } @@ -2564,6 +2750,7 @@ pub mod shorthands { background_position: position, background_repeat: repeat, background_attachment: attachment, + background_size: size, }) } else { Err(()) diff --git a/tests/ref/2x4.png b/tests/ref/2x4.png Binary files differnew file mode 100644 index 00000000000..7efc762459b --- /dev/null +++ b/tests/ref/2x4.png diff --git a/tests/ref/4x2.png b/tests/ref/4x2.png Binary files differnew file mode 100644 index 00000000000..eb0c5cda971 --- /dev/null +++ b/tests/ref/4x2.png diff --git a/tests/ref/background_size.png b/tests/ref/background_size.png Binary files differnew file mode 100644 index 00000000000..8d5824940c0 --- /dev/null +++ b/tests/ref/background_size.png diff --git a/tests/ref/background_size_a.html b/tests/ref/background_size_a.html new file mode 100644 index 00000000000..aa2df4fb8b2 --- /dev/null +++ b/tests/ref/background_size_a.html @@ -0,0 +1,62 @@ +<!DOCTYPE html> +<html> +<head> +<style> +section { + position: absolute; + top: 0; + width: 40px; +} +#tall { + left: 0; +} +#wide { + left: 40px; +} +div { + width: 40px; + height: 40px; + image-rendering: -moz-crisp-edges; /* for comparison with Firefox */ + image-rendering: pixelated; +} +#tall div { + background-image: url(2x4.png); +} +#wide div { + background-image: url(4x2.png); +} +.a { + background-size: 40px 20px; +} +.b { + background-size: 40px 40px; +} +.c { + background-size: 40px; +} +.d { + background-size: cover; +} +.e { + background-size: contain; +} +</style> +</head> +<body> +<section id=tall> +<div class=a></div> +<div class=b></div> +<div class=c></div> +<div class=d></div> +<div class=e></div> +</section> +<section id=wide> +<div class=a></div> +<div class=b></div> +<div class=c></div> +<div class=d></div> +<div class=e></div> +</section> +</body> +</html> + diff --git a/tests/ref/background_size_ref.html b/tests/ref/background_size_ref.html new file mode 100644 index 00000000000..7967b10ae09 --- /dev/null +++ b/tests/ref/background_size_ref.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html> +<head> +<style> +img { + image-rendering: -moz-crisp-edges; /* for comparison with Firefox */ + image-rendering: pixelated; +} +html, body { + margin: 0; +} +</style> +</head> +<body> +<img src=background_size.png> +</body> +</html> + + diff --git a/tests/ref/background_size_shorthand_a.html b/tests/ref/background_size_shorthand_a.html new file mode 100644 index 00000000000..30ce3a9cef2 --- /dev/null +++ b/tests/ref/background_size_shorthand_a.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html> +<head> +<!-- Tests that the `background-size` shorthand works. --> +<style> +section { + width: 100px; + height: 100px; + border: solid black 1px; +} +#a { + background: 10px 10px / 80px 80px url(rust_logo.png) no-repeat; +} +#b { + background: url(rust_logo.png) 10px 10px / 80px 80px no-repeat; +} +#c { + background: no-repeat url(rust_logo.png) 10px 10px / 80px 80px; +} +</style> +</head> +<body> +<section id=a> </section> +<section id=b> </section> +<section id=c> </section> +</body> +</html> + diff --git a/tests/ref/background_size_shorthand_ref.html b/tests/ref/background_size_shorthand_ref.html new file mode 100644 index 00000000000..48766310e1c --- /dev/null +++ b/tests/ref/background_size_shorthand_ref.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html> +<head> +<!-- Tests that the `background-size` shorthand works. --> +<style> +section { + width: 100px; + height: 100px; + border: solid black 1px; + background-image: url(rust_logo.png); + background-position: 10px 10px; + background-size: 80px 80px; + background-repeat: no-repeat; +} +</style> +</head> +<body> +<section> </section> +<section> </section> +<section> </section> +</body> +</html> + diff --git a/tests/ref/basic.list b/tests/ref/basic.list index 2361eb2e7df..2aec5daa48d 100644 --- a/tests/ref/basic.list +++ b/tests/ref/basic.list @@ -259,3 +259,7 @@ fragment=top != ../html/acid2.html acid2_ref.html == text_shadow_simple_a.html text_shadow_simple_ref.html == text_shadow_decorations_a.html text_shadow_decorations_ref.html == text_shadow_blur_a.html text_shadow_blur_ref.html +!= image_rendering_auto_a.html image_rendering_pixelated_a.html +== image_rendering_pixelated_a.html image_rendering_pixelated_ref.html +== background_size_a.html background_size_ref.html +== background_size_shorthand_a.html background_size_shorthand_ref.html diff --git a/tests/ref/image_rendering_auto_a.html b/tests/ref/image_rendering_auto_a.html new file mode 100644 index 00000000000..3b7282e5ff9 --- /dev/null +++ b/tests/ref/image_rendering_auto_a.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> +<head> +<!-- Tests that `image-rendering: auto` uses bilinear filtering. --> +</head> +<body> +<img width=100 height=50 src=4x2.png> +</body> +</html> + + diff --git a/tests/ref/image_rendering_pixelated_a.html b/tests/ref/image_rendering_pixelated_a.html new file mode 100644 index 00000000000..b4086e2fd33 --- /dev/null +++ b/tests/ref/image_rendering_pixelated_a.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html> +<head> +<!-- Tests that `image-rendering: pixelated` causes nearest-neighbor interpolation to be used. --> +<style> +img { + position: absolute; + top: 0; + left: 0; + image-rendering: -moz-crisp-edges; /* for testing in Firefox */ + image-rendering: pixelated; +} +</style> +</head> +<body> +<img width=100 height=50 src=4x2.png> +</body> +</html> + + diff --git a/tests/ref/image_rendering_pixelated_ref.html b/tests/ref/image_rendering_pixelated_ref.html new file mode 100644 index 00000000000..06b2f3249f6 --- /dev/null +++ b/tests/ref/image_rendering_pixelated_ref.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html> +<head> +<!-- Tests that `image-rendering: pixelated` causes nearest-neighbor interpolation to be used. --> +<style> +section { + position: absolute; + width: 50px; + height: 25px; +} +#a, #d { + background: red; +} +#b, #c { + background: blue; +} +#a, #b { + top: 0; +} +#c, #d { + top: 25px; +} +#a, #c { + left: 0; +} +#b, #d { + left: 50px; +} +</style> +</head> +<body> +<section id=a></section> +<section id=b></section> +<section id=c></section> +<section id=d></section> +</body> +</html> + + + |