Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / include / core / SkPoint.h
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 SkPoint_DEFINED
9 #define SkPoint_DEFINED
10
11 #include "SkMath.h"
12 #include "SkScalar.h"
13
14 /** \struct SkIPoint
15
16     SkIPoint holds two 32 bit integer coordinates
17 */
18 struct SkIPoint {
19     int32_t fX, fY;
20
21     static SkIPoint Make(int32_t x, int32_t y) {
22         SkIPoint pt;
23         pt.set(x, y);
24         return pt;
25     }
26
27     int32_t x() const { return fX; }
28     int32_t y() const { return fY; }
29     void setX(int32_t x) { fX = x; }
30     void setY(int32_t y) { fY = y; }
31
32     /**
33      *  Returns true iff fX and fY are both zero.
34      */
35     bool isZero() const { return (fX | fY) == 0; }
36
37     /**
38      *  Set both fX and fY to zero. Same as set(0, 0)
39      */
40     void setZero() { fX = fY = 0; }
41
42     /** Set the x and y values of the point. */
43     void set(int32_t x, int32_t y) { fX = x; fY = y; }
44
45     /** Rotate the point clockwise, writing the new point into dst
46         It is legal for dst == this
47     */
48     void rotateCW(SkIPoint* dst) const;
49
50     /** Rotate the point clockwise, writing the new point back into the point
51     */
52
53     void rotateCW() { this->rotateCW(this); }
54
55     /** Rotate the point counter-clockwise, writing the new point into dst.
56         It is legal for dst == this
57     */
58     void rotateCCW(SkIPoint* dst) const;
59
60     /** Rotate the point counter-clockwise, writing the new point back into
61         the point
62     */
63     void rotateCCW() { this->rotateCCW(this); }
64
65     /** Negate the X and Y coordinates of the point.
66     */
67     void negate() { fX = -fX; fY = -fY; }
68
69     /** Return a new point whose X and Y coordinates are the negative of the
70         original point's
71     */
72     SkIPoint operator-() const {
73         SkIPoint neg;
74         neg.fX = -fX;
75         neg.fY = -fY;
76         return neg;
77     }
78
79     /** Add v's coordinates to this point's */
80     void operator+=(const SkIPoint& v) {
81         fX += v.fX;
82         fY += v.fY;
83     }
84
85     /** Subtract v's coordinates from this point's */
86     void operator-=(const SkIPoint& v) {
87         fX -= v.fX;
88         fY -= v.fY;
89     }
90
91     /** Returns true if the point's coordinates equal (x,y) */
92     bool equals(int32_t x, int32_t y) const {
93         return fX == x && fY == y;
94     }
95
96     friend bool operator==(const SkIPoint& a, const SkIPoint& b) {
97         return a.fX == b.fX && a.fY == b.fY;
98     }
99
100     friend bool operator!=(const SkIPoint& a, const SkIPoint& b) {
101         return a.fX != b.fX || a.fY != b.fY;
102     }
103
104     /** Returns a new point whose coordinates are the difference between
105         a and b (i.e. a - b)
106     */
107     friend SkIPoint operator-(const SkIPoint& a, const SkIPoint& b) {
108         SkIPoint v;
109         v.set(a.fX - b.fX, a.fY - b.fY);
110         return v;
111     }
112
113     /** Returns a new point whose coordinates are the sum of a and b (a + b)
114     */
115     friend SkIPoint operator+(const SkIPoint& a, const SkIPoint& b) {
116         SkIPoint v;
117         v.set(a.fX + b.fX, a.fY + b.fY);
118         return v;
119     }
120
121     /** Returns the dot product of a and b, treating them as 2D vectors
122     */
123     static int32_t DotProduct(const SkIPoint& a, const SkIPoint& b) {
124         return a.fX * b.fX + a.fY * b.fY;
125     }
126
127     /** Returns the cross product of a and b, treating them as 2D vectors
128     */
129     static int32_t CrossProduct(const SkIPoint& a, const SkIPoint& b) {
130         return a.fX * b.fY - a.fY * b.fX;
131     }
132 };
133
134 struct SK_API SkPoint {
135     SkScalar    fX, fY;
136
137     static SkPoint Make(SkScalar x, SkScalar y) {
138         SkPoint pt;
139         pt.set(x, y);
140         return pt;
141     }
142
143     SkScalar x() const { return fX; }
144     SkScalar y() const { return fY; }
145
146     /**
147      *  Returns true iff fX and fY are both zero.
148      */
149     bool isZero() const { return (0 == fX) & (0 == fY); }
150
151     /** Set the point's X and Y coordinates */
152     void set(SkScalar x, SkScalar y) { fX = x; fY = y; }
153
154     /** Set the point's X and Y coordinates by automatically promoting (x,y) to
155         SkScalar values.
156     */
157     void iset(int32_t x, int32_t y) {
158         fX = SkIntToScalar(x);
159         fY = SkIntToScalar(y);
160     }
161
162     /** Set the point's X and Y coordinates by automatically promoting p's
163         coordinates to SkScalar values.
164     */
165     void iset(const SkIPoint& p) {
166         fX = SkIntToScalar(p.fX);
167         fY = SkIntToScalar(p.fY);
168     }
169
170     void setAbs(const SkPoint& pt) {
171         fX = SkScalarAbs(pt.fX);
172         fY = SkScalarAbs(pt.fY);
173     }
174
175     // counter-clockwise fan
176     void setIRectFan(int l, int t, int r, int b) {
177         SkPoint* v = this;
178         v[0].set(SkIntToScalar(l), SkIntToScalar(t));
179         v[1].set(SkIntToScalar(l), SkIntToScalar(b));
180         v[2].set(SkIntToScalar(r), SkIntToScalar(b));
181         v[3].set(SkIntToScalar(r), SkIntToScalar(t));
182     }
183     void setIRectFan(int l, int t, int r, int b, size_t stride);
184
185     // counter-clockwise fan
186     void setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
187         SkPoint* v = this;
188         v[0].set(l, t);
189         v[1].set(l, b);
190         v[2].set(r, b);
191         v[3].set(r, t);
192     }
193     void setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b, size_t stride);
194
195     static void Offset(SkPoint points[], int count, const SkPoint& offset) {
196         Offset(points, count, offset.fX, offset.fY);
197     }
198
199     static void Offset(SkPoint points[], int count, SkScalar dx, SkScalar dy) {
200         for (int i = 0; i < count; ++i) {
201             points[i].offset(dx, dy);
202         }
203     }
204
205     void offset(SkScalar dx, SkScalar dy) {
206         fX += dx;
207         fY += dy;
208     }
209
210     /** Return the euclidian distance from (0,0) to the point
211     */
212     SkScalar length() const { return SkPoint::Length(fX, fY); }
213     SkScalar distanceToOrigin() const { return this->length(); }
214
215     /**
216      *  Return true if the computed length of the vector is >= the internal
217      *  tolerance (used to avoid dividing by tiny values).
218      */
219     static bool CanNormalize(SkScalar dx, SkScalar dy) {
220         // Simple enough (and performance critical sometimes) so we inline it.
221         return (dx*dx + dy*dy) > (SK_ScalarNearlyZero * SK_ScalarNearlyZero);
222     }
223
224     bool canNormalize() const {
225         return CanNormalize(fX, fY);
226     }
227
228     /** Set the point (vector) to be unit-length in the same direction as it
229         already points.  If the point has a degenerate length (i.e. nearly 0)
230         then return false and do nothing; otherwise return true.
231     */
232     bool normalize();
233
234     /** Set the point (vector) to be unit-length in the same direction as the
235         x,y params. If the vector (x,y) has a degenerate length (i.e. nearly 0)
236         then return false and do nothing, otherwise return true.
237     */
238     bool setNormalize(SkScalar x, SkScalar y);
239
240     /** Scale the point (vector) to have the specified length, and return that
241         length. If the original length is degenerately small (nearly zero),
242         do nothing and return false, otherwise return true.
243     */
244     bool setLength(SkScalar length);
245
246     /** Set the point (vector) to have the specified length in the same
247      direction as (x,y). If the vector (x,y) has a degenerate length
248      (i.e. nearly 0) then return false and do nothing, otherwise return true.
249     */
250     bool setLength(SkScalar x, SkScalar y, SkScalar length);
251
252     /** Same as setLength, but favoring speed over accuracy.
253     */
254     bool setLengthFast(SkScalar length);
255
256     /** Same as setLength, but favoring speed over accuracy.
257     */
258     bool setLengthFast(SkScalar x, SkScalar y, SkScalar length);
259
260     /** Scale the point's coordinates by scale, writing the answer into dst.
261         It is legal for dst == this.
262     */
263     void scale(SkScalar scale, SkPoint* dst) const;
264
265     /** Scale the point's coordinates by scale, writing the answer back into
266         the point.
267     */
268     void scale(SkScalar value) { this->scale(value, this); }
269
270     /** Rotate the point clockwise by 90 degrees, writing the answer into dst.
271         It is legal for dst == this.
272     */
273     void rotateCW(SkPoint* dst) const;
274
275     /** Rotate the point clockwise by 90 degrees, writing the answer back into
276         the point.
277     */
278     void rotateCW() { this->rotateCW(this); }
279
280     /** Rotate the point counter-clockwise by 90 degrees, writing the answer
281         into dst. It is legal for dst == this.
282     */
283     void rotateCCW(SkPoint* dst) const;
284
285     /** Rotate the point counter-clockwise by 90 degrees, writing the answer
286         back into the point.
287     */
288     void rotateCCW() { this->rotateCCW(this); }
289
290     /** Negate the point's coordinates
291     */
292     void negate() {
293         fX = -fX;
294         fY = -fY;
295     }
296
297     /** Returns a new point whose coordinates are the negative of the point's
298     */
299     SkPoint operator-() const {
300         SkPoint neg;
301         neg.fX = -fX;
302         neg.fY = -fY;
303         return neg;
304     }
305
306     /** Add v's coordinates to the point's
307     */
308     void operator+=(const SkPoint& v) {
309         fX += v.fX;
310         fY += v.fY;
311     }
312
313     /** Subtract v's coordinates from the point's
314     */
315     void operator-=(const SkPoint& v) {
316         fX -= v.fX;
317         fY -= v.fY;
318     }
319
320     /**
321      *  Returns true if both X and Y are finite (not infinity or NaN)
322      */
323     bool isFinite() const {
324         SkScalar accum = 0;
325         accum *= fX;
326         accum *= fY;
327
328         // accum is either NaN or it is finite (zero).
329         SkASSERT(0 == accum || !(accum == accum));
330
331         // value==value will be true iff value is not NaN
332         // TODO: is it faster to say !accum or accum==accum?
333         return accum == accum;
334     }
335
336     /**
337      *  Returns true if the point's coordinates equal (x,y)
338      */
339     bool equals(SkScalar x, SkScalar y) const {
340         return fX == x && fY == y;
341     }
342
343     friend bool operator==(const SkPoint& a, const SkPoint& b) {
344         return a.fX == b.fX && a.fY == b.fY;
345     }
346
347     friend bool operator!=(const SkPoint& a, const SkPoint& b) {
348         return a.fX != b.fX || a.fY != b.fY;
349     }
350
351     /** Return true if this point and the given point are far enough apart
352         such that a vector between them would be non-degenerate.
353
354         WARNING: Unlike the explicit tolerance version,
355         this method does not use componentwise comparison.  Instead, it
356         uses a comparison designed to match judgments elsewhere regarding
357         degeneracy ("points A and B are so close that the vector between them
358         is essentially zero").
359     */
360     bool equalsWithinTolerance(const SkPoint& p) const {
361         return !CanNormalize(fX - p.fX, fY - p.fY);
362     }
363
364     /** WARNING: There is no guarantee that the result will reflect judgments
365         elsewhere regarding degeneracy ("points A and B are so close that the
366         vector between them is essentially zero").
367     */
368     bool equalsWithinTolerance(const SkPoint& p, SkScalar tol) const {
369         return SkScalarNearlyZero(fX - p.fX, tol)
370                && SkScalarNearlyZero(fY - p.fY, tol);
371     }
372
373     /** Returns a new point whose coordinates are the difference between
374         a's and b's (a - b)
375     */
376     friend SkPoint operator-(const SkPoint& a, const SkPoint& b) {
377         SkPoint v;
378         v.set(a.fX - b.fX, a.fY - b.fY);
379         return v;
380     }
381
382     /** Returns a new point whose coordinates are the sum of a's and b's (a + b)
383     */
384     friend SkPoint operator+(const SkPoint& a, const SkPoint& b) {
385         SkPoint v;
386         v.set(a.fX + b.fX, a.fY + b.fY);
387         return v;
388     }
389
390     /** Returns the euclidian distance from (0,0) to (x,y)
391     */
392     static SkScalar Length(SkScalar x, SkScalar y);
393
394     /** Normalize pt, returning its previous length. If the prev length is too
395         small (degenerate), return 0 and leave pt unchanged. This uses the same
396         tolerance as CanNormalize.
397
398         Note that this method may be significantly more expensive than
399         the non-static normalize(), because it has to return the previous length
400         of the point.  If you don't need the previous length, call the
401         non-static normalize() method instead.
402      */
403     static SkScalar Normalize(SkPoint* pt);
404
405     /** Returns the euclidian distance between a and b
406     */
407     static SkScalar Distance(const SkPoint& a, const SkPoint& b) {
408         return Length(a.fX - b.fX, a.fY - b.fY);
409     }
410
411     /** Returns the dot product of a and b, treating them as 2D vectors
412     */
413     static SkScalar DotProduct(const SkPoint& a, const SkPoint& b) {
414         return a.fX * b.fX + a.fY * b.fY;
415     }
416
417     /** Returns the cross product of a and b, treating them as 2D vectors
418     */
419     static SkScalar CrossProduct(const SkPoint& a, const SkPoint& b) {
420         return a.fX * b.fY - a.fY * b.fX;
421     }
422
423     SkScalar cross(const SkPoint& vec) const {
424         return CrossProduct(*this, vec);
425     }
426
427     SkScalar dot(const SkPoint& vec) const {
428         return DotProduct(*this, vec);
429     }
430
431     SkScalar lengthSqd() const {
432         return DotProduct(*this, *this);
433     }
434
435     SkScalar distanceToSqd(const SkPoint& pt) const {
436         SkScalar dx = fX - pt.fX;
437         SkScalar dy = fY - pt.fY;
438         return dx * dx + dy * dy;
439     }
440
441     /**
442      * The side of a point relative to a line. If the line is from a to b then
443      * the values are consistent with the sign of (b-a) cross (pt-a)
444      */
445     enum Side {
446         kLeft_Side  = -1,
447         kOn_Side    =  0,
448         kRight_Side =  1
449     };
450
451     /**
452      * Returns the squared distance to the infinite line between two pts. Also
453      * optionally returns the side of the line that the pt falls on (looking
454      * along line from a to b)
455      */
456     SkScalar distanceToLineBetweenSqd(const SkPoint& a,
457                                       const SkPoint& b,
458                                       Side* side = NULL) const;
459
460     /**
461      * Returns the distance to the infinite line between two pts. Also
462      * optionally returns the side of the line that the pt falls on (looking
463      * along the line from a to b)
464      */
465     SkScalar distanceToLineBetween(const SkPoint& a,
466                                    const SkPoint& b,
467                                    Side* side = NULL) const {
468         return SkScalarSqrt(this->distanceToLineBetweenSqd(a, b, side));
469     }
470
471     /**
472      * Returns the squared distance to the line segment between pts a and b
473      */
474     SkScalar distanceToLineSegmentBetweenSqd(const SkPoint& a,
475                                              const SkPoint& b) const;
476
477     /**
478      * Returns the distance to the line segment between pts a and b.
479      */
480     SkScalar distanceToLineSegmentBetween(const SkPoint& a,
481                                           const SkPoint& b) const {
482         return SkScalarSqrt(this->distanceToLineSegmentBetweenSqd(a, b));
483     }
484
485     /**
486      * Make this vector be orthogonal to vec. Looking down vec the
487      * new vector will point in direction indicated by side (which
488      * must be kLeft_Side or kRight_Side).
489      */
490     void setOrthog(const SkPoint& vec, Side side = kLeft_Side) {
491         // vec could be this
492         SkScalar tmp = vec.fX;
493         if (kRight_Side == side) {
494             fX = -vec.fY;
495             fY = tmp;
496         } else {
497             SkASSERT(kLeft_Side == side);
498             fX = vec.fY;
499             fY = -tmp;
500         }
501     }
502
503     /**
504      *  cast-safe way to treat the point as an array of (2) SkScalars.
505      */
506     const SkScalar* asScalars() const { return &fX; }
507 };
508
509 typedef SkPoint SkVector;
510
511 #endif