blob: c89f08003a796400556b4ec5431b0f2fafbfd107 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SkPoint_DEFINED
18#define SkPoint_DEFINED
19
20#include "SkMath.h"
21#include "SkScalar.h"
22
23/** \struct SkIPoint
24
25 SkIPoint holds two 32 bit integer coordinates
26*/
27struct SkIPoint {
28 int32_t fX, fY;
reed@google.com6f8f2922011-03-04 22:27:10 +000029
reed@android.comac753092010-01-28 21:34:33 +000030 static SkIPoint Make(int32_t x, int32_t y) {
31 SkIPoint pt;
32 pt.set(x, y);
33 return pt;
34 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000035
reed@google.com6f8f2922011-03-04 22:27:10 +000036 int32_t x() const { return fX; }
37 int32_t y() const { return fY; }
38 void setX(int32_t x) { fX = x; }
39 void setY(int32_t y) { fY = y; }
40
41 /**
42 * Returns true iff fX and fY are both zero.
43 */
44 bool isZero() const { return (fX | fY) == 0; }
45
46 /**
47 * Set both fX and fY to zero. Same as set(0, 0)
48 */
49 void setZero() { fX = fY = 0; }
50
reed@android.com8a1c16f2008-12-17 15:59:43 +000051 /** Set the x and y values of the point. */
52 void set(int32_t x, int32_t y) { fX = x; fY = y; }
53
54 /** Rotate the point clockwise, writing the new point into dst
55 It is legal for dst == this
56 */
57 void rotateCW(SkIPoint* dst) const;
58
59 /** Rotate the point clockwise, writing the new point back into the point
60 */
61
62 void rotateCW() { this->rotateCW(this); }
63
64 /** Rotate the point counter-clockwise, writing the new point into dst.
65 It is legal for dst == this
66 */
67 void rotateCCW(SkIPoint* dst) const;
68
69 /** Rotate the point counter-clockwise, writing the new point back into
70 the point
71 */
72 void rotateCCW() { this->rotateCCW(this); }
reed@google.com6f8f2922011-03-04 22:27:10 +000073
reed@android.com8a1c16f2008-12-17 15:59:43 +000074 /** Negate the X and Y coordinates of the point.
75 */
76 void negate() { fX = -fX; fY = -fY; }
reed@google.com6f8f2922011-03-04 22:27:10 +000077
reed@android.com8a1c16f2008-12-17 15:59:43 +000078 /** Return a new point whose X and Y coordinates are the negative of the
79 original point's
80 */
81 SkIPoint operator-() const {
82 SkIPoint neg;
83 neg.fX = -fX;
84 neg.fY = -fY;
85 return neg;
86 }
87
88 /** Add v's coordinates to this point's */
89 void operator+=(const SkIPoint& v) {
90 fX += v.fX;
91 fY += v.fY;
92 }
reed@google.com6f8f2922011-03-04 22:27:10 +000093
reed@android.com8a1c16f2008-12-17 15:59:43 +000094 /** Subtract v's coordinates from this point's */
95 void operator-=(const SkIPoint& v) {
96 fX -= v.fX;
97 fY -= v.fY;
98 }
99
100 /** Returns true if the point's coordinates equal (x,y) */
101 bool equals(int32_t x, int32_t y) const {
102 return fX == x && fY == y;
103 }
104
105 friend bool operator==(const SkIPoint& a, const SkIPoint& b) {
106 return a.fX == b.fX && a.fY == b.fY;
107 }
reed@google.com6f8f2922011-03-04 22:27:10 +0000108
reed@android.com8a1c16f2008-12-17 15:59:43 +0000109 friend bool operator!=(const SkIPoint& a, const SkIPoint& b) {
110 return a.fX != b.fX || a.fY != b.fY;
111 }
112
113 /** Returns a new point whose coordinates are the difference between
114 a and b (i.e. a - b)
115 */
116 friend SkIPoint operator-(const SkIPoint& a, const SkIPoint& b) {
117 SkIPoint v;
118 v.set(a.fX - b.fX, a.fY - b.fY);
119 return v;
120 }
121
122 /** Returns a new point whose coordinates are the sum of a and b (a + b)
123 */
124 friend SkIPoint operator+(const SkIPoint& a, const SkIPoint& b) {
125 SkIPoint v;
126 v.set(a.fX + b.fX, a.fY + b.fY);
127 return v;
128 }
reed@google.com6f8f2922011-03-04 22:27:10 +0000129
reed@android.com8a1c16f2008-12-17 15:59:43 +0000130 /** Returns the dot product of a and b, treating them as 2D vectors
131 */
132 static int32_t DotProduct(const SkIPoint& a, const SkIPoint& b) {
133 return a.fX * b.fX + a.fY * b.fY;
134 }
135
136 /** Returns the cross product of a and b, treating them as 2D vectors
137 */
138 static int32_t CrossProduct(const SkIPoint& a, const SkIPoint& b) {
139 return a.fX * b.fY - a.fY * b.fX;
140 }
141};
142
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +0000143struct SK_API SkPoint {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000144 SkScalar fX, fY;
145
reed@android.comac753092010-01-28 21:34:33 +0000146 static SkPoint Make(SkScalar x, SkScalar y) {
147 SkPoint pt;
148 pt.set(x, y);
149 return pt;
150 }
reed@google.com6f8f2922011-03-04 22:27:10 +0000151
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152 /** Set the point's X and Y coordinates */
153 void set(SkScalar x, SkScalar y) { fX = x; fY = y; }
reed@google.com6f8f2922011-03-04 22:27:10 +0000154
reed@android.com8a1c16f2008-12-17 15:59:43 +0000155 /** Set the point's X and Y coordinates by automatically promoting (x,y) to
156 SkScalar values.
157 */
158 void iset(int32_t x, int32_t y) {
159 fX = SkIntToScalar(x);
160 fY = SkIntToScalar(y);
161 }
reed@google.com6f8f2922011-03-04 22:27:10 +0000162
reed@android.com8a1c16f2008-12-17 15:59:43 +0000163 /** Set the point's X and Y coordinates by automatically promoting p's
164 coordinates to SkScalar values.
165 */
166 void iset(const SkIPoint& p) {
167 fX = SkIntToScalar(p.fX);
168 fY = SkIntToScalar(p.fY);
169 }
170
171 /** Return the euclidian distance from (0,0) to the point
172 */
173 SkScalar length() const { return SkPoint::Length(fX, fY); }
174
175 /** Set the point (vector) to be unit-length in the same direction as it
176 currently is, and return its old length. If the old length is
177 degenerately small (nearly zero), do nothing and return false, otherwise
178 return true.
179 */
180 bool normalize();
reed@google.com6f8f2922011-03-04 22:27:10 +0000181
reed@android.com8a1c16f2008-12-17 15:59:43 +0000182 /** Set the point (vector) to be unit-length in the same direction as the
183 x,y params. If the vector (x,y) has a degenerate length (i.e. nearly 0)
184 then return false and do nothing, otherwise return true.
185 */
186 bool setNormalize(SkScalar x, SkScalar y);
reed@google.com6f8f2922011-03-04 22:27:10 +0000187
reed@android.com8a1c16f2008-12-17 15:59:43 +0000188 /** Scale the point (vector) to have the specified length, and return that
189 length. If the original length is degenerately small (nearly zero),
190 do nothing and return false, otherwise return true.
191 */
192 bool setLength(SkScalar length);
reed@google.com6f8f2922011-03-04 22:27:10 +0000193
reed@android.com8a1c16f2008-12-17 15:59:43 +0000194 /** Set the point (vector) to have the specified length in the same
195 direction as (x,y). If the vector (x,y) has a degenerate length
196 (i.e. nearly 0) then return false and do nothing, otherwise return true.
197 */
198 bool setLength(SkScalar x, SkScalar y, SkScalar length);
199
200 /** Scale the point's coordinates by scale, writing the answer into dst.
201 It is legal for dst == this.
202 */
203 void scale(SkScalar scale, SkPoint* dst) const;
reed@google.com6f8f2922011-03-04 22:27:10 +0000204
reed@android.com8a1c16f2008-12-17 15:59:43 +0000205 /** Scale the point's coordinates by scale, writing the answer back into
206 the point.
207 */
reed@android.comfc25abd2009-01-15 14:38:33 +0000208 void scale(SkScalar value) { this->scale(value, this); }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000209
210 /** Rotate the point clockwise by 90 degrees, writing the answer into dst.
211 It is legal for dst == this.
212 */
213 void rotateCW(SkPoint* dst) const;
reed@google.com6f8f2922011-03-04 22:27:10 +0000214
reed@android.com8a1c16f2008-12-17 15:59:43 +0000215 /** Rotate the point clockwise by 90 degrees, writing the answer back into
216 the point.
217 */
218 void rotateCW() { this->rotateCW(this); }
reed@google.com6f8f2922011-03-04 22:27:10 +0000219
reed@android.com8a1c16f2008-12-17 15:59:43 +0000220 /** Rotate the point counter-clockwise by 90 degrees, writing the answer
221 into dst. It is legal for dst == this.
222 */
223 void rotateCCW(SkPoint* dst) const;
reed@google.com6f8f2922011-03-04 22:27:10 +0000224
reed@android.com8a1c16f2008-12-17 15:59:43 +0000225 /** Rotate the point counter-clockwise by 90 degrees, writing the answer
226 back into the point.
227 */
228 void rotateCCW() { this->rotateCCW(this); }
reed@google.com6f8f2922011-03-04 22:27:10 +0000229
reed@android.com8a1c16f2008-12-17 15:59:43 +0000230 /** Negate the point's coordinates
231 */
232 void negate() {
233 fX = -fX;
234 fY = -fY;
235 }
reed@google.com6f8f2922011-03-04 22:27:10 +0000236
reed@android.com8a1c16f2008-12-17 15:59:43 +0000237 /** Returns a new point whose coordinates are the negative of the point's
238 */
239 SkPoint operator-() const {
240 SkPoint neg;
241 neg.fX = -fX;
242 neg.fY = -fY;
243 return neg;
244 }
245
246 /** Add v's coordinates to the point's
247 */
248 void operator+=(const SkPoint& v) {
249 fX += v.fX;
250 fY += v.fY;
251 }
reed@google.com6f8f2922011-03-04 22:27:10 +0000252
reed@android.com8a1c16f2008-12-17 15:59:43 +0000253 /** Subtract v's coordinates from the point's
254 */
255 void operator-=(const SkPoint& v) {
256 fX -= v.fX;
257 fY -= v.fY;
258 }
259
260 /** Returns true if the point's coordinates equal (x,y)
261 */
262 bool equals(SkScalar x, SkScalar y) const { return fX == x && fY == y; }
263
264 friend bool operator==(const SkPoint& a, const SkPoint& b) {
265 return a.fX == b.fX && a.fY == b.fY;
266 }
reed@google.com6f8f2922011-03-04 22:27:10 +0000267
reed@android.com8a1c16f2008-12-17 15:59:43 +0000268 friend bool operator!=(const SkPoint& a, const SkPoint& b) {
269 return a.fX != b.fX || a.fY != b.fY;
270 }
271
272 /** Returns a new point whose coordinates are the difference between
273 a's and b's (a - b)
274 */
275 friend SkPoint operator-(const SkPoint& a, const SkPoint& b) {
276 SkPoint v;
277 v.set(a.fX - b.fX, a.fY - b.fY);
278 return v;
279 }
280
281 /** Returns a new point whose coordinates are the sum of a's and b's (a + b)
282 */
283 friend SkPoint operator+(const SkPoint& a, const SkPoint& b) {
284 SkPoint v;
285 v.set(a.fX + b.fX, a.fY + b.fY);
286 return v;
287 }
288
289 /** Returns the euclidian distance from (0,0) to (x,y)
290 */
291 static SkScalar Length(SkScalar x, SkScalar y);
reed@android.comac753092010-01-28 21:34:33 +0000292
293 /** Normalize pt, returning its previous length. If the prev length is too
294 small (degenerate), return 0 and leave pt unchanged.
295 */
296 static SkScalar Normalize(SkPoint* pt);
297
reed@android.com8a1c16f2008-12-17 15:59:43 +0000298 /** Returns the euclidian distance between a and b
299 */
300 static SkScalar Distance(const SkPoint& a, const SkPoint& b) {
301 return Length(a.fX - b.fX, a.fY - b.fY);
302 }
303
304 /** Returns the dot product of a and b, treating them as 2D vectors
305 */
306 static SkScalar DotProduct(const SkPoint& a, const SkPoint& b) {
307 return SkScalarMul(a.fX, b.fX) + SkScalarMul(a.fY, b.fY);
308 }
309
310 /** Returns the cross product of a and b, treating them as 2D vectors
311 */
312 static SkScalar CrossProduct(const SkPoint& a, const SkPoint& b) {
313 return SkScalarMul(a.fX, b.fY) - SkScalarMul(a.fY, b.fX);
314 }
315};
316
317typedef SkPoint SkVector;
318
319#endif
320