fill scribble
This commit is contained in:
parent
7933057062
commit
ccab723298
|
@ -1,11 +1,11 @@
|
|||
use alloc::vec::Vec;
|
||||
use tiny_skia::{
|
||||
BlendMode, Color, LineCap, Paint, PathBuilder, Pixmap, Rect, Shader, Stroke as SStroke,
|
||||
Transform,
|
||||
BlendMode, Color, FillRule, LineCap, Paint, Path, PathBuilder, Pixmap, Rect, Shader,
|
||||
Stroke as SStroke, Transform,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
value::{Ref, Rgba, Scribble, Shape, Stroke, Value},
|
||||
value::{Fill, Ref, Rgba, Scribble, Shape, Stroke, Value},
|
||||
vm::{Exception, Vm},
|
||||
};
|
||||
|
||||
|
@ -81,6 +81,7 @@ impl<'a> Renderer<'a> {
|
|||
}
|
||||
Ref::Scribble(scribble) => match scribble {
|
||||
Scribble::Stroke(stroke) => self.render_stroke(vm, value, stroke)?,
|
||||
Scribble::Fill(fill) => self.render_fill(vm, value, fill)?,
|
||||
},
|
||||
_ => return Err(Self::create_exception(vm, value, NOT_A_SCRIBBLE))?,
|
||||
}
|
||||
|
@ -88,19 +89,38 @@ impl<'a> Renderer<'a> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn shape_to_path(shape: &Shape) -> Path {
|
||||
let mut pb = PathBuilder::new();
|
||||
match shape {
|
||||
Shape::Point(vec) => {
|
||||
pb.move_to(vec.x, vec.y);
|
||||
pb.line_to(vec.x, vec.y);
|
||||
}
|
||||
Shape::Line(start, end) => {
|
||||
pb.move_to(start.x, start.y);
|
||||
pb.line_to(end.x, end.y);
|
||||
}
|
||||
Shape::Rect(position, size) => {
|
||||
if let Some(rect) =
|
||||
tiny_skia::Rect::from_xywh(position.x, position.y, size.x, size.y)
|
||||
{
|
||||
pb.push_rect(rect);
|
||||
}
|
||||
}
|
||||
Shape::Circle(position, radius) => {
|
||||
pb.push_circle(position.x, position.y, *radius);
|
||||
}
|
||||
}
|
||||
pb.finish().unwrap()
|
||||
}
|
||||
|
||||
fn render_stroke(&mut self, _vm: &Vm, _value: Value, stroke: &Stroke) -> Result<(), Exception> {
|
||||
let paint = Paint {
|
||||
shader: Shader::SolidColor(tiny_skia_color(stroke.color)),
|
||||
..default_paint()
|
||||
};
|
||||
let transform = self.transform();
|
||||
|
||||
match stroke.shape {
|
||||
Shape::Point(vec) => {
|
||||
let mut pb = PathBuilder::new();
|
||||
pb.move_to(vec.x, vec.y);
|
||||
pb.line_to(vec.x, vec.y);
|
||||
let path = pb.finish().unwrap();
|
||||
let path = Self::shape_to_path(&stroke.shape);
|
||||
|
||||
self.pixmap_mut().stroke_path(
|
||||
&path,
|
||||
|
@ -113,67 +133,20 @@ impl<'a> Renderer<'a> {
|
|||
transform,
|
||||
None,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Shape::Line(start, end) => {
|
||||
let mut pb = PathBuilder::new();
|
||||
pb.move_to(start.x, start.y);
|
||||
pb.line_to(end.x, end.y);
|
||||
let path = pb.finish().unwrap();
|
||||
fn render_fill(&mut self, _vm: &Vm, _value: Value, fill: &Fill) -> Result<(), Exception> {
|
||||
let paint = Paint {
|
||||
shader: Shader::SolidColor(tiny_skia_color(fill.color)),
|
||||
..default_paint()
|
||||
};
|
||||
let transform = self.transform();
|
||||
let path = Self::shape_to_path(&fill.shape);
|
||||
|
||||
self.pixmap_mut().stroke_path(
|
||||
&path,
|
||||
&paint,
|
||||
&SStroke {
|
||||
width: stroke.thickness,
|
||||
line_cap: LineCap::Square,
|
||||
..Default::default()
|
||||
},
|
||||
transform,
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
Shape::Rect(position, size) => {
|
||||
let mut pb = PathBuilder::new();
|
||||
if let Some(rect) =
|
||||
tiny_skia::Rect::from_xywh(position.x, position.y, size.x, size.y)
|
||||
{
|
||||
pb.push_rect(rect);
|
||||
}
|
||||
let path = pb.finish().unwrap();
|
||||
|
||||
self.pixmap_mut().stroke_path(
|
||||
&path,
|
||||
&paint,
|
||||
&SStroke {
|
||||
width: stroke.thickness,
|
||||
line_cap: LineCap::Square,
|
||||
..Default::default()
|
||||
},
|
||||
transform,
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
Shape::Circle(position, radius) => {
|
||||
let mut pb = PathBuilder::new();
|
||||
pb.push_circle(position.x, position.y, radius);
|
||||
let path = pb.finish().unwrap();
|
||||
|
||||
self.pixmap_mut().stroke_path(
|
||||
&path,
|
||||
&paint,
|
||||
&SStroke {
|
||||
width: stroke.thickness,
|
||||
line_cap: LineCap::Square,
|
||||
..Default::default()
|
||||
},
|
||||
transform,
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
self.pixmap_mut()
|
||||
.fill_path(&path, &paint, FillRule::EvenOdd, transform, None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ pub mod fns {
|
|||
use alloc::vec::Vec;
|
||||
|
||||
use crate::{
|
||||
value::{List, Ref, Rgba, Scribble, Shape, Stroke, Value, Vec2, Vec4},
|
||||
value::{Fill, List, Ref, Rgba, Scribble, Shape, Stroke, Value, Vec2, Vec4},
|
||||
vm::{Exception, FnArgs, Vm},
|
||||
};
|
||||
|
||||
|
@ -142,6 +142,7 @@ pub mod fns {
|
|||
0xc2 "rect" => rect,
|
||||
0xc3 "circle" => circle,
|
||||
0xe0 "stroke" => stroke,
|
||||
0xe1 "fill" => fill,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -509,4 +510,18 @@ pub mod fns {
|
|||
Ok(Value::Nil)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fill(vm: &mut Vm, args: FnArgs) -> Result<Value, Exception> {
|
||||
if args.num() != 2 {
|
||||
return Err(vm.create_exception("(fill) expects 2 arguments (fill color shape)"));
|
||||
}
|
||||
|
||||
let color = args.get_rgba(vm, 0, "1st argument to (fill) must be a color (rgba)")?;
|
||||
if let Some(shape) = to_shape(args.get(vm, 1), vm) {
|
||||
let id = vm.create_ref(Ref::Scribble(Scribble::Fill(Fill { color, shape })))?;
|
||||
Ok(Value::Ref(id))
|
||||
} else {
|
||||
Ok(Value::Nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -179,7 +179,14 @@ pub struct Stroke {
|
|||
pub shape: Shape,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Fill {
|
||||
pub color: Rgba,
|
||||
pub shape: Shape,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Scribble {
|
||||
Stroke(Stroke),
|
||||
Fill(Fill),
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue