diff options
| author | 2024-04-09 22:25:16 +0200 | |
|---|---|---|
| committer | 2024-04-09 22:25:16 +0200 | |
| commit | 6ad5bb3597f640ac329801adf735d633bf0a512f (patch) | |
| tree | f0928edacd09d6537878d22b00ad7ed7829c9ac0 /graphics/src/damage.rs | |
| parent | 2c6fd9ac14c5d270e05b97b7a7fab811d25834c4 (diff) | |
| download | iced-6ad5bb3597f640ac329801adf735d633bf0a512f.tar.gz iced-6ad5bb3597f640ac329801adf735d633bf0a512f.tar.bz2 iced-6ad5bb3597f640ac329801adf735d633bf0a512f.zip | |
Port `iced_tiny_skia` to new layering architecture
Diffstat (limited to 'graphics/src/damage.rs')
| -rw-r--r-- | graphics/src/damage.rs | 257 | 
1 files changed, 0 insertions, 257 deletions
| diff --git a/graphics/src/damage.rs b/graphics/src/damage.rs deleted file mode 100644 index 8edf69d7..00000000 --- a/graphics/src/damage.rs +++ /dev/null @@ -1,257 +0,0 @@ -//! Track and compute the damage of graphical primitives. -use crate::core::alignment; -use crate::core::{Rectangle, Size}; -use crate::Primitive; - -use std::sync::Arc; - -/// A type that has some damage bounds. -pub trait Damage: PartialEq { -    /// Returns the bounds of the [`Damage`]. -    fn bounds(&self) -> Rectangle; -} - -impl<T: Damage> Damage for Primitive<T> { -    fn bounds(&self) -> Rectangle { -        match self { -            Self::Text { -                bounds, -                horizontal_alignment, -                vertical_alignment, -                .. -            } => { -                let mut bounds = *bounds; - -                bounds.x = match horizontal_alignment { -                    alignment::Horizontal::Left => bounds.x, -                    alignment::Horizontal::Center => { -                        bounds.x - bounds.width / 2.0 -                    } -                    alignment::Horizontal::Right => bounds.x - bounds.width, -                }; - -                bounds.y = match vertical_alignment { -                    alignment::Vertical::Top => bounds.y, -                    alignment::Vertical::Center => { -                        bounds.y - bounds.height / 2.0 -                    } -                    alignment::Vertical::Bottom => bounds.y - bounds.height, -                }; - -                bounds.expand(1.5) -            } -            Self::Paragraph { -                paragraph, -                position, -                .. -            } => { -                let mut bounds = -                    Rectangle::new(*position, paragraph.min_bounds); - -                bounds.x = match paragraph.horizontal_alignment { -                    alignment::Horizontal::Left => bounds.x, -                    alignment::Horizontal::Center => { -                        bounds.x - bounds.width / 2.0 -                    } -                    alignment::Horizontal::Right => bounds.x - bounds.width, -                }; - -                bounds.y = match paragraph.vertical_alignment { -                    alignment::Vertical::Top => bounds.y, -                    alignment::Vertical::Center => { -                        bounds.y - bounds.height / 2.0 -                    } -                    alignment::Vertical::Bottom => bounds.y - bounds.height, -                }; - -                bounds.expand(1.5) -            } -            Self::Editor { -                editor, position, .. -            } => { -                let bounds = Rectangle::new(*position, editor.bounds); - -                bounds.expand(1.5) -            } -            Self::RawText(raw) => { -                // TODO: Add `size` field to `raw` to compute more accurate -                // damage bounds (?) -                raw.clip_bounds.expand(1.5) -            } -            Self::Quad { bounds, shadow, .. } if shadow.color.a > 0.0 => { -                let bounds_with_shadow = Rectangle { -                    x: bounds.x + shadow.offset.x.min(0.0) - shadow.blur_radius, -                    y: bounds.y + shadow.offset.y.min(0.0) - shadow.blur_radius, -                    width: bounds.width -                        + shadow.offset.x.abs() -                        + shadow.blur_radius * 2.0, -                    height: bounds.height -                        + shadow.offset.y.abs() -                        + shadow.blur_radius * 2.0, -                }; - -                bounds_with_shadow.expand(1.0) -            } -            Self::Quad { bounds, .. } -            | Self::Image { bounds, .. } -            | Self::Svg { bounds, .. } => bounds.expand(1.0), -            Self::Clip { bounds, .. } => bounds.expand(1.0), -            Self::Group { primitives } => primitives -                .iter() -                .map(Self::bounds) -                .fold(Rectangle::with_size(Size::ZERO), |a, b| { -                    Rectangle::union(&a, &b) -                }), -            Self::Transform { -                transformation, -                content, -            } => content.bounds() * *transformation, -            Self::Cache { content } => content.bounds(), -            Self::Custom(custom) => custom.bounds(), -        } -    } -} - -fn regions<T: Damage>(a: &Primitive<T>, b: &Primitive<T>) -> Vec<Rectangle> { -    match (a, b) { -        ( -            Primitive::Group { -                primitives: primitives_a, -            }, -            Primitive::Group { -                primitives: primitives_b, -            }, -        ) => return list(primitives_a, primitives_b), -        ( -            Primitive::Clip { -                bounds: bounds_a, -                content: content_a, -                .. -            }, -            Primitive::Clip { -                bounds: bounds_b, -                content: content_b, -                .. -            }, -        ) => { -            if bounds_a == bounds_b { -                return regions(content_a, content_b) -                    .into_iter() -                    .filter_map(|r| r.intersection(&bounds_a.expand(1.0))) -                    .collect(); -            } else { -                return vec![bounds_a.expand(1.0), bounds_b.expand(1.0)]; -            } -        } -        ( -            Primitive::Transform { -                transformation: transformation_a, -                content: content_a, -            }, -            Primitive::Transform { -                transformation: transformation_b, -                content: content_b, -            }, -        ) => { -            if transformation_a == transformation_b { -                return regions(content_a, content_b) -                    .into_iter() -                    .map(|r| r * *transformation_a) -                    .collect(); -            } -        } -        ( -            Primitive::Cache { content: content_a }, -            Primitive::Cache { content: content_b }, -        ) => { -            if Arc::ptr_eq(content_a, content_b) { -                return vec![]; -            } -        } -        _ if a == b => return vec![], -        _ => {} -    } - -    let bounds_a = a.bounds(); -    let bounds_b = b.bounds(); - -    if bounds_a == bounds_b { -        vec![bounds_a] -    } else { -        vec![bounds_a, bounds_b] -    } -} - -/// Computes the damage regions between the two given lists of primitives. -pub fn list<T: Damage>( -    previous: &[Primitive<T>], -    current: &[Primitive<T>], -) -> Vec<Rectangle> { -    let damage = previous -        .iter() -        .zip(current) -        .flat_map(|(a, b)| regions(a, b)); - -    if previous.len() == current.len() { -        damage.collect() -    } else { -        let (smaller, bigger) = if previous.len() < current.len() { -            (previous, current) -        } else { -            (current, previous) -        }; - -        // Extend damage by the added/removed primitives -        damage -            .chain(bigger[smaller.len()..].iter().map(Damage::bounds)) -            .collect() -    } -} - -/// Groups the given damage regions that are close together inside the given -/// bounds. -pub fn group( -    mut damage: Vec<Rectangle>, -    scale_factor: f32, -    bounds: Size<u32>, -) -> Vec<Rectangle> { -    use std::cmp::Ordering; - -    const AREA_THRESHOLD: f32 = 20_000.0; - -    let bounds = Rectangle { -        x: 0.0, -        y: 0.0, -        width: bounds.width as f32, -        height: bounds.height as f32, -    }; - -    damage.sort_by(|a, b| { -        a.x.partial_cmp(&b.x) -            .unwrap_or(Ordering::Equal) -            .then_with(|| a.y.partial_cmp(&b.y).unwrap_or(Ordering::Equal)) -    }); - -    let mut output = Vec::new(); -    let mut scaled = damage -        .into_iter() -        .filter_map(|region| (region * scale_factor).intersection(&bounds)) -        .filter(|region| region.width >= 1.0 && region.height >= 1.0); - -    if let Some(mut current) = scaled.next() { -        for region in scaled { -            let union = current.union(®ion); - -            if union.area() - current.area() - region.area() <= AREA_THRESHOLD { -                current = union; -            } else { -                output.push(current); -                current = region; -            } -        } - -        output.push(current); -    } - -    output -} | 
