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