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 "include/core/SkPoint.h"
12#include "include/core/SkRect.h"
13
14class SkPointPriv {
15public:
16 enum Side {
17 kLeft_Side = -1,
18 kOn_Side = 0,
19 kRight_Side = 1,
20 };
21
22 static bool AreFinite(const SkPoint array[], int count) {
23 return SkScalarsAreFinite(&array[0].fX, count << 1);
24 }
25
26 static const SkScalar* AsScalars(const SkPoint& pt) { return &pt.fX; }
27
28 static bool CanNormalize(SkScalar dx, SkScalar dy) {
29 return SkScalarsAreFinite(dx, dy) && (dx || dy);
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
43 static SkScalar DistanceToLineSegmentBetween(const SkPoint& pt, const SkPoint& a,
44 const SkPoint& b) {
45 return SkScalarSqrt(DistanceToLineSegmentBetweenSqd(pt, a, b));
46 }
47
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
54 static bool EqualsWithinTolerance(const SkPoint& p1, const SkPoint& p2) {
55 return !CanNormalize(p1.fX - p2.fX, p1.fY - p2.fY);
56 }
57
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
63 static SkScalar LengthSqd(const SkPoint& pt) {
64 return SkPoint::DotProduct(pt, pt);
65 }
66
67 static void Negate(SkIPoint& pt) {
68 pt.fX = -pt.fX;
69 pt.fY = -pt.fY;
70 }
71
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
79 static void RotateCCW(SkPoint* pt) {
80 RotateCCW(*pt, pt);
81 }
82
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
90 static void RotateCW(SkPoint* pt) {
91 RotateCW(*pt, pt);
92 }
93
94 static bool SetLengthFast(SkPoint* pt, float length);
95
96 static SkPoint MakeOrthog(const SkPoint& vec, Side side = kLeft_Side) {
97 SkASSERT(side == kRight_Side || side == kLeft_Side);
98 return (side == kRight_Side) ? SkPoint{-vec.fY, vec.fX} : SkPoint{vec.fY, -vec.fX};
99 }
100
101 // counter-clockwise fan
102 static void SetRectFan(SkPoint v[], SkScalar l, SkScalar t, SkScalar r, SkScalar b,
103 size_t stride) {
104 SkASSERT(stride >= sizeof(SkPoint));
105
106 ((SkPoint*)((intptr_t)v + 0 * stride))->set(l, t);
107 ((SkPoint*)((intptr_t)v + 1 * stride))->set(l, b);
108 ((SkPoint*)((intptr_t)v + 2 * stride))->set(r, b);
109 ((SkPoint*)((intptr_t)v + 3 * stride))->set(r, t);
110 }
111
112 // tri strip with two counter-clockwise triangles
113 static void SetRectTriStrip(SkPoint v[], SkScalar l, SkScalar t, SkScalar r, SkScalar b,
114 size_t stride) {
115 SkASSERT(stride >= sizeof(SkPoint));
116
117 ((SkPoint*)((intptr_t)v + 0 * stride))->set(l, t);
118 ((SkPoint*)((intptr_t)v + 1 * stride))->set(l, b);
119 ((SkPoint*)((intptr_t)v + 2 * stride))->set(r, t);
120 ((SkPoint*)((intptr_t)v + 3 * stride))->set(r, b);
121 }
122 static void SetRectTriStrip(SkPoint v[], const SkRect& rect, size_t stride) {
123 SetRectTriStrip(v, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, stride);
124 }
125};
126
127#endif
128