• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2006 The Android Open Source Project
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #ifndef SkPoint_DEFINED
11 #define SkPoint_DEFINED
12 
13 #include "SkMath.h"
14 #include "SkScalar.h"
15 
16 /** \struct SkIPoint
17 
18     SkIPoint holds two 32 bit integer coordinates
19 */
20 struct SkIPoint {
21     int32_t fX, fY;
22 
MakeSkIPoint23     static SkIPoint Make(int32_t x, int32_t y) {
24         SkIPoint pt;
25         pt.set(x, y);
26         return pt;
27     }
28 
xSkIPoint29     int32_t x() const { return fX; }
ySkIPoint30     int32_t y() const { return fY; }
setXSkIPoint31     void setX(int32_t x) { fX = x; }
setYSkIPoint32     void setY(int32_t y) { fY = y; }
33 
34     /**
35      *  Returns true iff fX and fY are both zero.
36      */
isZeroSkIPoint37     bool isZero() const { return (fX | fY) == 0; }
38 
39     /**
40      *  Set both fX and fY to zero. Same as set(0, 0)
41      */
setZeroSkIPoint42     void setZero() { fX = fY = 0; }
43 
44     /** Set the x and y values of the point. */
setSkIPoint45     void set(int32_t x, int32_t y) { fX = x; fY = y; }
46 
47     /** Rotate the point clockwise, writing the new point into dst
48         It is legal for dst == this
49     */
50     void rotateCW(SkIPoint* dst) const;
51 
52     /** Rotate the point clockwise, writing the new point back into the point
53     */
54 
rotateCWSkIPoint55     void rotateCW() { this->rotateCW(this); }
56 
57     /** Rotate the point counter-clockwise, writing the new point into dst.
58         It is legal for dst == this
59     */
60     void rotateCCW(SkIPoint* dst) const;
61 
62     /** Rotate the point counter-clockwise, writing the new point back into
63         the point
64     */
rotateCCWSkIPoint65     void rotateCCW() { this->rotateCCW(this); }
66 
67     /** Negate the X and Y coordinates of the point.
68     */
negateSkIPoint69     void negate() { fX = -fX; fY = -fY; }
70 
71     /** Return a new point whose X and Y coordinates are the negative of the
72         original point's
73     */
74     SkIPoint operator-() const {
75         SkIPoint neg;
76         neg.fX = -fX;
77         neg.fY = -fY;
78         return neg;
79     }
80 
81     /** Add v's coordinates to this point's */
82     void operator+=(const SkIPoint& v) {
83         fX += v.fX;
84         fY += v.fY;
85     }
86 
87     /** Subtract v's coordinates from this point's */
88     void operator-=(const SkIPoint& v) {
89         fX -= v.fX;
90         fY -= v.fY;
91     }
92 
93     /** Returns true if the point's coordinates equal (x,y) */
equalsSkIPoint94     bool equals(int32_t x, int32_t y) const {
95         return fX == x && fY == y;
96     }
97 
98     friend bool operator==(const SkIPoint& a, const SkIPoint& b) {
99         return a.fX == b.fX && a.fY == b.fY;
100     }
101 
102     friend bool operator!=(const SkIPoint& a, const SkIPoint& b) {
103         return a.fX != b.fX || a.fY != b.fY;
104     }
105 
106     /** Returns a new point whose coordinates are the difference between
107         a and b (i.e. a - b)
108     */
109     friend SkIPoint operator-(const SkIPoint& a, const SkIPoint& b) {
110         SkIPoint v;
111         v.set(a.fX - b.fX, a.fY - b.fY);
112         return v;
113     }
114 
115     /** Returns a new point whose coordinates are the sum of a and b (a + b)
116     */
117     friend SkIPoint operator+(const SkIPoint& a, const SkIPoint& b) {
118         SkIPoint v;
119         v.set(a.fX + b.fX, a.fY + b.fY);
120         return v;
121     }
122 
123     /** Returns the dot product of a and b, treating them as 2D vectors
124     */
DotProductSkIPoint125     static int32_t DotProduct(const SkIPoint& a, const SkIPoint& b) {
126         return a.fX * b.fX + a.fY * b.fY;
127     }
128 
129     /** Returns the cross product of a and b, treating them as 2D vectors
130     */
CrossProductSkIPoint131     static int32_t CrossProduct(const SkIPoint& a, const SkIPoint& b) {
132         return a.fX * b.fY - a.fY * b.fX;
133     }
134 };
135 
136 struct SK_API SkPoint {
137     SkScalar    fX, fY;
138 
MakeSkPoint139     static SkPoint Make(SkScalar x, SkScalar y) {
140         SkPoint pt;
141         pt.set(x, y);
142         return pt;
143     }
144 
xSkPoint145     SkScalar x() const { return fX; }
ySkPoint146     SkScalar y() const { return fY; }
147 
148     /** Set the point's X and Y coordinates */
setSkPoint149     void set(SkScalar x, SkScalar y) { fX = x; fY = y; }
150 
151     /** Set the point's X and Y coordinates by automatically promoting (x,y) to
152         SkScalar values.
153     */
isetSkPoint154     void iset(int32_t x, int32_t y) {
155         fX = SkIntToScalar(x);
156         fY = SkIntToScalar(y);
157     }
158 
159     /** Set the point's X and Y coordinates by automatically promoting p's
160         coordinates to SkScalar values.
161     */
isetSkPoint162     void iset(const SkIPoint& p) {
163         fX = SkIntToScalar(p.fX);
164         fY = SkIntToScalar(p.fY);
165     }
166 
setAbsSkPoint167     void setAbs(const SkPoint& pt) {
168         fX = SkScalarAbs(pt.fX);
169         fY = SkScalarAbs(pt.fY);
170     }
171 
172     // counter-clockwise fan
setIRectFanSkPoint173     void setIRectFan(int l, int t, int r, int b) {
174         SkPoint* v = this;
175         v[0].set(SkIntToScalar(l), SkIntToScalar(t));
176         v[1].set(SkIntToScalar(l), SkIntToScalar(b));
177         v[2].set(SkIntToScalar(r), SkIntToScalar(b));
178         v[3].set(SkIntToScalar(r), SkIntToScalar(t));
179     }
180     void setIRectFan(int l, int t, int r, int b, size_t stride);
181 
182     // counter-clockwise fan
setRectFanSkPoint183     void setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
184         SkPoint* v = this;
185         v[0].set(l, t);
186         v[1].set(l, b);
187         v[2].set(r, b);
188         v[3].set(r, t);
189     }
190     void setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b, size_t stride);
191 
OffsetSkPoint192     static void Offset(SkPoint points[], int count, const SkPoint& offset) {
193         Offset(points, count, offset.fX, offset.fY);
194     }
195 
OffsetSkPoint196     static void Offset(SkPoint points[], int count, SkScalar dx, SkScalar dy) {
197         for (int i = 0; i < count; ++i) {
198             points[i].offset(dx, dy);
199         }
200     }
201 
offsetSkPoint202     void offset(SkScalar dx, SkScalar dy) {
203         fX += dx;
204         fY += dy;
205     }
206 
207     /** Return the euclidian distance from (0,0) to the point
208     */
lengthSkPoint209     SkScalar length() const { return SkPoint::Length(fX, fY); }
distanceToOriginSkPoint210     SkScalar distanceToOrigin() const { return this->length(); }
211 
212     /**
213      *  Return true if the computed length of the vector is >= the internal
214      *  tolerance (used to avoid dividing by tiny values).
215      */
216     static bool CanNormalize(SkScalar dx, SkScalar dy);
217 
canNormalizeSkPoint218     bool canNormalize() const {
219         return CanNormalize(fX, fY);
220     }
221 
222     /** Set the point (vector) to be unit-length in the same direction as it
223         already points.  If the point has a degenerate length (i.e. nearly 0)
224         then return false and do nothing; otherwise return true.
225     */
226     bool normalize();
227 
228     /** Set the point (vector) to be unit-length in the same direction as the
229         x,y params. If the vector (x,y) has a degenerate length (i.e. nearly 0)
230         then return false and do nothing, otherwise return true.
231     */
232     bool setNormalize(SkScalar x, SkScalar y);
233 
234     /** Scale the point (vector) to have the specified length, and return that
235         length. If the original length is degenerately small (nearly zero),
236         do nothing and return false, otherwise return true.
237     */
238     bool setLength(SkScalar length);
239 
240     /** Set the point (vector) to have the specified length in the same
241      direction as (x,y). If the vector (x,y) has a degenerate length
242      (i.e. nearly 0) then return false and do nothing, otherwise return true.
243     */
244     bool setLength(SkScalar x, SkScalar y, SkScalar length);
245 
246     /** Scale the point's coordinates by scale, writing the answer into dst.
247         It is legal for dst == this.
248     */
249     void scale(SkScalar scale, SkPoint* dst) const;
250 
251     /** Scale the point's coordinates by scale, writing the answer back into
252         the point.
253     */
scaleSkPoint254     void scale(SkScalar value) { this->scale(value, this); }
255 
256     /** Rotate the point clockwise by 90 degrees, writing the answer into dst.
257         It is legal for dst == this.
258     */
259     void rotateCW(SkPoint* dst) const;
260 
261     /** Rotate the point clockwise by 90 degrees, writing the answer back into
262         the point.
263     */
rotateCWSkPoint264     void rotateCW() { this->rotateCW(this); }
265 
266     /** Rotate the point counter-clockwise by 90 degrees, writing the answer
267         into dst. It is legal for dst == this.
268     */
269     void rotateCCW(SkPoint* dst) const;
270 
271     /** Rotate the point counter-clockwise by 90 degrees, writing the answer
272         back into the point.
273     */
rotateCCWSkPoint274     void rotateCCW() { this->rotateCCW(this); }
275 
276     /** Negate the point's coordinates
277     */
negateSkPoint278     void negate() {
279         fX = -fX;
280         fY = -fY;
281     }
282 
283     /** Returns a new point whose coordinates are the negative of the point's
284     */
285     SkPoint operator-() const {
286         SkPoint neg;
287         neg.fX = -fX;
288         neg.fY = -fY;
289         return neg;
290     }
291 
292     /** Add v's coordinates to the point's
293     */
294     void operator+=(const SkPoint& v) {
295         fX += v.fX;
296         fY += v.fY;
297     }
298 
299     /** Subtract v's coordinates from the point's
300     */
301     void operator-=(const SkPoint& v) {
302         fX -= v.fX;
303         fY -= v.fY;
304     }
305 
306     /** Returns true if the point's coordinates equal (x,y)
307     */
equalsSkPoint308     bool equals(SkScalar x, SkScalar y) const { return fX == x && fY == y; }
309 
310     friend bool operator==(const SkPoint& a, const SkPoint& b) {
311         return a.fX == b.fX && a.fY == b.fY;
312     }
313 
314     friend bool operator!=(const SkPoint& a, const SkPoint& b) {
315         return a.fX != b.fX || a.fY != b.fY;
316     }
317 
318     /** Return true if this and the given point are componentwise within tol.
319     */
equalsWithinToleranceSkPoint320     bool equalsWithinTolerance(const SkPoint& v, SkScalar tol) const {
321         return SkScalarNearlyZero(fX - v.fX, tol)
322                && SkScalarNearlyZero(fY - v.fY, tol);
323     }
324 
325     /** Returns a new point whose coordinates are the difference between
326         a's and b's (a - b)
327     */
328     friend SkPoint operator-(const SkPoint& a, const SkPoint& b) {
329         SkPoint v;
330         v.set(a.fX - b.fX, a.fY - b.fY);
331         return v;
332     }
333 
334     /** Returns a new point whose coordinates are the sum of a's and b's (a + b)
335     */
336     friend SkPoint operator+(const SkPoint& a, const SkPoint& b) {
337         SkPoint v;
338         v.set(a.fX + b.fX, a.fY + b.fY);
339         return v;
340     }
341 
342     /** Returns the euclidian distance from (0,0) to (x,y)
343     */
344     static SkScalar Length(SkScalar x, SkScalar y);
345 
346     /** Normalize pt, returning its previous length. If the prev length is too
347         small (degenerate), return 0 and leave pt unchanged. This uses the same
348         tolerance as CanNormalize.
349 
350         Note that this method may be significantly more expensive than
351         the non-static normalize(), because it has to return the previous length
352         of the point.  If you don't need the previous length, call the
353         non-static normalize() method instead.
354      */
355     static SkScalar Normalize(SkPoint* pt);
356 
357     /** Returns the euclidian distance between a and b
358     */
DistanceSkPoint359     static SkScalar Distance(const SkPoint& a, const SkPoint& b) {
360         return Length(a.fX - b.fX, a.fY - b.fY);
361     }
362 
363     /** Returns the dot product of a and b, treating them as 2D vectors
364     */
DotProductSkPoint365     static SkScalar DotProduct(const SkPoint& a, const SkPoint& b) {
366         return SkScalarMul(a.fX, b.fX) + SkScalarMul(a.fY, b.fY);
367     }
368 
369     /** Returns the cross product of a and b, treating them as 2D vectors
370     */
CrossProductSkPoint371     static SkScalar CrossProduct(const SkPoint& a, const SkPoint& b) {
372         return SkScalarMul(a.fX, b.fY) - SkScalarMul(a.fY, b.fX);
373     }
374 
crossSkPoint375     SkScalar cross(const SkPoint& vec) const {
376         return CrossProduct(*this, vec);
377     }
378 
dotSkPoint379     SkScalar dot(const SkPoint& vec) const {
380         return DotProduct(*this, vec);
381     }
382 
lengthSqdSkPoint383     SkScalar lengthSqd() const {
384         return DotProduct(*this, *this);
385     }
386 
distanceToSqdSkPoint387     SkScalar distanceToSqd(const SkPoint& pt) const {
388         SkScalar dx = fX - pt.fX;
389         SkScalar dy = fY - pt.fY;
390         return SkScalarMul(dx, dx) + SkScalarMul(dy, dy);
391     }
392 
393     /**
394      * The side of a point relative to a line. If the line is from a to b then
395      * the values are consistent with the sign of (b-a) cross (pt-a)
396      */
397     enum Side {
398         kLeft_Side  = -1,
399         kOn_Side    =  0,
400         kRight_Side =  1
401     };
402 
403     /**
404      * Returns the squared distance to the infinite line between two pts. Also
405      * optionally returns the side of the line that the pt falls on (looking
406      * along line from a to b)
407      */
408     SkScalar distanceToLineBetweenSqd(const SkPoint& a,
409                                       const SkPoint& b,
410                                       Side* side = NULL) const;
411 
412     /**
413      * Returns the distance to the infinite line between two pts. Also
414      * optionally returns the side of the line that the pt falls on (looking
415      * along the line from a to b)
416      */
417     SkScalar distanceToLineBetween(const SkPoint& a,
418                                    const SkPoint& b,
419                                    Side* side = NULL) const {
420         return SkScalarSqrt(this->distanceToLineBetweenSqd(a, b, side));
421     }
422 
423     /**
424      * Returns the squared distance to the line segment between pts a and b
425      */
426     SkScalar distanceToLineSegmentBetweenSqd(const SkPoint& a,
427                                              const SkPoint& b) const;
428 
429     /**
430      * Returns the distance to the line segment between pts a and b.
431      */
distanceToLineSegmentBetweenSkPoint432     SkScalar distanceToLineSegmentBetween(const SkPoint& a,
433                                           const SkPoint& b) const {
434         return SkScalarSqrt(this->distanceToLineSegmentBetweenSqd(a, b));
435     }
436 
437     /**
438      * Make this vector be orthogonal to vec. Looking down vec the
439      * new vector will point in direction indicated by side (which
440      * must be kLeft_Side or kRight_Side).
441      */
442     void setOrthog(const SkPoint& vec, Side side = kLeft_Side) {
443         // vec could be this
444         SkScalar tmp = vec.fX;
445         if (kRight_Side == side) {
446             fX = -vec.fY;
447             fY = tmp;
448         } else {
449             SkASSERT(kLeft_Side == side);
450             fX = vec.fY;
451             fY = -tmp;
452         }
453     }
454 };
455 
456 typedef SkPoint SkVector;
457 
458 #endif
459