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.
This commit is contained in:
Patrick Walton 2014-12-13 19:09:06 -08:00 committed by Simon Sapin
parent 6fcc02e92f
commit 09c53f461d
16 changed files with 521 additions and 34 deletions

View file

@ -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;
}

View file

@ -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,