standard_plugin/draw/
mod.rs1#![doc = include_str!("../../examples/shapes_stage.rs")]
12mod cells;
15pub mod font;
16mod pixels;
17
18pub use font::{GLYPH_ADVANCE, GLYPH_HEIGHT, GLYPH_WIDTH};
19pub use pixels::Image;
20
21#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
23pub struct Area {
24 pub x: i32,
25 pub y: i32,
26 pub w: u32,
27 pub h: u32,
28}
29
30impl Area {
31 pub const fn new(x: i32, y: i32, w: u32, h: u32) -> Self {
32 Self { x, y, w, h }
33 }
34
35 pub(crate) fn left(&self) -> i64 {
36 i64::from(self.x)
37 }
38
39 pub(crate) fn top(&self) -> i64 {
40 i64::from(self.y)
41 }
42
43 pub(crate) fn right(&self) -> i64 {
44 i64::from(self.x) + i64::from(self.w)
45 }
46
47 pub(crate) fn bottom(&self) -> i64 {
48 i64::from(self.y) + i64::from(self.h)
49 }
50}
51
52impl From<crate::Rect> for Area {
53 fn from(rect: crate::Rect) -> Self {
54 Self {
55 x: rect.x.min(i32::MAX as u32) as i32,
56 y: rect.y.min(i32::MAX as u32) as i32,
57 w: rect.w,
58 h: rect.h,
59 }
60 }
61}
62
63pub trait Shapes {
66 type Ink: Copy;
67
68 fn stroke_rect(&mut self, area: Area, ink: Self::Ink);
70
71 fn fill_rect(&mut self, area: Area, ink: Self::Ink);
73
74 fn line(&mut self, from: (i32, i32), to: (i32, i32), ink: Self::Ink);
76
77 fn bar(&mut self, area: Area, fraction: f32, fill: Self::Ink, track: Self::Ink);
81
82 fn rounded_rect(&mut self, area: Area, radius: u32, ink: Self::Ink);
85
86 fn fill_rounded_rect(&mut self, area: Area, radius: u32, ink: Self::Ink);
88
89 fn circle(&mut self, centre: (f32, f32), radius: f32, ink: Self::Ink);
96
97 fn fill_circle(&mut self, centre: (f32, f32), radius: f32, ink: Self::Ink);
99
100 fn label(&mut self, x: i32, y: i32, text: &str, ink: Self::Ink) -> u32;
104}
105
106pub(crate) fn unit(fraction: f32) -> f32 {
108 if fraction.is_nan() {
109 0.0
110 } else {
111 fraction.clamp(0.0, 1.0)
112 }
113}
114
115pub(crate) fn clip_segment(
119 from: (i64, i64),
120 to: (i64, i64),
121 width: u32,
122 height: u32,
123) -> Option<((i64, i64), (i64, i64))> {
124 let (x0, y0) = (from.0 as f64, from.1 as f64);
125 let (dx, dy) = ((to.0 - from.0) as f64, (to.1 - from.1) as f64);
126 let (min_x, max_x) = (-1.0, f64::from(width));
127 let (min_y, max_y) = (-1.0, f64::from(height));
128 let (mut enter, mut leave) = (0.0f64, 1.0f64);
129 for (p, q) in [
130 (-dx, x0 - min_x),
131 (dx, max_x - x0),
132 (-dy, y0 - min_y),
133 (dy, max_y - y0),
134 ] {
135 if p == 0.0 {
136 if q < 0.0 {
137 return None;
138 }
139 continue;
140 }
141 let t = q / p;
142 if p < 0.0 {
143 enter = enter.max(t);
144 } else {
145 leave = leave.min(t);
146 }
147 if enter > leave {
148 return None;
149 }
150 }
151 let point = |t: f64| {
152 (
153 libm::round(x0 + t * dx) as i64,
154 libm::round(y0 + t * dy) as i64,
155 )
156 };
157 Some((point(enter), point(leave)))
158}