1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
use tiny_skia::{BlendMode, Color, FillRule, Paint, Path, Pixmap, PixmapPaint, Stroke, Transform};
use crate::definitions::StrokeAlign;
pub fn apply_aligned_stroke(
pixmap: &mut Pixmap,
path: &Path,
stroke_width: f64,
stroke_align: StrokeAlign,
stroke_color: Color,
) {
if stroke_width <= 0.0 {
return;
}
match stroke_align {
StrokeAlign::Inside => {
let Some(mut stroke_pixmap) = Pixmap::new(pixmap.width(), pixmap.height()) else {
return;
};
stroke_path(&mut stroke_pixmap, path, stroke_width * 2.0, stroke_color);
erase_outside(&mut stroke_pixmap, path, BlendMode::DestinationIn);
composite(pixmap, &stroke_pixmap);
}
StrokeAlign::Outside => {
let Some(mut stroke_pixmap) = Pixmap::new(pixmap.width(), pixmap.height()) else {
return;
};
stroke_path(&mut stroke_pixmap, path, stroke_width * 2.0, stroke_color);
erase_outside(&mut stroke_pixmap, path, BlendMode::DestinationOut);
composite(pixmap, &stroke_pixmap);
}
StrokeAlign::Center => {
stroke_path(pixmap, path, stroke_width, stroke_color);
}
}
}
fn stroke_path(pixmap: &mut Pixmap, path: &Path, width: f64, color: Color) {
let paint = Paint {
shader: tiny_skia::Shader::SolidColor(color),
anti_alias: true,
..Paint::default()
};
let stroke = Stroke {
width: width as f32,
..Stroke::default()
};
pixmap.stroke_path(path, &paint, &stroke, Transform::default(), None);
}
fn erase_outside(pixmap: &mut Pixmap, path: &Path, blend_mode: BlendMode) {
let paint = Paint {
shader: tiny_skia::Shader::SolidColor(Color::BLACK),
anti_alias: true,
blend_mode,
..Paint::default()
};
pixmap.fill_path(path, &paint, FillRule::Winding, Transform::default(), None);
}
fn composite(target: &mut Pixmap, source: &Pixmap) {
target.draw_pixmap(
0,
0,
source.as_ref(),
&PixmapPaint::default(),
Transform::default(),
None,
);
}
|