diff --git a/src/web.rs b/src/web.rs index 48ceac3..5dd2687 100644 --- a/src/web.rs +++ b/src/web.rs @@ -107,34 +107,10 @@ impl WebImpl { pub(crate) fn buffer_mut(&mut self) -> Result { Ok(BufferImpl { imp: self }) } -} - -pub struct BufferImpl<'a> { - imp: &'a mut WebImpl, -} - -impl<'a> BufferImpl<'a> { - pub fn pixels(&self) -> &[u32] { - &self.imp.buffer - } - - pub fn pixels_mut(&mut self) -> &mut [u32] { - &mut self.imp.buffer - } - pub fn age(&self) -> u8 { - if self.imp.buffer_presented { - 1 - } else { - 0 - } - } - - /// Push the buffer to the canvas. - pub fn present(self) -> Result<(), SoftBufferError> { + fn present_with_damage(&mut self, damage: &[Rect]) -> Result<(), SoftBufferError> { // Create a bitmap from the buffer. let bitmap: Vec<_> = self - .imp .buffer .iter() .copied() @@ -159,26 +135,86 @@ impl<'a> BufferImpl<'a> { let array = Uint8Array::new_with_length(bitmap.len() as u32); array.copy_from(&bitmap); let array = Uint8ClampedArray::new(&array); - ImageDataExt::new(array, self.imp.width) + ImageDataExt::new(array, self.width) .map(JsValue::from) .map(ImageData::unchecked_from_js) }; #[cfg(not(target_feature = "atomics"))] let result = - ImageData::new_with_u8_clamped_array(wasm_bindgen::Clamped(&bitmap), self.imp.width); + ImageData::new_with_u8_clamped_array(wasm_bindgen::Clamped(&bitmap), self.width); // This should only throw an error if the buffer we pass's size is incorrect. let image_data = result.unwrap(); - // This can only throw an error if `data` is detached, which is impossible. - self.imp.ctx.put_image_data(&image_data, 0.0, 0.0).unwrap(); + for Rect { + x, + y, + width, + height, + } in damage + { + // This can only throw an error if `data` is detached, which is impossible. + self.ctx + .put_image_data_with_dirty_x_and_dirty_y_and_dirty_width_and_dirty_height( + &image_data, + (*x).into(), + (*y).into(), + (*x).into(), + (*y).into(), + (*width).into(), + (*height).into(), + ) + .unwrap(); + } - self.imp.buffer_presented = true; + self.buffer_presented = true; Ok(()) } +} + +pub struct BufferImpl<'a> { + imp: &'a mut WebImpl, +} + +impl<'a> BufferImpl<'a> { + pub fn pixels(&self) -> &[u32] { + &self.imp.buffer + } + + pub fn pixels_mut(&mut self) -> &mut [u32] { + &mut self.imp.buffer + } + + pub fn age(&self) -> u8 { + if self.imp.buffer_presented { + 1 + } else { + 0 + } + } + + /// Push the buffer to the canvas. + pub fn present(self) -> Result<(), SoftBufferError> { + let (width, height) = (|| { + let width = i32::try_from(self.imp.width).ok()?; + let height = i32::try_from(self.imp.height).ok()?; + Some((width, height)) + })() + .ok_or(SoftBufferError::SizeOutOfRange { + width: NonZeroU32::new(self.imp.width).unwrap(), + height: NonZeroU32::new(self.imp.height).unwrap(), + })?; + + self.imp.present_with_damage(&[Rect { + x: 0, + y: 0, + width, + height, + }]) + } - pub fn present_with_damage(self, _damage: &[Rect]) -> Result<(), SoftBufferError> { - self.present() + pub fn present_with_damage(self, damage: &[Rect]) -> Result<(), SoftBufferError> { + self.imp.present_with_damage(damage) } }