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