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/SkAssert.h"
13#include "include/private/base/SkSafe32.h"
14
15#include <cmath>
16#include <cstdint>
17
18struct SkIPoint;
19
20/** SkIVector provides an alternative name for SkIPoint. SkIVector and SkIPoint
21 can be used interchangeably for all purposes.
22*/
23typedef SkIPoint SkIVector;
24
25/** \struct SkIPoint
26 SkIPoint holds two 32-bit integer coordinates.
27*/
28struct 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 */
38 static constexpr SkIPoint Make(int32_t x, int32_t y) {
39 return {.fX: x, .fY: y};
40 }
41
42 /** Returns x-axis value of SkIPoint.
43
44 @return fX
45 */
46 constexpr int32_t x() const { return fX; }
47
48 /** Returns y-axis value of SkIPoint.
49
50 @return fY
51 */
52 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 */
58 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 */
65 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: -fX, .fY: -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(a: fX, b: v.fX);
84 fY = Sk32_sat_add(a: fY, b: 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(a: fX, b: v.fX);
93 fY = Sk32_sat_sub(a: fY, b: 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 */
102 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 { .fX: Sk32_sat_sub(a: a.fX, b: b.fX), .fY: Sk32_sat_sub(a: a.fY, b: 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 { .fX: Sk32_sat_add(a: a.fX, b: b.fX), .fY: Sk32_sat_add(a: a.fY, b: b.fY) };
150 }
151};
152
153struct SkPoint;
154
155/** SkVector provides an alternative name for SkPoint. SkVector and SkPoint can
156 be used interchangeably for all purposes.
157*/
158typedef SkPoint SkVector;
159
160/** \struct SkPoint
161 SkPoint holds two 32-bit floating point coordinates.
162*/
163struct 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 */
173 static constexpr SkPoint Make(float x, float y) {
174 return {.fX: x, .fY: y};
175 }
176
177 /** Returns x-axis value of SkPoint or vector.
178
179 @return fX
180 */
181 constexpr float x() const { return fX; }
182
183 /** Returns y-axis value of SkPoint or vector.
184
185 @return fY
186 */
187 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 */
193 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 */
200 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 */
214 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 */
227 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 */
236 void setAbs(const SkPoint& pt) {
237 fX = std::abs(lcpp_x: pt.fX);
238 fY = std::abs(lcpp_x: 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 */
247 static void Offset(SkPoint points[], int count, const SkVector& offset) {
248 Offset(points, count, dx: offset.fX, dy: 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 */
258 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 */
269 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 */
282 float length() const { return SkPoint::Length(x: fX, y: 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 */
292 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 */
353 void scale(float value) { this->scale(scale: value, dst: this); }
354
355 /** Changes the sign of fX and fY.
356 */
357 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: -fX, .fY: -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: fX * scale, .fY: 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 */
412 bool isFinite() const {
413 float accum = 0;
414 accum *= fX;
415 accum *= fY;
416
417 // accum is either NaN or it is finite (zero).
418 SkASSERT(0 == accum || std::isnan(accum));
419
420 // value==value will be true iff value is not NaN
421 // TODO: is it faster to say !accum or accum==accum?
422 return !std::isnan(lcpp_x: accum);
423 }
424
425 /** Returns true if SkPoint is equivalent to SkPoint constructed from (x, y).
426
427 @param x value compared with fX
428 @param y value compared with fY
429 @return true if SkPoint equals (x, y)
430 */
431 bool equals(float x, float y) const {
432 return fX == x && fY == y;
433 }
434
435 /** Returns true if a is equivalent to b.
436
437 @param a SkPoint to compare
438 @param b SkPoint to compare
439 @return true if a.fX == b.fX and a.fY == b.fY
440 */
441 friend bool operator==(const SkPoint& a, const SkPoint& b) {
442 return a.fX == b.fX && a.fY == b.fY;
443 }
444
445 /** Returns true if a is not equivalent to b.
446
447 @param a SkPoint to compare
448 @param b SkPoint to compare
449 @return true if a.fX != b.fX or a.fY != b.fY
450 */
451 friend bool operator!=(const SkPoint& a, const SkPoint& b) {
452 return a.fX != b.fX || a.fY != b.fY;
453 }
454
455 /** Returns vector from b to a, computed as (a.fX - b.fX, a.fY - b.fY).
456
457 Can also be used to subtract vector from SkPoint, returning SkPoint.
458 Can also be used to subtract vector from vector, returning vector.
459
460 @param a SkPoint to subtract from
461 @param b SkPoint to subtract
462 @return vector from b to a
463 */
464 friend SkVector operator-(const SkPoint& a, const SkPoint& b) {
465 return {.fX: a.fX - b.fX, .fY: a.fY - b.fY};
466 }
467
468 /** Returns SkPoint resulting from SkPoint a offset by vector b, computed as:
469 (a.fX + b.fX, a.fY + b.fY).
470
471 Can also be used to offset SkPoint b by vector a, returning SkPoint.
472 Can also be used to add vector to vector, returning vector.
473
474 @param a SkPoint or vector to add to
475 @param b SkPoint or vector to add
476 @return SkPoint equal to a offset by b
477 */
478 friend SkPoint operator+(const SkPoint& a, const SkVector& b) {
479 return {.fX: a.fX + b.fX, .fY: a.fY + b.fY};
480 }
481
482 /** Returns the Euclidean distance from origin, computed as:
483
484 sqrt(x * x + y * y)
485
486 .
487
488 @param x component of length
489 @param y component of length
490 @return straight-line distance to origin
491
492 example: https://fiddle.skia.org/c/@Point_Length
493 */
494 static float Length(float x, float y);
495
496 /** Scales (vec->fX, vec->fY) so that length() returns one, while preserving ratio of vec->fX
497 to vec->fY, if possible. If original length is nearly zero, sets vec to (0, 0) and returns
498 zero; otherwise, returns length of vec before vec is scaled.
499
500 Returned prior length may be INFINITY if it can not be represented by float.
501
502 Note that normalize() is faster if prior length is not required.
503
504 @param vec normalized to unit length
505 @return original vec length
506
507 example: https://fiddle.skia.org/c/@Point_Normalize
508 */
509 static float Normalize(SkVector* vec);
510
511 /** Returns the Euclidean distance between a and b.
512
513 @param a line end point
514 @param b line end point
515 @return straight-line distance from a to b
516 */
517 static float Distance(const SkPoint& a, const SkPoint& b) {
518 return Length(x: a.fX - b.fX, y: a.fY - b.fY);
519 }
520
521 /** Returns the dot product of vector a and vector b.
522
523 @param a left side of dot product
524 @param b right side of dot product
525 @return product of input magnitudes and cosine of the angle between them
526 */
527 static float DotProduct(const SkVector& a, const SkVector& b) {
528 return a.fX * b.fX + a.fY * b.fY;
529 }
530
531 /** Returns the cross product of vector a and vector b.
532
533 a and b form three-dimensional vectors with z-axis value equal to zero. The
534 cross product is a three-dimensional vector with x-axis and y-axis values equal
535 to zero. The cross product z-axis component is returned.
536
537 @param a left side of cross product
538 @param b right side of cross product
539 @return area spanned by vectors signed by angle direction
540 */
541 static float CrossProduct(const SkVector& a, const SkVector& b) {
542 return a.fX * b.fY - a.fY * b.fX;
543 }
544
545 /** Returns the cross product of vector and vec.
546
547 Vector and vec form three-dimensional vectors with z-axis value equal to zero.
548 The cross product is a three-dimensional vector with x-axis and y-axis values
549 equal to zero. The cross product z-axis component is returned.
550
551 @param vec right side of cross product
552 @return area spanned by vectors signed by angle direction
553 */
554 float cross(const SkVector& vec) const {
555 return CrossProduct(a: *this, b: vec);
556 }
557
558 /** Returns the dot product of vector and vector vec.
559
560 @param vec right side of dot product
561 @return product of input magnitudes and cosine of the angle between them
562 */
563 float dot(const SkVector& vec) const {
564 return DotProduct(a: *this, b: vec);
565 }
566
567};
568
569#endif
570

source code of flutter_engine/third_party/skia/include/private/base/SkPoint_impl.h