fill scribble
This commit is contained in:
parent
7933057062
commit
ccab723298
|
@ -1,11 +1,11 @@
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use tiny_skia::{
|
use tiny_skia::{
|
||||||
BlendMode, Color, LineCap, Paint, PathBuilder, Pixmap, Rect, Shader, Stroke as SStroke,
|
BlendMode, Color, FillRule, LineCap, Paint, Path, PathBuilder, Pixmap, Rect, Shader,
|
||||||
Transform,
|
Stroke as SStroke, Transform,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
value::{Ref, Rgba, Scribble, Shape, Stroke, Value},
|
value::{Fill, Ref, Rgba, Scribble, Shape, Stroke, Value},
|
||||||
vm::{Exception, Vm},
|
vm::{Exception, Vm},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@ impl<'a> Renderer<'a> {
|
||||||
}
|
}
|
||||||
Ref::Scribble(scribble) => match scribble {
|
Ref::Scribble(scribble) => match scribble {
|
||||||
Scribble::Stroke(stroke) => self.render_stroke(vm, value, stroke)?,
|
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))?,
|
_ => return Err(Self::create_exception(vm, value, NOT_A_SCRIBBLE))?,
|
||||||
}
|
}
|
||||||
|
@ -88,19 +89,38 @@ impl<'a> Renderer<'a> {
|
||||||
Ok(())
|
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> {
|
fn render_stroke(&mut self, _vm: &Vm, _value: Value, stroke: &Stroke) -> Result<(), Exception> {
|
||||||
let paint = Paint {
|
let paint = Paint {
|
||||||
shader: Shader::SolidColor(tiny_skia_color(stroke.color)),
|
shader: Shader::SolidColor(tiny_skia_color(stroke.color)),
|
||||||
..default_paint()
|
..default_paint()
|
||||||
};
|
};
|
||||||
let transform = self.transform();
|
let transform = self.transform();
|
||||||
|
let path = Self::shape_to_path(&stroke.shape);
|
||||||
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();
|
|
||||||
|
|
||||||
self.pixmap_mut().stroke_path(
|
self.pixmap_mut().stroke_path(
|
||||||
&path,
|
&path,
|
||||||
|
@ -113,67 +133,20 @@ impl<'a> Renderer<'a> {
|
||||||
transform,
|
transform,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape::Line(start, end) => {
|
fn render_fill(&mut self, _vm: &Vm, _value: Value, fill: &Fill) -> Result<(), Exception> {
|
||||||
let mut pb = PathBuilder::new();
|
let paint = Paint {
|
||||||
pb.move_to(start.x, start.y);
|
shader: Shader::SolidColor(tiny_skia_color(fill.color)),
|
||||||
pb.line_to(end.x, end.y);
|
..default_paint()
|
||||||
let path = pb.finish().unwrap();
|
};
|
||||||
|
let transform = self.transform();
|
||||||
|
let path = Self::shape_to_path(&fill.shape);
|
||||||
|
|
||||||
self.pixmap_mut().stroke_path(
|
self.pixmap_mut()
|
||||||
&path,
|
.fill_path(&path, &paint, FillRule::EvenOdd, transform, None);
|
||||||
&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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,7 @@ pub mod fns {
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
use crate::{
|
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},
|
vm::{Exception, FnArgs, Vm},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -142,6 +142,7 @@ pub mod fns {
|
||||||
0xc2 "rect" => rect,
|
0xc2 "rect" => rect,
|
||||||
0xc3 "circle" => circle,
|
0xc3 "circle" => circle,
|
||||||
0xe0 "stroke" => stroke,
|
0xe0 "stroke" => stroke,
|
||||||
|
0xe1 "fill" => fill,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,4 +510,18 @@ pub mod fns {
|
||||||
Ok(Value::Nil)
|
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,
|
pub shape: Shape,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Fill {
|
||||||
|
pub color: Rgba,
|
||||||
|
pub shape: Shape,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Scribble {
|
pub enum Scribble {
|
||||||
Stroke(Stroke),
|
Stroke(Stroke),
|
||||||
|
Fill(Fill),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue