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