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