/src/skia/include/private/base/SkPoint_impl.h
Line | Count | Source (jump to first uncovered line) |
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 | | */ |
38 | 53.6k | static constexpr SkIPoint Make(int32_t x, int32_t y) { |
39 | 53.6k | return {x, y}; |
40 | 53.6k | } |
41 | | |
42 | | /** Returns x-axis value of SkIPoint. |
43 | | |
44 | | @return fX |
45 | | */ |
46 | 1.41M | constexpr int32_t x() const { return fX; } |
47 | | |
48 | | /** Returns y-axis value of SkIPoint. |
49 | | |
50 | | @return fY |
51 | | */ |
52 | 1.41M | 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 | 0 | 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 | 337k | void set(int32_t x, int32_t y) { |
66 | 337k | fX = x; |
67 | 337k | fY = y; |
68 | 337k | } |
69 | | |
70 | | /** Returns SkIPoint changing the signs of fX and fY. |
71 | | |
72 | | @return SkIPoint as (-fX, -fY) |
73 | | */ |
74 | 49.9k | SkIPoint operator-() const { |
75 | 49.9k | return {-fX, -fY}; |
76 | 49.9k | } |
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 | 0 | void operator+=(const SkIVector& v) { |
83 | 0 | fX = Sk32_sat_add(fX, v.fX); |
84 | 0 | fY = Sk32_sat_add(fY, v.fY); |
85 | 0 | } |
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 | 1.25k | void operator-=(const SkIVector& v) { |
92 | 1.25k | fX = Sk32_sat_sub(fX, v.fX); |
93 | 1.25k | fY = Sk32_sat_sub(fY, v.fY); |
94 | 1.25k | } |
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 | 0 | bool equals(int32_t x, int32_t y) const { |
103 | 0 | return fX == x && fY == y; |
104 | 0 | } |
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 | 0 | friend bool operator==(const SkIPoint& a, const SkIPoint& b) { |
113 | 0 | return a.fX == b.fX && a.fY == b.fY; |
114 | 0 | } |
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 | 0 | friend bool operator!=(const SkIPoint& a, const SkIPoint& b) { |
123 | 0 | return a.fX != b.fX || a.fY != b.fY; |
124 | 0 | } |
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 | 4.70k | friend SkIVector operator-(const SkIPoint& a, const SkIPoint& b) { |
135 | 4.70k | return { Sk32_sat_sub(a.fX, b.fX), Sk32_sat_sub(a.fY, b.fY) }; |
136 | 4.70k | } |
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 | 0 | friend SkIPoint operator+(const SkIPoint& a, const SkIVector& b) { |
149 | 0 | return { Sk32_sat_add(a.fX, b.fX), Sk32_sat_add(a.fY, b.fY) }; |
150 | 0 | } |
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 | | */ |
173 | 74.7M | static constexpr SkPoint Make(float x, float y) { |
174 | 74.7M | return {x, y}; |
175 | 74.7M | } |
176 | | |
177 | | /** Returns x-axis value of SkPoint or vector. |
178 | | |
179 | | @return fX |
180 | | */ |
181 | 97.3M | constexpr float x() const { return fX; } |
182 | | |
183 | | /** Returns y-axis value of SkPoint or vector. |
184 | | |
185 | | @return fY |
186 | | */ |
187 | 97.4M | 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 | 49.9M | 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 | 1.52G | void set(float x, float y) { |
201 | 1.52G | fX = x; |
202 | 1.52G | fY = y; |
203 | 1.52G | } |
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 | 0 | void iset(int32_t x, int32_t y) { |
215 | 0 | fX = static_cast<float>(x); |
216 | 0 | fY = static_cast<float>(y); |
217 | 0 | } |
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 | 0 | void iset(const SkIPoint& p) { |
228 | 0 | fX = static_cast<float>(p.fX); |
229 | 0 | fY = static_cast<float>(p.fY); |
230 | 0 | } |
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 | 0 | void setAbs(const SkPoint& pt) { |
237 | 0 | fX = std::abs(pt.fX); |
238 | 0 | fY = std::abs(pt.fY); |
239 | 0 | } |
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 | 0 | static void Offset(SkPoint points[], int count, const SkVector& offset) { |
248 | 0 | Offset(points, count, offset.fX, offset.fY); |
249 | 0 | } |
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 | 0 | static void Offset(SkPoint points[], int count, float dx, float dy) { |
259 | 0 | for (int i = 0; i < count; ++i) { |
260 | 0 | points[i].offset(dx, dy); |
261 | 0 | } |
262 | 0 | } |
263 | | |
264 | | /** Adds offset (dx, dy) to SkPoint. |
265 | | |
266 | | @param dx added to fX |
267 | | @param dy added to fY |
268 | | */ |
269 | 4.83k | void offset(float dx, float dy) { |
270 | 4.83k | fX += dx; |
271 | 4.83k | fY += dy; |
272 | 4.83k | } |
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 | 288k | 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 | | */ |
292 | 0 | 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 | 5.00M | void scale(float value) { this->scale(value, this); } |
354 | | |
355 | | /** Changes the sign of fX and fY. |
356 | | */ |
357 | 3.35M | void negate() { |
358 | 3.35M | fX = -fX; |
359 | 3.35M | fY = -fY; |
360 | 3.35M | } |
361 | | |
362 | | /** Returns SkPoint changing the signs of fX and fY. |
363 | | |
364 | | @return SkPoint as (-fX, -fY) |
365 | | */ |
366 | 3.78M | SkPoint operator-() const { |
367 | 3.78M | return {-fX, -fY}; |
368 | 3.78M | } |
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 | 95.1M | void operator+=(const SkVector& v) { |
375 | 95.1M | fX += v.fX; |
376 | 95.1M | fY += v.fY; |
377 | 95.1M | } |
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 | 2.95M | void operator-=(const SkVector& v) { |
384 | 2.95M | fX -= v.fX; |
385 | 2.95M | fY -= v.fY; |
386 | 2.95M | } |
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 | 126M | SkPoint operator*(float scale) const { |
394 | 126M | return {fX * scale, fY * scale}; |
395 | 126M | } |
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 | 21.4M | SkPoint& operator*=(float scale) { |
403 | 21.4M | fX *= scale; |
404 | 21.4M | fY *= scale; |
405 | 21.4M | return *this; |
406 | 21.4M | } |
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 | 273M | bool isFinite() const { |
413 | 273M | return SkIsFinite(fX, fY); |
414 | 273M | } |
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 | | */ |
422 | 7.27M | bool equals(float x, float y) const { |
423 | 7.27M | return fX == x && fY == y; |
424 | 7.27M | } |
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 | 35.3G | friend bool operator==(const SkPoint& a, const SkPoint& b) { |
433 | 35.3G | return a.fX == b.fX && a.fY == b.fY; |
434 | 35.3G | } |
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 | 780M | friend bool operator!=(const SkPoint& a, const SkPoint& b) { |
443 | 780M | return a.fX != b.fX || a.fY != b.fY; |
444 | 780M | } |
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 | 1.78G | friend SkVector operator-(const SkPoint& a, const SkPoint& b) { |
456 | 1.78G | return {a.fX - b.fX, a.fY - b.fY}; |
457 | 1.78G | } |
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 | 286M | friend SkPoint operator+(const SkPoint& a, const SkVector& b) { |
470 | 286M | return {a.fX + b.fX, a.fY + b.fY}; |
471 | 286M | } |
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 | | */ |
508 | 56.8M | static float Distance(const SkPoint& a, const SkPoint& b) { |
509 | 56.8M | return Length(a.fX - b.fX, a.fY - b.fY); |
510 | 56.8M | } |
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 | | */ |
518 | 1.47G | static float DotProduct(const SkVector& a, const SkVector& b) { |
519 | 1.47G | return a.fX * b.fX + a.fY * b.fY; |
520 | 1.47G | } |
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 | | */ |
532 | 1.06G | static float CrossProduct(const SkVector& a, const SkVector& b) { |
533 | 1.06G | return a.fX * b.fY - a.fY * b.fX; |
534 | 1.06G | } |
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 | | */ |
545 | 1.04G | float cross(const SkVector& vec) const { |
546 | 1.04G | return CrossProduct(*this, vec); |
547 | 1.04G | } |
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 | | */ |
554 | 157M | float dot(const SkVector& vec) const { |
555 | 157M | return DotProduct(*this, vec); |
556 | 157M | } |
557 | | |
558 | | }; |
559 | | |
560 | | #endif |