diff options
Diffstat (limited to '')
| -rw-r--r-- | tiny_skia/src/backend.rs | 153 | 
1 files changed, 150 insertions, 3 deletions
| diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs index 62373ec7..54752a21 100644 --- a/tiny_skia/src/backend.rs +++ b/tiny_skia/src/backend.rs @@ -2,7 +2,7 @@ use crate::{Color, Font, Settings, Size, Viewport};  use iced_graphics::backend;  use iced_graphics::text; -use iced_graphics::Primitive; +use iced_graphics::{Background, Primitive, Rectangle, Vector};  use std::borrow::Cow; @@ -22,12 +22,133 @@ impl Backend {      pub fn draw<T: AsRef<str>>(          &mut self,          pixels: &mut tiny_skia::Pixmap, -        _primitives: &[Primitive], -        _viewport: &Viewport, +        primitives: &[Primitive], +        viewport: &Viewport,          background_color: Color,          _overlay: &[T],      ) {          pixels.fill(into_color(background_color)); + +        let scale_factor = viewport.scale_factor() as f32; + +        for primitive in primitives { +            draw_primitive(primitive, pixels, None, scale_factor, Vector::ZERO); +        } +    } +} + +fn draw_primitive( +    primitive: &Primitive, +    pixels: &mut tiny_skia::Pixmap, +    clip_mask: Option<&tiny_skia::ClipMask>, +    scale_factor: f32, +    translation: Vector, +) { +    match primitive { +        Primitive::None => {} +        Primitive::Quad { +            bounds, +            background, +            border_radius: _, // TODO +            border_width, +            border_color, +        } => { +            let transform = tiny_skia::Transform::from_translate( +                translation.x, +                translation.y, +            ) +            .post_scale(scale_factor, scale_factor); + +            let path = tiny_skia::PathBuilder::from_rect( +                tiny_skia::Rect::from_xywh( +                    bounds.x, +                    bounds.y, +                    bounds.width, +                    bounds.height, +                ) +                .expect("Create quad rectangle"), +            ); + +            pixels.fill_path( +                &path, +                &tiny_skia::Paint { +                    shader: match background { +                        Background::Color(color) => { +                            tiny_skia::Shader::SolidColor(into_color(*color)) +                        } +                    }, +                    anti_alias: true, +                    ..tiny_skia::Paint::default() +                }, +                tiny_skia::FillRule::EvenOdd, +                transform, +                clip_mask, +            ); + +            if *border_width > 0.0 { +                pixels.stroke_path( +                    &path, +                    &tiny_skia::Paint { +                        shader: tiny_skia::Shader::SolidColor(into_color( +                            *border_color, +                        )), +                        anti_alias: true, +                        ..tiny_skia::Paint::default() +                    }, +                    &tiny_skia::Stroke { +                        width: *border_width, +                        ..tiny_skia::Stroke::default() +                    }, +                    transform, +                    clip_mask, +                ); +            } +        } +        Primitive::Text { .. } => { +            // TODO +        } +        Primitive::Image { .. } => { +            // TODO +        } +        Primitive::Svg { .. } => { +            // TODO +        } +        Primitive::Group { primitives } => { +            for primitive in primitives { +                draw_primitive( +                    primitive, +                    pixels, +                    clip_mask, +                    scale_factor, +                    translation, +                ); +            } +        } +        Primitive::Translate { +            translation: offset, +            content, +        } => { +            draw_primitive( +                content, +                pixels, +                clip_mask, +                scale_factor, +                translation + *offset, +            ); +        } +        Primitive::Clip { bounds, content } => { +            draw_primitive( +                content, +                pixels, +                Some(&rectangular_clip_mask(pixels, *bounds * scale_factor)), +                scale_factor, +                translation, +            ); +        } +        Primitive::Cached { cache } => { +            draw_primitive(cache, pixels, clip_mask, scale_factor, translation); +        } +        Primitive::SolidMesh { .. } | Primitive::GradientMesh { .. } => {}      }  } @@ -36,6 +157,32 @@ fn into_color(color: Color) -> tiny_skia::Color {          .expect("Convert color from iced to tiny_skia")  } +fn rectangular_clip_mask( +    pixels: &tiny_skia::Pixmap, +    bounds: Rectangle, +) -> tiny_skia::ClipMask { +    let mut clip_mask = tiny_skia::ClipMask::new(); + +    let path = { +        let mut builder = tiny_skia::PathBuilder::new(); +        builder.push_rect(bounds.x, bounds.y, bounds.width, bounds.height); + +        builder.finish().unwrap() +    }; + +    clip_mask +        .set_path( +            pixels.width(), +            pixels.height(), +            &path, +            tiny_skia::FillRule::EvenOdd, +            true, +        ) +        .expect("Set path of clipping area"); + +    clip_mask +} +  impl iced_graphics::Backend for Backend {      fn trim_measurements(&mut self) {          // TODO | 
