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; |
| 103 SkASSERT(fRRectStart < 8); |
98 break; | 104 break; |
99 case Type::kPath: | 105 case Type::kPath: |
100 SkASSERT(!fPath.get()->isVolatile()); | 106 SkASSERT(!fPath.get()->isVolatile()); |
101 *key++ = fPath.get()->getGenerationID(); | 107 *key++ = fPath.get()->getGenerationID(); |
102 break; | 108 break; |
103 } | 109 } |
104 } | 110 } |
105 SkASSERT(key - origKey == this->unstyledKeySize()); | 111 SkASSERT(key - origKey == this->unstyledKeySize()); |
106 } | 112 } |
107 | 113 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 if (GrStyle::Apply::kPathEffectAndStrokeRec == apply) { | 216 if (GrStyle::Apply::kPathEffectAndStrokeRec == apply) { |
211 if (strokeRec.needToApply()) { | 217 if (strokeRec.needToApply()) { |
212 // The intermediate shape may not be a general path. If we we're
just applying | 218 // 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 | 219 // 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 | 220 // 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. | 221 // 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 | 222 // 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 | 223 // the simpler shape so that applying both path effect and the s
trokerec all at |
218 // once produces the same key. | 224 // once produces the same key. |
219 SkRRect rrect; | 225 SkRRect rrect; |
220 Type parentType = AttemptToReduceFromPathImpl(*fPath.get(), &rre
ct, nullptr, | 226 SkPath::Direction dir; |
221 strokeRec); | 227 unsigned start; |
| 228 Type parentType = AttemptToReduceFromPathImpl(*fPath.get(), &rre
ct, &dir, &start, |
| 229 nullptr, strokeRec
); |
222 switch (parentType) { | 230 switch (parentType) { |
223 case Type::kEmpty: | 231 case Type::kEmpty: |
224 tmpParent.init(); | 232 tmpParent.init(); |
225 parentForKey = tmpParent.get(); | 233 parentForKey = tmpParent.get(); |
226 break; | 234 break; |
227 case Type::kRRect: | 235 case Type::kRRect: |
228 tmpParent.init(rrect, GrStyle(strokeRec, nullptr)); | 236 tmpParent.init(rrect, dir, start, GrStyle(strokeRec, nul
lptr)); |
229 parentForKey = tmpParent.get(); | 237 parentForKey = tmpParent.get(); |
230 case Type::kPath: | 238 case Type::kPath: |
231 break; | 239 break; |
232 } | 240 } |
233 SkAssertResult(strokeRec.applyToPath(fPath.get(), *fPath.get()))
; | 241 SkAssertResult(strokeRec.applyToPath(fPath.get(), *fPath.get()))
; |
234 } else { | 242 } else { |
235 fStyle = GrStyle(strokeRec, nullptr); | 243 fStyle = GrStyle(strokeRec, nullptr); |
236 } | 244 } |
237 } else { | 245 } else { |
238 fStyle = GrStyle(strokeRec, nullptr); | 246 fStyle = GrStyle(strokeRec, nullptr); |
239 } | 247 } |
240 } else { | 248 } else { |
241 const SkPath* srcForParentStyle; | 249 const SkPath* srcForParentStyle; |
242 if (parent.fType == Type::kPath) { | 250 if (parent.fType == Type::kPath) { |
243 srcForParentStyle = parent.fPath.get(); | 251 srcForParentStyle = parent.fPath.get(); |
244 } else { | 252 } else { |
245 srcForParentStyle = tmpPath.init(); | 253 srcForParentStyle = tmpPath.init(); |
246 parent.asPath(tmpPath.get()); | 254 parent.asPath(tmpPath.get()); |
247 } | 255 } |
248 SkStrokeRec::InitStyle fillOrHairline; | 256 SkStrokeRec::InitStyle fillOrHairline; |
249 SkASSERT(parent.fStyle.applies()); | 257 SkASSERT(parent.fStyle.applies()); |
250 SkASSERT(!parent.fStyle.pathEffect()); | 258 SkASSERT(!parent.fStyle.pathEffect()); |
251 SkAssertResult(parent.fStyle.applyToPath(fPath.get(), &fillOrHairline, *
srcForParentStyle, | 259 SkAssertResult(parent.fStyle.applyToPath(fPath.get(), &fillOrHairline, *
srcForParentStyle, |
252 scale)); | 260 scale)); |
253 fStyle.resetToInitStyle(fillOrHairline); | 261 fStyle.resetToInitStyle(fillOrHairline); |
254 } | 262 } |
255 this->attemptToReduceFromPath(); | 263 this->attemptToReduceFromPath(); |
256 this->setInheritedKey(*parentForKey, apply, scale); | 264 this->setInheritedKey(*parentForKey, apply, scale); |
257 } | 265 } |
| 266 |
| 267 GrShape::Type GrShape::AttemptToReduceFromPathImpl(const SkPath& path, SkRRect*
rrect, |
| 268 SkPath::Direction* rrectDir, |
| 269 unsigned* rrectStart, |
| 270 const SkPathEffect* pe, |
| 271 const SkStrokeRec& strokeRec)
{ |
| 272 if (path.isEmpty()) { |
| 273 return Type::kEmpty; |
| 274 } |
| 275 if (path.isRRect(rrect, rrectDir, rrectStart)) { |
| 276 // Currently SkPath does not acknowledge that empty, rect, or oval subty
pes as rrects. |
| 277 SkASSERT(!rrect->isEmpty()); |
| 278 SkASSERT(rrect->getType() != SkRRect::kRect_Type); |
| 279 SkASSERT(rrect->getType() != SkRRect::kOval_Type); |
| 280 if (!pe) { |
| 281 *rrectStart = DefaultRRectDirAndStartIndex(*rrect, false, rrectDir); |
| 282 } |
| 283 return Type::kRRect; |
| 284 } |
| 285 SkRect rect; |
| 286 if (path.isOval(&rect, rrectDir, rrectStart)) { |
| 287 rrect->setOval(rect); |
| 288 if (!pe) { |
| 289 *rrectDir = kDefaultRRectDir; |
| 290 *rrectStart = kDefaultRRectStart; |
| 291 } else { |
| 292 // convert from oval indexing to rrect indexiing. |
| 293 *rrectStart *= 2; |
| 294 } |
| 295 return Type::kRRect; |
| 296 } |
| 297 // When there is a path effect we restrict rect detection to the narrower AP
I that |
| 298 // gives us the starting position. Otherwise, we will retry with the more ag
gressive isRect(). |
| 299 if (SkPathPriv::IsSimpleClosedRect(path, &rect, rrectDir, rrectStart)) { |
| 300 if (!pe) { |
| 301 *rrectDir = kDefaultRRectDir; |
| 302 *rrectStart = kDefaultRRectStart; |
| 303 } else { |
| 304 // convert from rect indexing to rrect indexiing. |
| 305 *rrectStart *= 2; |
| 306 } |
| 307 rrect->setRect(rect); |
| 308 return Type::kRRect; |
| 309 } |
| 310 if (!pe) { |
| 311 bool closed; |
| 312 if (path.isRect(&rect, &closed, nullptr)) { |
| 313 if (closed || strokeRec.isFillStyle()) { |
| 314 rrect->setRect(rect); |
| 315 // Since there is no path effect the dir and start index is imma
terial. |
| 316 *rrectDir = kDefaultRRectDir; |
| 317 *rrectStart = kDefaultRRectStart; |
| 318 return Type::kRRect; |
| 319 } |
| 320 } |
| 321 } |
| 322 return Type::kPath; |
| 323 } |
OLD | NEW |