• 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     constexpr int32_t x() const { return fX; }
44 
45     /** Returns y-axis value of SkIPoint.
46 
47         @return  fY
48     */
ySkIPoint49     constexpr 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     constexpr SkScalar x() const { return fX; }
179 
180     /** Returns y-axis value of SkPoint or vector.
181 
182         @return  fY
183     */
ySkPoint184     constexpr 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         example: https://fiddle.skia.org/c/@Point_normalize_2
298     */
299     bool normalize();
300 
301     /** Sets vector to (x, y) scaled so length() returns one, and so that
302         (fX, fY) is proportional to (x, y).  If (x, y) length is nearly zero,
303         sets vector to (0, 0) and returns false; otherwise returns true.
304 
305         @param x  proportional value for fX
306         @param y  proportional value for fY
307         @return   true if (x, y) length is not zero or nearly zero
308 
309         example: https://fiddle.skia.org/c/@Point_setNormalize
310     */
311     bool setNormalize(SkScalar x, SkScalar y);
312 
313     /** Scales vector so that distanceToOrigin() returns length, if possible. If former
314         length is nearly zero, sets vector to (0, 0) and return false; otherwise returns
315         true.
316 
317         @param length  straight-line distance to origin
318         @return        true if former length is not zero or nearly zero
319 
320         example: https://fiddle.skia.org/c/@Point_setLength
321     */
322     bool setLength(SkScalar length);
323 
324     /** Sets vector to (x, y) scaled to length, if possible. If former
325         length is nearly zero, sets vector to (0, 0) and return false; otherwise returns
326         true.
327 
328         @param x       proportional value for fX
329         @param y       proportional value for fY
330         @param length  straight-line distance to origin
331         @return        true if (x, y) length is not zero or nearly zero
332 
333         example: https://fiddle.skia.org/c/@Point_setLength_2
334     */
335     bool setLength(SkScalar x, SkScalar y, SkScalar length);
336 
337     /** Sets dst to SkPoint times scale. dst may be SkPoint to modify SkPoint in place.
338 
339         @param scale  factor to multiply SkPoint by
340         @param dst    storage for scaled SkPoint
341 
342         example: https://fiddle.skia.org/c/@Point_scale
343     */
344     void scale(SkScalar scale, SkPoint* dst) const;
345 
346     /** Scales SkPoint in place by scale.
347 
348         @param value  factor to multiply SkPoint by
349     */
scaleSkPoint350     void scale(SkScalar value) { this->scale(value, this); }
351 
352     /** Changes the sign of fX and fY.
353     */
negateSkPoint354     void negate() {
355         fX = -fX;
356         fY = -fY;
357     }
358 
359     /** Returns SkPoint changing the signs of fX and fY.
360 
361         @return  SkPoint as (-fX, -fY)
362     */
363     SkPoint operator-() const {
364         return {-fX, -fY};
365     }
366 
367     /** Adds vector v to SkPoint. Sets SkPoint to: (fX + v.fX, fY + v.fY).
368 
369         @param v  vector to add
370     */
371     void operator+=(const SkVector& v) {
372         fX += v.fX;
373         fY += v.fY;
374     }
375 
376     /** Subtracts vector v from SkPoint. Sets SkPoint to: (fX - v.fX, fY - v.fY).
377 
378         @param v  vector to subtract
379     */
380     void operator-=(const SkVector& v) {
381         fX -= v.fX;
382         fY -= v.fY;
383     }
384 
385     /** Returns SkPoint multiplied by scale.
386 
387         @param scale  scalar to multiply by
388         @return       SkPoint as (fX * scale, fY * scale)
389     */
390     SkPoint operator*(SkScalar scale) const {
391         return {fX * scale, fY * scale};
392     }
393 
394     /** Multiplies SkPoint by scale. Sets SkPoint to: (fX * scale, fY * scale).
395 
396         @param scale  scalar to multiply by
397         @return       reference to SkPoint
398     */
399     SkPoint& operator*=(SkScalar scale) {
400         fX *= scale;
401         fY *= scale;
402         return *this;
403     }
404 
405     /** Returns true if both fX and fY are measurable values.
406 
407         @return  true for values other than infinities and NaN
408     */
isFiniteSkPoint409     bool isFinite() const {
410         SkScalar accum = 0;
411         accum *= fX;
412         accum *= fY;
413 
414         // accum is either NaN or it is finite (zero).
415         SkASSERT(0 == accum || SkScalarIsNaN(accum));
416 
417         // value==value will be true iff value is not NaN
418         // TODO: is it faster to say !accum or accum==accum?
419         return !SkScalarIsNaN(accum);
420     }
421 
422     /** Returns true if SkPoint is equivalent to SkPoint constructed from (x, y).
423 
424         @param x  value compared with fX
425         @param y  value compared with fY
426         @return   true if SkPoint equals (x, y)
427     */
equalsSkPoint428     bool equals(SkScalar x, SkScalar y) const {
429         return fX == x && fY == y;
430     }
431 
432     /** Returns true if a is equivalent to b.
433 
434         @param a  SkPoint to compare
435         @param b  SkPoint to compare
436         @return   true if a.fX == b.fX and 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 true if a is not equivalent to b.
443 
444         @param a  SkPoint to compare
445         @param b  SkPoint to compare
446         @return   true if a.fX != b.fX or a.fY != b.fY
447     */
448     friend bool operator!=(const SkPoint& a, const SkPoint& b) {
449         return a.fX != b.fX || a.fY != b.fY;
450     }
451 
452     /** Returns vector from b to a, computed as (a.fX - b.fX, a.fY - b.fY).
453 
454         Can also be used to subtract vector from SkPoint, returning SkPoint.
455         Can also be used to subtract vector from vector, returning vector.
456 
457         @param a  SkPoint to subtract from
458         @param b  SkPoint to subtract
459         @return   vector from b to a
460     */
461     friend SkVector operator-(const SkPoint& a, const SkPoint& b) {
462         return {a.fX - b.fX, a.fY - b.fY};
463     }
464 
465     /** Returns SkPoint resulting from SkPoint a offset by vector b, computed as:
466         (a.fX + b.fX, a.fY + b.fY).
467 
468         Can also be used to offset SkPoint b by vector a, returning SkPoint.
469         Can also be used to add vector to vector, returning vector.
470 
471         @param a  SkPoint or vector to add to
472         @param b  SkPoint or vector to add
473         @return   SkPoint equal to a offset by b
474     */
475     friend SkPoint operator+(const SkPoint& a, const SkVector& b) {
476         return {a.fX + b.fX, a.fY + b.fY};
477     }
478 
479     /** Returns the Euclidean distance from origin, computed as:
480 
481             sqrt(x * x + y * y)
482 
483         .
484 
485         @param x  component of length
486         @param y  component of length
487         @return   straight-line distance to origin
488 
489         example: https://fiddle.skia.org/c/@Point_Length
490     */
491     static SkScalar Length(SkScalar x, SkScalar y);
492 
493     /** Scales (vec->fX, vec->fY) so that length() returns one, while preserving ratio of vec->fX
494         to vec->fY, if possible. If original length is nearly zero, sets vec to (0, 0) and returns
495         zero; otherwise, returns length of vec before vec is scaled.
496 
497         Returned prior length may be SK_ScalarInfinity if it can not be represented by SkScalar.
498 
499         Note that normalize() is faster if prior length is not required.
500 
501         @param vec  normalized to unit length
502         @return     original vec length
503 
504         example: https://fiddle.skia.org/c/@Point_Normalize
505     */
506     static SkScalar Normalize(SkVector* vec);
507 
508     /** Returns the Euclidean distance between a and b.
509 
510         @param a  line end point
511         @param b  line end point
512         @return   straight-line distance from a to b
513     */
DistanceSkPoint514     static SkScalar Distance(const SkPoint& a, const SkPoint& b) {
515         return Length(a.fX - b.fX, a.fY - b.fY);
516     }
517 
518     /** Returns the dot product of vector a and vector b.
519 
520         @param a  left side of dot product
521         @param b  right side of dot product
522         @return   product of input magnitudes and cosine of the angle between them
523     */
DotProductSkPoint524     static SkScalar DotProduct(const SkVector& a, const SkVector& b) {
525         return a.fX * b.fX + a.fY * b.fY;
526     }
527 
528     /** Returns the cross product of vector a and vector b.
529 
530         a and b form three-dimensional vectors with z-axis value equal to zero. The
531         cross product is a three-dimensional vector with x-axis and y-axis values equal
532         to zero. The cross product z-axis component is returned.
533 
534         @param a  left side of cross product
535         @param b  right side of cross product
536         @return   area spanned by vectors signed by angle direction
537     */
CrossProductSkPoint538     static SkScalar CrossProduct(const SkVector& a, const SkVector& b) {
539         return a.fX * b.fY - a.fY * b.fX;
540     }
541 
542     /** Returns the cross product of vector and vec.
543 
544         Vector and vec form three-dimensional vectors with z-axis value equal to zero.
545         The cross product is a three-dimensional vector with x-axis and y-axis values
546         equal to zero. The cross product z-axis component is returned.
547 
548         @param vec  right side of cross product
549         @return     area spanned by vectors signed by angle direction
550     */
crossSkPoint551     SkScalar cross(const SkVector& vec) const {
552         return CrossProduct(*this, vec);
553     }
554 
555     /** Returns the dot product of vector and vector vec.
556 
557         @param vec  right side of dot product
558         @return     product of input magnitudes and cosine of the angle between them
559     */
dotSkPoint560     SkScalar dot(const SkVector& vec) const {
561         return DotProduct(*this, vec);
562     }
563 
564 };
565 
566 #endif
567