mirror of
https://github.com/servo/servo.git
synced 2025-08-02 20:20:14 +01:00
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.
This commit is contained in:
parent
784fbb2bc1
commit
19f40cdf0b
5 changed files with 52 additions and 55 deletions
|
@ -1277,19 +1277,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
|||
return;
|
||||
}
|
||||
|
||||
// FIXME(nox): There is no need to make a Vec<u8> of all the pixels
|
||||
// if we didn't want to put the entire image.
|
||||
let buffer = imagedata.get_data_array();
|
||||
let dirty_size = Size2D::new(dirty_width, dirty_height);
|
||||
let dirty_rect = Rect::new(Point2D::new(dirty_x, dirty_y), dirty_size);
|
||||
|
||||
// Step 7.
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(
|
||||
buffer.into(),
|
||||
imagedata.get_rect(dirty_rect.try_cast().unwrap()).into(),
|
||||
origin.to_vector(),
|
||||
imagedata_size,
|
||||
Rect::new(
|
||||
Point2D::new(dirty_x, dirty_y),
|
||||
Size2D::new(dirty_width, dirty_height),
|
||||
),
|
||||
dirty_size,
|
||||
));
|
||||
self.mark_as_dirty();
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use dom::bindings::reflector::{Reflector, reflect_dom_object};
|
|||
use dom::bindings::root::DomRoot;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom_struct::dom_struct;
|
||||
use euclid::Size2D;
|
||||
use euclid::{Rect, Size2D};
|
||||
use js::jsapi::{Heap, JSContext, JSObject};
|
||||
use js::rust::Runtime;
|
||||
use js::typedarray::{Uint8ClampedArray, CreateWith};
|
||||
|
@ -149,9 +149,40 @@ impl ImageData {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub fn get_rect(&self, rect: Rect<u32>) -> Vec<u8> {
|
||||
unsafe {
|
||||
assert!(!rect.is_empty());
|
||||
assert!(self.rect().contains_rect(&rect));
|
||||
assert!(!self.data.get().is_null());
|
||||
let cx = Runtime::get();
|
||||
assert!(!cx.is_null());
|
||||
typedarray!(in(cx) let array: Uint8ClampedArray = self.data.get());
|
||||
let slice = array.as_ref().unwrap().as_slice();
|
||||
let area = rect.size.area() as usize;
|
||||
let first_column_start = rect.origin.x as usize * 4;
|
||||
let row_length = self.width as usize * 4;
|
||||
let first_row_start = rect.origin.y as usize * row_length;
|
||||
if rect.origin.x == 0 && rect.size.width == self.width || rect.size.height == 1 {
|
||||
let start = first_column_start + first_row_start;
|
||||
// FIXME(nox): This should be a borrow.
|
||||
return slice[start..start + area * 4].into();
|
||||
}
|
||||
let mut data = Vec::with_capacity(area * 4);
|
||||
for row in slice[first_row_start..].chunks(row_length).take(rect.size.height as usize) {
|
||||
data.extend_from_slice(&row[first_column_start..][..rect.size.width as usize * 4]);
|
||||
}
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_size(&self) -> Size2D<u32> {
|
||||
Size2D::new(self.Width(), self.Height())
|
||||
}
|
||||
|
||||
pub fn rect(&self) -> Rect<u32> {
|
||||
Rect::from_size(self.get_size())
|
||||
}
|
||||
}
|
||||
|
||||
impl ImageDataMethods for ImageData {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue