Skip to content

Commit 2bcdd64

Browse files
committed
Panic hardening of shadows module
1 parent f5401f6 commit 2bcdd64

File tree

1 file changed

+48
-37
lines changed

1 file changed

+48
-37
lines changed

src/shadow.rs

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::{parts::DecorationParts, theme};
2-
use std::collections::BTreeMap;
2+
use std::collections::{btree_map, BTreeMap};
33
use tiny_skia::{Pixmap, PixmapMut, PixmapRef, Point, PremultipliedColorU8};
44

55
// These values were generated from a screenshot of an libadwaita window using a script.
@@ -25,38 +25,47 @@ struct RenderedShadow {
2525
}
2626

2727
impl RenderedShadow {
28-
fn new(scale: u32, active: bool) -> RenderedShadow {
28+
fn new(scale: u32, active: bool) -> Option<RenderedShadow> {
2929
let shadow_size = SHADOW_SIZE * scale;
3030
let corner_radius = theme::CORNER_RADIUS * scale;
3131

32-
#[allow(clippy::unwrap_used)]
33-
let mut side = Pixmap::new(shadow_size, 1).unwrap();
32+
let mut side = Pixmap::new(shadow_size, 1)?;
3433
for x in 0..side.width() as usize {
35-
let alpha = (shadow(x as f32 + 0.5, scale, active) * u8::MAX as f32).round() as u8;
34+
let shadow = shadow(x as f32 + 0.5, scale, active);
35+
let alpha = (shadow * u8::MAX as f32).round() as u8;
3636

37-
#[allow(clippy::unwrap_used)]
38-
let color = PremultipliedColorU8::from_rgba(0, 0, 0, alpha).unwrap();
39-
side.pixels_mut()[x] = color;
37+
let Some(color) = PremultipliedColorU8::from_rgba(0, 0, 0, alpha) else {
38+
continue;
39+
};
40+
41+
if let Some(pixel) = side.pixels_mut().get_mut(x) {
42+
*pixel = color;
43+
}
4044
}
4145

4246
let edges_size = (corner_radius + shadow_size) * 2;
43-
#[allow(clippy::unwrap_used)]
44-
let mut edges = Pixmap::new(edges_size, edges_size).unwrap();
47+
let mut edges = Pixmap::new(edges_size, edges_size)?;
4548
let edges_middle = Point::from_xy(edges_size as f32 / 2.0, edges_size as f32 / 2.0);
4649
for y in 0..edges_size as usize {
4750
let y_pos = y as f32 + 0.5;
4851
for x in 0..edges_size as usize {
4952
let dist = edges_middle.distance(Point::from_xy(x as f32 + 0.5, y_pos))
5053
- corner_radius as f32;
51-
let alpha = (shadow(dist, scale, active) * u8::MAX as f32).round() as u8;
5254

53-
#[allow(clippy::unwrap_used)]
54-
let color = PremultipliedColorU8::from_rgba(0, 0, 0, alpha).unwrap();
55-
edges.pixels_mut()[y * edges_size as usize + x] = color;
55+
let shadow = shadow(dist, scale, active);
56+
let alpha = (shadow * u8::MAX as f32).round() as u8;
57+
58+
let Some(color) = PremultipliedColorU8::from_rgba(0, 0, 0, alpha) else {
59+
continue;
60+
};
61+
62+
if let Some(pixel) = edges.pixels_mut().get_mut(y * edges_size as usize + x) {
63+
*pixel = color;
64+
}
5665
}
5766
}
5867

59-
RenderedShadow { side, edges }
68+
Some(RenderedShadow { side, edges })
6069
}
6170

6271
fn side_draw(
@@ -150,7 +159,11 @@ impl RenderedShadow {
150159
let shadow_size = (SHADOW_SIZE * scale) as usize;
151160
let visible_border_size = (theme::VISIBLE_BORDER_SIZE * scale) as usize;
152161
let corner_radius = (theme::CORNER_RADIUS * scale) as usize;
153-
assert!(corner_radius > visible_border_size);
162+
163+
debug_assert!(corner_radius > visible_border_size);
164+
if corner_radius <= visible_border_size {
165+
return;
166+
}
154167

155168
let dst_width = dst_pixmap.width() as usize;
156169
let dst_height = dst_pixmap.height() as usize;
@@ -333,16 +346,15 @@ impl CachedPart {
333346
scale: u32,
334347
active: bool,
335348
part_idx: usize,
336-
) -> CachedPart {
337-
#[allow(clippy::unwrap_used)]
338-
let mut pixmap = Pixmap::new(dst_pixmap.width(), dst_pixmap.height()).unwrap();
349+
) -> Option<CachedPart> {
350+
let mut pixmap = Pixmap::new(dst_pixmap.width(), dst_pixmap.height())?;
339351
rendered.draw(&mut pixmap.as_mut(), scale, part_idx);
340352

341-
CachedPart {
353+
Some(CachedPart {
342354
pixmap,
343355
scale,
344356
active,
345-
}
357+
})
346358
}
347359

348360
fn matches(&self, dst_pixmap: &PixmapRef, dst_scale: u32, dst_active: bool) -> bool {
@@ -367,7 +379,9 @@ pub struct Shadow {
367379

368380
impl Shadow {
369381
pub fn draw(&mut self, pixmap: &mut PixmapMut, scale: u32, active: bool, part_idx: usize) {
370-
let cache = &mut self.part_cache[part_idx];
382+
let Some(cache) = self.part_cache.get_mut(part_idx) else {
383+
return;
384+
};
371385

372386
if let Some(cache_value) = cache {
373387
if !cache_value.matches(&pixmap.as_ref(), scale, active) {
@@ -376,22 +390,19 @@ impl Shadow {
376390
}
377391

378392
if cache.is_none() {
379-
let rendered = self
380-
.rendered
381-
.entry((scale, active))
382-
.or_insert_with(|| RenderedShadow::new(scale, active));
383-
384-
*cache = Some(CachedPart::new(
385-
&pixmap.as_ref(),
386-
rendered,
387-
scale,
388-
active,
389-
part_idx,
390-
));
393+
let rendered = match self.rendered.entry((scale, active)) {
394+
btree_map::Entry::Occupied(entry) => entry.into_mut(),
395+
btree_map::Entry::Vacant(entry) => match RenderedShadow::new(scale, active) {
396+
Some(v) => entry.insert(v),
397+
None => return,
398+
},
399+
};
400+
401+
*cache = CachedPart::new(&pixmap.as_ref(), rendered, scale, active, part_idx);
391402
}
392403

393-
// We filled the cache above.
394-
#[allow(clippy::unwrap_used)]
395-
cache.as_ref().unwrap().draw(pixmap);
404+
if let Some(cache) = cache.as_ref() {
405+
cache.draw(pixmap);
406+
}
396407
}
397408
}

0 commit comments

Comments
 (0)