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