Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(825)

Side by Side Diff: src/gpu/GrShape.h

Issue 2042813002: Make GrShape track the winding direction and starting point for rrect types. (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: minor Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include/core/SkRRect.h ('k') | src/gpu/GrShape.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2016 Google Inc. 2 * Copyright 2016 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #ifndef GrShape_DEFINED 8 #ifndef GrShape_DEFINED
9 #define GrShape_DEFINED 9 #define GrShape_DEFINED
10 10
11 #include "GrStyle.h" 11 #include "GrStyle.h"
12 #include "SkPath.h" 12 #include "SkPath.h"
13 #include "SkPathPriv.h"
13 #include "SkRRect.h" 14 #include "SkRRect.h"
14 #include "SkTemplates.h" 15 #include "SkTemplates.h"
15 #include "SkTLazy.h" 16 #include "SkTLazy.h"
16 17
17 /** 18 /**
18 * Represents a geometric shape (rrect or path) and the GrStyle that it should b e rendered with. 19 * Represents a geometric shape (rrect or path) and the GrStyle that it should b e rendered with.
19 * It is possible to apply the style to the GrShape to produce a new GrShape whe re the geometry 20 * It is possible to apply the style to the GrShape to produce a new GrShape whe re the geometry
20 * reflects the styling information (e.g. is stroked). It is also possible to ap ply just the 21 * reflects the styling information (e.g. is stroked). It is also possible to ap ply just the
21 * path effect from the style. In this case the resulting shape will include any remaining 22 * path effect from the style. In this case the resulting shape will include any remaining
22 * stroking information that is to be applied after the path effect. 23 * stroking information that is to be applied after the path effect.
23 * 24 *
24 * Shapes can produce keys that represent only the geometry information, not the style. Note that 25 * Shapes can produce keys that represent only the geometry information, not the style. Note that
25 * when styling information is applied to produce a new shape then the style has been converted 26 * when styling information is applied to produce a new shape then the style has been converted
26 * to geometric information and is included in the new shape's key. When the sam e style is applied 27 * to geometric information and is included in the new shape's key. When the sam e style is applied
27 * to two shapes that reflect the same underlying geometry the computed keys of the stylized shapes 28 * to two shapes that reflect the same underlying geometry the computed keys of the stylized shapes
28 * will be the same. 29 * will be the same.
29 * 30 *
30 * Currently this can only be constructed from a rrect, though it can become a p ath by applying 31 * Currently this can only be constructed from a path, rect, or rrect though it can become a path
31 * style to the geometry. The idea is to expand this to cover most or all of the geometries that 32 * applying style to the geometry. The idea is to expand this to cover most or a ll of the geometries
32 * have SkCanvas::draw APIs. 33 * that have SkCanvas::draw APIs.
33 */ 34 */
34 class GrShape { 35 class GrShape {
35 public: 36 public:
36 GrShape() : fType(Type::kEmpty) {} 37 GrShape() : fType(Type::kEmpty) {}
37 38
38 explicit GrShape(const SkPath& path) 39 explicit GrShape(const SkPath& path)
39 : fType(Type::kPath) 40 : fType(Type::kPath)
40 , fPath(&path) { 41 , fPath(&path) {
41 this->attemptToReduceFromPath(); 42 this->attemptToReduceFromPath();
42 } 43 }
43 44
44 explicit GrShape(const SkRRect& rrect) 45 explicit GrShape(const SkRRect& rrect)
45 : fType(Type::kRRect) 46 : fType(Type::kRRect)
46 , fRRect(rrect) { 47 , fRRect(rrect)
48 , fRRectDir(SkPath::kCW_Direction)
49 , fRRectStart(DefaultRRectStartIndex(rrect, false)) {
47 this->attemptToReduceFromRRect(); 50 this->attemptToReduceFromRRect();
48 } 51 }
49 52
50 explicit GrShape(const SkRect& rect) 53 explicit GrShape(const SkRect& rect)
51 : fType(Type::kRRect) 54 : fType(Type::kRRect)
52 , fRRect(SkRRect::MakeRect(rect)) { 55 , fRRect(SkRRect::MakeRect(rect))
56 , fRRectDir(SkPath::kCW_Direction)
57 , fRRectStart(1) {
53 this->attemptToReduceFromRRect(); 58 this->attemptToReduceFromRRect();
54 } 59 }
55 60
56 GrShape(const SkPath& path, const GrStyle& style) 61 GrShape(const SkPath& path, const GrStyle& style)
57 : fType(Type::kPath) 62 : fType(Type::kPath)
58 , fPath(&path) 63 , fPath(&path)
59 , fStyle(style) { 64 , fStyle(style) {
60 this->attemptToReduceFromPath(); 65 this->attemptToReduceFromPath();
61 } 66 }
62 67
63 GrShape(const SkRRect& rrect, const GrStyle& style) 68 GrShape(const SkRRect& rrect, const GrStyle& style)
64 : fType(Type::kRRect) 69 : fType(Type::kRRect)
65 , fRRect(rrect) 70 , fRRect(rrect)
71 , fRRectDir(SkPath::kCW_Direction)
72 , fRRectStart(DefaultRRectStartIndex(rrect, SkToBool(style.pathEffect()) ))
66 , fStyle(style) { 73 , fStyle(style) {
67 this->attemptToReduceFromRRect(); 74 this->attemptToReduceFromRRect();
68 } 75 }
69 76
77 GrShape(const SkRRect& rrect, SkPath::Direction dir, unsigned start, const G rStyle& style)
78 : fType(Type::kRRect)
79 , fRRect(rrect)
80 , fStyle(style) {
81 if (style.pathEffect()) {
82 fRRectDir = dir;
83 fRRectStart = start;
84 } else {
85 fRRectDir = SkPath::kCW_Direction;
86 fRRectStart = DefaultRRectStartIndex(rrect, false);
87 }
88 this->attemptToReduceFromRRect();
89 }
90
70 GrShape(const SkRect& rect, const GrStyle& style) 91 GrShape(const SkRect& rect, const GrStyle& style)
71 : fType(Type::kRRect) 92 : fType(Type::kRRect)
72 , fRRect(SkRRect::MakeRect(rect)) 93 , fRRect(SkRRect::MakeRect(rect))
73 , fStyle(style) { 94 , fStyle(style) {
95 fRRectStart = DefaultRectDirAndStartIndex(rect, style.pathEffect(), &fRR ectDir);
74 this->attemptToReduceFromRRect(); 96 this->attemptToReduceFromRRect();
75 } 97 }
76 98
77 GrShape(const SkPath& path, const SkPaint& paint) 99 GrShape(const SkPath& path, const SkPaint& paint)
78 : fType(Type::kPath) 100 : fType(Type::kPath)
79 , fPath(&path) 101 , fPath(&path)
80 , fStyle(paint) { 102 , fStyle(paint) {
81 this->attemptToReduceFromPath(); 103 this->attemptToReduceFromPath();
82 } 104 }
83 105
84 GrShape(const SkRRect& rrect, const SkPaint& paint) 106 GrShape(const SkRRect& rrect, const SkPaint& paint)
85 : fType(Type::kRRect) 107 : fType(Type::kRRect)
86 , fRRect(rrect) 108 , fRRect(rrect)
109 , fRRectDir(SkPath::kCW_Direction)
87 , fStyle(paint) { 110 , fStyle(paint) {
111 fRRectStart = DefaultRRectStartIndex(rrect, SkToBool(fStyle.pathEffect() ));
88 this->attemptToReduceFromRRect(); 112 this->attemptToReduceFromRRect();
89 } 113 }
90 114
91 GrShape(const SkRect& rect, const SkPaint& paint) 115 GrShape(const SkRect& rect, const SkPaint& paint)
92 : fType(Type::kRRect) 116 : fType(Type::kRRect)
93 , fRRect(SkRRect::MakeRect(rect)) 117 , fRRect(SkRRect::MakeRect(rect))
94 , fStyle(paint) { 118 , fStyle(paint) {
119 fRRectStart = DefaultRectDirAndStartIndex(rect, fStyle.pathEffect(), &fR RectDir);
95 this->attemptToReduceFromRRect(); 120 this->attemptToReduceFromRRect();
96 } 121 }
97 122
98 GrShape(const GrShape&); 123 GrShape(const GrShape&);
99 GrShape& operator=(const GrShape& that); 124 GrShape& operator=(const GrShape& that);
100 125
101 ~GrShape() { 126 ~GrShape() {
102 if (Type::kPath == fType) { 127 if (Type::kPath == fType) {
103 fPath.reset(); 128 fPath.reset();
104 } 129 }
105 } 130 }
106 131
107 const GrStyle& style() const { return fStyle; } 132 const GrStyle& style() const { return fStyle; }
108 133
109 /** 134 /**
110 * Returns a shape that has either applied the path effect or path effect an d stroking 135 * Returns a shape that has either applied the path effect or path effect an d stroking
111 * information from this shape's style to its geometry. Scale is used when a pproximating the 136 * information from this shape's style to its geometry. Scale is used when a pproximating the
112 * output geometry and typically is computed from the view matrix 137 * output geometry and typically is computed from the view matrix
113 */ 138 */
114 GrShape applyStyle(GrStyle::Apply apply, SkScalar scale) { 139 GrShape applyStyle(GrStyle::Apply apply, SkScalar scale) {
115 return GrShape(*this, apply, scale); 140 return GrShape(*this, apply, scale);
116 } 141 }
117 142
118 /** Returns the unstyled geometry as a rrect if possible. */ 143 /** Returns the unstyled geometry as a rrect if possible. */
119 bool asRRect(SkRRect* rrect) const { 144 bool asRRect(SkRRect* rrect, SkPath::Direction* dir, unsigned* start) const {
120 if (Type::kRRect != fType) { 145 if (Type::kRRect != fType) {
121 return false; 146 return false;
122 } 147 }
123 if (rrect) { 148 if (rrect) {
124 *rrect = fRRect; 149 *rrect = fRRect;
125 } 150 }
151 if (dir) {
152 *dir = fRRectDir;
153 }
154 if (start) {
155 *start = fRRectStart;
156 }
126 return true; 157 return true;
127 } 158 }
128 159
129 /** Returns the unstyled geometry as a path. */ 160 /** Returns the unstyled geometry as a path. */
130 void asPath(SkPath* out) const { 161 void asPath(SkPath* out) const {
131 switch (fType) { 162 switch (fType) {
132 case Type::kEmpty: 163 case Type::kEmpty:
133 out->reset(); 164 out->reset();
134 break; 165 break;
135 case Type::kRRect: 166 case Type::kRRect:
136 out->reset(); 167 out->reset();
137 out->addRRect(fRRect); 168 out->addRRect(fRRect, fRRectDir, fRRectStart);
138 break; 169 break;
139 case Type::kPath: 170 case Type::kPath:
140 *out = *fPath.get(); 171 *out = *fPath.get();
141 break; 172 break;
142 } 173 }
143 } 174 }
144 175
145 /** 176 /**
146 * Returns whether the geometry is empty. Note that applying the style could produce a 177 * Returns whether the geometry is empty. Note that applying the style could produce a
147 * non-empty shape. 178 * non-empty shape.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 */ 214 */
184 void writeUnstyledKey(uint32_t* key) const; 215 void writeUnstyledKey(uint32_t* key) const;
185 216
186 private: 217 private:
187 enum class Type { 218 enum class Type {
188 kEmpty, 219 kEmpty,
189 kRRect, 220 kRRect,
190 kPath, 221 kPath,
191 }; 222 };
192 223
193
194 /** Constructor used by the applyStyle() function */ 224 /** Constructor used by the applyStyle() function */
195 GrShape(const GrShape& parentShape, GrStyle::Apply, SkScalar scale); 225 GrShape(const GrShape& parentShape, GrStyle::Apply, SkScalar scale);
196 226
197 /** 227 /**
198 * Determines the key we should inherit from the input shape's geometry and style when 228 * Determines the key we should inherit from the input shape's geometry and style when
199 * we are applying the style to create a new shape. 229 * we are applying the style to create a new shape.
200 */ 230 */
201 void setInheritedKey(const GrShape& parentShape, GrStyle::Apply, SkScalar sc ale); 231 void setInheritedKey(const GrShape& parentShape, GrStyle::Apply, SkScalar sc ale);
202 232
203 void attemptToReduceFromPath() { 233 void attemptToReduceFromPath() {
204 SkASSERT(Type::kPath == fType); 234 SkASSERT(Type::kPath == fType);
205 fType = AttemptToReduceFromPathImpl(*fPath.get(), &fRRect, fStyle.pathEf fect(), 235 fType = AttemptToReduceFromPathImpl(*fPath.get(), &fRRect, &fRRectDir, & fRRectStart,
206 fStyle.strokeRec()); 236 fStyle.pathEffect(), fStyle.strokeRe c());
207 if (Type::kPath != fType) { 237 if (Type::kPath != fType) {
208 fPath.reset(); 238 fPath.reset();
209 fInheritedKey.reset(0); 239 fInheritedKey.reset(0);
210 } 240 }
211 } 241 }
212 242
213 void attemptToReduceFromRRect() { 243 void attemptToReduceFromRRect() {
214 SkASSERT(Type::kRRect == fType); 244 SkASSERT(Type::kRRect == fType);
215 SkASSERT(!fInheritedKey.count()); 245 SkASSERT(!fInheritedKey.count());
216 if (fRRect.isEmpty()) { 246 if (fRRect.isEmpty()) {
217 fType = Type::kEmpty; 247 fType = Type::kEmpty;
218 } 248 }
219 } 249 }
220 250
221 static Type AttemptToReduceFromPathImpl(const SkPath& path, SkRRect* rrect, 251 static Type AttemptToReduceFromPathImpl(const SkPath& path, SkRRect* rrect,
222 const SkPathEffect* pe, const SkStro keRec& strokeRec) { 252 SkPath::Direction* rrectDir, unsigne d* rrectStart,
223 if (path.isEmpty()) { 253 const SkPathEffect* pe, const SkStro keRec& strokeRec);
224 return Type::kEmpty; 254
255 static unsigned DefaultRectDirAndStartIndex(const SkRect& rect, bool hasPath Effect,
256 SkPath::Direction* dir) {
257 // This is the default direction when a rect is added to a path.
258 *dir = SkPath::kCW_Direction;
259 // This comes from SkPath's interface. The default for adding a SkRect i s counter clockwise
260 // beginning at index 0 (which happens to correspond to rrect index 0 or 7).
261 if (!hasPathEffect) {
262 return 0;
225 } 263 }
226 if (path.isRRect(rrect)) { 264 // We store rects as rrects. RRects don't preserve the invertedness, but rather sort the
227 SkASSERT(!rrect->isEmpty()); 265 // rect edges. Thus, we may need to modify the rrect's start index to ac count for the sort.
228 return Type::kRRect; 266 *dir = SkPath::kCW_Direction;
egdaniel 2016/06/06 15:50:29 This line is repeated above
bsalomon 2016/06/06 16:28:05 Done.
267 bool swapX = rect.fLeft > rect.fRight;
268 bool swapY = rect.fTop > rect.fBottom;
269 if (swapX && swapY) {
270 // 0 becomes start index 2 and times 2 to convert from rect the rrec t indices.
271 return 2 * 2;
272 } else if (swapX) {
273 *dir = SkPath::kCW_Direction;
egdaniel 2016/06/06 15:50:29 CCW?
bsalomon 2016/06/06 16:28:04 Done.
274 // 0 becomes start index 1 and times 2 to convert from rect the rrec t indices.
275 return 2 * 1;
276 } else if (swapY) {
277 *dir = SkPath::kCW_Direction;
egdaniel 2016/06/06 15:50:29 CCW?
bsalomon 2016/06/06 16:28:05 Done.
278 // 0 becomes start index 3 and times 2 to convert from rect the rrec t indices.
279 return 2 * 3;
229 } 280 }
230 SkRect rect; 281 return 0;
231 if (path.isOval(&rect)) { 282 }
232 rrect->setOval(rect); 283
233 return Type::kRRect; 284 static unsigned DefaultRRectStartIndex(const SkRRect& rrect, bool hasPathEff ect) {
234 } 285 // This comes from SkPath's interface. The default for adding a SkRRect to a path is
235 bool closed; 286 // clockwise beginning at starting index 6.
236 if (path.isRect(&rect, &closed, nullptr)) { 287 static constexpr unsigned kDefaultRRectStartIdx = 6;
237 if (closed || (!pe && strokeRec.isFillStyle())) { 288 if (!hasPathEffect) {
238 rrect->setRect(rect); 289 // Rect and Oval subtypes have their own default/canonical starting index. This agrees
239 return Type::kRRect; 290 // with AttemptToReduceFromPathImpl and SkPath's add[Oval Rect] meth ods.
291 if (rrect.getType() == SkRRect::kRect_Type) {
292 // The default rect starting point in SkPath::addRect is 0 which stays 0
293 // in terms of rrect indices.
294 return 0;
295 } else if (rrect.getType() == SkRRect::kOval_Type) {
296 // The default oval starting point in SkPath::addOval is 1 which converts to 2
297 // in terms of rrect indices.
298 return 2;
240 } 299 }
241 } 300 }
242 return Type::kPath; 301 return kDefaultRRectStartIdx;
243 } 302 }
244 303
245 Type fType; 304 Type fType;
246 SkRRect fRRect; 305 SkRRect fRRect;
306 SkPath::Direction fRRectDir;
307 unsigned fRRectStart;
247 SkTLazy<SkPath> fPath; 308 SkTLazy<SkPath> fPath;
248 GrStyle fStyle; 309 GrStyle fStyle;
249 SkAutoSTArray<8, uint32_t> fInheritedKey; 310 SkAutoSTArray<8, uint32_t> fInheritedKey;
250 }; 311 };
251 #endif 312 #endif
OLDNEW
« no previous file with comments | « include/core/SkRRect.h ('k') | src/gpu/GrShape.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698