gfx/skia/trunk/include/core/SkPoint.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /*
michael@0 2 * Copyright 2006 The Android Open Source Project
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license that can be
michael@0 5 * found in the LICENSE file.
michael@0 6 */
michael@0 7
michael@0 8 #ifndef SkPoint_DEFINED
michael@0 9 #define SkPoint_DEFINED
michael@0 10
michael@0 11 #include "SkMath.h"
michael@0 12 #include "SkScalar.h"
michael@0 13
michael@0 14 /** \struct SkIPoint
michael@0 15
michael@0 16 SkIPoint holds two 32 bit integer coordinates
michael@0 17 */
michael@0 18 struct SkIPoint {
michael@0 19 int32_t fX, fY;
michael@0 20
michael@0 21 static SkIPoint Make(int32_t x, int32_t y) {
michael@0 22 SkIPoint pt;
michael@0 23 pt.set(x, y);
michael@0 24 return pt;
michael@0 25 }
michael@0 26
michael@0 27 int32_t x() const { return fX; }
michael@0 28 int32_t y() const { return fY; }
michael@0 29 void setX(int32_t x) { fX = x; }
michael@0 30 void setY(int32_t y) { fY = y; }
michael@0 31
michael@0 32 /**
michael@0 33 * Returns true iff fX and fY are both zero.
michael@0 34 */
michael@0 35 bool isZero() const { return (fX | fY) == 0; }
michael@0 36
michael@0 37 /**
michael@0 38 * Set both fX and fY to zero. Same as set(0, 0)
michael@0 39 */
michael@0 40 void setZero() { fX = fY = 0; }
michael@0 41
michael@0 42 /** Set the x and y values of the point. */
michael@0 43 void set(int32_t x, int32_t y) { fX = x; fY = y; }
michael@0 44
michael@0 45 /** Rotate the point clockwise, writing the new point into dst
michael@0 46 It is legal for dst == this
michael@0 47 */
michael@0 48 void rotateCW(SkIPoint* dst) const;
michael@0 49
michael@0 50 /** Rotate the point clockwise, writing the new point back into the point
michael@0 51 */
michael@0 52
michael@0 53 void rotateCW() { this->rotateCW(this); }
michael@0 54
michael@0 55 /** Rotate the point counter-clockwise, writing the new point into dst.
michael@0 56 It is legal for dst == this
michael@0 57 */
michael@0 58 void rotateCCW(SkIPoint* dst) const;
michael@0 59
michael@0 60 /** Rotate the point counter-clockwise, writing the new point back into
michael@0 61 the point
michael@0 62 */
michael@0 63 void rotateCCW() { this->rotateCCW(this); }
michael@0 64
michael@0 65 /** Negate the X and Y coordinates of the point.
michael@0 66 */
michael@0 67 void negate() { fX = -fX; fY = -fY; }
michael@0 68
michael@0 69 /** Return a new point whose X and Y coordinates are the negative of the
michael@0 70 original point's
michael@0 71 */
michael@0 72 SkIPoint operator-() const {
michael@0 73 SkIPoint neg;
michael@0 74 neg.fX = -fX;
michael@0 75 neg.fY = -fY;
michael@0 76 return neg;
michael@0 77 }
michael@0 78
michael@0 79 /** Add v's coordinates to this point's */
michael@0 80 void operator+=(const SkIPoint& v) {
michael@0 81 fX += v.fX;
michael@0 82 fY += v.fY;
michael@0 83 }
michael@0 84
michael@0 85 /** Subtract v's coordinates from this point's */
michael@0 86 void operator-=(const SkIPoint& v) {
michael@0 87 fX -= v.fX;
michael@0 88 fY -= v.fY;
michael@0 89 }
michael@0 90
michael@0 91 /** Returns true if the point's coordinates equal (x,y) */
michael@0 92 bool equals(int32_t x, int32_t y) const {
michael@0 93 return fX == x && fY == y;
michael@0 94 }
michael@0 95
michael@0 96 friend bool operator==(const SkIPoint& a, const SkIPoint& b) {
michael@0 97 return a.fX == b.fX && a.fY == b.fY;
michael@0 98 }
michael@0 99
michael@0 100 friend bool operator!=(const SkIPoint& a, const SkIPoint& b) {
michael@0 101 return a.fX != b.fX || a.fY != b.fY;
michael@0 102 }
michael@0 103
michael@0 104 /** Returns a new point whose coordinates are the difference between
michael@0 105 a and b (i.e. a - b)
michael@0 106 */
michael@0 107 friend SkIPoint operator-(const SkIPoint& a, const SkIPoint& b) {
michael@0 108 SkIPoint v;
michael@0 109 v.set(a.fX - b.fX, a.fY - b.fY);
michael@0 110 return v;
michael@0 111 }
michael@0 112
michael@0 113 /** Returns a new point whose coordinates are the sum of a and b (a + b)
michael@0 114 */
michael@0 115 friend SkIPoint operator+(const SkIPoint& a, const SkIPoint& b) {
michael@0 116 SkIPoint v;
michael@0 117 v.set(a.fX + b.fX, a.fY + b.fY);
michael@0 118 return v;
michael@0 119 }
michael@0 120
michael@0 121 /** Returns the dot product of a and b, treating them as 2D vectors
michael@0 122 */
michael@0 123 static int32_t DotProduct(const SkIPoint& a, const SkIPoint& b) {
michael@0 124 return a.fX * b.fX + a.fY * b.fY;
michael@0 125 }
michael@0 126
michael@0 127 /** Returns the cross product of a and b, treating them as 2D vectors
michael@0 128 */
michael@0 129 static int32_t CrossProduct(const SkIPoint& a, const SkIPoint& b) {
michael@0 130 return a.fX * b.fY - a.fY * b.fX;
michael@0 131 }
michael@0 132 };
michael@0 133
michael@0 134 struct SK_API SkPoint {
michael@0 135 SkScalar fX, fY;
michael@0 136
michael@0 137 static SkPoint Make(SkScalar x, SkScalar y) {
michael@0 138 SkPoint pt;
michael@0 139 pt.set(x, y);
michael@0 140 return pt;
michael@0 141 }
michael@0 142
michael@0 143 SkScalar x() const { return fX; }
michael@0 144 SkScalar y() const { return fY; }
michael@0 145
michael@0 146 /**
michael@0 147 * Returns true iff fX and fY are both zero.
michael@0 148 */
michael@0 149 bool isZero() const { return (0 == fX) & (0 == fY); }
michael@0 150
michael@0 151 /** Set the point's X and Y coordinates */
michael@0 152 void set(SkScalar x, SkScalar y) { fX = x; fY = y; }
michael@0 153
michael@0 154 /** Set the point's X and Y coordinates by automatically promoting (x,y) to
michael@0 155 SkScalar values.
michael@0 156 */
michael@0 157 void iset(int32_t x, int32_t y) {
michael@0 158 fX = SkIntToScalar(x);
michael@0 159 fY = SkIntToScalar(y);
michael@0 160 }
michael@0 161
michael@0 162 /** Set the point's X and Y coordinates by automatically promoting p's
michael@0 163 coordinates to SkScalar values.
michael@0 164 */
michael@0 165 void iset(const SkIPoint& p) {
michael@0 166 fX = SkIntToScalar(p.fX);
michael@0 167 fY = SkIntToScalar(p.fY);
michael@0 168 }
michael@0 169
michael@0 170 void setAbs(const SkPoint& pt) {
michael@0 171 fX = SkScalarAbs(pt.fX);
michael@0 172 fY = SkScalarAbs(pt.fY);
michael@0 173 }
michael@0 174
michael@0 175 // counter-clockwise fan
michael@0 176 void setIRectFan(int l, int t, int r, int b) {
michael@0 177 SkPoint* v = this;
michael@0 178 v[0].set(SkIntToScalar(l), SkIntToScalar(t));
michael@0 179 v[1].set(SkIntToScalar(l), SkIntToScalar(b));
michael@0 180 v[2].set(SkIntToScalar(r), SkIntToScalar(b));
michael@0 181 v[3].set(SkIntToScalar(r), SkIntToScalar(t));
michael@0 182 }
michael@0 183 void setIRectFan(int l, int t, int r, int b, size_t stride);
michael@0 184
michael@0 185 // counter-clockwise fan
michael@0 186 void setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
michael@0 187 SkPoint* v = this;
michael@0 188 v[0].set(l, t);
michael@0 189 v[1].set(l, b);
michael@0 190 v[2].set(r, b);
michael@0 191 v[3].set(r, t);
michael@0 192 }
michael@0 193 void setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b, size_t stride);
michael@0 194
michael@0 195 static void Offset(SkPoint points[], int count, const SkPoint& offset) {
michael@0 196 Offset(points, count, offset.fX, offset.fY);
michael@0 197 }
michael@0 198
michael@0 199 static void Offset(SkPoint points[], int count, SkScalar dx, SkScalar dy) {
michael@0 200 for (int i = 0; i < count; ++i) {
michael@0 201 points[i].offset(dx, dy);
michael@0 202 }
michael@0 203 }
michael@0 204
michael@0 205 void offset(SkScalar dx, SkScalar dy) {
michael@0 206 fX += dx;
michael@0 207 fY += dy;
michael@0 208 }
michael@0 209
michael@0 210 /** Return the euclidian distance from (0,0) to the point
michael@0 211 */
michael@0 212 SkScalar length() const { return SkPoint::Length(fX, fY); }
michael@0 213 SkScalar distanceToOrigin() const { return this->length(); }
michael@0 214
michael@0 215 /**
michael@0 216 * Return true if the computed length of the vector is >= the internal
michael@0 217 * tolerance (used to avoid dividing by tiny values).
michael@0 218 */
michael@0 219 static bool CanNormalize(SkScalar dx, SkScalar dy) {
michael@0 220 // Simple enough (and performance critical sometimes) so we inline it.
michael@0 221 return (dx*dx + dy*dy) > (SK_ScalarNearlyZero * SK_ScalarNearlyZero);
michael@0 222 }
michael@0 223
michael@0 224 bool canNormalize() const {
michael@0 225 return CanNormalize(fX, fY);
michael@0 226 }
michael@0 227
michael@0 228 /** Set the point (vector) to be unit-length in the same direction as it
michael@0 229 already points. If the point has a degenerate length (i.e. nearly 0)
michael@0 230 then return false and do nothing; otherwise return true.
michael@0 231 */
michael@0 232 bool normalize();
michael@0 233
michael@0 234 /** Set the point (vector) to be unit-length in the same direction as the
michael@0 235 x,y params. If the vector (x,y) has a degenerate length (i.e. nearly 0)
michael@0 236 then return false and do nothing, otherwise return true.
michael@0 237 */
michael@0 238 bool setNormalize(SkScalar x, SkScalar y);
michael@0 239
michael@0 240 /** Scale the point (vector) to have the specified length, and return that
michael@0 241 length. If the original length is degenerately small (nearly zero),
michael@0 242 do nothing and return false, otherwise return true.
michael@0 243 */
michael@0 244 bool setLength(SkScalar length);
michael@0 245
michael@0 246 /** Set the point (vector) to have the specified length in the same
michael@0 247 direction as (x,y). If the vector (x,y) has a degenerate length
michael@0 248 (i.e. nearly 0) then return false and do nothing, otherwise return true.
michael@0 249 */
michael@0 250 bool setLength(SkScalar x, SkScalar y, SkScalar length);
michael@0 251
michael@0 252 /** Same as setLength, but favoring speed over accuracy.
michael@0 253 */
michael@0 254 bool setLengthFast(SkScalar length);
michael@0 255
michael@0 256 /** Same as setLength, but favoring speed over accuracy.
michael@0 257 */
michael@0 258 bool setLengthFast(SkScalar x, SkScalar y, SkScalar length);
michael@0 259
michael@0 260 /** Scale the point's coordinates by scale, writing the answer into dst.
michael@0 261 It is legal for dst == this.
michael@0 262 */
michael@0 263 void scale(SkScalar scale, SkPoint* dst) const;
michael@0 264
michael@0 265 /** Scale the point's coordinates by scale, writing the answer back into
michael@0 266 the point.
michael@0 267 */
michael@0 268 void scale(SkScalar value) { this->scale(value, this); }
michael@0 269
michael@0 270 /** Rotate the point clockwise by 90 degrees, writing the answer into dst.
michael@0 271 It is legal for dst == this.
michael@0 272 */
michael@0 273 void rotateCW(SkPoint* dst) const;
michael@0 274
michael@0 275 /** Rotate the point clockwise by 90 degrees, writing the answer back into
michael@0 276 the point.
michael@0 277 */
michael@0 278 void rotateCW() { this->rotateCW(this); }
michael@0 279
michael@0 280 /** Rotate the point counter-clockwise by 90 degrees, writing the answer
michael@0 281 into dst. It is legal for dst == this.
michael@0 282 */
michael@0 283 void rotateCCW(SkPoint* dst) const;
michael@0 284
michael@0 285 /** Rotate the point counter-clockwise by 90 degrees, writing the answer
michael@0 286 back into the point.
michael@0 287 */
michael@0 288 void rotateCCW() { this->rotateCCW(this); }
michael@0 289
michael@0 290 /** Negate the point's coordinates
michael@0 291 */
michael@0 292 void negate() {
michael@0 293 fX = -fX;
michael@0 294 fY = -fY;
michael@0 295 }
michael@0 296
michael@0 297 /** Returns a new point whose coordinates are the negative of the point's
michael@0 298 */
michael@0 299 SkPoint operator-() const {
michael@0 300 SkPoint neg;
michael@0 301 neg.fX = -fX;
michael@0 302 neg.fY = -fY;
michael@0 303 return neg;
michael@0 304 }
michael@0 305
michael@0 306 /** Add v's coordinates to the point's
michael@0 307 */
michael@0 308 void operator+=(const SkPoint& v) {
michael@0 309 fX += v.fX;
michael@0 310 fY += v.fY;
michael@0 311 }
michael@0 312
michael@0 313 /** Subtract v's coordinates from the point's
michael@0 314 */
michael@0 315 void operator-=(const SkPoint& v) {
michael@0 316 fX -= v.fX;
michael@0 317 fY -= v.fY;
michael@0 318 }
michael@0 319
michael@0 320 /**
michael@0 321 * Returns true if both X and Y are finite (not infinity or NaN)
michael@0 322 */
michael@0 323 bool isFinite() const {
michael@0 324 SkScalar accum = 0;
michael@0 325 accum *= fX;
michael@0 326 accum *= fY;
michael@0 327
michael@0 328 // accum is either NaN or it is finite (zero).
michael@0 329 SkASSERT(0 == accum || !(accum == accum));
michael@0 330
michael@0 331 // value==value will be true iff value is not NaN
michael@0 332 // TODO: is it faster to say !accum or accum==accum?
michael@0 333 return accum == accum;
michael@0 334 }
michael@0 335
michael@0 336 /**
michael@0 337 * Returns true if the point's coordinates equal (x,y)
michael@0 338 */
michael@0 339 bool equals(SkScalar x, SkScalar y) const {
michael@0 340 return fX == x && fY == y;
michael@0 341 }
michael@0 342
michael@0 343 friend bool operator==(const SkPoint& a, const SkPoint& b) {
michael@0 344 return a.fX == b.fX && a.fY == b.fY;
michael@0 345 }
michael@0 346
michael@0 347 friend bool operator!=(const SkPoint& a, const SkPoint& b) {
michael@0 348 return a.fX != b.fX || a.fY != b.fY;
michael@0 349 }
michael@0 350
michael@0 351 /** Return true if this point and the given point are far enough apart
michael@0 352 such that a vector between them would be non-degenerate.
michael@0 353
michael@0 354 WARNING: Unlike the explicit tolerance version,
michael@0 355 this method does not use componentwise comparison. Instead, it
michael@0 356 uses a comparison designed to match judgments elsewhere regarding
michael@0 357 degeneracy ("points A and B are so close that the vector between them
michael@0 358 is essentially zero").
michael@0 359 */
michael@0 360 bool equalsWithinTolerance(const SkPoint& p) const {
michael@0 361 return !CanNormalize(fX - p.fX, fY - p.fY);
michael@0 362 }
michael@0 363
michael@0 364 /** WARNING: There is no guarantee that the result will reflect judgments
michael@0 365 elsewhere regarding degeneracy ("points A and B are so close that the
michael@0 366 vector between them is essentially zero").
michael@0 367 */
michael@0 368 bool equalsWithinTolerance(const SkPoint& p, SkScalar tol) const {
michael@0 369 return SkScalarNearlyZero(fX - p.fX, tol)
michael@0 370 && SkScalarNearlyZero(fY - p.fY, tol);
michael@0 371 }
michael@0 372
michael@0 373 /** Returns a new point whose coordinates are the difference between
michael@0 374 a's and b's (a - b)
michael@0 375 */
michael@0 376 friend SkPoint operator-(const SkPoint& a, const SkPoint& b) {
michael@0 377 SkPoint v;
michael@0 378 v.set(a.fX - b.fX, a.fY - b.fY);
michael@0 379 return v;
michael@0 380 }
michael@0 381
michael@0 382 /** Returns a new point whose coordinates are the sum of a's and b's (a + b)
michael@0 383 */
michael@0 384 friend SkPoint operator+(const SkPoint& a, const SkPoint& b) {
michael@0 385 SkPoint v;
michael@0 386 v.set(a.fX + b.fX, a.fY + b.fY);
michael@0 387 return v;
michael@0 388 }
michael@0 389
michael@0 390 /** Returns the euclidian distance from (0,0) to (x,y)
michael@0 391 */
michael@0 392 static SkScalar Length(SkScalar x, SkScalar y);
michael@0 393
michael@0 394 /** Normalize pt, returning its previous length. If the prev length is too
michael@0 395 small (degenerate), return 0 and leave pt unchanged. This uses the same
michael@0 396 tolerance as CanNormalize.
michael@0 397
michael@0 398 Note that this method may be significantly more expensive than
michael@0 399 the non-static normalize(), because it has to return the previous length
michael@0 400 of the point. If you don't need the previous length, call the
michael@0 401 non-static normalize() method instead.
michael@0 402 */
michael@0 403 static SkScalar Normalize(SkPoint* pt);
michael@0 404
michael@0 405 /** Returns the euclidian distance between a and b
michael@0 406 */
michael@0 407 static SkScalar Distance(const SkPoint& a, const SkPoint& b) {
michael@0 408 return Length(a.fX - b.fX, a.fY - b.fY);
michael@0 409 }
michael@0 410
michael@0 411 /** Returns the dot product of a and b, treating them as 2D vectors
michael@0 412 */
michael@0 413 static SkScalar DotProduct(const SkPoint& a, const SkPoint& b) {
michael@0 414 return a.fX * b.fX + a.fY * b.fY;
michael@0 415 }
michael@0 416
michael@0 417 /** Returns the cross product of a and b, treating them as 2D vectors
michael@0 418 */
michael@0 419 static SkScalar CrossProduct(const SkPoint& a, const SkPoint& b) {
michael@0 420 return a.fX * b.fY - a.fY * b.fX;
michael@0 421 }
michael@0 422
michael@0 423 SkScalar cross(const SkPoint& vec) const {
michael@0 424 return CrossProduct(*this, vec);
michael@0 425 }
michael@0 426
michael@0 427 SkScalar dot(const SkPoint& vec) const {
michael@0 428 return DotProduct(*this, vec);
michael@0 429 }
michael@0 430
michael@0 431 SkScalar lengthSqd() const {
michael@0 432 return DotProduct(*this, *this);
michael@0 433 }
michael@0 434
michael@0 435 SkScalar distanceToSqd(const SkPoint& pt) const {
michael@0 436 SkScalar dx = fX - pt.fX;
michael@0 437 SkScalar dy = fY - pt.fY;
michael@0 438 return dx * dx + dy * dy;
michael@0 439 }
michael@0 440
michael@0 441 /**
michael@0 442 * The side of a point relative to a line. If the line is from a to b then
michael@0 443 * the values are consistent with the sign of (b-a) cross (pt-a)
michael@0 444 */
michael@0 445 enum Side {
michael@0 446 kLeft_Side = -1,
michael@0 447 kOn_Side = 0,
michael@0 448 kRight_Side = 1
michael@0 449 };
michael@0 450
michael@0 451 /**
michael@0 452 * Returns the squared distance to the infinite line between two pts. Also
michael@0 453 * optionally returns the side of the line that the pt falls on (looking
michael@0 454 * along line from a to b)
michael@0 455 */
michael@0 456 SkScalar distanceToLineBetweenSqd(const SkPoint& a,
michael@0 457 const SkPoint& b,
michael@0 458 Side* side = NULL) const;
michael@0 459
michael@0 460 /**
michael@0 461 * Returns the distance to the infinite line between two pts. Also
michael@0 462 * optionally returns the side of the line that the pt falls on (looking
michael@0 463 * along the line from a to b)
michael@0 464 */
michael@0 465 SkScalar distanceToLineBetween(const SkPoint& a,
michael@0 466 const SkPoint& b,
michael@0 467 Side* side = NULL) const {
michael@0 468 return SkScalarSqrt(this->distanceToLineBetweenSqd(a, b, side));
michael@0 469 }
michael@0 470
michael@0 471 /**
michael@0 472 * Returns the squared distance to the line segment between pts a and b
michael@0 473 */
michael@0 474 SkScalar distanceToLineSegmentBetweenSqd(const SkPoint& a,
michael@0 475 const SkPoint& b) const;
michael@0 476
michael@0 477 /**
michael@0 478 * Returns the distance to the line segment between pts a and b.
michael@0 479 */
michael@0 480 SkScalar distanceToLineSegmentBetween(const SkPoint& a,
michael@0 481 const SkPoint& b) const {
michael@0 482 return SkScalarSqrt(this->distanceToLineSegmentBetweenSqd(a, b));
michael@0 483 }
michael@0 484
michael@0 485 /**
michael@0 486 * Make this vector be orthogonal to vec. Looking down vec the
michael@0 487 * new vector will point in direction indicated by side (which
michael@0 488 * must be kLeft_Side or kRight_Side).
michael@0 489 */
michael@0 490 void setOrthog(const SkPoint& vec, Side side = kLeft_Side) {
michael@0 491 // vec could be this
michael@0 492 SkScalar tmp = vec.fX;
michael@0 493 if (kRight_Side == side) {
michael@0 494 fX = -vec.fY;
michael@0 495 fY = tmp;
michael@0 496 } else {
michael@0 497 SkASSERT(kLeft_Side == side);
michael@0 498 fX = vec.fY;
michael@0 499 fY = -tmp;
michael@0 500 }
michael@0 501 }
michael@0 502
michael@0 503 /**
michael@0 504 * cast-safe way to treat the point as an array of (2) SkScalars.
michael@0 505 */
michael@0 506 const SkScalar* asScalars() const { return &fX; }
michael@0 507 };
michael@0 508
michael@0 509 typedef SkPoint SkVector;
michael@0 510
michael@0 511 #endif

mercurial