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