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 */ MakeSkIPoint38 static constexpr SkIPoint Make(int32_t x, int32_t y) { 39 return {x, y}; 40 } 41 42 /** Returns x-axis value of SkIPoint. 43 44 @return fX 45 */ xSkIPoint46 constexpr int32_t x() const { return fX; } 47 48 /** Returns y-axis value of SkIPoint. 49 50 @return fY 51 */ ySkIPoint52 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 */ isZeroSkIPoint58 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 */ setSkIPoint65 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, -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(fX, v.fX); 84 fY = Sk32_sat_add(fY, 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(fX, v.fX); 93 fY = Sk32_sat_sub(fY, 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 */ equalsSkIPoint102 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 { Sk32_sat_sub(a.fX, b.fX), Sk32_sat_sub(a.fY, 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 { Sk32_sat_add(a.fX, b.fX), Sk32_sat_add(a.fY, b.fY) }; 150 } 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 */ MakeSkPoint173 static constexpr SkPoint Make(float x, float y) { 174 return {x, y}; 175 } 176 177 /** Returns x-axis value of SkPoint or vector. 178 179 @return fX 180 */ xSkPoint181 constexpr float x() const { return fX; } 182 183 /** Returns y-axis value of SkPoint or vector. 184 185 @return fY 186 */ ySkPoint187 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 */ isZeroSkPoint193 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 */ setSkPoint200 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 */ isetSkPoint214 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 */ isetSkPoint227 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 */ setAbsSkPoint236 void setAbs(const SkPoint& pt) { 237 fX = std::abs(pt.fX); 238 fY = std::abs(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 */ OffsetSkPoint247 static void Offset(SkPoint points[], int count, const SkVector& offset) { 248 Offset(points, count, offset.fX, 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 */ OffsetSkPoint258 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 */ offsetSkPoint269 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 */ lengthSkPoint282 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 */ distanceToOriginSkPoint292 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 */ scaleSkPoint353 void scale(float value) { this->scale(value, this); } 354 355 /** Changes the sign of fX and fY. 356 */ negateSkPoint357 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, -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 * scale, 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 */ isFiniteSkPoint412 bool isFinite() const { 413 return SkIsFinite(fX, fY); 414 } 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 */ equalsSkPoint422 bool equals(float x, float y) const { 423 return fX == x && fY == y; 424 } 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 friend bool operator==(const SkPoint& a, const SkPoint& b) { 433 return a.fX == b.fX && a.fY == b.fY; 434 } 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 friend bool operator!=(const SkPoint& a, const SkPoint& b) { 443 return a.fX != b.fX || a.fY != b.fY; 444 } 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 friend SkVector operator-(const SkPoint& a, const SkPoint& b) { 456 return {a.fX - b.fX, a.fY - b.fY}; 457 } 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 friend SkPoint operator+(const SkPoint& a, const SkVector& b) { 470 return {a.fX + b.fX, a.fY + b.fY}; 471 } 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 */ DistanceSkPoint508 static float Distance(const SkPoint& a, const SkPoint& b) { 509 return Length(a.fX - b.fX, a.fY - b.fY); 510 } 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 */ DotProductSkPoint518 static float DotProduct(const SkVector& a, const SkVector& b) { 519 return a.fX * b.fX + a.fY * b.fY; 520 } 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 */ CrossProductSkPoint532 static float CrossProduct(const SkVector& a, const SkVector& b) { 533 return a.fX * b.fY - a.fY * b.fX; 534 } 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 */ crossSkPoint545 float cross(const SkVector& vec) const { 546 return CrossProduct(*this, vec); 547 } 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 */ dotSkPoint554 float dot(const SkVector& vec) const { 555 return DotProduct(*this, vec); 556 } 557 558 }; 559 560 #endif 561