🎉 Render path fills

This commit is contained in:
Belén Albeza 2024-12-09 15:26:51 +01:00
parent 0bfcc1f854
commit 99bb3ee962
6 changed files with 118 additions and 90 deletions

View file

@ -7,7 +7,6 @@ mod state;
mod utils;
mod view;
use shapes::RawPathData;
use skia_safe as skia;
use crate::state::State;
@ -107,7 +106,7 @@ pub extern "C" fn use_shape(a: u32, b: u32, c: u32, d: u32) {
pub extern "C" fn set_shape_selrect(left: f32, top: f32, right: f32, bottom: f32) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
shape.selrect.set_ltrb(left, top, right, bottom);
shape.set_selrect(left, top, right, bottom);
}
}

View file

@ -6,7 +6,7 @@ use uuid::Uuid;
use crate::debug;
use crate::math::Rect;
use crate::shapes::{draw_image_in_container, Fill, Image, Shape};
use crate::shapes::{draw_image_in_container, Fill, Image, Kind, Shape};
use crate::view::Viewbox;
struct GpuState {
@ -224,7 +224,7 @@ impl RenderState {
self.drawing_surface.canvas().concat(&matrix);
for fill in shape.fills().rev() {
self.render_fill(fill, shape.selrect);
self.render_fill(fill, shape.selrect, &shape.kind);
}
let mut paint = skia::Paint::default();
@ -281,22 +281,30 @@ impl RenderState {
self.flush();
}
fn render_fill(&mut self, fill: &Fill, selrect: Rect) {
if let Fill::Image(image_fill) = fill {
let image = self.images.get(&image_fill.id());
if let Some(image) = image {
draw_image_in_container(
&self.drawing_surface.canvas(),
&image,
image_fill.size(),
selrect,
&fill.to_paint(&selrect),
);
fn render_fill(&mut self, fill: &Fill, selrect: Rect, kind: &Kind) {
match (fill, kind) {
(Fill::Image(image_fill), kind) => {
let image = self.images.get(&image_fill.id());
if let Some(image) = image {
draw_image_in_container(
&self.drawing_surface.canvas(),
&image,
image_fill.size(),
kind,
&fill.to_paint(&selrect),
);
}
}
(_, Kind::Rect(rect)) => {
self.drawing_surface
.canvas()
.draw_rect(rect, &fill.to_paint(&selrect));
}
(_, Kind::Path(path)) => {
self.drawing_surface
.canvas()
.draw_path(&path.to_skia_path(), &fill.to_paint(&selrect));
}
} else {
self.drawing_surface
.canvas()
.draw_rect(selrect, &fill.to_paint(&selrect));
}
}

View file

@ -13,7 +13,7 @@ pub use paths::*;
#[derive(Debug, Clone, PartialEq)]
pub enum Kind {
Rect,
Rect(math::Rect),
Path(Path),
}
@ -62,7 +62,7 @@ impl Shape {
Self {
id,
children: Vec::<Uuid>::new(),
kind: Kind::Rect,
kind: Kind::Rect(math::Rect::new_empty()),
selrect: math::Rect::new_empty(),
transform: Matrix::identity(),
rotation: 0.,
@ -73,6 +73,13 @@ impl Shape {
}
}
pub fn set_selrect(&mut self, left: f32, top: f32, right: f32, bottom: f32) {
self.selrect.set_ltrb(left, top, right, bottom);
if let Kind::Rect(_) = self.kind {
self.kind = Kind::Rect(self.selrect.to_owned());
}
}
pub fn translation(&self) -> (f32, f32) {
(self.transform.e, self.transform.f)
}

View file

@ -3,17 +3,24 @@ use skia_safe as skia;
pub type Image = skia::Image;
use crate::shapes::Kind;
pub fn draw_image_in_container(
canvas: &skia::Canvas,
image: &Image,
size: (i32, i32),
container: skia::Rect,
kind: &Kind,
paint: &skia::Paint,
) {
let width = size.0 as f32;
let height = size.1 as f32;
let image_aspect_ratio = width / height;
let container = match kind {
Kind::Rect(r) => r.to_owned(),
Kind::Path(p) => p.to_skia_path().bounds().to_owned(),
};
// Container size
let container_width = container.width();
let container_height = container.height();
@ -42,7 +49,14 @@ pub fn draw_image_in_container(
canvas.save();
// Set the clipping rectangle to the container bounds
canvas.clip_rect(container, skia::ClipOp::Intersect, true);
match kind {
Kind::Rect(_) => {
canvas.clip_rect(container, skia::ClipOp::Intersect, true);
}
Kind::Path(p) => {
canvas.clip_path(&p.to_skia_path(), skia::ClipOp::Intersect, true);
}
}
// Draw the image with the calculated destination rectangle
canvas.draw_image_rect(image, None, dest_rect, &paint);