• 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 #include <string>
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     /** Writes text representation of SkPoint to string.
167 
168         @param desc     the string storing a description of parameters.
169         @param depth    the number of tabs preceding each line.
170     */
171     void dump(std::string& desc, int depth) const;
172 
173     /** Sets fX to x, fY to y. Used both to set SkPoint and vector.
174 
175         @param x  SkScalar x-axis value of constructed SkPoint or vector
176         @param y  SkScalar y-axis value of constructed SkPoint or vector
177         @return   SkPoint (x, y)
178     */
MakeSkPoint179     static constexpr SkPoint Make(SkScalar x, SkScalar y) {
180         return {x, y};
181     }
182 
183     /** Returns x-axis value of SkPoint or vector.
184 
185         @return  fX
186     */
xSkPoint187     constexpr SkScalar x() const { return fX; }
188 
189     /** Returns y-axis value of SkPoint or vector.
190 
191         @return  fY
192     */
ySkPoint193     constexpr SkScalar y() const { return fY; }
194 
195     /** Returns true if fX and fY are both zero.
196 
197         @return  true if fX is zero and fY is zero
198     */
isZeroSkPoint199     bool isZero() const { return (0 == fX) & (0 == fY); }
200 
201     /** Sets fX to x and fY to y.
202 
203         @param x  new value for fX
204         @param y  new value for fY
205     */
setSkPoint206     void set(SkScalar x, SkScalar y) {
207         fX = x;
208         fY = y;
209     }
210 
211     /** Sets fX to x and fY to y, promoting integers to SkScalar values.
212 
213         Assigning a large integer value directly to fX or fY may cause a compiler
214         error, triggered by narrowing conversion of int to SkScalar. This safely
215         casts x and y to avoid the error.
216 
217         @param x  new value for fX
218         @param y  new value for fY
219     */
isetSkPoint220     void iset(int32_t x, int32_t y) {
221         fX = SkIntToScalar(x);
222         fY = SkIntToScalar(y);
223     }
224 
225     /** Sets fX to p.fX and fY to p.fY, promoting integers to SkScalar values.
226 
227         Assigning an SkIPoint containing a large integer value directly to fX or fY may
228         cause a compiler error, triggered by narrowing conversion of int to SkScalar.
229         This safely casts p.fX and p.fY to avoid the error.
230 
231         @param p  SkIPoint members promoted to SkScalar
232     */
isetSkPoint233     void iset(const SkIPoint& p) {
234         fX = SkIntToScalar(p.fX);
235         fY = SkIntToScalar(p.fY);
236     }
237 
238     /** Sets fX to absolute value of pt.fX; and fY to absolute value of pt.fY.
239 
240         @param pt  members providing magnitude for fX and fY
241     */
setAbsSkPoint242     void setAbs(const SkPoint& pt) {
243         fX = SkScalarAbs(pt.fX);
244         fY = SkScalarAbs(pt.fY);
245     }
246 
247     /** Adds offset to each SkPoint in points array with count entries.
248 
249         @param points  SkPoint array
250         @param count   entries in array
251         @param offset  vector added to points
252     */
OffsetSkPoint253     static void Offset(SkPoint points[], int count, const SkVector& offset) {
254         Offset(points, count, offset.fX, offset.fY);
255     }
256 
257     /** Adds offset (dx, dy) to each SkPoint in points array of length count.
258 
259         @param points  SkPoint array
260         @param count   entries in array
261         @param dx      added to fX in points
262         @param dy      added to fY in points
263     */
OffsetSkPoint264     static void Offset(SkPoint points[], int count, SkScalar dx, SkScalar dy) {
265         for (int i = 0; i < count; ++i) {
266             points[i].offset(dx, dy);
267         }
268     }
269 
270     /** Adds offset (dx, dy) to SkPoint.
271 
272         @param dx  added to fX
273         @param dy  added to fY
274     */
offsetSkPoint275     void offset(SkScalar dx, SkScalar dy) {
276         fX += dx;
277         fY += dy;
278     }
279 
280     /** Returns the Euclidean distance from origin, computed as:
281 
282             sqrt(fX * fX + fY * fY)
283 
284         .
285 
286         @return  straight-line distance to origin
287     */
lengthSkPoint288     SkScalar length() const { return SkPoint::Length(fX, fY); }
289 
290     /** Returns the Euclidean distance from origin, computed as:
291 
292             sqrt(fX * fX + fY * fY)
293 
294         .
295 
296         @return  straight-line distance to origin
297     */
distanceToOriginSkPoint298     SkScalar distanceToOrigin() const { return this->length(); }
299 
300     /** Scales (fX, fY) so that length() returns one, while preserving ratio of fX to fY,
301         if possible. If prior length is nearly zero, sets vector to (0, 0) and returns
302         false; otherwise returns true.
303 
304         @return  true if former length is not zero or nearly zero
305 
306         example: https://fiddle.skia.org/c/@Point_normalize_2
307     */
308     bool normalize();
309 
310     /** Sets vector to (x, y) scaled so length() returns one, and so that
311         (fX, fY) is proportional to (x, y).  If (x, y) length is nearly zero,
312         sets vector to (0, 0) and returns false; otherwise returns true.
313 
314         @param x  proportional value for fX
315         @param y  proportional value for fY
316         @return   true if (x, y) length is not zero or nearly zero
317 
318         example: https://fiddle.skia.org/c/@Point_setNormalize
319     */
320     bool setNormalize(SkScalar x, SkScalar y);
321 
322     /** Scales vector so that distanceToOrigin() returns length, if possible. If former
323         length is nearly zero, sets vector to (0, 0) and return false; otherwise returns
324         true.
325 
326         @param length  straight-line distance to origin
327         @return        true if former length is not zero or nearly zero
328 
329         example: https://fiddle.skia.org/c/@Point_setLength
330     */
331     bool setLength(SkScalar length);
332 
333     /** Sets vector to (x, y) scaled to length, if possible. If former
334         length is nearly zero, sets vector to (0, 0) and return false; otherwise returns
335         true.
336 
337         @param x       proportional value for fX
338         @param y       proportional value for fY
339         @param length  straight-line distance to origin
340         @return        true if (x, y) length is not zero or nearly zero
341 
342         example: https://fiddle.skia.org/c/@Point_setLength_2
343     */
344     bool setLength(SkScalar x, SkScalar y, SkScalar length);
345 
346     /** Sets dst to SkPoint times scale. dst may be SkPoint to modify SkPoint in place.
347 
348         @param scale  factor to multiply SkPoint by
349         @param dst    storage for scaled SkPoint
350 
351         example: https://fiddle.skia.org/c/@Point_scale
352     */
353     void scale(SkScalar scale, SkPoint* dst) const;
354 
355     /** Scales SkPoint in place by scale.
356 
357         @param value  factor to multiply SkPoint by
358     */
scaleSkPoint359     void scale(SkScalar value) { this->scale(value, this); }
360 
361     /** Changes the sign of fX and fY.
362     */
negateSkPoint363     void negate() {
364         fX = -fX;
365         fY = -fY;
366     }
367 
368     /** Returns SkPoint changing the signs of fX and fY.
369 
370         @return  SkPoint as (-fX, -fY)
371     */
372     SkPoint operator-() const {
373         return {-fX, -fY};
374     }
375 
376     /** Adds vector v to SkPoint. Sets SkPoint to: (fX + v.fX, fY + v.fY).
377 
378         @param v  vector to add
379     */
380     void operator+=(const SkVector& v) {
381         fX += v.fX;
382         fY += v.fY;
383     }
384 
385     /** Subtracts vector v from SkPoint. Sets SkPoint to: (fX - v.fX, fY - v.fY).
386 
387         @param v  vector to subtract
388     */
389     void operator-=(const SkVector& v) {
390         fX -= v.fX;
391         fY -= v.fY;
392     }
393 
394     /** Returns SkPoint multiplied by scale.
395 
396         @param scale  scalar to multiply by
397         @return       SkPoint as (fX * scale, fY * scale)
398     */
399     SkPoint operator*(SkScalar scale) const {
400         return {fX * scale, fY * scale};
401     }
402 
403     /** Multiplies SkPoint by scale. Sets SkPoint to: (fX * scale, fY * scale).
404 
405         @param scale  scalar to multiply by
406         @return       reference to SkPoint
407     */
408     SkPoint& operator*=(SkScalar scale) {
409         fX *= scale;
410         fY *= scale;
411         return *this;
412     }
413 
414     /** Returns true if both fX and fY are measurable values.
415 
416         @return  true for values other than infinities and NaN
417     */
isFiniteSkPoint418     bool isFinite() const {
419         SkScalar accum = 0;
420         accum *= fX;
421         accum *= fY;
422 
423         // accum is either NaN or it is finite (zero).
424         SkASSERT(0 == accum || SkScalarIsNaN(accum));
425 
426         // value==value will be true iff value is not NaN
427         // TODO: is it faster to say !accum or accum==accum?
428         return !SkScalarIsNaN(accum);
429     }
430 
431     /** Returns true if SkPoint is equivalent to SkPoint constructed from (x, y).
432 
433         @param x  value compared with fX
434         @param y  value compared with fY
435         @return   true if SkPoint equals (x, y)
436     */
equalsSkPoint437     bool equals(SkScalar x, SkScalar y) const {
438         return fX == x && fY == y;
439     }
440 
441     /** Returns true if a is equivalent to b.
442 
443         @param a  SkPoint to compare
444         @param b  SkPoint to compare
445         @return   true if a.fX == b.fX and a.fY == b.fY
446     */
447     friend bool operator==(const SkPoint& a, const SkPoint& b) {
448         return a.fX == b.fX && a.fY == b.fY;
449     }
450 
451     /** Returns true if a is not equivalent to b.
452 
453         @param a  SkPoint to compare
454         @param b  SkPoint to compare
455         @return   true if a.fX != b.fX or a.fY != b.fY
456     */
457     friend bool operator!=(const SkPoint& a, const SkPoint& b) {
458         return a.fX != b.fX || a.fY != b.fY;
459     }
460 
461     /** Returns vector from b to a, computed as (a.fX - b.fX, a.fY - b.fY).
462 
463         Can also be used to subtract vector from SkPoint, returning SkPoint.
464         Can also be used to subtract vector from vector, returning vector.
465 
466         @param a  SkPoint to subtract from
467         @param b  SkPoint to subtract
468         @return   vector from b to a
469     */
470     friend SkVector operator-(const SkPoint& a, const SkPoint& b) {
471         return {a.fX - b.fX, a.fY - b.fY};
472     }
473 
474     /** Returns SkPoint resulting from SkPoint a offset by vector b, computed as:
475         (a.fX + b.fX, a.fY + b.fY).
476 
477         Can also be used to offset SkPoint b by vector a, returning SkPoint.
478         Can also be used to add vector to vector, returning vector.
479 
480         @param a  SkPoint or vector to add to
481         @param b  SkPoint or vector to add
482         @return   SkPoint equal to a offset by b
483     */
484     friend SkPoint operator+(const SkPoint& a, const SkVector& b) {
485         return {a.fX + b.fX, a.fY + b.fY};
486     }
487 
488     /** Returns the Euclidean distance from origin, computed as:
489 
490             sqrt(x * x + y * y)
491 
492         .
493 
494         @param x  component of length
495         @param y  component of length
496         @return   straight-line distance to origin
497 
498         example: https://fiddle.skia.org/c/@Point_Length
499     */
500     static SkScalar Length(SkScalar x, SkScalar y);
501 
502     /** Scales (vec->fX, vec->fY) so that length() returns one, while preserving ratio of vec->fX
503         to vec->fY, if possible. If original length is nearly zero, sets vec to (0, 0) and returns
504         zero; otherwise, returns length of vec before vec is scaled.
505 
506         Returned prior length may be SK_ScalarInfinity if it can not be represented by SkScalar.
507 
508         Note that normalize() is faster if prior length is not required.
509 
510         @param vec  normalized to unit length
511         @return     original vec length
512 
513         example: https://fiddle.skia.org/c/@Point_Normalize
514     */
515     static SkScalar Normalize(SkVector* vec);
516 
517     /** Returns the Euclidean distance between a and b.
518 
519         @param a  line end point
520         @param b  line end point
521         @return   straight-line distance from a to b
522     */
DistanceSkPoint523     static SkScalar Distance(const SkPoint& a, const SkPoint& b) {
524         return Length(a.fX - b.fX, a.fY - b.fY);
525     }
526 
527     /** Returns the dot product of vector a and vector b.
528 
529         @param a  left side of dot product
530         @param b  right side of dot product
531         @return   product of input magnitudes and cosine of the angle between them
532     */
DotProductSkPoint533     static SkScalar DotProduct(const SkVector& a, const SkVector& b) {
534         return a.fX * b.fX + a.fY * b.fY;
535     }
536 
537     /** Returns the cross product of vector a and vector b.
538 
539         a and b form three-dimensional vectors with z-axis value equal to zero. The
540         cross product is a three-dimensional vector with x-axis and y-axis values equal
541         to zero. The cross product z-axis component is returned.
542 
543         @param a  left side of cross product
544         @param b  right side of cross product
545         @return   area spanned by vectors signed by angle direction
546     */
CrossProductSkPoint547     static SkScalar CrossProduct(const SkVector& a, const SkVector& b) {
548         return a.fX * b.fY - a.fY * b.fX;
549     }
550 
551     /** Returns the cross product of vector and vec.
552 
553         Vector and vec form three-dimensional vectors with z-axis value equal to zero.
554         The cross product is a three-dimensional vector with x-axis and y-axis values
555         equal to zero. The cross product z-axis component is returned.
556 
557         @param vec  right side of cross product
558         @return     area spanned by vectors signed by angle direction
559     */
crossSkPoint560     SkScalar cross(const SkVector& vec) const {
561         return CrossProduct(*this, vec);
562     }
563 
564     /** Returns the dot product of vector and vector vec.
565 
566         @param vec  right side of dot product
567         @return     product of input magnitudes and cosine of the angle between them
568     */
dotSkPoint569     SkScalar dot(const SkVector& vec) const {
570         return DotProduct(*this, vec);
571     }
572 
573 };
574 
575 #endif
576