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 int32_t x() const { return fX; } 44 45 /** Returns y-axis value of SkIPoint. 46 47 @return fY 48 */ ySkIPoint49 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 SkScalar x() const { return fX; } 179 180 /** Returns y-axis value of SkPoint or vector. 181 182 @return fY 183 */ ySkPoint184 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 bool normalize(); 298 299 /** Sets vector to (x, y) scaled so length() returns one, and so that 300 (fX, fY) is proportional to (x, y). If (x, y) length is nearly zero, 301 sets vector to (0, 0) and returns false; otherwise returns true. 302 303 @param x proportional value for fX 304 @param y proportional value for fY 305 @return true if (x, y) length is not zero or nearly zero 306 */ 307 bool setNormalize(SkScalar x, SkScalar y); 308 309 /** Scales vector so that distanceToOrigin() returns length, if possible. If former 310 length is nearly zero, sets vector to (0, 0) and return false; otherwise returns 311 true. 312 313 @param length straight-line distance to origin 314 @return true if former length is not zero or nearly zero 315 */ 316 bool setLength(SkScalar length); 317 318 /** Sets vector to (x, y) scaled to length, if possible. If former 319 length is nearly zero, sets vector to (0, 0) and return false; otherwise returns 320 true. 321 322 @param x proportional value for fX 323 @param y proportional value for fY 324 @param length straight-line distance to origin 325 @return true if (x, y) length is not zero or nearly zero 326 */ 327 bool setLength(SkScalar x, SkScalar y, SkScalar length); 328 329 /** Sets dst to SkPoint times scale. dst may be SkPoint to modify SkPoint in place. 330 331 @param scale factor to multiply SkPoint by 332 @param dst storage for scaled SkPoint 333 */ 334 void scale(SkScalar scale, SkPoint* dst) const; 335 336 /** Scales SkPoint in place by scale. 337 338 @param value factor to multiply SkPoint by 339 */ scaleSkPoint340 void scale(SkScalar value) { this->scale(value, this); } 341 342 /** Changes the sign of fX and fY. 343 */ negateSkPoint344 void negate() { 345 fX = -fX; 346 fY = -fY; 347 } 348 349 /** Returns SkPoint changing the signs of fX and fY. 350 351 @return SkPoint as (-fX, -fY) 352 */ 353 SkPoint operator-() const { 354 return {-fX, -fY}; 355 } 356 357 /** Adds vector v to SkPoint. Sets SkPoint to: (fX + v.fX, fY + v.fY). 358 359 @param v vector to add 360 */ 361 void operator+=(const SkVector& v) { 362 fX += v.fX; 363 fY += v.fY; 364 } 365 366 /** Subtracts vector v from SkPoint. Sets SkPoint to: (fX - v.fX, fY - v.fY). 367 368 @param v vector to subtract 369 */ 370 void operator-=(const SkVector& v) { 371 fX -= v.fX; 372 fY -= v.fY; 373 } 374 375 /** Returns SkPoint multiplied by scale. 376 377 @param scale scalar to multiply by 378 @return SkPoint as (fX * scale, fY * scale) 379 */ 380 SkPoint operator*(SkScalar scale) const { 381 return {fX * scale, fY * scale}; 382 } 383 384 /** Multiplies SkPoint by scale. Sets SkPoint to: (fX * scale, fY * scale). 385 386 @param scale scalar to multiply by 387 @return reference to SkPoint 388 */ 389 SkPoint& operator*=(SkScalar scale) { 390 fX *= scale; 391 fY *= scale; 392 return *this; 393 } 394 395 /** Returns true if both fX and fY are measurable values. 396 397 @return true for values other than infinities and NaN 398 */ isFiniteSkPoint399 bool isFinite() const { 400 SkScalar accum = 0; 401 accum *= fX; 402 accum *= fY; 403 404 // accum is either NaN or it is finite (zero). 405 SkASSERT(0 == accum || SkScalarIsNaN(accum)); 406 407 // value==value will be true iff value is not NaN 408 // TODO: is it faster to say !accum or accum==accum? 409 return !SkScalarIsNaN(accum); 410 } 411 412 /** Returns true if SkPoint is equivalent to SkPoint constructed from (x, y). 413 414 @param x value compared with fX 415 @param y value compared with fY 416 @return true if SkPoint equals (x, y) 417 */ equalsSkPoint418 bool equals(SkScalar x, SkScalar y) const { 419 return fX == x && fY == y; 420 } 421 422 /** Returns true if a is equivalent to b. 423 424 @param a SkPoint to compare 425 @param b SkPoint to compare 426 @return true if a.fX == b.fX and a.fY == b.fY 427 */ 428 friend bool operator==(const SkPoint& a, const SkPoint& b) { 429 return a.fX == b.fX && a.fY == b.fY; 430 } 431 432 /** Returns true if a is not equivalent to b. 433 434 @param a SkPoint to compare 435 @param b SkPoint to compare 436 @return true if a.fX != b.fX or 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 vector from b to a, computed as (a.fX - b.fX, a.fY - b.fY). 443 444 Can also be used to subtract vector from SkPoint, returning SkPoint. 445 Can also be used to subtract vector from vector, returning vector. 446 447 @param a SkPoint to subtract from 448 @param b SkPoint to subtract 449 @return vector from b to a 450 */ 451 friend SkVector operator-(const SkPoint& a, const SkPoint& b) { 452 return {a.fX - b.fX, a.fY - b.fY}; 453 } 454 455 /** Returns SkPoint resulting from SkPoint a offset by vector b, computed as: 456 (a.fX + b.fX, a.fY + b.fY). 457 458 Can also be used to offset SkPoint b by vector a, returning SkPoint. 459 Can also be used to add vector to vector, returning vector. 460 461 @param a SkPoint or vector to add to 462 @param b SkPoint or vector to add 463 @return SkPoint equal to a offset by b 464 */ 465 friend SkPoint operator+(const SkPoint& a, const SkVector& b) { 466 return {a.fX + b.fX, a.fY + b.fY}; 467 } 468 469 /** Returns the Euclidean distance from origin, computed as: 470 471 sqrt(x * x + y * y) 472 473 . 474 475 @param x component of length 476 @param y component of length 477 @return straight-line distance to origin 478 */ 479 static SkScalar Length(SkScalar x, SkScalar y); 480 481 /** Scales (vec->fX, vec->fY) so that length() returns one, while preserving ratio of vec->fX 482 to vec->fY, if possible. If original length is nearly zero, sets vec to (0, 0) and returns 483 zero; otherwise, returns length of vec before vec is scaled. 484 485 Returned prior length may be SK_ScalarInfinity if it can not be represented by SkScalar. 486 487 Note that normalize() is faster if prior length is not required. 488 489 @param vec normalized to unit length 490 @return original vec length 491 */ 492 static SkScalar Normalize(SkVector* vec); 493 494 /** Returns the Euclidean distance between a and b. 495 496 @param a line end point 497 @param b line end point 498 @return straight-line distance from a to b 499 */ DistanceSkPoint500 static SkScalar Distance(const SkPoint& a, const SkPoint& b) { 501 return Length(a.fX - b.fX, a.fY - b.fY); 502 } 503 504 /** Returns the dot product of vector a and vector b. 505 506 @param a left side of dot product 507 @param b right side of dot product 508 @return product of input magnitudes and cosine of the angle between them 509 */ DotProductSkPoint510 static SkScalar DotProduct(const SkVector& a, const SkVector& b) { 511 return a.fX * b.fX + a.fY * b.fY; 512 } 513 514 /** Returns the cross product of vector a and vector b. 515 516 a and b form three-dimensional vectors with z-axis value equal to zero. The 517 cross product is a three-dimensional vector with x-axis and y-axis values equal 518 to zero. The cross product z-axis component is returned. 519 520 @param a left side of cross product 521 @param b right side of cross product 522 @return area spanned by vectors signed by angle direction 523 */ CrossProductSkPoint524 static SkScalar CrossProduct(const SkVector& a, const SkVector& b) { 525 return a.fX * b.fY - a.fY * b.fX; 526 } 527 528 /** Returns the cross product of vector and vec. 529 530 Vector and vec form three-dimensional vectors with z-axis value equal to zero. 531 The cross product is a three-dimensional vector with x-axis and y-axis values 532 equal to zero. The cross product z-axis component is returned. 533 534 @param vec right side of cross product 535 @return area spanned by vectors signed by angle direction 536 */ crossSkPoint537 SkScalar cross(const SkVector& vec) const { 538 return CrossProduct(*this, vec); 539 } 540 541 /** Returns the dot product of vector and vector vec. 542 543 @param vec right side of dot product 544 @return product of input magnitudes and cosine of the angle between them 545 */ dotSkPoint546 SkScalar dot(const SkVector& vec) const { 547 return DotProduct(*this, vec); 548 } 549 550 }; 551 552 #endif 553