aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/canvas_traits/lib.rs3
-rw-r--r--components/gfx/display_list/mod.rs25
-rw-r--r--components/gfx/paint_context.rs83
-rw-r--r--components/servo/Cargo.lock2
-rw-r--r--ports/cef/Cargo.lock2
-rw-r--r--ports/gonk/Cargo.lock2
-rw-r--r--tests/ref/line.pngbin135 -> 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
index dd11b292da7..bedcfda2056 100644
--- a/tests/ref/line.png
+++ b/tests/ref/line.png
Binary files differ