зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
8b7d8473f3
Коммит
0141dfbe06
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)",
|
||||||
|
|
|
@ -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)",
|
||||||
|
|
|
@ -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)",
|
||||||
|
|
Загрузка…
Ссылка в новой задаче