OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #ifndef SkPath_DEFINED | 10 #ifndef SkPath_DEFINED |
11 #define SkPath_DEFINED | 11 #define SkPath_DEFINED |
12 | 12 |
13 #include "SkInstCnt.h" | 13 #include "SkInstCnt.h" |
14 #include "SkMatrix.h" | 14 #include "SkMatrix.h" |
| 15 #include "SkPathRef.h" |
15 #include "SkTDArray.h" | 16 #include "SkTDArray.h" |
16 #include "SkRefCnt.h" | 17 #include "SkRefCnt.h" |
17 | 18 |
18 #ifdef SK_BUILD_FOR_ANDROID | 19 #ifdef SK_BUILD_FOR_ANDROID |
19 #define GEN_ID_INC fGenerationID++ | 20 #define GEN_ID_INC fGenerationID++ |
20 #define GEN_ID_PTR_INC(ptr) (ptr)->fGenerationID++ | 21 #define GEN_ID_PTR_INC(ptr) (ptr)->fGenerationID++ |
21 #else | 22 #else |
22 #define GEN_ID_INC | 23 #define GEN_ID_INC |
23 #define GEN_ID_PTR_INC(ptr) | 24 #define GEN_ID_PTR_INC(ptr) |
24 #endif | 25 #endif |
25 | 26 |
26 class SkReader32; | 27 class SkReader32; |
27 class SkWriter32; | 28 class SkWriter32; |
28 class SkAutoPathBoundsUpdate; | 29 class SkAutoPathBoundsUpdate; |
29 class SkString; | 30 class SkString; |
30 class SkPathRef; | |
31 class SkRRect; | 31 class SkRRect; |
32 | 32 |
33 /** \class SkPath | 33 /** \class SkPath |
34 | 34 |
35 The SkPath class encapsulates compound (multiple contour) geometric paths | 35 The SkPath class encapsulates compound (multiple contour) geometric paths |
36 consisting of straight line segments, quadratic curves, and cubic curves. | 36 consisting of straight line segments, quadratic curves, and cubic curves. |
37 */ | 37 */ |
38 class SK_API SkPath { | 38 class SK_API SkPath { |
39 public: | 39 public: |
40 SK_DECLARE_INST_COUNT_ROOT(SkPath); | 40 SK_DECLARE_INST_COUNT_ROOT(SkPath); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 path. However, any internal storage for those lines/curves is retained, | 174 path. However, any internal storage for those lines/curves is retained, |
175 making reuse of the path potentially faster. | 175 making reuse of the path potentially faster. |
176 On Android, does not change fSourcePath. | 176 On Android, does not change fSourcePath. |
177 */ | 177 */ |
178 void rewind(); | 178 void rewind(); |
179 | 179 |
180 /** Returns true if the path is empty (contains no lines or curves) | 180 /** Returns true if the path is empty (contains no lines or curves) |
181 | 181 |
182 @return true if the path is empty (contains no lines or curves) | 182 @return true if the path is empty (contains no lines or curves) |
183 */ | 183 */ |
184 bool isEmpty() const; | 184 bool isEmpty() const { |
| 185 SkDEBUGCODE(this->validate();) |
| 186 return 0 == fPathRef->countVerbs(); |
| 187 } |
185 | 188 |
186 /** | 189 /** |
187 * Returns true if all of the points in this path are finite, meaning there | 190 * Returns true if all of the points in this path are finite, meaning there |
188 * are no infinities and no NaNs. | 191 * are no infinities and no NaNs. |
189 */ | 192 */ |
190 bool isFinite() const { | 193 bool isFinite() const { |
191 if (fBoundsIsDirty) { | 194 SkDEBUGCODE(this->validate();) |
192 this->computeBounds(); | 195 return fPathRef->isFinite(); |
193 } | |
194 return SkToBool(fIsFinite); | |
195 } | 196 } |
196 | 197 |
197 /** Test a line for zero length | 198 /** Test a line for zero length |
198 | 199 |
199 @return true if the line is of zero length; otherwise false. | 200 @return true if the line is of zero length; otherwise false. |
200 */ | 201 */ |
201 static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2) { | 202 static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2) { |
202 return p1.equalsWithinTolerance(p2); | 203 return p1.equalsWithinTolerance(p2); |
203 } | 204 } |
204 | 205 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 | 275 |
275 //! Swap contents of this and other. Guaranteed not to throw | 276 //! Swap contents of this and other. Guaranteed not to throw |
276 void swap(SkPath& other); | 277 void swap(SkPath& other); |
277 | 278 |
278 /** Returns the bounds of the path's points. If the path contains 0 or 1 | 279 /** Returns the bounds of the path's points. If the path contains 0 or 1 |
279 points, the bounds is set to (0,0,0,0), and isEmpty() will return true. | 280 points, the bounds is set to (0,0,0,0), and isEmpty() will return true. |
280 Note: this bounds may be larger than the actual shape, since curves | 281 Note: this bounds may be larger than the actual shape, since curves |
281 do not extend as far as their control points. | 282 do not extend as far as their control points. |
282 */ | 283 */ |
283 const SkRect& getBounds() const { | 284 const SkRect& getBounds() const { |
284 if (fBoundsIsDirty) { | 285 return fPathRef->getBounds(); |
285 this->computeBounds(); | |
286 } | |
287 return fBounds; | |
288 } | 286 } |
289 | 287 |
290 /** Calling this will, if the internal cache of the bounds is out of date, | 288 /** Calling this will, if the internal cache of the bounds is out of date, |
291 update it so that subsequent calls to getBounds will be instantaneous. | 289 update it so that subsequent calls to getBounds will be instantaneous. |
292 This also means that any copies or simple transformations of the path | 290 This also means that any copies or simple transformations of the path |
293 will inherit the cached bounds. | 291 will inherit the cached bounds. |
294 */ | 292 */ |
295 void updateBoundsCache() const { | 293 void updateBoundsCache() const { |
296 // for now, just calling getBounds() is sufficient | 294 // for now, just calling getBounds() is sufficient |
297 this->getBounds(); | 295 this->getBounds(); |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
591 @return true if the path describes a pair of nested rectangles | 589 @return true if the path describes a pair of nested rectangles |
592 */ | 590 */ |
593 bool isNestedRects(SkRect rect[2], Direction dirs[2] = NULL) const; | 591 bool isNestedRects(SkRect rect[2], Direction dirs[2] = NULL) const; |
594 | 592 |
595 /** | 593 /** |
596 * Add a closed rectangle contour to the path | 594 * Add a closed rectangle contour to the path |
597 * @param rect The rectangle to add as a closed contour to the path | 595 * @param rect The rectangle to add as a closed contour to the path |
598 * @param dir The direction to wind the rectangle's contour. Cannot be | 596 * @param dir The direction to wind the rectangle's contour. Cannot be |
599 * kUnknown_Direction. | 597 * kUnknown_Direction. |
600 */ | 598 */ |
601 void addRect(const SkRect& rect, Direction dir = kCW_Direction); | 599 void addRect(const SkRect& rect, Direction dir = kCW_Direction); |
602 | 600 |
603 /** | 601 /** |
604 * Add a closed rectangle contour to the path | 602 * Add a closed rectangle contour to the path |
605 * | 603 * |
606 * @param left The left side of a rectangle to add as a closed contour | 604 * @param left The left side of a rectangle to add as a closed contour |
607 * to the path | 605 * to the path |
608 * @param top The top of a rectangle to add as a closed contour to the | 606 * @param top The top of a rectangle to add as a closed contour to the |
609 * path | 607 * path |
610 * @param right The right side of a rectangle to add as a closed contour | 608 * @param right The right side of a rectangle to add as a closed contour |
611 * to the path | 609 * to the path |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
650 void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle); | 648 void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle); |
651 | 649 |
652 /** | 650 /** |
653 * Add a closed round-rectangle contour to the path | 651 * Add a closed round-rectangle contour to the path |
654 * @param rect The bounds of a round-rectangle to add as a closed contour | 652 * @param rect The bounds of a round-rectangle to add as a closed contour |
655 * @param rx The x-radius of the rounded corners on the round-rectangle | 653 * @param rx The x-radius of the rounded corners on the round-rectangle |
656 * @param ry The y-radius of the rounded corners on the round-rectangle | 654 * @param ry The y-radius of the rounded corners on the round-rectangle |
657 * @param dir The direction to wind the rectangle's contour. Cannot be | 655 * @param dir The direction to wind the rectangle's contour. Cannot be |
658 * kUnknown_Direction. | 656 * kUnknown_Direction. |
659 */ | 657 */ |
660 void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, | 658 void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, |
661 Direction dir = kCW_Direction); | 659 Direction dir = kCW_Direction); |
662 | 660 |
663 /** | 661 /** |
664 * Add a closed round-rectangle contour to the path. Each corner receives | 662 * Add a closed round-rectangle contour to the path. Each corner receives |
665 * two radius values [X, Y]. The corners are ordered top-left, top-right, | 663 * two radius values [X, Y]. The corners are ordered top-left, top-right, |
666 * bottom-right, bottom-left. | 664 * bottom-right, bottom-left. |
667 * @param rect The bounds of a round-rectangle to add as a closed contour | 665 * @param rect The bounds of a round-rectangle to add as a closed contour |
668 * @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner | 666 * @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner |
669 * @param dir The direction to wind the rectangle's contour. Cannot be | 667 * @param dir The direction to wind the rectangle's contour. Cannot be |
670 * kUnknown_Direction. | 668 * kUnknown_Direction. |
671 * Note: The radii here now go through the same constraint handling as the | 669 * Note: The radii here now go through the same constraint handling as the |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
925 #ifdef SK_BUILD_FOR_ANDROID | 923 #ifdef SK_BUILD_FOR_ANDROID |
926 uint32_t getGenerationID() const; | 924 uint32_t getGenerationID() const; |
927 const SkPath* getSourcePath() const; | 925 const SkPath* getSourcePath() const; |
928 void setSourcePath(const SkPath* path); | 926 void setSourcePath(const SkPath* path); |
929 #endif | 927 #endif |
930 | 928 |
931 SkDEBUGCODE(void validate() const;) | 929 SkDEBUGCODE(void validate() const;) |
932 | 930 |
933 private: | 931 private: |
934 enum SerializationOffsets { | 932 enum SerializationOffsets { |
| 933 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TO
O |
| 934 kNewFormat_SerializationShift = 28, // requires 1 bit |
| 935 #endif |
935 kDirection_SerializationShift = 26, // requires 2 bits | 936 kDirection_SerializationShift = 26, // requires 2 bits |
936 kIsFinite_SerializationShift = 25, // requires 1 bit | 937 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TO
O |
| 938 // rename to kUnused_SerializationShift |
| 939 kOldIsFinite_SerializationShift = 25, // 1 bit |
| 940 #endif |
937 kIsOval_SerializationShift = 24, // requires 1 bit | 941 kIsOval_SerializationShift = 24, // requires 1 bit |
938 kConvexity_SerializationShift = 16, // requires 2 bits | 942 kConvexity_SerializationShift = 16, // requires 8 bits |
939 kFillType_SerializationShift = 8, // requires 2 bits | 943 kFillType_SerializationShift = 8, // requires 8 bits |
940 kSegmentMask_SerializationShift = 0 // requires 4 bits | 944 kSegmentMask_SerializationShift = 0 // requires 4 bits |
941 }; | 945 }; |
942 | 946 |
943 SkAutoTUnref<SkPathRef> fPathRef; | 947 SkAutoTUnref<SkPathRef> fPathRef; |
944 | 948 |
945 mutable SkRect fBounds; | |
946 int fLastMoveToIndex; | 949 int fLastMoveToIndex; |
947 uint8_t fFillType; | 950 uint8_t fFillType; |
948 uint8_t fSegmentMask; | 951 uint8_t fSegmentMask; |
949 mutable uint8_t fBoundsIsDirty; | |
950 mutable uint8_t fConvexity; | 952 mutable uint8_t fConvexity; |
951 mutable uint8_t fDirection; | 953 mutable uint8_t fDirection; |
952 mutable SkBool8 fIsFinite; // only meaningful if bounds are valid | |
953 mutable SkBool8 fIsOval; | 954 mutable SkBool8 fIsOval; |
954 #ifdef SK_BUILD_FOR_ANDROID | 955 #ifdef SK_BUILD_FOR_ANDROID |
955 uint32_t fGenerationID; | 956 uint32_t fGenerationID; |
956 const SkPath* fSourcePath; | 957 const SkPath* fSourcePath; |
957 #endif | 958 #endif |
958 | 959 |
959 /** Resets all fields other than fPathRef to their initial 'empty' values. | 960 /** Resets all fields other than fPathRef to their initial 'empty' values. |
960 * Assumes the caller has already emptied fPathRef. | 961 * Assumes the caller has already emptied fPathRef. |
961 * On Android increments fGenerationID without reseting it. | 962 * On Android increments fGenerationID without reseting it. |
962 */ | 963 */ |
963 void resetFields(); | 964 void resetFields(); |
964 | 965 |
965 /** Sets all fields other than fPathRef to the values in 'that'. | 966 /** Sets all fields other than fPathRef to the values in 'that'. |
966 * Assumes the caller has already set fPathRef. | 967 * Assumes the caller has already set fPathRef. |
967 * Doesn't change fGenerationID or fSourcePath on Android. | 968 * Doesn't change fGenerationID or fSourcePath on Android. |
968 */ | 969 */ |
969 void copyFields(const SkPath& that); | 970 void copyFields(const SkPath& that); |
970 | 971 |
971 // called, if dirty, by getBounds() | |
972 void computeBounds() const; | |
973 | |
974 friend class Iter; | 972 friend class Iter; |
975 | 973 |
976 friend class SkPathStroker; | 974 friend class SkPathStroker; |
977 /* Append the first contour of path, ignoring path's initial point. If no | 975 /* Append the first contour of path, ignoring path's initial point. If no |
978 moveTo() call has been made for this contour, the first point is | 976 moveTo() call has been made for this contour, the first point is |
979 automatically set to (0,0). | 977 automatically set to (0,0). |
980 */ | 978 */ |
981 void pathTo(const SkPath& path); | 979 void pathTo(const SkPath& path); |
982 | 980 |
983 /* Append, in reverse order, the first contour of path, ignoring path's | 981 /* Append, in reverse order, the first contour of path, ignoring path's |
(...skipping 10 matching lines...) Expand all Loading... |
994 // | 992 // |
995 inline void injectMoveToIfNeeded(); | 993 inline void injectMoveToIfNeeded(); |
996 | 994 |
997 inline bool hasOnlyMoveTos() const; | 995 inline bool hasOnlyMoveTos() const; |
998 | 996 |
999 Convexity internalGetConvexity() const; | 997 Convexity internalGetConvexity() const; |
1000 | 998 |
1001 bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts, | 999 bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts, |
1002 bool* isClosed, Direction* direction) const; | 1000 bool* isClosed, Direction* direction) const; |
1003 | 1001 |
| 1002 /** Returns if the path can return a bound at no cost (true) or will have to |
| 1003 perform some computation (false). |
| 1004 */ |
| 1005 bool hasComputedBounds() const { |
| 1006 SkDEBUGCODE(this->validate();) |
| 1007 return fPathRef->hasComputedBounds(); |
| 1008 } |
| 1009 |
| 1010 |
| 1011 // 'rect' needs to be sorted |
| 1012 void setBounds(const SkRect& rect) { |
| 1013 fPathRef->setBounds(rect); |
| 1014 } |
| 1015 |
| 1016 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TO
O |
| 1017 friend class SkPathRef; // just for SerializationOffsets |
| 1018 #endif |
1004 friend class SkAutoPathBoundsUpdate; | 1019 friend class SkAutoPathBoundsUpdate; |
1005 friend class SkAutoDisableOvalCheck; | 1020 friend class SkAutoDisableOvalCheck; |
1006 friend class SkAutoDisableDirectionCheck; | 1021 friend class SkAutoDisableDirectionCheck; |
1007 friend class SkBench_AddPathTest; // perf test pathTo/reversePathTo | 1022 friend class SkBench_AddPathTest; // perf test pathTo/reversePathTo |
1008 }; | 1023 }; |
1009 | 1024 |
1010 #endif | 1025 #endif |
OLD | NEW |