diff options
-rw-r--r-- | components/canvas_traits/lib.rs | 3 | ||||
-rw-r--r-- | components/gfx/display_list/mod.rs | 25 | ||||
-rw-r--r-- | components/gfx/paint_context.rs | 83 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 2 | ||||
-rw-r--r-- | ports/cef/Cargo.lock | 2 | ||||
-rw-r--r-- | ports/gonk/Cargo.lock | 2 | ||||
-rw-r--r-- | tests/ref/line.png | bin | 135 -> 135 bytes |
7 files changed, 77 insertions, 40 deletions
diff --git a/components/canvas_traits/lib.rs b/components/canvas_traits/lib.rs index 0fee050d78d..55ac7dfd9c5 100644 --- a/components/canvas_traits/lib.rs +++ b/components/canvas_traits/lib.rs @@ -261,7 +261,8 @@ impl FillOrStrokeStyle { Pattern::Surface(SurfacePattern::new( source_surface.azure_source_surface, surface_style.repeat_x, - surface_style.repeat_y)) + surface_style.repeat_y, + &Matrix2D::identity())) } } } diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 93a11d6b605..442601091df 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -1068,28 +1068,11 @@ impl DisplayItem { } DisplayItem::ImageClass(ref image_item) => { - // FIXME(pcwalton): This is a really inefficient way to draw a tiled image; use a - // brush instead. debug!("Drawing image at {:?}.", image_item.base.bounds); - - let mut y_offset = Au(0); - while y_offset < image_item.base.bounds.size.height { - let mut x_offset = Au(0); - while x_offset < image_item.base.bounds.size.width { - let mut bounds = image_item.base.bounds; - bounds.origin.x = bounds.origin.x + x_offset; - bounds.origin.y = bounds.origin.y + y_offset; - bounds.size = image_item.stretch_size; - - paint_context.draw_image(&bounds, - image_item.image.clone(), - image_item.image_rendering.clone()); - - x_offset = x_offset + image_item.stretch_size.width; - } - - y_offset = y_offset + image_item.stretch_size.height; - } + paint_context.draw_image(&image_item.base.bounds, + &image_item.stretch_size, + image_item.image.clone(), + image_item.image_rendering.clone()); } DisplayItem::BorderClass(ref border) => { diff --git a/components/gfx/paint_context.rs b/components/gfx/paint_context.rs index 6e45c5354e5..a13e718591a 100644 --- a/components/gfx/paint_context.rs +++ b/components/gfx/paint_context.rs @@ -14,12 +14,12 @@ use text::TextRun; use text::glyph::CharIndex; use azure::azure::AzIntSize; -use azure::azure_hl::{Color, ColorPattern}; +use azure::azure_hl::{AntialiasMode, Color, ColorPattern, CompositionOp}; use azure::azure_hl::{DrawOptions, DrawSurfaceOptions, DrawTarget, ExtendMode, FilterType}; use azure::azure_hl::{GaussianBlurAttribute, StrokeOptions, SurfaceFormat}; use azure::azure_hl::{GaussianBlurInput, GradientStop, Filter, FilterNode, LinearGradientPattern}; use azure::azure_hl::{JoinStyle, CapStyle}; -use azure::azure_hl::{Pattern, PatternRef, Path, PathBuilder, CompositionOp, AntialiasMode}; +use azure::azure_hl::{Pattern, PatternRef, Path, PathBuilder, SurfacePattern}; use azure::scaled_font::ScaledFont; use azure::{AzFloat, struct__AzDrawOptions, struct__AzGlyph}; use azure::{struct__AzGlyphBuffer, struct__AzPoint, AzDrawTargetFillGlyphs}; @@ -131,6 +131,7 @@ impl<'a> PaintContext<'a> { pub fn draw_image(&self, bounds: &Rect<Au>, + stretch_size: &Size2D<Au>, image: Arc<Image>, image_rendering: image_rendering::T) { let size = Size2D::new(image.width as i32, image.height as i32); @@ -155,19 +156,60 @@ impl<'a> PaintContext<'a> { // 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_surface_filter = match image_rendering { + image_rendering::T::Auto => Filter::Linear, + image_rendering::T::CrispEdges | image_rendering::T::Pixelated => Filter::Point, }; + let draw_surface_options = DrawSurfaceOptions::new(draw_surface_filter, true); + let draw_options = DrawOptions::new(1.0, CompositionOp::Over, AntialiasMode::None); + + // Fast path: No need to create a pattern. + if bounds.size == *stretch_size { + draw_target_ref.draw_surface(azure_surface, + dest_rect, + source_rect, + draw_surface_options, + draw_options); + return + } + + // Slightly slower path: No need to stretch. + // + // Annoyingly, surface patterns in Azure/Skia are relative to the top left of the *canvas*, + // not the rectangle we're drawing to. So we need to translate it explicitly. + let matrix = Matrix2D::identity().translate(dest_rect.origin.x, dest_rect.origin.y); + let stretch_size = stretch_size.to_nearest_azure_size(); + if source_rect.size == stretch_size { + let pattern = SurfacePattern::new(azure_surface.azure_source_surface, + true, + true, + &matrix); + draw_target_ref.fill_rect(&dest_rect, + PatternRef::Surface(&pattern), + Some(&draw_options)); + return + } + + // Slow path: Both stretch and a pattern are needed. + let draw_surface_options = DrawSurfaceOptions::new(draw_surface_filter, true); let draw_options = DrawOptions::new(1.0, CompositionOp::Over, AntialiasMode::None); - draw_target_ref.draw_surface(azure_surface, - dest_rect, - source_rect, - draw_surface_options, - draw_options); + let temporary_draw_target = + self.draw_target.create_similar_draw_target(&stretch_size.to_azure_int_size(), + self.draw_target.get_format()); + let temporary_dest_rect = Rect::new(Point2D::new(0.0, 0.0), stretch_size); + temporary_draw_target.draw_surface(azure_surface, + temporary_dest_rect, + source_rect, + draw_surface_options, + draw_options); + + let temporary_surface = temporary_draw_target.snapshot(); + let pattern = SurfacePattern::new(temporary_surface.azure_source_surface, + true, + true, + &matrix); + draw_target_ref.fill_rect(&dest_rect, PatternRef::Surface(&pattern), None); } pub fn clear(&self) { @@ -1130,9 +1172,7 @@ pub trait ToAzureRect { impl ToAzureRect for Rect<Au> { fn to_nearest_azure_rect(&self) -> Rect<AzFloat> { - Rect::new(self.origin.to_nearest_azure_point(), Size2D::new(self.size.width.to_nearest_px() as AzFloat, - self.size.height.to_nearest_px() as AzFloat)) - + Rect::new(self.origin.to_nearest_azure_point(), self.size.to_nearest_azure_size()) } fn to_azure_rect(&self) -> Rect<AzFloat> { Rect::new(self.origin.to_azure_point(), Size2D::new(self.size.width.to_f32_px(), @@ -1141,10 +1181,23 @@ impl ToAzureRect for Rect<Au> { } pub trait ToAzureSize { + fn to_nearest_azure_size(&self) -> Size2D<AzFloat>; fn to_azure_size(&self) -> Size2D<AzFloat>; } +impl ToAzureSize for Size2D<Au> { + fn to_nearest_azure_size(&self) -> Size2D<AzFloat> { + Size2D::new(self.width.to_nearest_px() as AzFloat, self.height.to_nearest_px() as AzFloat) + } + fn to_azure_size(&self) -> Size2D<AzFloat> { + Size2D::new(self.width.to_f32_px(), self.height.to_f32_px()) + } +} + impl ToAzureSize for AzIntSize { + fn to_nearest_azure_size(&self) -> Size2D<AzFloat> { + Size2D::new(self.width as AzFloat, self.height as AzFloat) + } fn to_azure_size(&self) -> Size2D<AzFloat> { Size2D::new(self.width as AzFloat, self.height as AzFloat) } diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 7201c574fd8..0270f4a6fc2 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -50,7 +50,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "azure" version = "0.1.0" -source = "git+https://github.com/servo/rust-azure#2e75a1ce23c44720612e050c214ee673d0b89cd7" +source = "git+https://github.com/servo/rust-azure#d8c86d7864bdf782734981f17ca7561c97bdaf98" dependencies = [ "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 986cd8ab9aa..b22de2afdac 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -49,7 +49,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "azure" version = "0.1.0" -source = "git+https://github.com/servo/rust-azure#2e75a1ce23c44720612e050c214ee673d0b89cd7" +source = "git+https://github.com/servo/rust-azure#d8c86d7864bdf782734981f17ca7561c97bdaf98" dependencies = [ "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index d9e9d2e48c9..f2a665d9019 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -36,7 +36,7 @@ dependencies = [ [[package]] name = "azure" version = "0.1.0" -source = "git+https://github.com/servo/rust-azure#2e75a1ce23c44720612e050c214ee673d0b89cd7" +source = "git+https://github.com/servo/rust-azure#d8c86d7864bdf782734981f17ca7561c97bdaf98" dependencies = [ "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/tests/ref/line.png b/tests/ref/line.png Binary files differindex dd11b292da7..bedcfda2056 100644 --- a/tests/ref/line.png +++ b/tests/ref/line.png |