Skip to content

Commit e554904

Browse files
committed
refactor: Add clamp_rect utility
1 parent 461e81c commit e554904

File tree

5 files changed

+52
-25
lines changed

5 files changed

+52
-25
lines changed

src/backends/wayland/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,8 @@ impl BufferInterface for BufferImpl<'_> {
260260
self.surface.damage(0, 0, i32::MAX, i32::MAX);
261261
} else {
262262
for rect in damage {
263-
// Damage that falls outside the surface is ignored.
263+
// Damage that falls outside the surface is ignored, so we don't need to clamp the
264+
// rect manually.
264265
// https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_surface
265266
let x = to_i32_saturating(rect.x);
266267
let y = to_i32_saturating(rect.y);

src/backends/web.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ impl BufferInterface for BufferImpl<'_> {
337337
.expect("Must set size of surface before calling `present_with_damage()`");
338338

339339
let union_damage = if let Some(rect) = util::union_damage(damage) {
340-
rect
340+
util::clamp_rect(rect, buffer_width, buffer_height)
341341
} else {
342342
return Ok(());
343343
};
@@ -359,9 +359,7 @@ impl BufferInterface for BufferImpl<'_> {
359359

360360
debug_assert_eq!(
361361
bitmap.len(),
362-
union_damage.width.get().min(buffer_width.get()) as usize
363-
* union_damage.height.get().min(buffer_height.get()) as usize
364-
* 4
362+
union_damage.width.get() as usize * union_damage.height.get() as usize * 4
365363
);
366364

367365
#[cfg(target_feature = "atomics")]
@@ -384,29 +382,31 @@ impl BufferInterface for BufferImpl<'_> {
384382
let array = Uint8Array::new_with_length(bitmap.len() as u32);
385383
array.copy_from(&bitmap);
386384
let array = Uint8ClampedArray::new(&array);
387-
ImageDataExt::new(array, union_damage.width.get().min(buffer_width.get()))
385+
ImageDataExt::new(array, union_damage.width.get())
388386
.map(JsValue::from)
389387
.map(ImageData::unchecked_from_js)
390388
};
391389
#[cfg(not(target_feature = "atomics"))]
392390
let result = ImageData::new_with_u8_clamped_array(
393391
wasm_bindgen::Clamped(&bitmap),
394-
union_damage.width.get().min(buffer_width.get()),
392+
union_damage.width.get(),
395393
);
396394
// This should only throw an error if the buffer we pass's size is incorrect.
397395
let image_data = result.unwrap();
398396

399397
for rect in damage {
398+
let rect = util::clamp_rect(*rect, buffer_width, buffer_height);
399+
400400
// This can only throw an error if `data` is detached, which is impossible.
401401
self.canvas
402402
.put_image_data(
403403
&image_data,
404-
union_damage.x.min(buffer_width.get()).into(),
405-
union_damage.y.min(buffer_height.get()).into(),
404+
union_damage.x.into(),
405+
union_damage.y.into(),
406406
(rect.x - union_damage.x).into(),
407407
(rect.y - union_damage.y).into(),
408-
rect.width.get().min(buffer_width.get()).into(),
409-
rect.height.get().min(buffer_height.get()).into(),
408+
rect.width.get().into(),
409+
rect.height.get().into(),
410410
)
411411
.unwrap();
412412
}

src/backends/win32.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! This module converts the input buffer into a bitmap and then stretches it to the window.
44
55
use crate::backend_interface::*;
6-
use crate::{Rect, SoftBufferError};
6+
use crate::{util, Rect, SoftBufferError};
77
use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawWindowHandle};
88

99
use std::io;
@@ -273,21 +273,26 @@ impl BufferInterface for BufferImpl<'_> {
273273

274274
fn present_with_damage(self, damage: &[Rect]) -> Result<(), SoftBufferError> {
275275
unsafe {
276-
for rect in damage.iter().copied() {
276+
for rect in damage {
277+
let rect = util::clamp_rect(
278+
*rect,
279+
self.buffer.width.try_into().unwrap(),
280+
self.buffer.height.try_into().unwrap(),
281+
);
277282
let x = to_i32_saturating(rect.x);
278283
let y = to_i32_saturating(rect.y);
279284
let width = to_i32_saturating(rect.width.get());
280285
let height = to_i32_saturating(rect.height.get());
281286

282287
Gdi::BitBlt(
283288
self.dc.0,
284-
x.min(self.buffer.width.get()),
285-
y.min(self.buffer.height.get()),
286-
width.min(self.buffer.width.get()),
287-
height.min(self.buffer.height.get()),
289+
x,
290+
y,
291+
width,
292+
height,
288293
self.buffer.dc,
289-
x.min(self.buffer.width.get()),
290-
y.min(self.buffer.height.get()),
294+
x,
295+
y,
291296
Gdi::SRCCOPY,
292297
);
293298
}

src/backends/x11.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,11 @@ impl BufferInterface for BufferImpl<'_> {
469469
damage
470470
.iter()
471471
.try_for_each(|rect| {
472+
let rect = util::clamp_rect(
473+
*rect,
474+
surface_width.into(),
475+
surface_height.into(),
476+
);
472477
let src_x = to_u16_saturating(rect.x);
473478
let src_y = to_u16_saturating(rect.y);
474479
let dst_x = to_i16_saturating(rect.x);
@@ -482,12 +487,12 @@ impl BufferInterface for BufferImpl<'_> {
482487
self.gc,
483488
surface_width.get(),
484489
surface_height.get(),
485-
src_x.min(surface_width.get()),
486-
src_y.min(surface_height.get()),
487-
width.min(surface_width.get()),
488-
height.min(surface_height.get()),
489-
dst_x.min(surface_width.get() as i16),
490-
dst_y.min(surface_height.get() as i16),
490+
src_x,
491+
src_y,
492+
width,
493+
height,
494+
dst_x,
495+
dst_y,
491496
self.depth,
492497
xproto::ImageFormat::Z_PIXMAP.into(),
493498
false,

src/util.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,22 @@ pub(crate) fn union_damage(damage: &[Rect]) -> Option<Rect> {
4343
})
4444
}
4545

46+
/// Clamp the damage rectangle to be within the given bounds.
47+
pub(crate) fn clamp_rect(rect: Rect, width: NonZeroU32, height: NonZeroU32) -> Rect {
48+
// The positions of the edges of the rectangle.
49+
let left = rect.x.min(width.get());
50+
let top = rect.y.min(height.get());
51+
let right = rect.x.saturating_add(rect.width.get()).min(width.get());
52+
let bottom = rect.y.saturating_add(rect.height.get()).min(height.get());
53+
54+
Rect {
55+
x: left,
56+
y: top,
57+
width: NonZeroU32::new(right - left).expect("rect ended up being zero-sized"),
58+
height: NonZeroU32::new(bottom - top).expect("rect ended up being zero-sized"),
59+
}
60+
}
61+
4662
/// A wrapper around a `Vec` of pixels that doesn't print the whole buffer on `Debug`.
4763
#[derive(PartialEq, Eq, Hash, Clone)]
4864
pub(crate) struct PixelBuffer(pub Vec<u32>);

0 commit comments

Comments
 (0)