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