aboutsummaryrefslogtreecommitdiffstats
path: root/components/canvas/canvas_data.rs
diff options
context:
space:
mode:
authorAnthony Ramine <n.oxyde@gmail.com>2018-10-06 01:10:34 +0200
committerAnthony Ramine <n.oxyde@gmail.com>2018-10-06 01:12:05 +0200
commit19f40cdf0ba09a767e65ee3f0bd37622cc341bde (patch)
tree5941c56bed71aaf9c33bece5f778c1455ae15926 /components/canvas/canvas_data.rs
parent784fbb2bc17d311fe3322cc48d2dca8a902161ca (diff)
downloadservo-19f40cdf0ba09a767e65ee3f0bd37622cc341bde.tar.gz
servo-19f40cdf0ba09a767e65ee3f0bd37622cc341bde.zip
Introduce ImageData::get_rect
We use that to send only the pixels that will be actually drawn to the canvas thread in CanvasRenderingContext2d::PutImageData. We also make the canvas thread byte swap and premultiply colours in-place.
Diffstat (limited to 'components/canvas/canvas_data.rs')
-rw-r--r--components/canvas/canvas_data.rs45
1 files changed, 13 insertions, 32 deletions
diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs
index d4f083ae1e8..30e6218d604 100644
--- a/components/canvas/canvas_data.rs
+++ b/components/canvas/canvas_data.rs
@@ -13,6 +13,7 @@ use cssparser::RGBA;
use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D};
use ipc_channel::ipc::{IpcBytesSender, IpcSender};
use num_traits::ToPrimitive;
+use pixels;
use serde_bytes::ByteBuf;
use std::mem;
use std::sync::Arc;
@@ -451,42 +452,22 @@ impl<'a> CanvasData<'a> {
// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
pub fn put_image_data(
&mut self,
- imagedata: Vec<u8>,
+ mut imagedata: Vec<u8>,
offset: Vector2D<i32>,
- image_data_size: Size2D<i32>,
- dest_rect: Rect<i32>,
+ imagedata_size: Size2D<i32>,
) {
- assert_eq!(image_data_size.width * image_data_size.height * 4, imagedata.len() as i32);
-
- let image_size = image_data_size;
-
- let first_pixel = dest_rect.origin;
- let mut src_line = (first_pixel.y * (image_size.width * 4) + first_pixel.x * 4) as usize;
-
- let mut dest =
- Vec::with_capacity((dest_rect.size.width * dest_rect.size.height * 4) as usize);
-
- for _ in 0 .. dest_rect.size.height {
- let mut src_offset = src_line;
- for _ in 0 .. dest_rect.size.width {
- let alpha = imagedata[src_offset + 3] as u16;
- // add 127 before dividing for more accurate rounding
- let premultiply_channel = |channel: u8| (((channel as u16 * alpha) + 127) / 255) as u8;
- dest.push(premultiply_channel(imagedata[src_offset + 2]));
- dest.push(premultiply_channel(imagedata[src_offset + 1]));
- dest.push(premultiply_channel(imagedata[src_offset + 0]));
- dest.push(imagedata[src_offset + 3]);
- src_offset += 4;
- }
- src_line += (image_size.width * 4) as usize;
- }
-
+ assert_eq!(imagedata_size.area() * 4, imagedata.len() as i32);
+ pixels::byte_swap_and_premultiply_inplace(&mut imagedata);
if let Some(source_surface) = self.drawtarget.create_source_surface_from_data(
- &dest,
- dest_rect.size,
- dest_rect.size.width * 4,
+ &imagedata,
+ imagedata_size,
+ imagedata_size.width * 4,
SurfaceFormat::B8G8R8A8) {
- self.drawtarget.copy_surface(source_surface, Rect::from_size(dest_rect.size), offset.to_point());
+ self.drawtarget.copy_surface(
+ source_surface,
+ Rect::from_size(imagedata_size),
+ offset.to_point(),
+ );
}
}