1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE.skia file.
6  */
7 use crate::Point;
8 
intrect<T: Copy>(x1: T, y1: T, x2: T, y2: T) -> euclid::default::Box2D<T>9 pub fn intrect<T: Copy>(x1: T, y1: T, x2: T, y2: T) -> euclid::default::Box2D<T> {
10     euclid::default::Box2D::new(euclid::point2(x1, y1), euclid::point2(x2, y2))
11 }
12 
abs(a: f32) -> f3213 pub fn abs(a: f32) -> f32 {
14     if a < 0. {
15         return -a;
16     }
17     return a;
18 }
19 
20 // we can do this
valid_unit_divide(mut numer: f32, mut denom: f32, ratio: &mut f32) -> bool21 pub fn valid_unit_divide(mut numer: f32, mut denom: f32, ratio: &mut f32) -> bool {
22     if numer < 0. {
23         numer = -numer;
24         denom = -denom;
25     }
26 
27     if denom == 0. || numer == 0. || numer >= denom {
28         return false;
29     }
30 
31     let r = numer / denom;
32     if r.is_nan() {
33         return false;
34     }
35     debug_assert!(r >= 0. && r < 1.);
36     if r == 0. {
37         // catch underflow if numer <<<< denom
38         return false;
39     }
40     *ratio = r;
41     return true;
42 }
43 
is_not_monotonic(a: f32, b: f32, c: f32) -> bool44 pub fn is_not_monotonic(a: f32, b: f32, c: f32) -> bool {
45     let ab = a - b;
46     let mut bc = b - c;
47     if ab < 0. {
48         bc = -bc;
49     }
50     return ab == 0. || bc < 0.;
51 }
52 
interp(a: f32, b: f32, t: f32) -> f3253 fn interp(a: f32, b: f32, t: f32) -> f32 {
54     debug_assert!(t >= 0. && t <= 1.);
55     return a + (b - a) * t;
56 }
57 
58 // Skia does a weird thing where it treats arrays of points as castable to array of floats.
59 // For now we just duplicate quad_x and quad_y
interp_quad_x_coords(src: &[Point; 3], dst: &mut [Point; 5], t: f32)60 fn interp_quad_x_coords(src: &[Point; 3], dst: &mut [Point; 5], t: f32) {
61     let ab = interp(src[0].x, src[1].x, t);
62     let bc = interp(src[1].x, src[2].x, t);
63 
64     dst[0].x = src[0].x;
65     dst[1].x = ab;
66     dst[2].x = interp(ab, bc, t);
67     dst[3].x = bc;
68     dst[4].x = src[2].x;
69 }
70 
interp_quad_y_coords(src: &[Point; 3], dst: &mut [Point; 5], t: f32)71 fn interp_quad_y_coords(src: &[Point; 3], dst: &mut [Point; 5], t: f32) {
72     let ab = interp(src[0].y, src[1].y, t);
73     let bc = interp(src[1].y, src[2].y, t);
74 
75     dst[0].y = src[0].y;
76     dst[1].y = ab;
77     dst[2].y = interp(ab, bc, t);
78     dst[3].y = bc;
79     dst[4].y = src[2].y;
80 }
81 
chop_quad_at(src: &[Point; 3], dst: &mut [Point; 5], t: f32)82 pub fn chop_quad_at(src: &[Point; 3], dst: &mut [Point; 5], t: f32) {
83     debug_assert!(t > 0. && t < 1.);
84 
85     interp_quad_x_coords(src, dst, t);
86     interp_quad_y_coords(src, dst, t);
87 }
88 
89 // ensures that the y values are contiguous
90 // dst[1].fY = dst[3].fY = dst[2].fY
91 // I'm not sure why we need this
flatten_double_quad_extrema(dst: &mut [Point; 5])92 pub fn flatten_double_quad_extrema(dst: &mut [Point; 5]) {
93     dst[1].y = dst[2].y;
94     dst[3].y = dst[2].y;
95 }
96