• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "include/core/SkMath.h"
12 #include "include/core/SkScalar.h"
13 #include "include/private/SkSafe32.h"
14 
15 struct SkIPoint;
16 
17 /** SkIVector provides an alternative name for SkIPoint. SkIVector and SkIPoint
18     can be used interchangeably for all purposes.
19 */
20 typedef SkIPoint SkIVector;
21 
22 /** \struct SkIPoint
23     SkIPoint holds two 32-bit integer coordinates.
24 */
25 struct SkIPoint {
26     int32_t fX; //!< x-axis value
27     int32_t fY; //!< y-axis value
28 
29     /** Sets fX to x, fY to y.
30 
31         @param x  integer x-axis value of constructed SkIPoint
32         @param y  integer y-axis value of constructed SkIPoint
33         @return   SkIPoint (x, y)
34     */
MakeSkIPoint35     static constexpr SkIPoint Make(int32_t x, int32_t y) {
36         return {x, y};
37     }
38 
39     /** Returns x-axis value of SkIPoint.
40 
41         @return  fX
42     */
xSkIPoint43     int32_t x() const { return fX; }
44 
45     /** Returns y-axis value of SkIPoint.
46 
47         @return  fY
48     */
ySkIPoint49     int32_t y() const { return fY; }
50 
51     /** Returns true if fX and fY are both zero.
52 
53         @return  true if fX is zero and fY is zero
54     */
isZeroSkIPoint55     bool isZero() const { return (fX | fY) == 0; }
56 
57     /** Sets fX to x and fY to y.
58 
59         @param x  new value for fX
60         @param y  new value for fY
61     */
setSkIPoint62     void set(int32_t x, int32_t y) {
63         fX = x;
64         fY = y;
65     }
66 
67     /** Returns SkIPoint changing the signs of fX and fY.
68 
69         @return  SkIPoint as (-fX, -fY)
70     */
71     SkIPoint operator-() const {
72         return {-fX, -fY};
73     }
74 
75     /** Offsets SkIPoint by ivector v. Sets SkIPoint to (fX + v.fX, fY + v.fY).
76 
77         @param v  ivector to add
78     */
79     void operator+=(const SkIVector& v) {
80         fX = Sk32_sat_add(fX, v.fX);
81         fY = Sk32_sat_add(fY, v.fY);
82     }
83 
84     /** Subtracts ivector v from SkIPoint. Sets SkIPoint to: (fX - v.fX, fY - v.fY).
85 
86         @param v  ivector to subtract
87     */
88     void operator-=(const SkIVector& v) {
89         fX = Sk32_sat_sub(fX, v.fX);
90         fY = Sk32_sat_sub(fY, v.fY);
91     }
92 
93     /** Returns true if SkIPoint is equivalent to SkIPoint constructed from (x, y).
94 
95         @param x  value compared with fX
96         @param y  value compared with fY
97         @return   true if SkIPoint equals (x, y)
98     */
equalsSkIPoint99     bool equals(int32_t x, int32_t y) const {
100         return fX == x && fY == y;
101     }
102 
103     /** Returns true if a is equivalent to b.
104 
105         @param a  SkIPoint to compare
106         @param b  SkIPoint to compare
107         @return   true if a.fX == b.fX and a.fY == b.fY
108     */
109     friend bool operator==(const SkIPoint& a, const SkIPoint& b) {
110         return a.fX == b.fX && a.fY == b.fY;
111     }
112 
113     /** Returns true if a is not equivalent to b.
114 
115         @param a  SkIPoint to compare
116         @param b  SkIPoint to compare
117         @return   true if a.fX != b.fX or a.fY != b.fY
118     */
119     friend bool operator!=(const SkIPoint& a, const SkIPoint& b) {
120         return a.fX != b.fX || a.fY != b.fY;
121     }
122 
123     /** Returns ivector from b to a; computed as (a.fX - b.fX, a.fY - b.fY).
124 
125         Can also be used to subtract ivector from ivector, returning ivector.
126 
127         @param a  SkIPoint or ivector to subtract from
128         @param b  ivector to subtract
129         @return   ivector from b to a
130     */
131     friend SkIVector operator-(const SkIPoint& a, const SkIPoint& b) {
132         return { Sk32_sat_sub(a.fX, b.fX), Sk32_sat_sub(a.fY, b.fY) };
133     }
134 
135     /** Returns SkIPoint resulting from SkIPoint a offset by ivector b, computed as:
136         (a.fX + b.fX, a.fY + b.fY).
137 
138         Can also be used to offset SkIPoint b by ivector a, returning SkIPoint.
139         Can also be used to add ivector to ivector, returning ivector.
140 
141         @param a  SkIPoint or ivector to add to
142         @param b  SkIPoint or ivector to add
143         @return   SkIPoint equal to a offset by b
144     */
145     friend SkIPoint operator+(const SkIPoint& a, const SkIVector& b) {
146         return { Sk32_sat_add(a.fX, b.fX), Sk32_sat_add(a.fY, b.fY) };
147     }
148 };
149 
150 struct SkPoint;
151 
152 /** SkVector provides an alternative name for SkPoint. SkVector and SkPoint can
153     be used interchangeably for all purposes.
154 */
155 typedef SkPoint SkVector;
156 
157 /** \struct SkPoint
158     SkPoint holds two 32-bit floating point coordinates.
159 */
160 struct SK_API SkPoint {
161     SkScalar fX; //!< x-axis value
162     SkScalar fY; //!< y-axis value
163 
164     /** Sets fX to x, fY to y. Used both to set SkPoint and vector.
165 
166         @param x  SkScalar x-axis value of constructed SkPoint or vector
167         @param y  SkScalar y-axis value of constructed SkPoint or vector
168         @return   SkPoint (x, y)
169     */
MakeSkPoint170     static constexpr SkPoint Make(SkScalar x, SkScalar y) {
171         return {x, y};
172     }
173 
174     /** Returns x-axis value of SkPoint or vector.
175 
176         @return  fX
177     */
xSkPoint178     SkScalar x() const { return fX; }
179 
180     /** Returns y-axis value of SkPoint or vector.
181 
182         @return  fY
183     */
ySkPoint184     SkScalar y() const { return fY; }
185 
186     /** Returns true if fX and fY are both zero.
187 
188         @return  true if fX is zero and fY is zero
189     */
isZeroSkPoint190     bool isZero() const { return (0 == fX) & (0 == fY); }
191 
192     /** Sets fX to x and fY to y.
193 
194         @param x  new value for fX
195         @param y  new value for fY
196     */
setSkPoint197     void set(SkScalar x, SkScalar y) {
198         fX = x;
199         fY = y;
200     }
201 
202     /** Sets fX to x and fY to y, promoting integers to SkScalar values.
203 
204         Assigning a large integer value directly to fX or fY may cause a compiler
205         error, triggered by narrowing conversion of int to SkScalar. This safely
206         casts x and y to avoid the error.
207 
208         @param x  new value for fX
209         @param y  new value for fY
210     */
isetSkPoint211     void iset(int32_t x, int32_t y) {
212         fX = SkIntToScalar(x);
213         fY = SkIntToScalar(y);
214     }
215 
216     /** Sets fX to p.fX and fY to p.fY, promoting integers to SkScalar values.
217 
218         Assigning an SkIPoint containing a large integer value directly to fX or fY may
219         cause a compiler error, triggered by narrowing conversion of int to SkScalar.
220         This safely casts p.fX and p.fY to avoid the error.
221 
222         @param p  SkIPoint members promoted to SkScalar
223     */
isetSkPoint224     void iset(const SkIPoint& p) {
225         fX = SkIntToScalar(p.fX);
226         fY = SkIntToScalar(p.fY);
227     }
228 
229     /** Sets fX to absolute value of pt.fX; and fY to absolute value of pt.fY.
230 
231         @param pt  members providing magnitude for fX and fY
232     */
setAbsSkPoint233     void setAbs(const SkPoint& pt) {
234         fX = SkScalarAbs(pt.fX);
235         fY = SkScalarAbs(pt.fY);
236     }
237 
238     /** Adds offset to each SkPoint in points array with count entries.
239 
240         @param points  SkPoint array
241         @param count   entries in array
242         @param offset  vector added to points
243     */
OffsetSkPoint244     static void Offset(SkPoint points[], int count, const SkVector& offset) {
245         Offset(points, count, offset.fX, offset.fY);
246     }
247 
248     /** Adds offset (dx, dy) to each SkPoint in points array of length count.
249 
250         @param points  SkPoint array
251         @param count   entries in array
252         @param dx      added to fX in points
253         @param dy      added to fY in points
254     */
OffsetSkPoint255     static void Offset(SkPoint points[], int count, SkScalar dx, SkScalar dy) {
256         for (int i = 0; i < count; ++i) {
257             points[i].offset(dx, dy);
258         }
259     }
260 
261     /** Adds offset (dx, dy) to SkPoint.
262 
263         @param dx  added to fX
264         @param dy  added to fY
265     */
offsetSkPoint266     void offset(SkScalar dx, SkScalar dy) {
267         fX += dx;
268         fY += dy;
269     }
270 
271     /** Returns the Euclidean distance from origin, computed as:
272 
273             sqrt(fX * fX + fY * fY)
274 
275         .
276 
277         @return  straight-line distance to origin
278     */
lengthSkPoint279     SkScalar length() const { return SkPoint::Length(fX, fY); }
280 
281     /** Returns the Euclidean distance from origin, computed as:
282 
283             sqrt(fX * fX + fY * fY)
284 
285         .
286 
287         @return  straight-line distance to origin
288     */
distanceToOriginSkPoint289     SkScalar distanceToOrigin() const { return this->length(); }
290 
291     /** Scales (fX, fY) so that length() returns one, while preserving ratio of fX to fY,
292         if possible. If prior length is nearly zero, sets vector to (0, 0) and returns
293         false; otherwise returns true.
294 
295         @return  true if former length is not zero or nearly zero
296     */
297     bool normalize();
298 
299     /** Sets vector to (x, y) scaled so length() returns one, and so that
300         (fX, fY) is proportional to (x, y).  If (x, y) length is nearly zero,
301         sets vector to (0, 0) and returns false; otherwise returns true.
302 
303         @param x  proportional value for fX
304         @param y  proportional value for fY
305         @return   true if (x, y) length is not zero or nearly zero
306     */
307     bool setNormalize(SkScalar x, SkScalar y);
308 
309     /** Scales vector so that distanceToOrigin() returns length, if possible. If former
310         length is nearly zero, sets vector to (0, 0) and return false; otherwise returns
311         true.
312 
313         @param length  straight-line distance to origin
314         @return        true if former length is not zero or nearly zero
315     */
316     bool setLength(SkScalar length);
317 
318     /** Sets vector to (x, y) scaled to length, if possible. If former
319         length is nearly zero, sets vector to (0, 0) and return false; otherwise returns
320         true.
321 
322         @param x       proportional value for fX
323         @param y       proportional value for fY
324         @param length  straight-line distance to origin
325         @return        true if (x, y) length is not zero or nearly zero
326     */
327     bool setLength(SkScalar x, SkScalar y, SkScalar length);
328 
329     /** Sets dst to SkPoint times scale. dst may be SkPoint to modify SkPoint in place.
330 
331         @param scale  factor to multiply SkPoint by
332         @param dst    storage for scaled SkPoint
333     */
334     void scale(SkScalar scale, SkPoint* dst) const;
335 
336     /** Scales SkPoint in place by scale.
337 
338         @param value  factor to multiply SkPoint by
339     */
scaleSkPoint340     void scale(SkScalar value) { this->scale(value, this); }
341 
342     /** Changes the sign of fX and fY.
343     */
negateSkPoint344     void negate() {
345         fX = -fX;
346         fY = -fY;
347     }
348 
349     /** Returns SkPoint changing the signs of fX and fY.
350 
351         @return  SkPoint as (-fX, -fY)
352     */
353     SkPoint operator-() const {
354         return {-fX, -fY};
355     }
356 
357     /** Adds vector v to SkPoint. Sets SkPoint to: (fX + v.fX, fY + v.fY).
358 
359         @param v  vector to add
360     */
361     void operator+=(const SkVector& v) {
362         fX += v.fX;
363         fY += v.fY;
364     }
365 
366     /** Subtracts vector v from SkPoint. Sets SkPoint to: (fX - v.fX, fY - v.fY).
367 
368         @param v  vector to subtract
369     */
370     void operator-=(const SkVector& v) {
371         fX -= v.fX;
372         fY -= v.fY;
373     }
374 
375     /** Returns SkPoint multiplied by scale.
376 
377         @param scale  scalar to multiply by
378         @return       SkPoint as (fX * scale, fY * scale)
379     */
380     SkPoint operator*(SkScalar scale) const {
381         return {fX * scale, fY * scale};
382     }
383 
384     /** Multiplies SkPoint by scale. Sets SkPoint to: (fX * scale, fY * scale).
385 
386         @param scale  scalar to multiply by
387         @return       reference to SkPoint
388     */
389     SkPoint& operator*=(SkScalar scale) {
390         fX *= scale;
391         fY *= scale;
392         return *this;
393     }
394 
395     /** Returns true if both fX and fY are measurable values.
396 
397         @return  true for values other than infinities and NaN
398     */
isFiniteSkPoint399     bool isFinite() const {
400         SkScalar accum = 0;
401         accum *= fX;
402         accum *= fY;
403 
404         // accum is either NaN or it is finite (zero).
405         SkASSERT(0 == accum || SkScalarIsNaN(accum));
406 
407         // value==value will be true iff value is not NaN
408         // TODO: is it faster to say !accum or accum==accum?
409         return !SkScalarIsNaN(accum);
410     }
411 
412     /** Returns true if SkPoint is equivalent to SkPoint constructed from (x, y).
413 
414         @param x  value compared with fX
415         @param y  value compared with fY
416         @return   true if SkPoint equals (x, y)
417     */
equalsSkPoint418     bool equals(SkScalar x, SkScalar y) const {
419         return fX == x && fY == y;
420     }
421 
422     /** Returns true if a is equivalent to b.
423 
424         @param a  SkPoint to compare
425         @param b  SkPoint to compare
426         @return   true if a.fX == b.fX and a.fY == b.fY
427     */
428     friend bool operator==(const SkPoint& a, const SkPoint& b) {
429         return a.fX == b.fX && a.fY == b.fY;
430     }
431 
432     /** Returns true if a is not equivalent to b.
433 
434         @param a  SkPoint to compare
435         @param b  SkPoint to compare
436         @return   true if a.fX != b.fX or a.fY != b.fY
437     */
438     friend bool operator!=(const SkPoint& a, const SkPoint& b) {
439         return a.fX != b.fX || a.fY != b.fY;
440     }
441 
442     /** Returns vector from b to a, computed as (a.fX - b.fX, a.fY - b.fY).
443 
444         Can also be used to subtract vector from SkPoint, returning SkPoint.
445         Can also be used to subtract vector from vector, returning vector.
446 
447         @param a  SkPoint to subtract from
448         @param b  SkPoint to subtract
449         @return   vector from b to a
450     */
451     friend SkVector operator-(const SkPoint& a, const SkPoint& b) {
452         return {a.fX - b.fX, a.fY - b.fY};
453     }
454 
455     /** Returns SkPoint resulting from SkPoint a offset by vector b, computed as:
456         (a.fX + b.fX, a.fY + b.fY).
457 
458         Can also be used to offset SkPoint b by vector a, returning SkPoint.
459         Can also be used to add vector to vector, returning vector.
460 
461         @param a  SkPoint or vector to add to
462         @param b  SkPoint or vector to add
463         @return   SkPoint equal to a offset by b
464     */
465     friend SkPoint operator+(const SkPoint& a, const SkVector& b) {
466         return {a.fX + b.fX, a.fY + b.fY};
467     }
468 
469     /** Returns the Euclidean distance from origin, computed as:
470 
471             sqrt(x * x + y * y)
472 
473         .
474 
475         @param x  component of length
476         @param y  component of length
477         @return   straight-line distance to origin
478     */
479     static SkScalar Length(SkScalar x, SkScalar y);
480 
481     /** Scales (vec->fX, vec->fY) so that length() returns one, while preserving ratio of vec->fX
482         to vec->fY, if possible. If original length is nearly zero, sets vec to (0, 0) and returns
483         zero; otherwise, returns length of vec before vec is scaled.
484 
485         Returned prior length may be SK_ScalarInfinity if it can not be represented by SkScalar.
486 
487         Note that normalize() is faster if prior length is not required.
488 
489         @param vec  normalized to unit length
490         @return     original vec length
491     */
492     static SkScalar Normalize(SkVector* vec);
493 
494     /** Returns the Euclidean distance between a and b.
495 
496         @param a  line end point
497         @param b  line end point
498         @return   straight-line distance from a to b
499     */
DistanceSkPoint500     static SkScalar Distance(const SkPoint& a, const SkPoint& b) {
501         return Length(a.fX - b.fX, a.fY - b.fY);
502     }
503 
504     /** Returns the dot product of vector a and vector b.
505 
506         @param a  left side of dot product
507         @param b  right side of dot product
508         @return   product of input magnitudes and cosine of the angle between them
509     */
DotProductSkPoint510     static SkScalar DotProduct(const SkVector& a, const SkVector& b) {
511         return a.fX * b.fX + a.fY * b.fY;
512     }
513 
514     /** Returns the cross product of vector a and vector b.
515 
516         a and b form three-dimensional vectors with z-axis value equal to zero. The
517         cross product is a three-dimensional vector with x-axis and y-axis values equal
518         to zero. The cross product z-axis component is returned.
519 
520         @param a  left side of cross product
521         @param b  right side of cross product
522         @return   area spanned by vectors signed by angle direction
523     */
CrossProductSkPoint524     static SkScalar CrossProduct(const SkVector& a, const SkVector& b) {
525         return a.fX * b.fY - a.fY * b.fX;
526     }
527 
528     /** Returns the cross product of vector and vec.
529 
530         Vector and vec form three-dimensional vectors with z-axis value equal to zero.
531         The cross product is a three-dimensional vector with x-axis and y-axis values
532         equal to zero. The cross product z-axis component is returned.
533 
534         @param vec  right side of cross product
535         @return     area spanned by vectors signed by angle direction
536     */
crossSkPoint537     SkScalar cross(const SkVector& vec) const {
538         return CrossProduct(*this, vec);
539     }
540 
541     /** Returns the dot product of vector and vector vec.
542 
543         @param vec  right side of dot product
544         @return     product of input magnitudes and cosine of the angle between them
545     */
dotSkPoint546     SkScalar dot(const SkVector& vec) const {
547         return DotProduct(*this, vec);
548     }
549 
550 };
551 
552 #endif
553