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

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: 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
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;
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 *rrectDir = SkPath::kCW_Direction;
278 *rrectStart = DefaultRRectStartIndex(*rrect, false);
279 } else {
280 // For oval and rect subtypes of rrects pairs of start indices colla pse to the same
281 // point. Here we canonicalize which of the start points we use.
282 if (rrect->getType() == SkRRect::kOval_Type) {
283 *rrectStart |= ~0b1;
284 } else if (rrect->getType() == SkRRect::kRect_Type) {
285 *rrectStart = ((*rrectStart + 1) & 0b110);
286 }
287 }
288 return Type::kRRect;
289 }
290 SkRect rect;
291 if (path.isOval(&rect, rrectDir, rrectStart)) {
292 rrect->setOval(rect);
293 if (!pe) {
294 *rrectDir = SkPath::kCW_Direction;
295 *rrectStart = 2;
296 } else {
297 // convert from oval indexing to rrect indexiing.
298 *rrectStart *= 2;
299 }
300 return Type::kRRect;
301 }
302 // When there is a path effect we restrict rect detection to the narrower AP I that
303 // gives us the starting position. Otherwise, we will retry with the more ag gressive isRect().
304 if (SkPathPriv::IsSimpleClosedRect(path, &rect, rrectDir, rrectStart)) {
305 if (!pe) {
306 *rrectDir = SkPath::kCW_Direction;
307 *rrectStart = 0;
308 } else {
309 // convert from rect indexing to rrect indexiing.
310 *rrectStart *= 2;
311 }
312 rrect->setRect(rect);
313 return Type::kRRect;
314 }
315 if (!pe) {
316 bool closed;
317 if (path.isRect(&rect, &closed, nullptr)) {
318 if (closed || strokeRec.isFillStyle()) {
319 rrect->setRect(rect);
320 // Since there is no path effect the dir and start index is imma terial.
321 *rrectDir = SkPath::kCW_Direction;
322 *rrectStart = 0;
323 return Type::kRRect;
324 }
325 }
326 }
327 return Type::kPath;
328 }
OLDNEW
« src/gpu/GrShape.h ('K') | « src/gpu/GrShape.h ('k') | tests/GrShapeTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698