1use super::scene::{Path, PathVertex};
2use crate::{color::Color, json::ToJson};
3use derive_more::Neg;
4pub use pathfinder_geometry::*;
5use rect::RectF;
6use refineable::Refineable;
7use serde::{Deserialize, Deserializer};
8use serde_json::json;
9use std::fmt::Debug;
10use vector::{vec2f, Vector2F};
11
12pub struct PathBuilder {
13 vertices: Vec<PathVertex>,
14 start: Vector2F,
15 current: Vector2F,
16 contour_count: usize,
17 bounds: RectF,
18}
19
20enum PathVertexKind {
21 Solid,
22 Quadratic,
23}
24
25impl Default for PathBuilder {
26 fn default() -> Self {
27 PathBuilder::new()
28 }
29}
30
31impl PathBuilder {
32 pub fn new() -> Self {
33 Self {
34 vertices: Vec::new(),
35 start: vec2f(0., 0.),
36 current: vec2f(0., 0.),
37 contour_count: 0,
38 bounds: RectF::default(),
39 }
40 }
41
42 pub fn reset(&mut self, point: Vector2F) {
43 self.vertices.clear();
44 self.start = point;
45 self.current = point;
46 self.contour_count = 0;
47 }
48
49 pub fn line_to(&mut self, point: Vector2F) {
50 self.contour_count += 1;
51 if self.contour_count > 1 {
52 self.push_triangle(self.start, self.current, point, PathVertexKind::Solid);
53 }
54
55 self.current = point;
56 }
57
58 pub fn curve_to(&mut self, point: Vector2F, ctrl: Vector2F) {
59 self.contour_count += 1;
60 if self.contour_count > 1 {
61 self.push_triangle(self.start, self.current, point, PathVertexKind::Solid);
62 }
63
64 self.push_triangle(self.current, ctrl, point, PathVertexKind::Quadratic);
65 self.current = point;
66 }
67
68 pub fn build(mut self, color: Color, clip_bounds: Option<RectF>) -> Path {
69 if let Some(clip_bounds) = clip_bounds {
70 self.bounds = self.bounds.intersection(clip_bounds).unwrap_or_default();
71 }
72 Path {
73 bounds: self.bounds,
74 color,
75 vertices: self.vertices,
76 }
77 }
78
79 fn push_triangle(&mut self, a: Vector2F, b: Vector2F, c: Vector2F, kind: PathVertexKind) {
80 if self.vertices.is_empty() {
81 self.bounds = RectF::new(a, Vector2F::zero());
82 }
83 self.bounds = self.bounds.union_point(a).union_point(b).union_point(c);
84
85 match kind {
86 PathVertexKind::Solid => {
87 self.vertices.push(PathVertex {
88 xy_position: a,
89 st_position: vec2f(0., 1.),
90 });
91 self.vertices.push(PathVertex {
92 xy_position: b,
93 st_position: vec2f(0., 1.),
94 });
95 self.vertices.push(PathVertex {
96 xy_position: c,
97 st_position: vec2f(0., 1.),
98 });
99 }
100 PathVertexKind::Quadratic => {
101 self.vertices.push(PathVertex {
102 xy_position: a,
103 st_position: vec2f(0., 0.),
104 });
105 self.vertices.push(PathVertex {
106 xy_position: b,
107 st_position: vec2f(0.5, 0.),
108 });
109 self.vertices.push(PathVertex {
110 xy_position: c,
111 st_position: vec2f(1., 1.),
112 });
113 }
114 }
115 }
116}
117
118pub fn deserialize_vec2f<'de, D>(deserializer: D) -> Result<Vector2F, D::Error>
119where
120 D: Deserializer<'de>,
121{
122 let [x, y]: [f32; 2] = Deserialize::deserialize(deserializer)?;
123 Ok(vec2f(x, y))
124}
125
126impl ToJson for Vector2F {
127 fn to_json(&self) -> serde_json::Value {
128 json!([self.x(), self.y()])
129 }
130}
131
132impl ToJson for RectF {
133 fn to_json(&self) -> serde_json::Value {
134 json!({"origin": self.origin().to_json(), "size": self.size().to_json()})
135 }
136}
137
138#[derive(Refineable, Debug)]
139#[refineable(Debug)]
140pub struct Point<T: Clone + Default + Debug> {
141 pub x: T,
142 pub y: T,
143}
144
145impl<T: Clone + Default + Debug> Clone for Point<T> {
146 fn clone(&self) -> Self {
147 Self {
148 x: self.x.clone(),
149 y: self.y.clone(),
150 }
151 }
152}
153
154impl<T: Clone + Default + Debug> Into<taffy::geometry::Point<T>> for Point<T> {
155 fn into(self) -> taffy::geometry::Point<T> {
156 taffy::geometry::Point {
157 x: self.x,
158 y: self.y,
159 }
160 }
161}
162
163#[derive(Refineable, Clone, Debug)]
164#[refineable(Debug)]
165pub struct Size<T: Clone + Default + Debug> {
166 pub width: T,
167 pub height: T,
168}
169
170impl<S, T: Clone + Default + Debug> From<taffy::geometry::Size<S>> for Size<T>
171where
172 S: Into<T>,
173{
174 fn from(value: taffy::geometry::Size<S>) -> Self {
175 Self {
176 width: value.width.into(),
177 height: value.height.into(),
178 }
179 }
180}
181
182impl<S, T: Clone + Default + Debug> Into<taffy::geometry::Size<S>> for Size<T>
183where
184 T: Into<S>,
185{
186 fn into(self) -> taffy::geometry::Size<S> {
187 taffy::geometry::Size {
188 width: self.width.into(),
189 height: self.height.into(),
190 }
191 }
192}
193
194impl Size<DefiniteLength> {
195 pub fn zero() -> Self {
196 Self {
197 width: pixels(0.).into(),
198 height: pixels(0.).into(),
199 }
200 }
201
202 pub fn to_taffy(&self, rem_size: f32) -> taffy::geometry::Size<taffy::style::LengthPercentage> {
203 taffy::geometry::Size {
204 width: self.width.to_taffy(rem_size),
205 height: self.height.to_taffy(rem_size),
206 }
207 }
208}
209
210impl Size<Length> {
211 pub fn auto() -> Self {
212 Self {
213 width: Length::Auto,
214 height: Length::Auto,
215 }
216 }
217
218 pub fn to_taffy<T: From<taffy::prelude::LengthPercentageAuto>>(
219 &self,
220 rem_size: f32,
221 ) -> taffy::geometry::Size<T> {
222 taffy::geometry::Size {
223 width: self.width.to_taffy(rem_size).into(),
224 height: self.height.to_taffy(rem_size).into(),
225 }
226 }
227}
228
229#[derive(Clone, Default, Refineable, Debug)]
230#[refineable(Debug)]
231pub struct Edges<T: Clone + Default + Debug> {
232 pub top: T,
233 pub right: T,
234 pub bottom: T,
235 pub left: T,
236}
237
238impl<T: Clone + Default + Debug> Edges<T> {
239 pub fn uniform(value: T) -> Self {
240 Self {
241 top: value.clone(),
242 right: value.clone(),
243 bottom: value.clone(),
244 left: value.clone(),
245 }
246 }
247}
248
249impl Edges<Length> {
250 pub fn auto() -> Self {
251 Self {
252 top: Length::Auto,
253 right: Length::Auto,
254 bottom: Length::Auto,
255 left: Length::Auto,
256 }
257 }
258
259 pub fn zero() -> Self {
260 Self {
261 top: pixels(0.).into(),
262 right: pixels(0.).into(),
263 bottom: pixels(0.).into(),
264 left: pixels(0.).into(),
265 }
266 }
267
268 pub fn to_taffy(
269 &self,
270 rem_size: f32,
271 ) -> taffy::geometry::Rect<taffy::style::LengthPercentageAuto> {
272 taffy::geometry::Rect {
273 top: self.top.to_taffy(rem_size),
274 right: self.right.to_taffy(rem_size),
275 bottom: self.bottom.to_taffy(rem_size),
276 left: self.left.to_taffy(rem_size),
277 }
278 }
279}
280
281impl Edges<DefiniteLength> {
282 pub fn zero() -> Self {
283 Self {
284 top: pixels(0.).into(),
285 right: pixels(0.).into(),
286 bottom: pixels(0.).into(),
287 left: pixels(0.).into(),
288 }
289 }
290
291 pub fn to_taffy(&self, rem_size: f32) -> taffy::geometry::Rect<taffy::style::LengthPercentage> {
292 taffy::geometry::Rect {
293 top: self.top.to_taffy(rem_size),
294 right: self.right.to_taffy(rem_size),
295 bottom: self.bottom.to_taffy(rem_size),
296 left: self.left.to_taffy(rem_size),
297 }
298 }
299}
300
301impl Edges<AbsoluteLength> {
302 pub fn zero() -> Self {
303 Self {
304 top: pixels(0.),
305 right: pixels(0.),
306 bottom: pixels(0.),
307 left: pixels(0.),
308 }
309 }
310
311 pub fn to_taffy(&self, rem_size: f32) -> taffy::geometry::Rect<taffy::style::LengthPercentage> {
312 taffy::geometry::Rect {
313 top: self.top.to_taffy(rem_size),
314 right: self.right.to_taffy(rem_size),
315 bottom: self.bottom.to_taffy(rem_size),
316 left: self.left.to_taffy(rem_size),
317 }
318 }
319
320 pub fn to_pixels(&self, rem_size: f32) -> Edges<f32> {
321 Edges {
322 top: self.top.to_pixels(rem_size),
323 right: self.right.to_pixels(rem_size),
324 bottom: self.bottom.to_pixels(rem_size),
325 left: self.left.to_pixels(rem_size),
326 }
327 }
328}
329
330impl Edges<f32> {
331 pub fn is_empty(&self) -> bool {
332 self.top == 0.0 && self.right == 0.0 && self.bottom == 0.0 && self.left == 0.0
333 }
334}
335
336#[derive(Clone, Copy, Neg)]
337pub enum AbsoluteLength {
338 Pixels(f32),
339 Rems(f32),
340}
341
342impl std::fmt::Debug for AbsoluteLength {
343 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
344 match self {
345 AbsoluteLength::Pixels(pixels) => write!(f, "{}px", pixels),
346 AbsoluteLength::Rems(rems) => write!(f, "{}rems", rems),
347 }
348 }
349}
350
351impl AbsoluteLength {
352 pub fn to_pixels(&self, rem_size: f32) -> f32 {
353 match self {
354 AbsoluteLength::Pixels(pixels) => *pixels,
355 AbsoluteLength::Rems(rems) => rems * rem_size,
356 }
357 }
358
359 pub fn to_taffy(&self, rem_size: f32) -> taffy::style::LengthPercentage {
360 match self {
361 AbsoluteLength::Pixels(pixels) => taffy::style::LengthPercentage::Length(*pixels),
362 AbsoluteLength::Rems(rems) => taffy::style::LengthPercentage::Length(rems * rem_size),
363 }
364 }
365}
366
367impl Default for AbsoluteLength {
368 fn default() -> Self {
369 Self::Pixels(0.0)
370 }
371}
372
373/// A non-auto length that can be defined in pixels, rems, or percent of parent.
374#[derive(Clone, Copy, Neg)]
375pub enum DefiniteLength {
376 Absolute(AbsoluteLength),
377 Relative(f32), // 0. to 1.
378}
379
380impl DefiniteLength {
381 fn to_taffy(&self, rem_size: f32) -> taffy::style::LengthPercentage {
382 match self {
383 DefiniteLength::Absolute(length) => match length {
384 AbsoluteLength::Pixels(pixels) => taffy::style::LengthPercentage::Length(*pixels),
385 AbsoluteLength::Rems(rems) => {
386 taffy::style::LengthPercentage::Length(rems * rem_size)
387 }
388 },
389 DefiniteLength::Relative(fraction) => {
390 taffy::style::LengthPercentage::Percent(*fraction)
391 }
392 }
393 }
394}
395
396impl std::fmt::Debug for DefiniteLength {
397 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
398 match self {
399 DefiniteLength::Absolute(length) => std::fmt::Debug::fmt(length, f),
400 DefiniteLength::Relative(fract) => write!(f, "{}%", (fract * 100.0) as i32),
401 }
402 }
403}
404
405impl From<AbsoluteLength> for DefiniteLength {
406 fn from(length: AbsoluteLength) -> Self {
407 Self::Absolute(length)
408 }
409}
410
411impl Default for DefiniteLength {
412 fn default() -> Self {
413 Self::Absolute(AbsoluteLength::default())
414 }
415}
416
417/// A length that can be defined in pixels, rems, percent of parent, or auto.
418#[derive(Clone, Copy, Neg)]
419pub enum Length {
420 Definite(DefiniteLength),
421 Auto,
422}
423
424impl std::fmt::Debug for Length {
425 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
426 match self {
427 Length::Definite(definite_length) => write!(f, "{:?}", definite_length),
428 Length::Auto => write!(f, "auto"),
429 }
430 }
431}
432
433pub fn relative(fraction: f32) -> DefiniteLength {
434 DefiniteLength::Relative(fraction)
435}
436
437pub fn rems(rems: f32) -> AbsoluteLength {
438 AbsoluteLength::Rems(rems)
439}
440
441pub fn pixels(pixels: f32) -> AbsoluteLength {
442 AbsoluteLength::Pixels(pixels)
443}
444
445pub fn auto() -> Length {
446 Length::Auto
447}
448
449impl Length {
450 pub fn to_taffy(&self, rem_size: f32) -> taffy::prelude::LengthPercentageAuto {
451 match self {
452 Length::Definite(length) => length.to_taffy(rem_size).into(),
453 Length::Auto => taffy::prelude::LengthPercentageAuto::Auto,
454 }
455 }
456}
457
458impl From<DefiniteLength> for Length {
459 fn from(length: DefiniteLength) -> Self {
460 Self::Definite(length)
461 }
462}
463
464impl From<AbsoluteLength> for Length {
465 fn from(length: AbsoluteLength) -> Self {
466 Self::Definite(length.into())
467 }
468}
469
470impl Default for Length {
471 fn default() -> Self {
472 Self::Definite(DefiniteLength::default())
473 }
474}
475
476impl From<()> for Length {
477 fn from(_: ()) -> Self {
478 Self::Definite(DefiniteLength::default())
479 }
480}