use { jay_geometry::Rect, jay_tree_types::Transform, jay_units::fixed::Fixed, }; #[derive(Copy, Clone, Debug)] pub struct DamageMatrix { transform: Transform, mx: f64, my: f64, dx: f64, dy: f64, smear: i32, } impl Default for DamageMatrix { fn default() -> Self { Self { transform: Default::default(), mx: 1.0, my: 1.0, dx: 0.0, dy: 0.0, smear: 0, } } } impl DamageMatrix { pub fn apply(&self, dx: i32, dy: i32, rect: Rect) -> Rect { let x1 = rect.x1() - self.smear; let x2 = rect.x2() + self.smear; let y1 = rect.y1() - self.smear; let y2 = rect.y2() + self.smear; let [x1, y1, x2, y2] = match self.transform { Transform::None => [x1, y1, x2, y2], Transform::Rotate90 => [-y2, x1, -y1, x2], Transform::Rotate180 => [-x2, -y2, -x1, -y1], Transform::Rotate270 => [y1, -x2, y2, -x1], Transform::Flip => [-x2, y1, -x1, y2], Transform::FlipRotate90 => [y1, x1, y2, x2], Transform::FlipRotate180 => [x1, -y2, x2, -y1], Transform::FlipRotate270 => [-y2, -x2, -y1, -x1], }; let x1 = (x1 as f64 * self.mx + self.dx).floor() as i32 + dx; let y1 = (y1 as f64 * self.my + self.dy).floor() as i32 + dy; let x2 = (x2 as f64 * self.mx + self.dx).ceil() as i32 + dx; let y2 = (y2 as f64 * self.my + self.dy).ceil() as i32 + dy; Rect::new_saturating(x1, y1, x2, y2) } pub fn new( transform: Transform, legacy_scale: i32, buffer_width: i32, buffer_height: i32, viewport: Option<[Fixed; 4]>, dst_width: i32, dst_height: i32, ) -> DamageMatrix { let mut buffer_width = buffer_width as f64; let mut buffer_height = buffer_height as f64; let dst_width = dst_width as f64; let dst_height = dst_height as f64; let mut mx = 1.0; let mut my = 1.0; if legacy_scale != 1 { let scale_inv = 1.0 / (legacy_scale as f64); mx = scale_inv; my = scale_inv; buffer_width *= scale_inv; buffer_height *= scale_inv; } let (mut buffer_width, mut buffer_height) = transform.maybe_swap((buffer_width, buffer_height)); let (mut dx, mut dy) = match transform { Transform::None => (0.0, 0.0), Transform::Rotate90 => (buffer_width, 0.0), Transform::Rotate180 => (buffer_width, buffer_height), Transform::Rotate270 => (0.0, buffer_height), Transform::Flip => (buffer_width, 0.0), Transform::FlipRotate90 => (0.0, 0.0), Transform::FlipRotate180 => (0.0, buffer_height), Transform::FlipRotate270 => (buffer_width, buffer_height), }; if let Some([x, y, w, h]) = viewport { dx -= x.to_f64(); dy -= y.to_f64(); buffer_width = w.to_f64(); buffer_height = h.to_f64(); } let mut smear = false; if dst_width != buffer_width { let scale = dst_width / buffer_width; mx *= scale; dx *= scale; smear |= dst_width > buffer_width; } if dst_height != buffer_height { let scale = dst_height / buffer_height; my *= scale; dy *= scale; smear |= dst_height > buffer_height; } DamageMatrix { transform, mx, my, dx, dy, smear: smear as _, } } }