gfx/skia/trunk/include/core/SkPath.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 /*
michael@0 3 * Copyright 2006 The Android Open Source Project
michael@0 4 *
michael@0 5 * Use of this source code is governed by a BSD-style license that can be
michael@0 6 * found in the LICENSE file.
michael@0 7 */
michael@0 8
michael@0 9
michael@0 10 #ifndef SkPath_DEFINED
michael@0 11 #define SkPath_DEFINED
michael@0 12
michael@0 13 #include "SkInstCnt.h"
michael@0 14 #include "SkMatrix.h"
michael@0 15 #include "SkPathRef.h"
michael@0 16 #include "SkTDArray.h"
michael@0 17 #include "SkRefCnt.h"
michael@0 18
michael@0 19 class SkReader32;
michael@0 20 class SkWriter32;
michael@0 21 class SkAutoPathBoundsUpdate;
michael@0 22 class SkString;
michael@0 23 class SkRRect;
michael@0 24
michael@0 25 /** \class SkPath
michael@0 26
michael@0 27 The SkPath class encapsulates compound (multiple contour) geometric paths
michael@0 28 consisting of straight line segments, quadratic curves, and cubic curves.
michael@0 29 */
michael@0 30 class SK_API SkPath {
michael@0 31 public:
michael@0 32 SK_DECLARE_INST_COUNT_ROOT(SkPath);
michael@0 33
michael@0 34 SkPath();
michael@0 35 SkPath(const SkPath&);
michael@0 36 ~SkPath();
michael@0 37
michael@0 38 SkPath& operator=(const SkPath&);
michael@0 39 friend SK_API bool operator==(const SkPath&, const SkPath&);
michael@0 40 friend bool operator!=(const SkPath& a, const SkPath& b) {
michael@0 41 return !(a == b);
michael@0 42 }
michael@0 43
michael@0 44 enum FillType {
michael@0 45 /** Specifies that "inside" is computed by a non-zero sum of signed
michael@0 46 edge crossings
michael@0 47 */
michael@0 48 kWinding_FillType,
michael@0 49 /** Specifies that "inside" is computed by an odd number of edge
michael@0 50 crossings
michael@0 51 */
michael@0 52 kEvenOdd_FillType,
michael@0 53 /** Same as Winding, but draws outside of the path, rather than inside
michael@0 54 */
michael@0 55 kInverseWinding_FillType,
michael@0 56 /** Same as EvenOdd, but draws outside of the path, rather than inside
michael@0 57 */
michael@0 58 kInverseEvenOdd_FillType
michael@0 59 };
michael@0 60
michael@0 61 /** Return the path's fill type. This is used to define how "inside" is
michael@0 62 computed. The default value is kWinding_FillType.
michael@0 63
michael@0 64 @return the path's fill type
michael@0 65 */
michael@0 66 FillType getFillType() const { return (FillType)fFillType; }
michael@0 67
michael@0 68 /** Set the path's fill type. This is used to define how "inside" is
michael@0 69 computed. The default value is kWinding_FillType.
michael@0 70
michael@0 71 @param ft The new fill type for this path
michael@0 72 */
michael@0 73 void setFillType(FillType ft) {
michael@0 74 fFillType = SkToU8(ft);
michael@0 75 }
michael@0 76
michael@0 77 /** Returns true if the filltype is one of the Inverse variants */
michael@0 78 bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); }
michael@0 79
michael@0 80 /**
michael@0 81 * Toggle between inverse and normal filltypes. This reverse the return
michael@0 82 * value of isInverseFillType()
michael@0 83 */
michael@0 84 void toggleInverseFillType() {
michael@0 85 fFillType ^= 2;
michael@0 86 }
michael@0 87
michael@0 88 enum Convexity {
michael@0 89 kUnknown_Convexity,
michael@0 90 kConvex_Convexity,
michael@0 91 kConcave_Convexity
michael@0 92 };
michael@0 93
michael@0 94 /**
michael@0 95 * Return the path's convexity, as stored in the path. If it is currently unknown,
michael@0 96 * then this function will attempt to compute the convexity (and cache the result).
michael@0 97 */
michael@0 98 Convexity getConvexity() const {
michael@0 99 if (kUnknown_Convexity != fConvexity) {
michael@0 100 return static_cast<Convexity>(fConvexity);
michael@0 101 } else {
michael@0 102 return this->internalGetConvexity();
michael@0 103 }
michael@0 104 }
michael@0 105
michael@0 106 /**
michael@0 107 * Return the currently cached value for convexity, even if that is set to
michael@0 108 * kUnknown_Convexity. Note: getConvexity() will automatically call
michael@0 109 * ComputeConvexity and cache its return value if the current setting is
michael@0 110 * kUnknown.
michael@0 111 */
michael@0 112 Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; }
michael@0 113
michael@0 114 /**
michael@0 115 * Store a convexity setting in the path. There is no automatic check to
michael@0 116 * see if this value actually agrees with the return value that would be
michael@0 117 * computed by getConvexity().
michael@0 118 *
michael@0 119 * Note: even if this is set to a "known" value, if the path is later
michael@0 120 * changed (e.g. lineTo(), addRect(), etc.) then the cached value will be
michael@0 121 * reset to kUnknown_Convexity.
michael@0 122 */
michael@0 123 void setConvexity(Convexity);
michael@0 124
michael@0 125 /**
michael@0 126 * Returns true if the path is flagged as being convex. This is not a
michael@0 127 * confirmed by any analysis, it is just the value set earlier.
michael@0 128 */
michael@0 129 bool isConvex() const {
michael@0 130 return kConvex_Convexity == this->getConvexity();
michael@0 131 }
michael@0 132
michael@0 133 /**
michael@0 134 * Set the isConvex flag to true or false. Convex paths may draw faster if
michael@0 135 * this flag is set, though setting this to true on a path that is in fact
michael@0 136 * not convex can give undefined results when drawn. Paths default to
michael@0 137 * isConvex == false
michael@0 138 */
michael@0 139 SK_ATTR_DEPRECATED("use setConvexity")
michael@0 140 void setIsConvex(bool isConvex) {
michael@0 141 this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity);
michael@0 142 }
michael@0 143
michael@0 144 /** Returns true if the path is an oval.
michael@0 145 *
michael@0 146 * @param rect returns the bounding rect of this oval. It's a circle
michael@0 147 * if the height and width are the same.
michael@0 148 *
michael@0 149 * @return true if this path is an oval.
michael@0 150 * Tracking whether a path is an oval is considered an
michael@0 151 * optimization for performance and so some paths that are in
michael@0 152 * fact ovals can report false.
michael@0 153 */
michael@0 154 bool isOval(SkRect* rect) const { return fPathRef->isOval(rect); }
michael@0 155
michael@0 156 /** Clear any lines and curves from the path, making it empty. This frees up
michael@0 157 internal storage associated with those segments.
michael@0 158 On Android, does not change fSourcePath.
michael@0 159 */
michael@0 160 void reset();
michael@0 161
michael@0 162 /** Similar to reset(), in that all lines and curves are removed from the
michael@0 163 path. However, any internal storage for those lines/curves is retained,
michael@0 164 making reuse of the path potentially faster.
michael@0 165 On Android, does not change fSourcePath.
michael@0 166 */
michael@0 167 void rewind();
michael@0 168
michael@0 169 /** Returns true if the path is empty (contains no lines or curves)
michael@0 170
michael@0 171 @return true if the path is empty (contains no lines or curves)
michael@0 172 */
michael@0 173 bool isEmpty() const {
michael@0 174 SkDEBUGCODE(this->validate();)
michael@0 175 return 0 == fPathRef->countVerbs();
michael@0 176 }
michael@0 177
michael@0 178 /**
michael@0 179 * Returns true if all of the points in this path are finite, meaning there
michael@0 180 * are no infinities and no NaNs.
michael@0 181 */
michael@0 182 bool isFinite() const {
michael@0 183 SkDEBUGCODE(this->validate();)
michael@0 184 return fPathRef->isFinite();
michael@0 185 }
michael@0 186
michael@0 187 /** Test a line for zero length
michael@0 188
michael@0 189 @return true if the line is of zero length; otherwise false.
michael@0 190 */
michael@0 191 static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2) {
michael@0 192 return p1.equalsWithinTolerance(p2);
michael@0 193 }
michael@0 194
michael@0 195 /** Test a quad for zero length
michael@0 196
michael@0 197 @return true if the quad is of zero length; otherwise false.
michael@0 198 */
michael@0 199 static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2,
michael@0 200 const SkPoint& p3) {
michael@0 201 return p1.equalsWithinTolerance(p2) &&
michael@0 202 p2.equalsWithinTolerance(p3);
michael@0 203 }
michael@0 204
michael@0 205 /** Test a cubic curve for zero length
michael@0 206
michael@0 207 @return true if the cubic is of zero length; otherwise false.
michael@0 208 */
michael@0 209 static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2,
michael@0 210 const SkPoint& p3, const SkPoint& p4) {
michael@0 211 return p1.equalsWithinTolerance(p2) &&
michael@0 212 p2.equalsWithinTolerance(p3) &&
michael@0 213 p3.equalsWithinTolerance(p4);
michael@0 214 }
michael@0 215
michael@0 216 /**
michael@0 217 * Returns true if the path specifies a single line (i.e. it contains just
michael@0 218 * a moveTo and a lineTo). If so, and line[] is not null, it sets the 2
michael@0 219 * points in line[] to the end-points of the line. If the path is not a
michael@0 220 * line, returns false and ignores line[].
michael@0 221 */
michael@0 222 bool isLine(SkPoint line[2]) const;
michael@0 223
michael@0 224 /** Returns true if the path specifies a rectangle. If so, and if rect is
michael@0 225 not null, set rect to the bounds of the path. If the path does not
michael@0 226 specify a rectangle, return false and ignore rect.
michael@0 227
michael@0 228 @param rect If not null, returns the bounds of the path if it specifies
michael@0 229 a rectangle
michael@0 230 @return true if the path specifies a rectangle
michael@0 231 */
michael@0 232 bool isRect(SkRect* rect) const;
michael@0 233
michael@0 234 /** Return the number of points in the path
michael@0 235 */
michael@0 236 int countPoints() const;
michael@0 237
michael@0 238 /** Return the point at the specified index. If the index is out of range
michael@0 239 (i.e. is not 0 <= index < countPoints()) then the returned coordinates
michael@0 240 will be (0,0)
michael@0 241 */
michael@0 242 SkPoint getPoint(int index) const;
michael@0 243
michael@0 244 /** Returns the number of points in the path. Up to max points are copied.
michael@0 245
michael@0 246 @param points If not null, receives up to max points
michael@0 247 @param max The maximum number of points to copy into points
michael@0 248 @return the actual number of points in the path
michael@0 249 */
michael@0 250 int getPoints(SkPoint points[], int max) const;
michael@0 251
michael@0 252 /** Return the number of verbs in the path
michael@0 253 */
michael@0 254 int countVerbs() const;
michael@0 255
michael@0 256 /** Returns the number of verbs in the path. Up to max verbs are copied. The
michael@0 257 verbs are copied as one byte per verb.
michael@0 258
michael@0 259 @param verbs If not null, receives up to max verbs
michael@0 260 @param max The maximum number of verbs to copy into verbs
michael@0 261 @return the actual number of verbs in the path
michael@0 262 */
michael@0 263 int getVerbs(uint8_t verbs[], int max) const;
michael@0 264
michael@0 265 //! Swap contents of this and other. Guaranteed not to throw
michael@0 266 void swap(SkPath& other);
michael@0 267
michael@0 268 /** Returns the bounds of the path's points. If the path contains 0 or 1
michael@0 269 points, the bounds is set to (0,0,0,0), and isEmpty() will return true.
michael@0 270 Note: this bounds may be larger than the actual shape, since curves
michael@0 271 do not extend as far as their control points.
michael@0 272 */
michael@0 273 const SkRect& getBounds() const {
michael@0 274 return fPathRef->getBounds();
michael@0 275 }
michael@0 276
michael@0 277 /** Calling this will, if the internal cache of the bounds is out of date,
michael@0 278 update it so that subsequent calls to getBounds will be instantaneous.
michael@0 279 This also means that any copies or simple transformations of the path
michael@0 280 will inherit the cached bounds.
michael@0 281 */
michael@0 282 void updateBoundsCache() const {
michael@0 283 // for now, just calling getBounds() is sufficient
michael@0 284 this->getBounds();
michael@0 285 }
michael@0 286
michael@0 287 /**
michael@0 288 * Does a conservative test to see whether a rectangle is inside a path. Currently it only
michael@0 289 * will ever return true for single convex contour paths. The empty-status of the rect is not
michael@0 290 * considered (e.g. a rect that is a point can be inside a path). Points or line segments where
michael@0 291 * the rect edge touches the path border are not considered containment violations.
michael@0 292 */
michael@0 293 bool conservativelyContainsRect(const SkRect& rect) const;
michael@0 294
michael@0 295 // Construction methods
michael@0 296
michael@0 297 /** Hint to the path to prepare for adding more points. This can allow the
michael@0 298 path to more efficiently grow its storage.
michael@0 299
michael@0 300 @param extraPtCount The number of extra points the path should
michael@0 301 preallocate for.
michael@0 302 */
michael@0 303 void incReserve(unsigned extraPtCount);
michael@0 304
michael@0 305 /** Set the beginning of the next contour to the point (x,y).
michael@0 306
michael@0 307 @param x The x-coordinate of the start of a new contour
michael@0 308 @param y The y-coordinate of the start of a new contour
michael@0 309 */
michael@0 310 void moveTo(SkScalar x, SkScalar y);
michael@0 311
michael@0 312 /** Set the beginning of the next contour to the point
michael@0 313
michael@0 314 @param p The start of a new contour
michael@0 315 */
michael@0 316 void moveTo(const SkPoint& p) {
michael@0 317 this->moveTo(p.fX, p.fY);
michael@0 318 }
michael@0 319
michael@0 320 /** Set the beginning of the next contour relative to the last point on the
michael@0 321 previous contour. If there is no previous contour, this is treated the
michael@0 322 same as moveTo().
michael@0 323
michael@0 324 @param dx The amount to add to the x-coordinate of the end of the
michael@0 325 previous contour, to specify the start of a new contour
michael@0 326 @param dy The amount to add to the y-coordinate of the end of the
michael@0 327 previous contour, to specify the start of a new contour
michael@0 328 */
michael@0 329 void rMoveTo(SkScalar dx, SkScalar dy);
michael@0 330
michael@0 331 /** Add a line from the last point to the specified point (x,y). If no
michael@0 332 moveTo() call has been made for this contour, the first point is
michael@0 333 automatically set to (0,0).
michael@0 334
michael@0 335 @param x The x-coordinate of the end of a line
michael@0 336 @param y The y-coordinate of the end of a line
michael@0 337 */
michael@0 338 void lineTo(SkScalar x, SkScalar y);
michael@0 339
michael@0 340 /** Add a line from the last point to the specified point. If no moveTo()
michael@0 341 call has been made for this contour, the first point is automatically
michael@0 342 set to (0,0).
michael@0 343
michael@0 344 @param p The end of a line
michael@0 345 */
michael@0 346 void lineTo(const SkPoint& p) {
michael@0 347 this->lineTo(p.fX, p.fY);
michael@0 348 }
michael@0 349
michael@0 350 /** Same as lineTo, but the coordinates are considered relative to the last
michael@0 351 point on this contour. If there is no previous point, then a moveTo(0,0)
michael@0 352 is inserted automatically.
michael@0 353
michael@0 354 @param dx The amount to add to the x-coordinate of the previous point
michael@0 355 on this contour, to specify a line
michael@0 356 @param dy The amount to add to the y-coordinate of the previous point
michael@0 357 on this contour, to specify a line
michael@0 358 */
michael@0 359 void rLineTo(SkScalar dx, SkScalar dy);
michael@0 360
michael@0 361 /** Add a quadratic bezier from the last point, approaching control point
michael@0 362 (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
michael@0 363 this contour, the first point is automatically set to (0,0).
michael@0 364
michael@0 365 @param x1 The x-coordinate of the control point on a quadratic curve
michael@0 366 @param y1 The y-coordinate of the control point on a quadratic curve
michael@0 367 @param x2 The x-coordinate of the end point on a quadratic curve
michael@0 368 @param y2 The y-coordinate of the end point on a quadratic curve
michael@0 369 */
michael@0 370 void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
michael@0 371
michael@0 372 /** Add a quadratic bezier from the last point, approaching control point
michael@0 373 p1, and ending at p2. If no moveTo() call has been made for this
michael@0 374 contour, the first point is automatically set to (0,0).
michael@0 375
michael@0 376 @param p1 The control point on a quadratic curve
michael@0 377 @param p2 The end point on a quadratic curve
michael@0 378 */
michael@0 379 void quadTo(const SkPoint& p1, const SkPoint& p2) {
michael@0 380 this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
michael@0 381 }
michael@0 382
michael@0 383 /** Same as quadTo, but the coordinates are considered relative to the last
michael@0 384 point on this contour. If there is no previous point, then a moveTo(0,0)
michael@0 385 is inserted automatically.
michael@0 386
michael@0 387 @param dx1 The amount to add to the x-coordinate of the last point on
michael@0 388 this contour, to specify the control point of a quadratic curve
michael@0 389 @param dy1 The amount to add to the y-coordinate of the last point on
michael@0 390 this contour, to specify the control point of a quadratic curve
michael@0 391 @param dx2 The amount to add to the x-coordinate of the last point on
michael@0 392 this contour, to specify the end point of a quadratic curve
michael@0 393 @param dy2 The amount to add to the y-coordinate of the last point on
michael@0 394 this contour, to specify the end point of a quadratic curve
michael@0 395 */
michael@0 396 void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);
michael@0 397
michael@0 398 void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
michael@0 399 SkScalar w);
michael@0 400 void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) {
michael@0 401 this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w);
michael@0 402 }
michael@0 403 void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
michael@0 404 SkScalar w);
michael@0 405
michael@0 406 /** Add a cubic bezier from the last point, approaching control points
michael@0 407 (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
michael@0 408 made for this contour, the first point is automatically set to (0,0).
michael@0 409
michael@0 410 @param x1 The x-coordinate of the 1st control point on a cubic curve
michael@0 411 @param y1 The y-coordinate of the 1st control point on a cubic curve
michael@0 412 @param x2 The x-coordinate of the 2nd control point on a cubic curve
michael@0 413 @param y2 The y-coordinate of the 2nd control point on a cubic curve
michael@0 414 @param x3 The x-coordinate of the end point on a cubic curve
michael@0 415 @param y3 The y-coordinate of the end point on a cubic curve
michael@0 416 */
michael@0 417 void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
michael@0 418 SkScalar x3, SkScalar y3);
michael@0 419
michael@0 420 /** Add a cubic bezier from the last point, approaching control points p1
michael@0 421 and p2, and ending at p3. If no moveTo() call has been made for this
michael@0 422 contour, the first point is automatically set to (0,0).
michael@0 423
michael@0 424 @param p1 The 1st control point on a cubic curve
michael@0 425 @param p2 The 2nd control point on a cubic curve
michael@0 426 @param p3 The end point on a cubic curve
michael@0 427 */
michael@0 428 void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
michael@0 429 this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
michael@0 430 }
michael@0 431
michael@0 432 /** Same as cubicTo, but the coordinates are considered relative to the
michael@0 433 current point on this contour. If there is no previous point, then a
michael@0 434 moveTo(0,0) is inserted automatically.
michael@0 435
michael@0 436 @param dx1 The amount to add to the x-coordinate of the last point on
michael@0 437 this contour, to specify the 1st control point of a cubic curve
michael@0 438 @param dy1 The amount to add to the y-coordinate of the last point on
michael@0 439 this contour, to specify the 1st control point of a cubic curve
michael@0 440 @param dx2 The amount to add to the x-coordinate of the last point on
michael@0 441 this contour, to specify the 2nd control point of a cubic curve
michael@0 442 @param dy2 The amount to add to the y-coordinate of the last point on
michael@0 443 this contour, to specify the 2nd control point of a cubic curve
michael@0 444 @param dx3 The amount to add to the x-coordinate of the last point on
michael@0 445 this contour, to specify the end point of a cubic curve
michael@0 446 @param dy3 The amount to add to the y-coordinate of the last point on
michael@0 447 this contour, to specify the end point of a cubic curve
michael@0 448 */
michael@0 449 void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
michael@0 450 SkScalar x3, SkScalar y3);
michael@0 451
michael@0 452 /** Append the specified arc to the path as a new contour. If the start of
michael@0 453 the path is different from the path's current last point, then an
michael@0 454 automatic lineTo() is added to connect the current contour to the start
michael@0 455 of the arc. However, if the path is empty, then we call moveTo() with
michael@0 456 the first point of the arc. The sweep angle is treated mod 360.
michael@0 457
michael@0 458 @param oval The bounding oval defining the shape and size of the arc
michael@0 459 @param startAngle Starting angle (in degrees) where the arc begins
michael@0 460 @param sweepAngle Sweep angle (in degrees) measured clockwise. This is
michael@0 461 treated mod 360.
michael@0 462 @param forceMoveTo If true, always begin a new contour with the arc
michael@0 463 */
michael@0 464 void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
michael@0 465 bool forceMoveTo);
michael@0 466
michael@0 467 /** Append a line and arc to the current path. This is the same as the
michael@0 468 PostScript call "arct".
michael@0 469 */
michael@0 470 void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
michael@0 471 SkScalar radius);
michael@0 472
michael@0 473 /** Append a line and arc to the current path. This is the same as the
michael@0 474 PostScript call "arct".
michael@0 475 */
michael@0 476 void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
michael@0 477 this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
michael@0 478 }
michael@0 479
michael@0 480 /** Close the current contour. If the current point is not equal to the
michael@0 481 first point of the contour, a line segment is automatically added.
michael@0 482 */
michael@0 483 void close();
michael@0 484
michael@0 485 enum Direction {
michael@0 486 /** Direction either has not been or could not be computed */
michael@0 487 kUnknown_Direction,
michael@0 488 /** clockwise direction for adding closed contours */
michael@0 489 kCW_Direction,
michael@0 490 /** counter-clockwise direction for adding closed contours */
michael@0 491 kCCW_Direction,
michael@0 492 };
michael@0 493
michael@0 494 /**
michael@0 495 * Return the opposite of the specified direction. kUnknown is its own
michael@0 496 * opposite.
michael@0 497 */
michael@0 498 static Direction OppositeDirection(Direction dir) {
michael@0 499 static const Direction gOppositeDir[] = {
michael@0 500 kUnknown_Direction, kCCW_Direction, kCW_Direction
michael@0 501 };
michael@0 502 return gOppositeDir[dir];
michael@0 503 }
michael@0 504
michael@0 505 /**
michael@0 506 * Returns whether or not a fill type is inverted
michael@0 507 *
michael@0 508 * kWinding_FillType -> false
michael@0 509 * kEvenOdd_FillType -> false
michael@0 510 * kInverseWinding_FillType -> true
michael@0 511 * kInverseEvenOdd_FillType -> true
michael@0 512 */
michael@0 513 static bool IsInverseFillType(FillType fill) {
michael@0 514 SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
michael@0 515 SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
michael@0 516 SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);
michael@0 517 SK_COMPILE_ASSERT(3 == kInverseEvenOdd_FillType, fill_type_mismatch);
michael@0 518 return (fill & 2) != 0;
michael@0 519 }
michael@0 520
michael@0 521 /**
michael@0 522 * Returns the equivalent non-inverted fill type to the given fill type
michael@0 523 *
michael@0 524 * kWinding_FillType -> kWinding_FillType
michael@0 525 * kEvenOdd_FillType -> kEvenOdd_FillType
michael@0 526 * kInverseWinding_FillType -> kWinding_FillType
michael@0 527 * kInverseEvenOdd_FillType -> kEvenOdd_FillType
michael@0 528 */
michael@0 529 static FillType ConvertToNonInverseFillType(FillType fill) {
michael@0 530 SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
michael@0 531 SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
michael@0 532 SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);
michael@0 533 SK_COMPILE_ASSERT(3 == kInverseEvenOdd_FillType, fill_type_mismatch);
michael@0 534 return (FillType)(fill & 1);
michael@0 535 }
michael@0 536
michael@0 537 /**
michael@0 538 * Tries to quickly compute the direction of the first non-degenerate
michael@0 539 * contour. If it can be computed, return true and set dir to that
michael@0 540 * direction. If it cannot be (quickly) determined, return false and ignore
michael@0 541 * the dir parameter. If the direction was determined, it is cached to make
michael@0 542 * subsequent calls return quickly.
michael@0 543 */
michael@0 544 bool cheapComputeDirection(Direction* dir) const;
michael@0 545
michael@0 546 /**
michael@0 547 * Returns true if the path's direction can be computed via
michael@0 548 * cheapComputDirection() and if that computed direction matches the
michael@0 549 * specified direction. If dir is kUnknown, returns true if the direction
michael@0 550 * cannot be computed.
michael@0 551 */
michael@0 552 bool cheapIsDirection(Direction dir) const {
michael@0 553 Direction computedDir = kUnknown_Direction;
michael@0 554 (void)this->cheapComputeDirection(&computedDir);
michael@0 555 return computedDir == dir;
michael@0 556 }
michael@0 557
michael@0 558 enum PathAsRect {
michael@0 559 /** The path can not draw the same as its bounds. */
michael@0 560 kNone_PathAsRect,
michael@0 561 /** The path draws the same as its bounds when filled. */
michael@0 562 kFill_PathAsRect,
michael@0 563 /** The path draws the same as its bounds when stroked or filled. */
michael@0 564 kStroke_PathAsRect,
michael@0 565 };
michael@0 566
michael@0 567 /** Returns kFill_PathAsRect or kStroke_PathAsRect if drawing the path (either filled or
michael@0 568 stroked) will be equivalent to filling/stroking the path's bounding rect. If
michael@0 569 either is true, and direction is not null, sets the direction of the contour. If the
michael@0 570 path is not drawn equivalent to a rect, returns kNone_PathAsRect and ignores direction.
michael@0 571
michael@0 572 @param direction If not null, set to the contour's direction when it is drawn as a rect
michael@0 573 @return the path's PathAsRect type
michael@0 574 */
michael@0 575 PathAsRect asRect(Direction* direction = NULL) const;
michael@0 576
michael@0 577 /** Returns true if the path specifies a rectangle. If so, and if isClosed is
michael@0 578 not null, set isClosed to true if the path is closed. Also, if returning true
michael@0 579 and direction is not null, return the rect direction. If the path does not
michael@0 580 specify a rectangle, return false and ignore isClosed and direction.
michael@0 581
michael@0 582 @param isClosed If not null, set to true if the path is closed
michael@0 583 @param direction If not null, set to the rectangle's direction
michael@0 584 @return true if the path specifies a rectangle
michael@0 585 */
michael@0 586 bool isRect(bool* isClosed, Direction* direction) const;
michael@0 587
michael@0 588 /** Returns true if the path specifies a pair of nested rectangles. If so, and if
michael@0 589 rect is not null, set rect[0] to the outer rectangle and rect[1] to the inner
michael@0 590 rectangle. If so, and dirs is not null, set dirs[0] to the direction of
michael@0 591 the outer rectangle and dirs[1] to the direction of the inner rectangle. If
michael@0 592 the path does not specify a pair of nested rectangles, return
michael@0 593 false and ignore rect and dirs.
michael@0 594
michael@0 595 @param rect If not null, returns the path as a pair of nested rectangles
michael@0 596 @param dirs If not null, returns the direction of the rects
michael@0 597 @return true if the path describes a pair of nested rectangles
michael@0 598 */
michael@0 599 bool isNestedRects(SkRect rect[2], Direction dirs[2] = NULL) const;
michael@0 600
michael@0 601 /**
michael@0 602 * Add a closed rectangle contour to the path
michael@0 603 * @param rect The rectangle to add as a closed contour to the path
michael@0 604 * @param dir The direction to wind the rectangle's contour. Cannot be
michael@0 605 * kUnknown_Direction.
michael@0 606 */
michael@0 607 void addRect(const SkRect& rect, Direction dir = kCW_Direction);
michael@0 608
michael@0 609 /**
michael@0 610 * Add a closed rectangle contour to the path
michael@0 611 *
michael@0 612 * @param left The left side of a rectangle to add as a closed contour
michael@0 613 * to the path
michael@0 614 * @param top The top of a rectangle to add as a closed contour to the
michael@0 615 * path
michael@0 616 * @param right The right side of a rectangle to add as a closed contour
michael@0 617 * to the path
michael@0 618 * @param bottom The bottom of a rectangle to add as a closed contour to
michael@0 619 * the path
michael@0 620 * @param dir The direction to wind the rectangle's contour. Cannot be
michael@0 621 * kUnknown_Direction.
michael@0 622 */
michael@0 623 void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
michael@0 624 Direction dir = kCW_Direction);
michael@0 625
michael@0 626 /**
michael@0 627 * Add a closed oval contour to the path
michael@0 628 *
michael@0 629 * @param oval The bounding oval to add as a closed contour to the path
michael@0 630 * @param dir The direction to wind the oval's contour. Cannot be
michael@0 631 * kUnknown_Direction.
michael@0 632 */
michael@0 633 void addOval(const SkRect& oval, Direction dir = kCW_Direction);
michael@0 634
michael@0 635 /**
michael@0 636 * Add a closed circle contour to the path
michael@0 637 *
michael@0 638 * @param x The x-coordinate of the center of a circle to add as a
michael@0 639 * closed contour to the path
michael@0 640 * @param y The y-coordinate of the center of a circle to add as a
michael@0 641 * closed contour to the path
michael@0 642 * @param radius The radius of a circle to add as a closed contour to the
michael@0 643 * path
michael@0 644 * @param dir The direction to wind the circle's contour. Cannot be
michael@0 645 * kUnknown_Direction.
michael@0 646 */
michael@0 647 void addCircle(SkScalar x, SkScalar y, SkScalar radius,
michael@0 648 Direction dir = kCW_Direction);
michael@0 649
michael@0 650 /** Add the specified arc to the path as a new contour.
michael@0 651
michael@0 652 @param oval The bounds of oval used to define the size of the arc
michael@0 653 @param startAngle Starting angle (in degrees) where the arc begins
michael@0 654 @param sweepAngle Sweep angle (in degrees) measured clockwise
michael@0 655 */
michael@0 656 void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);
michael@0 657
michael@0 658 /**
michael@0 659 * Add a closed round-rectangle contour to the path
michael@0 660 * @param rect The bounds of a round-rectangle to add as a closed contour
michael@0 661 * @param rx The x-radius of the rounded corners on the round-rectangle
michael@0 662 * @param ry The y-radius of the rounded corners on the round-rectangle
michael@0 663 * @param dir The direction to wind the rectangle's contour. Cannot be
michael@0 664 * kUnknown_Direction.
michael@0 665 */
michael@0 666 void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
michael@0 667 Direction dir = kCW_Direction);
michael@0 668
michael@0 669 /**
michael@0 670 * Add a closed round-rectangle contour to the path. Each corner receives
michael@0 671 * two radius values [X, Y]. The corners are ordered top-left, top-right,
michael@0 672 * bottom-right, bottom-left.
michael@0 673 * @param rect The bounds of a round-rectangle to add as a closed contour
michael@0 674 * @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner
michael@0 675 * @param dir The direction to wind the rectangle's contour. Cannot be
michael@0 676 * kUnknown_Direction.
michael@0 677 * Note: The radii here now go through the same constraint handling as the
michael@0 678 * SkRRect radii (i.e., either radii at a corner being 0 implies a
michael@0 679 * sqaure corner and oversized radii are proportionally scaled down).
michael@0 680 */
michael@0 681 void addRoundRect(const SkRect& rect, const SkScalar radii[],
michael@0 682 Direction dir = kCW_Direction);
michael@0 683
michael@0 684 /**
michael@0 685 * Add an SkRRect contour to the path
michael@0 686 * @param rrect The rounded rect to add as a closed contour
michael@0 687 * @param dir The winding direction for the new contour. Cannot be
michael@0 688 * kUnknown_Direction.
michael@0 689 */
michael@0 690 void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction);
michael@0 691
michael@0 692 /**
michael@0 693 * Add a new contour made of just lines. This is just a fast version of
michael@0 694 * the following:
michael@0 695 * this->moveTo(pts[0]);
michael@0 696 * for (int i = 1; i < count; ++i) {
michael@0 697 * this->lineTo(pts[i]);
michael@0 698 * }
michael@0 699 * if (close) {
michael@0 700 * this->close();
michael@0 701 * }
michael@0 702 */
michael@0 703 void addPoly(const SkPoint pts[], int count, bool close);
michael@0 704
michael@0 705 enum AddPathMode {
michael@0 706 /** Source path contours are added as new contours.
michael@0 707 */
michael@0 708 kAppend_AddPathMode,
michael@0 709 /** Path is added by extending the last contour of the destination path
michael@0 710 with the first contour of the source path. If the last contour of
michael@0 711 the destination path is closed, then it will not be extended.
michael@0 712 Instead, the start of source path will be extended by a straight
michael@0 713 line to the end point of the destination path.
michael@0 714 */
michael@0 715 kExtend_AddPathMode
michael@0 716 };
michael@0 717
michael@0 718 /** Add a copy of src to the path, offset by (dx,dy)
michael@0 719 @param src The path to add as a new contour
michael@0 720 @param dx The amount to translate the path in X as it is added
michael@0 721 @param dx The amount to translate the path in Y as it is added
michael@0 722 */
michael@0 723 void addPath(const SkPath& src, SkScalar dx, SkScalar dy,
michael@0 724 AddPathMode mode = kAppend_AddPathMode);
michael@0 725
michael@0 726 /** Add a copy of src to the path
michael@0 727 */
michael@0 728 void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) {
michael@0 729 SkMatrix m;
michael@0 730 m.reset();
michael@0 731 this->addPath(src, m, mode);
michael@0 732 }
michael@0 733
michael@0 734 /** Add a copy of src to the path, transformed by matrix
michael@0 735 @param src The path to add as a new contour
michael@0 736 @param matrix Transform applied to src
michael@0 737 @param mode Determines how path is added
michael@0 738 */
michael@0 739 void addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode);
michael@0 740
michael@0 741 /**
michael@0 742 * Same as addPath(), but reverses the src input
michael@0 743 */
michael@0 744 void reverseAddPath(const SkPath& src);
michael@0 745
michael@0 746 /** Offset the path by (dx,dy), returning true on success
michael@0 747
michael@0 748 @param dx The amount in the X direction to offset the entire path
michael@0 749 @param dy The amount in the Y direction to offset the entire path
michael@0 750 @param dst The translated path is written here
michael@0 751 */
michael@0 752 void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;
michael@0 753
michael@0 754 /** Offset the path by (dx,dy), returning true on success
michael@0 755
michael@0 756 @param dx The amount in the X direction to offset the entire path
michael@0 757 @param dy The amount in the Y direction to offset the entire path
michael@0 758 */
michael@0 759 void offset(SkScalar dx, SkScalar dy) {
michael@0 760 this->offset(dx, dy, this);
michael@0 761 }
michael@0 762
michael@0 763 /** Transform the points in this path by matrix, and write the answer into
michael@0 764 dst.
michael@0 765
michael@0 766 @param matrix The matrix to apply to the path
michael@0 767 @param dst The transformed path is written here
michael@0 768 */
michael@0 769 void transform(const SkMatrix& matrix, SkPath* dst) const;
michael@0 770
michael@0 771 /** Transform the points in this path by matrix
michael@0 772
michael@0 773 @param matrix The matrix to apply to the path
michael@0 774 */
michael@0 775 void transform(const SkMatrix& matrix) {
michael@0 776 this->transform(matrix, this);
michael@0 777 }
michael@0 778
michael@0 779 /** Return the last point on the path. If no points have been added, (0,0)
michael@0 780 is returned. If there are no points, this returns false, otherwise it
michael@0 781 returns true.
michael@0 782
michael@0 783 @param lastPt The last point on the path is returned here
michael@0 784 */
michael@0 785 bool getLastPt(SkPoint* lastPt) const;
michael@0 786
michael@0 787 /** Set the last point on the path. If no points have been added,
michael@0 788 moveTo(x,y) is automatically called.
michael@0 789
michael@0 790 @param x The new x-coordinate for the last point
michael@0 791 @param y The new y-coordinate for the last point
michael@0 792 */
michael@0 793 void setLastPt(SkScalar x, SkScalar y);
michael@0 794
michael@0 795 /** Set the last point on the path. If no points have been added, moveTo(p)
michael@0 796 is automatically called.
michael@0 797
michael@0 798 @param p The new location for the last point
michael@0 799 */
michael@0 800 void setLastPt(const SkPoint& p) {
michael@0 801 this->setLastPt(p.fX, p.fY);
michael@0 802 }
michael@0 803
michael@0 804 enum SegmentMask {
michael@0 805 kLine_SegmentMask = 1 << 0,
michael@0 806 kQuad_SegmentMask = 1 << 1,
michael@0 807 kConic_SegmentMask = 1 << 2,
michael@0 808 kCubic_SegmentMask = 1 << 3,
michael@0 809 };
michael@0 810
michael@0 811 /**
michael@0 812 * Returns a mask, where each bit corresponding to a SegmentMask is
michael@0 813 * set if the path contains 1 or more segments of that type.
michael@0 814 * Returns 0 for an empty path (no segments).
michael@0 815 */
michael@0 816 uint32_t getSegmentMasks() const { return fPathRef->getSegmentMasks(); }
michael@0 817
michael@0 818 enum Verb {
michael@0 819 kMove_Verb, //!< iter.next returns 1 point
michael@0 820 kLine_Verb, //!< iter.next returns 2 points
michael@0 821 kQuad_Verb, //!< iter.next returns 3 points
michael@0 822 kConic_Verb, //!< iter.next returns 3 points + iter.conicWeight()
michael@0 823 kCubic_Verb, //!< iter.next returns 4 points
michael@0 824 kClose_Verb, //!< iter.next returns 1 point (contour's moveTo pt)
michael@0 825 kDone_Verb, //!< iter.next returns 0 points
michael@0 826 };
michael@0 827
michael@0 828 /** Iterate through all of the segments (lines, quadratics, cubics) of
michael@0 829 each contours in a path.
michael@0 830
michael@0 831 The iterator cleans up the segments along the way, removing degenerate
michael@0 832 segments and adding close verbs where necessary. When the forceClose
michael@0 833 argument is provided, each contour (as defined by a new starting
michael@0 834 move command) will be completed with a close verb regardless of the
michael@0 835 contour's contents.
michael@0 836 */
michael@0 837 class SK_API Iter {
michael@0 838 public:
michael@0 839 Iter();
michael@0 840 Iter(const SkPath&, bool forceClose);
michael@0 841
michael@0 842 void setPath(const SkPath&, bool forceClose);
michael@0 843
michael@0 844 /** Return the next verb in this iteration of the path. When all
michael@0 845 segments have been visited, return kDone_Verb.
michael@0 846
michael@0 847 @param pts The points representing the current verb and/or segment
michael@0 848 @param doConsumeDegerates If true, first scan for segments that are
michael@0 849 deemed degenerate (too short) and skip those.
michael@0 850 @return The verb for the current segment
michael@0 851 */
michael@0 852 Verb next(SkPoint pts[4], bool doConsumeDegerates = true) {
michael@0 853 if (doConsumeDegerates) {
michael@0 854 this->consumeDegenerateSegments();
michael@0 855 }
michael@0 856 return this->doNext(pts);
michael@0 857 }
michael@0 858
michael@0 859 /**
michael@0 860 * Return the weight for the current conic. Only valid if the current
michael@0 861 * segment return by next() was a conic.
michael@0 862 */
michael@0 863 SkScalar conicWeight() const { return *fConicWeights; }
michael@0 864
michael@0 865 /** If next() returns kLine_Verb, then this query returns true if the
michael@0 866 line was the result of a close() command (i.e. the end point is the
michael@0 867 initial moveto for this contour). If next() returned a different
michael@0 868 verb, this returns an undefined value.
michael@0 869
michael@0 870 @return If the last call to next() returned kLine_Verb, return true
michael@0 871 if it was the result of an explicit close command.
michael@0 872 */
michael@0 873 bool isCloseLine() const { return SkToBool(fCloseLine); }
michael@0 874
michael@0 875 /** Returns true if the current contour is closed (has a kClose_Verb)
michael@0 876 @return true if the current contour is closed (has a kClose_Verb)
michael@0 877 */
michael@0 878 bool isClosedContour() const;
michael@0 879
michael@0 880 private:
michael@0 881 const SkPoint* fPts;
michael@0 882 const uint8_t* fVerbs;
michael@0 883 const uint8_t* fVerbStop;
michael@0 884 const SkScalar* fConicWeights;
michael@0 885 SkPoint fMoveTo;
michael@0 886 SkPoint fLastPt;
michael@0 887 SkBool8 fForceClose;
michael@0 888 SkBool8 fNeedClose;
michael@0 889 SkBool8 fCloseLine;
michael@0 890 SkBool8 fSegmentState;
michael@0 891
michael@0 892 inline const SkPoint& cons_moveTo();
michael@0 893 Verb autoClose(SkPoint pts[2]);
michael@0 894 void consumeDegenerateSegments();
michael@0 895 Verb doNext(SkPoint pts[4]);
michael@0 896 };
michael@0 897
michael@0 898 /** Iterate through the verbs in the path, providing the associated points.
michael@0 899 */
michael@0 900 class SK_API RawIter {
michael@0 901 public:
michael@0 902 RawIter();
michael@0 903 RawIter(const SkPath&);
michael@0 904
michael@0 905 void setPath(const SkPath&);
michael@0 906
michael@0 907 /** Return the next verb in this iteration of the path. When all
michael@0 908 segments have been visited, return kDone_Verb.
michael@0 909
michael@0 910 @param pts The points representing the current verb and/or segment
michael@0 911 This must not be NULL.
michael@0 912 @return The verb for the current segment
michael@0 913 */
michael@0 914 Verb next(SkPoint pts[4]);
michael@0 915
michael@0 916 SkScalar conicWeight() const { return *fConicWeights; }
michael@0 917
michael@0 918 private:
michael@0 919 const SkPoint* fPts;
michael@0 920 const uint8_t* fVerbs;
michael@0 921 const uint8_t* fVerbStop;
michael@0 922 const SkScalar* fConicWeights;
michael@0 923 SkPoint fMoveTo;
michael@0 924 SkPoint fLastPt;
michael@0 925 };
michael@0 926
michael@0 927 /**
michael@0 928 * Returns true if the point { x, y } is contained by the path, taking into
michael@0 929 * account the FillType.
michael@0 930 */
michael@0 931 bool contains(SkScalar x, SkScalar y) const;
michael@0 932
michael@0 933 void dump(bool forceClose, const char title[] = NULL) const;
michael@0 934 void dump() const;
michael@0 935
michael@0 936 /**
michael@0 937 * Write the path to the buffer, and return the number of bytes written.
michael@0 938 * If buffer is NULL, it still returns the number of bytes.
michael@0 939 */
michael@0 940 size_t writeToMemory(void* buffer) const;
michael@0 941 /**
michael@0 942 * Initializes the path from the buffer
michael@0 943 *
michael@0 944 * @param buffer Memory to read from
michael@0 945 * @param length Amount of memory available in the buffer
michael@0 946 * @return number of bytes read (must be a multiple of 4) or
michael@0 947 * 0 if there was not enough memory available
michael@0 948 */
michael@0 949 size_t readFromMemory(const void* buffer, size_t length);
michael@0 950
michael@0 951 /** Returns a non-zero, globally unique value corresponding to the set of verbs
michael@0 952 and points in the path (but not the fill type [except on Android skbug.com/1762]).
michael@0 953 Each time the path is modified, a different generation ID will be returned.
michael@0 954 */
michael@0 955 uint32_t getGenerationID() const;
michael@0 956
michael@0 957 #ifdef SK_BUILD_FOR_ANDROID
michael@0 958 static const int kPathRefGenIDBitCnt = 30; // leave room for the fill type (skbug.com/1762)
michael@0 959 const SkPath* getSourcePath() const;
michael@0 960 void setSourcePath(const SkPath* path);
michael@0 961 #else
michael@0 962 static const int kPathRefGenIDBitCnt = 32;
michael@0 963 #endif
michael@0 964
michael@0 965 SkDEBUGCODE(void validate() const;)
michael@0 966
michael@0 967 private:
michael@0 968 enum SerializationOffsets {
michael@0 969 // 1 free bit at 29
michael@0 970 kUnused1_SerializationShift = 28, // 1 free bit
michael@0 971 kDirection_SerializationShift = 26, // requires 2 bits
michael@0 972 kUnused2_SerializationShift = 25, // 1 free bit
michael@0 973 // 1 free bit at 24
michael@0 974 kConvexity_SerializationShift = 16, // requires 8 bits
michael@0 975 kFillType_SerializationShift = 8, // requires 8 bits
michael@0 976 // 8 free bits at 0
michael@0 977 };
michael@0 978
michael@0 979 SkAutoTUnref<SkPathRef> fPathRef;
michael@0 980
michael@0 981 int fLastMoveToIndex;
michael@0 982 uint8_t fFillType;
michael@0 983 mutable uint8_t fConvexity;
michael@0 984 mutable uint8_t fDirection;
michael@0 985 #ifdef SK_BUILD_FOR_ANDROID
michael@0 986 const SkPath* fSourcePath;
michael@0 987 #endif
michael@0 988
michael@0 989 /** Resets all fields other than fPathRef to their initial 'empty' values.
michael@0 990 * Assumes the caller has already emptied fPathRef.
michael@0 991 * On Android increments fGenerationID without reseting it.
michael@0 992 */
michael@0 993 void resetFields();
michael@0 994
michael@0 995 /** Sets all fields other than fPathRef to the values in 'that'.
michael@0 996 * Assumes the caller has already set fPathRef.
michael@0 997 * Doesn't change fGenerationID or fSourcePath on Android.
michael@0 998 */
michael@0 999 void copyFields(const SkPath& that);
michael@0 1000
michael@0 1001 friend class Iter;
michael@0 1002
michael@0 1003 friend class SkPathStroker;
michael@0 1004
michael@0 1005 /* Append, in reverse order, the first contour of path, ignoring path's
michael@0 1006 last point. If no moveTo() call has been made for this contour, the
michael@0 1007 first point is automatically set to (0,0).
michael@0 1008 */
michael@0 1009 void reversePathTo(const SkPath&);
michael@0 1010
michael@0 1011 // called before we add points for lineTo, quadTo, cubicTo, checking to see
michael@0 1012 // if we need to inject a leading moveTo first
michael@0 1013 //
michael@0 1014 // SkPath path; path.lineTo(...); <--- need a leading moveTo(0, 0)
michael@0 1015 // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo)
michael@0 1016 //
michael@0 1017 inline void injectMoveToIfNeeded();
michael@0 1018
michael@0 1019 inline bool hasOnlyMoveTos() const;
michael@0 1020
michael@0 1021 Convexity internalGetConvexity() const;
michael@0 1022
michael@0 1023 bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts,
michael@0 1024 bool* isClosed, Direction* direction) const;
michael@0 1025
michael@0 1026 /** Returns if the path can return a bound at no cost (true) or will have to
michael@0 1027 perform some computation (false).
michael@0 1028 */
michael@0 1029 bool hasComputedBounds() const {
michael@0 1030 SkDEBUGCODE(this->validate();)
michael@0 1031 return fPathRef->hasComputedBounds();
michael@0 1032 }
michael@0 1033
michael@0 1034
michael@0 1035 // 'rect' needs to be sorted
michael@0 1036 void setBounds(const SkRect& rect) {
michael@0 1037 SkPathRef::Editor ed(&fPathRef);
michael@0 1038
michael@0 1039 ed.setBounds(rect);
michael@0 1040 }
michael@0 1041
michael@0 1042 friend class SkAutoPathBoundsUpdate;
michael@0 1043 friend class SkAutoDisableOvalCheck;
michael@0 1044 friend class SkAutoDisableDirectionCheck;
michael@0 1045 friend class SkBench_AddPathTest; // perf test reversePathTo
michael@0 1046 friend class PathTest_Private; // unit test reversePathTo
michael@0 1047 };
michael@0 1048
michael@0 1049 #endif

mercurial