servo: Merge #6487 - gfx: Use a pattern instead of tiling images manually (from pcwalton:background-tiling); r=glennw

r? @SimonSapin

Source-Repo: https://github.com/servo/servo
Source-Revision: ae01e97efa31a180374dc0fd623ff03a650f7878
This commit is contained in:
Patrick Walton 2015-07-07 05:42:07 -06:00
Родитель 8b7d8473f3
Коммит 0141dfbe06
6 изменённых файлов: 77 добавлений и 40 удалений

Просмотреть файл

@ -284,7 +284,8 @@ impl FillOrStrokeStyle {
Pattern::Surface(SurfacePattern::new( Pattern::Surface(SurfacePattern::new(
source_surface.azure_source_surface, source_surface.azure_source_surface,
surface_style.repeat_x, surface_style.repeat_x,
surface_style.repeat_y)) surface_style.repeat_y,
&Matrix2D::identity()))
} }
} }
} }

Просмотреть файл

@ -1068,28 +1068,11 @@ impl DisplayItem {
} }
DisplayItem::ImageClass(ref image_item) => { 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); debug!("Drawing image at {:?}.", image_item.base.bounds);
paint_context.draw_image(&image_item.base.bounds,
let mut y_offset = Au(0); &image_item.stretch_size,
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.clone(),
image_item.image_rendering.clone()); image_item.image_rendering.clone());
x_offset = x_offset + image_item.stretch_size.width;
}
y_offset = y_offset + image_item.stretch_size.height;
}
} }
DisplayItem::BorderClass(ref border) => { DisplayItem::BorderClass(ref border) => {

Просмотреть файл

@ -14,12 +14,12 @@ use text::TextRun;
use text::glyph::CharIndex; use text::glyph::CharIndex;
use azure::azure::AzIntSize; 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::{DrawOptions, DrawSurfaceOptions, DrawTarget, ExtendMode, FilterType};
use azure::azure_hl::{GaussianBlurAttribute, StrokeOptions, SurfaceFormat}; use azure::azure_hl::{GaussianBlurAttribute, StrokeOptions, SurfaceFormat};
use azure::azure_hl::{GaussianBlurInput, GradientStop, Filter, FilterNode, LinearGradientPattern}; use azure::azure_hl::{GaussianBlurInput, GradientStop, Filter, FilterNode, LinearGradientPattern};
use azure::azure_hl::{JoinStyle, CapStyle}; 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::scaled_font::ScaledFont;
use azure::{AzFloat, struct__AzDrawOptions, struct__AzGlyph}; use azure::{AzFloat, struct__AzDrawOptions, struct__AzGlyph};
use azure::{struct__AzGlyphBuffer, struct__AzPoint, AzDrawTargetFillGlyphs}; use azure::{struct__AzGlyphBuffer, struct__AzPoint, AzDrawTargetFillGlyphs};
@ -130,6 +130,7 @@ impl<'a> PaintContext<'a> {
pub fn draw_image(&self, pub fn draw_image(&self,
bounds: &Rect<Au>, bounds: &Rect<Au>,
stretch_size: &Size2D<Au>,
image: Arc<Image>, image: Arc<Image>,
image_rendering: image_rendering::T) { image_rendering: image_rendering::T) {
let size = Size2D::new(image.width as i32, image.height as i32); let size = Size2D::new(image.width as i32, image.height as i32);
@ -154,19 +155,60 @@ impl<'a> PaintContext<'a> {
// TODO(pcwalton): According to CSS-IMAGES-3 § 5.3, nearest-neighbor interpolation is 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. // conforming implementation of `crisp-edges`, but it is not the best we could do.
// Something like Scale2x would be ideal. // Something like Scale2x would be ideal.
let draw_surface_options = match image_rendering { let draw_surface_filter = match image_rendering {
image_rendering::T::Auto => DrawSurfaceOptions::new(Filter::Linear, true), image_rendering::T::Auto => Filter::Linear,
image_rendering::T::CrispEdges | image_rendering::T::Pixelated => { image_rendering::T::CrispEdges | image_rendering::T::Pixelated => Filter::Point,
DrawSurfaceOptions::new(Filter::Point, true)
}
}; };
let draw_surface_options = DrawSurfaceOptions::new(draw_surface_filter, true);
let draw_options = DrawOptions::new(1.0, CompositionOp::Over, AntialiasMode::None); 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, draw_target_ref.draw_surface(azure_surface,
dest_rect, dest_rect,
source_rect, source_rect,
draw_surface_options, draw_surface_options,
draw_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);
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) { pub fn clear(&self) {
@ -1129,9 +1171,7 @@ pub trait ToAzureRect {
impl ToAzureRect for Rect<Au> { impl ToAzureRect for Rect<Au> {
fn to_nearest_azure_rect(&self) -> Rect<AzFloat> { 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, Rect::new(self.origin.to_nearest_azure_point(), self.size.to_nearest_azure_size())
self.size.height.to_nearest_px() as AzFloat))
} }
fn to_azure_rect(&self) -> Rect<AzFloat> { fn to_azure_rect(&self) -> Rect<AzFloat> {
Rect::new(self.origin.to_azure_point(), Size2D::new(self.size.width.to_f32_px(), Rect::new(self.origin.to_azure_point(), Size2D::new(self.size.width.to_f32_px(),
@ -1140,10 +1180,23 @@ impl ToAzureRect for Rect<Au> {
} }
pub trait ToAzureSize { pub trait ToAzureSize {
fn to_nearest_azure_size(&self) -> Size2D<AzFloat>;
fn to_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 { 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> { fn to_azure_size(&self) -> Size2D<AzFloat> {
Size2D::new(self.width as AzFloat, self.height as AzFloat) Size2D::new(self.width as AzFloat, self.height as AzFloat)
} }

2
servo/components/servo/Cargo.lock сгенерированный
Просмотреть файл

@ -50,7 +50,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "azure" name = "azure"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/servo/rust-azure#2e75a1ce23c44720612e050c214ee673d0b89cd7" source = "git+https://github.com/servo/rust-azure#d8c86d7864bdf782734981f17ca7561c97bdaf98"
dependencies = [ dependencies = [
"core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",

2
servo/ports/cef/Cargo.lock сгенерированный
Просмотреть файл

@ -49,7 +49,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "azure" name = "azure"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/servo/rust-azure#2e75a1ce23c44720612e050c214ee673d0b89cd7" source = "git+https://github.com/servo/rust-azure#d8c86d7864bdf782734981f17ca7561c97bdaf98"
dependencies = [ dependencies = [
"core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",

2
servo/ports/gonk/Cargo.lock сгенерированный
Просмотреть файл

@ -36,7 +36,7 @@ dependencies = [
[[package]] [[package]]
name = "azure" name = "azure"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/servo/rust-azure#2e75a1ce23c44720612e050c214ee673d0b89cd7" source = "git+https://github.com/servo/rust-azure#d8c86d7864bdf782734981f17ca7561c97bdaf98"
dependencies = [ dependencies = [
"core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",