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 file.
6  */
7 
8 #ifndef SkPointPriv_DEFINED
9 #define SkPointPriv_DEFINED
10 
11 #include "SkPoint.h"
12 
13 class SkPointPriv {
14 public:
15     enum Side {
16         kLeft_Side  = -1,
17         kOn_Side    =  0,
18         kRight_Side =  1,
19     };
20 
AreFinite(const SkPoint array[],int count)21     static bool AreFinite(const SkPoint array[], int count) {
22         return SkScalarsAreFinite(&array[0].fX, count << 1);
23     }
24 
AsScalars(const SkPoint & pt)25     static const SkScalar* AsScalars(const SkPoint& pt) { return &pt.fX; }
26 
CanNormalize(SkScalar dx,SkScalar dy)27     static bool CanNormalize(SkScalar dx, SkScalar dy) {
28         // Simple enough (and performance critical sometimes) so we inline it.
29         return (dx*dx + dy*dy) > (SK_ScalarNearlyZero * SK_ScalarNearlyZero);
30     }
31 
32     static SkScalar DistanceToLineBetweenSqd(const SkPoint& pt, const SkPoint& a,
33                                              const SkPoint& b, Side* side = nullptr);
34 
35     static SkScalar DistanceToLineBetween(const SkPoint& pt, const SkPoint& a,
36                                           const SkPoint& b, Side* side = nullptr) {
37         return SkScalarSqrt(DistanceToLineBetweenSqd(pt, a, b, side));
38     }
39 
40     static SkScalar DistanceToLineSegmentBetweenSqd(const SkPoint& pt, const SkPoint& a,
41                                                    const SkPoint& b);
42 
DistanceToLineSegmentBetween(const SkPoint & pt,const SkPoint & a,const SkPoint & b)43     static SkScalar DistanceToLineSegmentBetween(const SkPoint& pt, const SkPoint& a,
44                                                  const SkPoint& b) {
45         return SkScalarSqrt(DistanceToLineSegmentBetweenSqd(pt, a, b));
46     }
47 
DistanceToSqd(const SkPoint & pt,const SkPoint & a)48     static SkScalar DistanceToSqd(const SkPoint& pt, const SkPoint& a) {
49         SkScalar dx = pt.fX - a.fX;
50         SkScalar dy = pt.fY - a.fY;
51         return dx * dx + dy * dy;
52     }
53 
EqualsWithinTolerance(const SkPoint & p1,const SkPoint & p2)54     static bool EqualsWithinTolerance(const SkPoint& p1, const SkPoint& p2) {
55         return !CanNormalize(p1.fX - p2.fX, p1.fY - p2.fY);
56     }
57 
EqualsWithinTolerance(const SkPoint & pt,const SkPoint & p,SkScalar tol)58     static bool EqualsWithinTolerance(const SkPoint& pt, const SkPoint& p, SkScalar tol) {
59         return SkScalarNearlyZero(pt.fX - p.fX, tol)
60                && SkScalarNearlyZero(pt.fY - p.fY, tol);
61     }
62 
LengthSqd(const SkPoint & pt)63     static SkScalar LengthSqd(const SkPoint& pt) {
64         return SkPoint::DotProduct(pt, pt);
65     }
66 
Negate(SkIPoint & pt)67     static void Negate(SkIPoint& pt) {
68         pt.fX = -pt.fX;
69         pt.fY = -pt.fY;
70     }
71 
RotateCCW(const SkPoint & src,SkPoint * dst)72     static void RotateCCW(const SkPoint& src, SkPoint* dst) {
73         // use a tmp in case src == dst
74         SkScalar tmp = src.fX;
75         dst->fX = src.fY;
76         dst->fY = -tmp;
77     }
78 
RotateCCW(SkPoint * pt)79     static void RotateCCW(SkPoint* pt) {
80         RotateCCW(*pt, pt);
81     }
82 
RotateCW(const SkPoint & src,SkPoint * dst)83     static void RotateCW(const SkPoint& src, SkPoint* dst) {
84         // use a tmp in case src == dst
85         SkScalar tmp = src.fX;
86         dst->fX = -src.fY;
87         dst->fY = tmp;
88     }
89 
RotateCW(SkPoint * pt)90     static void RotateCW(SkPoint* pt) {
91         RotateCW(*pt, pt);
92     }
93 
94     static bool SetLengthFast(SkPoint* pt, float length);
95 
96     static void SetOrthog(SkPoint* pt, const SkPoint& vec, Side side = kLeft_Side) {
97         // vec could be this
98         SkScalar tmp = vec.fX;
99         if (kRight_Side == side) {
100             pt->fX = -vec.fY;
101             pt->fY = tmp;
102         } else {
103             SkASSERT(kLeft_Side == side);
104             pt->fX = vec.fY;
105             pt->fY = -tmp;
106         }
107     }
108 
109     // counter-clockwise fan
SetRectFan(SkPoint v[],SkScalar l,SkScalar t,SkScalar r,SkScalar b,size_t stride)110     static void SetRectFan(SkPoint v[], SkScalar l, SkScalar t, SkScalar r, SkScalar b,
111             size_t stride) {
112         SkASSERT(stride >= sizeof(SkPoint));
113 
114         ((SkPoint*)((intptr_t)v + 0 * stride))->set(l, t);
115         ((SkPoint*)((intptr_t)v + 1 * stride))->set(l, b);
116         ((SkPoint*)((intptr_t)v + 2 * stride))->set(r, b);
117         ((SkPoint*)((intptr_t)v + 3 * stride))->set(r, t);
118     }
119 
120     // tri strip with two counter-clockwise triangles
SetRectTriStrip(SkPoint v[],SkScalar l,SkScalar t,SkScalar r,SkScalar b,size_t stride)121     static void SetRectTriStrip(SkPoint v[], SkScalar l, SkScalar t, SkScalar r, SkScalar b,
122             size_t stride) {
123         SkASSERT(stride >= sizeof(SkPoint));
124 
125         ((SkPoint*)((intptr_t)v + 0 * stride))->set(l, t);
126         ((SkPoint*)((intptr_t)v + 1 * stride))->set(l, b);
127         ((SkPoint*)((intptr_t)v + 2 * stride))->set(r, t);
128         ((SkPoint*)((intptr_t)v + 3 * stride))->set(r, b);
129     }
130 
131 };
132 
133 #endif
134