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

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

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: Address comments, default all rrect subtypes to start index 0 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
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 #include "GrShape.h" 8 #include "GrShape.h"
9 9
10 GrShape& GrShape::operator=(const GrShape& that) { 10 GrShape& GrShape::operator=(const GrShape& that) {
11 bool wasPath = Type::kPath == fType; 11 bool wasPath = Type::kPath == fType;
12 fStyle = that.fStyle; 12 fStyle = that.fStyle;
13 fType = that.fType; 13 fType = that.fType;
14 switch (fType) { 14 switch (fType) {
15 case Type::kEmpty: 15 case Type::kEmpty:
16 if (wasPath) { 16 if (wasPath) {
17 fPath.reset(); 17 fPath.reset();
18 } 18 }
19 break; 19 break;
20 case Type::kRRect: 20 case Type::kRRect:
21 if (wasPath) { 21 if (wasPath) {
22 fPath.reset(); 22 fPath.reset();
23 } 23 }
24 fRRect = that.fRRect; 24 fRRect = that.fRRect;
25 fRRectDir = that.fRRectDir;
26 fRRectStart = that.fRRectStart;
25 break; 27 break;
26 case Type::kPath: 28 case Type::kPath:
27 if (wasPath) { 29 if (wasPath) {
28 *fPath.get() = *that.fPath.get(); 30 *fPath.get() = *that.fPath.get();
29 } else { 31 } else {
30 fPath.set(*that.fPath.get()); 32 fPath.set(*that.fPath.get());
31 } 33 }
32 break; 34 break;
33 } 35 }
34 fInheritedKey.reset(that.fInheritedKey.count()); 36 fInheritedKey.reset(that.fInheritedKey.count());
(...skipping 27 matching lines...) Expand all
62 int GrShape::unstyledKeySize() const { 64 int GrShape::unstyledKeySize() const {
63 if (fInheritedKey.count()) { 65 if (fInheritedKey.count()) {
64 return fInheritedKey.count(); 66 return fInheritedKey.count();
65 } 67 }
66 switch (fType) { 68 switch (fType) {
67 case Type::kEmpty: 69 case Type::kEmpty:
68 return 1; 70 return 1;
69 case Type::kRRect: 71 case Type::kRRect:
70 SkASSERT(!fInheritedKey.count()); 72 SkASSERT(!fInheritedKey.count());
71 SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t)); 73 SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t));
72 return SkRRect::kSizeInMemory / sizeof(uint32_t); 74 // + 1 for the direction + start index.
75 return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1;
73 case Type::kPath: 76 case Type::kPath:
74 if (fPath.get()->isVolatile()) { 77 if (fPath.get()->isVolatile()) {
75 return -1; 78 return -1;
76 } else { 79 } else {
77 return 1; 80 return 1;
78 } 81 }
79 } 82 }
80 SkFAIL("Should never get here."); 83 SkFAIL("Should never get here.");
81 return 0; 84 return 0;
82 } 85 }
83 86
84 void GrShape::writeUnstyledKey(uint32_t* key) const { 87 void GrShape::writeUnstyledKey(uint32_t* key) const {
85 SkASSERT(this->unstyledKeySize()); 88 SkASSERT(this->unstyledKeySize());
86 SkDEBUGCODE(uint32_t* origKey = key;) 89 SkDEBUGCODE(uint32_t* origKey = key;)
87 if (fInheritedKey.count()) { 90 if (fInheritedKey.count()) {
88 memcpy(key, fInheritedKey.get(), sizeof(uint32_t) * fInheritedKey.count( )); 91 memcpy(key, fInheritedKey.get(), sizeof(uint32_t) * fInheritedKey.count( ));
89 SkDEBUGCODE(key += fInheritedKey.count();) 92 SkDEBUGCODE(key += fInheritedKey.count();)
90 } else { 93 } else {
91 switch (fType) { 94 switch (fType) {
92 case Type::kEmpty: 95 case Type::kEmpty:
93 *key++ = 1; 96 *key++ = 1;
94 break; 97 break;
95 case Type::kRRect: 98 case Type::kRRect:
96 fRRect.writeToMemory(key); 99 fRRect.writeToMemory(key);
97 key += SkRRect::kSizeInMemory / sizeof(uint32_t); 100 key += SkRRect::kSizeInMemory / sizeof(uint32_t);
101 *key = (fRRectDir == SkPath::kCCW_Direction) ? (1 << 31) : 0;
102 *key++ |= fRRectStart;
egdaniel 2016/06/06 18:34:36 So obviously fRRectStart will be less than 2^31, b
bsalomon 2016/06/06 19:41:29 Added SkASSERT(fRRectStart < 8)
98 break; 103 break;
99 case Type::kPath: 104 case Type::kPath:
100 SkASSERT(!fPath.get()->isVolatile()); 105 SkASSERT(!fPath.get()->isVolatile());
101 *key++ = fPath.get()->getGenerationID(); 106 *key++ = fPath.get()->getGenerationID();
102 break; 107 break;
103 } 108 }
104 } 109 }
105 SkASSERT(key - origKey == this->unstyledKeySize()); 110 SkASSERT(key - origKey == this->unstyledKeySize());
106 } 111 }
107 112
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 if (GrStyle::Apply::kPathEffectAndStrokeRec == apply) { 215 if (GrStyle::Apply::kPathEffectAndStrokeRec == apply) {
211 if (strokeRec.needToApply()) { 216 if (strokeRec.needToApply()) {
212 // The intermediate shape may not be a general path. If we we're just applying 217 // The intermediate shape may not be a general path. If we we're just applying
213 // the path effect then attemptToReduceFromPath would catch it. This means that 218 // the path effect then attemptToReduceFromPath would catch it. This means that
214 // when we subsequently applied the remaining strokeRec we would have a non-path 219 // when we subsequently applied the remaining strokeRec we would have a non-path
215 // parent shape that would be used to determine the the stroked path's key. 220 // parent shape that would be used to determine the the stroked path's key.
216 // We detect that case here and change parentForKey to a tempora ry that represents 221 // We detect that case here and change parentForKey to a tempora ry that represents
217 // the simpler shape so that applying both path effect and the s trokerec all at 222 // the simpler shape so that applying both path effect and the s trokerec all at
218 // once produces the same key. 223 // once produces the same key.
219 SkRRect rrect; 224 SkRRect rrect;
220 Type parentType = AttemptToReduceFromPathImpl(*fPath.get(), &rre ct, nullptr, 225 SkPath::Direction dir;
221 strokeRec); 226 unsigned start;
227 Type parentType = AttemptToReduceFromPathImpl(*fPath.get(), &rre ct, &dir, &start,
228 nullptr, strokeRec );
222 switch (parentType) { 229 switch (parentType) {
223 case Type::kEmpty: 230 case Type::kEmpty:
224 tmpParent.init(); 231 tmpParent.init();
225 parentForKey = tmpParent.get(); 232 parentForKey = tmpParent.get();
226 break; 233 break;
227 case Type::kRRect: 234 case Type::kRRect:
228 tmpParent.init(rrect, GrStyle(strokeRec, nullptr)); 235 tmpParent.init(rrect, dir, start, GrStyle(strokeRec, nul lptr));
229 parentForKey = tmpParent.get(); 236 parentForKey = tmpParent.get();
230 case Type::kPath: 237 case Type::kPath:
231 break; 238 break;
232 } 239 }
233 SkAssertResult(strokeRec.applyToPath(fPath.get(), *fPath.get())) ; 240 SkAssertResult(strokeRec.applyToPath(fPath.get(), *fPath.get())) ;
234 } else { 241 } else {
235 fStyle = GrStyle(strokeRec, nullptr); 242 fStyle = GrStyle(strokeRec, nullptr);
236 } 243 }
237 } else { 244 } else {
238 fStyle = GrStyle(strokeRec, nullptr); 245 fStyle = GrStyle(strokeRec, nullptr);
239 } 246 }
240 } else { 247 } else {
241 const SkPath* srcForParentStyle; 248 const SkPath* srcForParentStyle;
242 if (parent.fType == Type::kPath) { 249 if (parent.fType == Type::kPath) {
243 srcForParentStyle = parent.fPath.get(); 250 srcForParentStyle = parent.fPath.get();
244 } else { 251 } else {
245 srcForParentStyle = tmpPath.init(); 252 srcForParentStyle = tmpPath.init();
246 parent.asPath(tmpPath.get()); 253 parent.asPath(tmpPath.get());
247 } 254 }
248 SkStrokeRec::InitStyle fillOrHairline; 255 SkStrokeRec::InitStyle fillOrHairline;
249 SkASSERT(parent.fStyle.applies()); 256 SkASSERT(parent.fStyle.applies());
250 SkASSERT(!parent.fStyle.pathEffect()); 257 SkASSERT(!parent.fStyle.pathEffect());
251 SkAssertResult(parent.fStyle.applyToPath(fPath.get(), &fillOrHairline, * srcForParentStyle, 258 SkAssertResult(parent.fStyle.applyToPath(fPath.get(), &fillOrHairline, * srcForParentStyle,
252 scale)); 259 scale));
253 fStyle.resetToInitStyle(fillOrHairline); 260 fStyle.resetToInitStyle(fillOrHairline);
254 } 261 }
255 this->attemptToReduceFromPath(); 262 this->attemptToReduceFromPath();
256 this->setInheritedKey(*parentForKey, apply, scale); 263 this->setInheritedKey(*parentForKey, apply, scale);
257 } 264 }
265
266 GrShape::Type GrShape::AttemptToReduceFromPathImpl(const SkPath& path, SkRRect* rrect,
267 SkPath::Direction* rrectDir,
268 unsigned* rrectStart,
269 const SkPathEffect* pe,
270 const SkStrokeRec& strokeRec) {
271 if (path.isEmpty()) {
272 return Type::kEmpty;
273 }
274 if (path.isRRect(rrect, rrectDir, rrectStart)) {
275 SkASSERT(!rrect->isEmpty());
276 if (!pe) {
277 *rrectStart = DefaultRRectDirAndStartIndex(*rrect, false, rrectDir);
278 } else {
279 // For oval and rect subtypes of rrects pairs of start indices colla pse to the same
280 // point. Here ,we canonicalize which of the start points we use.
281 if (rrect->getType() == SkRRect::kOval_Type) {
282 *rrectStart |= ~0b1;
283 } else if (rrect->getType() == SkRRect::kRect_Type) {
284 *rrectStart = ((*rrectStart + 1) & 0b110);
285 }
286 }
287 return Type::kRRect;
288 }
289 SkRect rect;
290 if (path.isOval(&rect, rrectDir, rrectStart)) {
291 rrect->setOval(rect);
292 if (!pe) {
293 *rrectDir = kDefaultRRectDir;
294 *rrectStart = kDefaultRRectStart;
295 } else {
296 // convert from oval indexing to rrect indexiing.
297 *rrectStart *= 2;
298 }
299 return Type::kRRect;
300 }
301 // When there is a path effect we restrict rect detection to the narrower AP I that
302 // gives us the starting position. Otherwise, we will retry with the more ag gressive isRect().
303 if (SkPathPriv::IsSimpleClosedRect(path, &rect, rrectDir, rrectStart)) {
304 if (!pe) {
305 *rrectDir = kDefaultRRectDir;
306 *rrectStart = kDefaultRRectStart;
307 } else {
308 // convert from rect indexing to rrect indexiing.
309 *rrectStart *= 2;
310 }
311 rrect->setRect(rect);
312 return Type::kRRect;
313 }
314 if (!pe) {
315 bool closed;
316 if (path.isRect(&rect, &closed, nullptr)) {
317 if (closed || strokeRec.isFillStyle()) {
318 rrect->setRect(rect);
319 // Since there is no path effect the dir and start index is imma terial.
320 *rrectDir = kDefaultRRectDir;
321 *rrectStart = kDefaultRRectStart;
322 return Type::kRRect;
323 }
324 }
325 }
326 return Type::kPath;
327 }
OLDNEW
« no previous file with comments | « src/gpu/GrShape.h ('k') | tests/GrShapeTest.cpp » ('j') | tests/GrShapeTest.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698