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