OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 } | |
OLD | NEW |