diffenator3_lib/render/
utils.rs1use image::{GenericImage, GrayImage, ImageBuffer};
2use skrifa::outline::OutlinePen;
3use zeno::{Command, PathBuilder};
4
5pub(crate) fn terrible_bounding_box(pen_buffer: &[Command]) -> (f32, f32, f32, f32) {
12 let mut max_x: f32 = 0.0;
13 let mut min_x: f32 = 0.0;
14 let mut max_y: f32 = 0.0;
15 let mut min_y: f32 = 0.0;
16
17 for command in pen_buffer {
18 match command {
19 Command::MoveTo(to) => {
20 min_x = min_x.min(to.x);
21 max_x = max_x.max(to.x);
22 min_y = min_y.min(to.y);
23 max_y = max_y.max(to.y);
24 }
25 Command::LineTo(to) => {
26 min_x = min_x.min(to.x);
27 max_x = max_x.max(to.x);
28 min_y = min_y.min(to.y);
29 max_y = max_y.max(to.y);
30 }
31 Command::QuadTo(ctrl, to) => {
32 min_x = min_x.min(ctrl.x);
33 max_x = max_x.max(ctrl.x);
34 min_y = min_y.min(ctrl.y);
35 max_y = max_y.max(ctrl.y);
36 min_x = min_x.min(to.x);
37 max_x = max_x.max(to.x);
38 min_y = min_y.min(to.y);
39 max_y = max_y.max(to.y);
40 }
41 Command::CurveTo(ctrl0, ctrl1, to) => {
42 min_x = min_x.min(ctrl0.x);
43 max_x = max_x.max(ctrl0.x);
44 min_y = min_y.min(ctrl0.y);
45 max_y = max_y.max(ctrl0.y);
46 min_x = min_x.min(ctrl1.x);
47 max_x = max_x.max(ctrl1.x);
48 min_y = min_y.min(ctrl1.y);
49 max_y = max_y.max(ctrl1.y);
50 min_x = min_x.min(to.x);
51 max_x = max_x.max(to.x);
52 min_y = min_y.min(to.y);
53 max_y = max_y.max(to.y);
54 }
55 Command::Close => {}
56 };
57 }
58 (min_x, min_y, max_x, max_y)
59}
60
61#[derive(Default)]
62pub struct RecordingPen {
63 pub buffer: Vec<Command>,
64 pub offset_x: f32,
65 pub offset_y: f32,
66}
67
68impl OutlinePen for RecordingPen {
69 fn move_to(&mut self, x: f32, y: f32) {
70 self.buffer.move_to([self.offset_x + x, self.offset_y + y]);
71 }
72
73 fn line_to(&mut self, x: f32, y: f32) {
74 self.buffer.line_to([self.offset_x + x, self.offset_y + y]);
75 }
76
77 fn quad_to(&mut self, cx0: f32, cy0: f32, x: f32, y: f32) {
78 self.buffer.quad_to(
79 [self.offset_x + cx0, self.offset_y + cy0],
80 [self.offset_x + x, self.offset_y + y],
81 );
82 }
83
84 fn curve_to(&mut self, cx0: f32, cy0: f32, cx1: f32, cy1: f32, x: f32, y: f32) {
85 self.buffer.curve_to(
86 [self.offset_x + cx0, self.offset_y + cy0],
87 [self.offset_x + cx1, self.offset_y + cy1],
88 [self.offset_x + x, self.offset_y + y],
89 );
90 }
91
92 fn close(&mut self) {
93 self.buffer.close();
94 }
95}
96
97pub fn make_same_size(image_a: GrayImage, image_b: GrayImage) -> (GrayImage, GrayImage) {
101 let max_width = image_a.width().max(image_b.width());
102 let max_height = image_a.height().max(image_b.height());
103 let mut a = ImageBuffer::new(max_width, max_height);
104 let mut b = ImageBuffer::new(max_width, max_height);
105 a.copy_from(&image_a, 0, 0).unwrap();
106 b.copy_from(&image_b, 0, 0).unwrap();
107 (a, b)
108}
109
110pub fn count_differences(img_a: GrayImage, img_b: GrayImage, fuzz: u8) -> usize {
112 let (img_a, img_b) = make_same_size(img_a, img_b);
113 let img_a_vec = img_a.to_vec();
114 img_a_vec
115 .iter()
116 .zip(img_b.to_vec())
117 .filter(|(&cha, chb)| cha.abs_diff(*chb) > fuzz)
118 .count()
119}