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) { |
(...skipping 14 matching lines...) Expand all Loading... | |
25 fRRectDir = that.fRRectDir; | 25 fRRectDir = that.fRRectDir; |
26 fRRectStart = that.fRRectStart; | 26 fRRectStart = that.fRRectStart; |
27 fRRectIsInverted = that.fRRectIsInverted; | 27 fRRectIsInverted = that.fRRectIsInverted; |
28 break; | 28 break; |
29 case Type::kPath: | 29 case Type::kPath: |
30 if (wasPath) { | 30 if (wasPath) { |
31 *fPath.get() = *that.fPath.get(); | 31 *fPath.get() = *that.fPath.get(); |
32 } else { | 32 } else { |
33 fPath.set(*that.fPath.get()); | 33 fPath.set(*that.fPath.get()); |
34 } | 34 } |
35 fPathGenID = that.fPathGenID; | |
35 break; | 36 break; |
36 } | 37 } |
37 fInheritedKey.reset(that.fInheritedKey.count()); | 38 fInheritedKey.reset(that.fInheritedKey.count()); |
38 sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(), | 39 sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(), |
39 sizeof(uint32_t) * fInheritedKey.count()); | 40 sizeof(uint32_t) * fInheritedKey.count()); |
40 return *this; | 41 return *this; |
41 } | 42 } |
42 | 43 |
43 const SkRect& GrShape::bounds() const { | 44 const SkRect& GrShape::bounds() const { |
44 static constexpr SkRect kEmpty = SkRect::MakeEmpty(); | 45 static constexpr SkRect kEmpty = SkRect::MakeEmpty(); |
(...skipping 23 matching lines...) Expand all Loading... | |
68 } | 69 } |
69 switch (fType) { | 70 switch (fType) { |
70 case Type::kEmpty: | 71 case Type::kEmpty: |
71 return 1; | 72 return 1; |
72 case Type::kRRect: | 73 case Type::kRRect: |
73 SkASSERT(!fInheritedKey.count()); | 74 SkASSERT(!fInheritedKey.count()); |
74 SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t)); | 75 SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t)); |
75 // + 1 for the direction, start index, and inverseness. | 76 // + 1 for the direction, start index, and inverseness. |
76 return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1; | 77 return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1; |
77 case Type::kPath: | 78 case Type::kPath: |
78 if (fPath.get()->isVolatile()) { | 79 if (0 == fPathGenID) { |
79 return -1; | 80 return -1; |
80 } else { | 81 } else { |
81 // The key is the path ID and fill type. | 82 // The key is the path ID and fill type. |
82 return 2; | 83 return 2; |
83 } | 84 } |
84 } | 85 } |
85 SkFAIL("Should never get here."); | 86 SkFAIL("Should never get here."); |
86 return 0; | 87 return 0; |
87 } | 88 } |
88 | 89 |
(...skipping 10 matching lines...) Expand all Loading... | |
99 break; | 100 break; |
100 case Type::kRRect: | 101 case Type::kRRect: |
101 fRRect.writeToMemory(key); | 102 fRRect.writeToMemory(key); |
102 key += SkRRect::kSizeInMemory / sizeof(uint32_t); | 103 key += SkRRect::kSizeInMemory / sizeof(uint32_t); |
103 *key = (fRRectDir == SkPath::kCCW_Direction) ? (1 << 31) : 0; | 104 *key = (fRRectDir == SkPath::kCCW_Direction) ? (1 << 31) : 0; |
104 *key |= fRRectIsInverted ? (1 << 30) : 0; | 105 *key |= fRRectIsInverted ? (1 << 30) : 0; |
105 *key++ |= fRRectStart; | 106 *key++ |= fRRectStart; |
106 SkASSERT(fRRectStart < 8); | 107 SkASSERT(fRRectStart < 8); |
107 break; | 108 break; |
108 case Type::kPath: | 109 case Type::kPath: |
109 SkASSERT(!fPath.get()->isVolatile()); | 110 SkASSERT(fPathGenID); |
110 *key++ = fPath.get()->getGenerationID(); | 111 *key++ = fPathGenID; |
111 // We could canonicalize the fill rule for paths that don't diff erentiate between | 112 // We could canonicalize the fill rule for paths that don't diff erentiate between |
112 // even/odd or winding fill (e.g. convex). | 113 // even/odd or winding fill (e.g. convex). |
113 *key++ = fPath.get()->getFillType(); | 114 *key++ = fPath.get()->getFillType(); |
114 break; | 115 break; |
115 } | 116 } |
116 } | 117 } |
117 SkASSERT(key - origKey == this->unstyledKeySize()); | 118 SkASSERT(key - origKey == this->unstyledKeySize()); |
118 } | 119 } |
119 | 120 |
120 void GrShape::setInheritedKey(const GrShape &parent, GrStyle::Apply apply, SkSca lar scale) { | 121 void GrShape::setInheritedKey(const GrShape &parent, GrStyle::Apply apply, SkSca lar scale) { |
121 SkASSERT(!fInheritedKey.count()); | 122 SkASSERT(!fInheritedKey.count()); |
122 // If the output shape turns out to be simple, then we will just use its geo metric key | 123 // If the output shape turns out to be simple, then we will just use its geo metric key |
123 if (Type::kPath == fType) { | 124 if (Type::kPath == fType) { |
124 // We want ApplyFullStyle(ApplyPathEffect(shape)) to have the same key a s | 125 // We want ApplyFullStyle(ApplyPathEffect(shape)) to have the same key a s |
125 // ApplyFullStyle(shape). | 126 // ApplyFullStyle(shape). |
126 // The full key is structured as (geo,path_effect,stroke). | 127 // The full key is structured as (geo,path_effect,stroke). |
127 // If we do ApplyPathEffect we get get,path_effect as the inherited key. If we then | 128 // If we do ApplyPathEffect we get get,path_effect as the inherited key. If we then |
128 // do ApplyFullStyle we'll memcpy geo,path_effect into the new inherited key | 129 // do ApplyFullStyle we'll memcpy geo,path_effect into the new inherited key |
129 // and then append the style key (which should now be stroke only) at th e end. | 130 // and then append the style key (which should now be stroke only) at th e end. |
130 int parentCnt = parent.fInheritedKey.count(); | 131 int parentCnt = parent.fInheritedKey.count(); |
131 bool useParentGeoKey = !parentCnt; | 132 bool useParentGeoKey = !parentCnt; |
132 if (useParentGeoKey) { | 133 if (useParentGeoKey) { |
133 parentCnt = parent.unstyledKeySize(); | 134 parentCnt = parent.unstyledKeySize(); |
134 if (parentCnt < 0) { | 135 if (parentCnt < 0) { |
135 // The parent's geometry has no key so we will have no key. | 136 // The parent's geometry has no key so we will have no key. |
136 fPath.get()->setIsVolatile(true); | 137 fPathGenID = 0; |
137 return; | 138 return; |
138 } | 139 } |
139 } | 140 } |
140 uint32_t styleKeyFlags = 0; | 141 uint32_t styleKeyFlags = 0; |
141 if (parent.knownToBeClosed()) { | 142 if (parent.knownToBeClosed()) { |
142 styleKeyFlags |= GrStyle::kClosed_KeyFlag; | 143 styleKeyFlags |= GrStyle::kClosed_KeyFlag; |
143 } | 144 } |
144 int styleCnt = GrStyle::KeySize(parent.fStyle, apply, styleKeyFlags); | 145 int styleCnt = GrStyle::KeySize(parent.fStyle, apply, styleKeyFlags); |
145 if (styleCnt < 0) { | 146 if (styleCnt < 0) { |
146 // The style doesn't allow a key, set the path to volatile so that w e fail when | 147 // The style doesn't allow a key, set the path gen ID to 0 so that w e fail when |
147 // we try to get a key for the shape. | 148 // we try to get a key for the shape. |
148 fPath.get()->setIsVolatile(true); | 149 fPathGenID = 0; |
149 return; | 150 return; |
150 } | 151 } |
151 fInheritedKey.reset(parentCnt + styleCnt); | 152 fInheritedKey.reset(parentCnt + styleCnt); |
152 if (useParentGeoKey) { | 153 if (useParentGeoKey) { |
153 // This will be the geo key. | 154 // This will be the geo key. |
154 parent.writeUnstyledKey(fInheritedKey.get()); | 155 parent.writeUnstyledKey(fInheritedKey.get()); |
155 } else { | 156 } else { |
156 // This should be (geo,path_effect). | 157 // This should be (geo,path_effect). |
157 memcpy(fInheritedKey.get(), parent.fInheritedKey.get(), | 158 memcpy(fInheritedKey.get(), parent.fInheritedKey.get(), |
158 parentCnt * sizeof(uint32_t)); | 159 parentCnt * sizeof(uint32_t)); |
159 } | 160 } |
160 // Now turn (geo,path_effect) or (geo) into (geo,path_effect,stroke) | 161 // Now turn (geo,path_effect) or (geo) into (geo,path_effect,stroke) |
161 GrStyle::WriteKey(fInheritedKey.get() + parentCnt, parent.fStyle, apply, scale, | 162 GrStyle::WriteKey(fInheritedKey.get() + parentCnt, parent.fStyle, apply, scale, |
162 styleKeyFlags); | 163 styleKeyFlags); |
163 } | 164 } |
164 } | 165 } |
165 | 166 |
166 GrShape::GrShape(const GrShape& that) : fType(that.fType), fStyle(that.fStyle) { | 167 GrShape::GrShape(const GrShape& that) : fType(that.fType), fStyle(that.fStyle) { |
167 switch (fType) { | 168 switch (fType) { |
168 case Type::kEmpty: | 169 case Type::kEmpty: |
169 return; | 170 break; |
170 case Type::kRRect: | 171 case Type::kRRect: |
171 fRRect = that.fRRect; | 172 fRRect = that.fRRect; |
172 fRRectDir = that.fRRectDir; | 173 fRRectDir = that.fRRectDir; |
173 fRRectStart = that.fRRectStart; | 174 fRRectStart = that.fRRectStart; |
174 fRRectIsInverted = that.fRRectIsInverted; | 175 fRRectIsInverted = that.fRRectIsInverted; |
175 return; | 176 break; |
176 case Type::kPath: | 177 case Type::kPath: |
177 fPath.set(*that.fPath.get()); | 178 fPath.set(*that.fPath.get()); |
178 return; | 179 fPathGenID = that.fPathGenID; |
180 break; | |
179 } | 181 } |
180 fInheritedKey.reset(that.fInheritedKey.count()); | 182 fInheritedKey.reset(that.fInheritedKey.count()); |
181 memcpy(fInheritedKey.get(), that.fInheritedKey.get(), | 183 sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(), |
182 sizeof(uint32_t) * fInheritedKey.count()); | 184 sizeof(uint32_t) * fInheritedKey.count()); |
183 } | 185 } |
184 | 186 |
185 GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { | 187 GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { |
186 // TODO: Add some quantization of scale for better cache performance here or leave that up | 188 // TODO: Add some quantization of scale for better cache performance here or leave that up |
187 // to caller? | 189 // to caller? |
188 // TODO: For certain shapes and stroke params we could ignore the scale. (e. g. miter or bevel | 190 // TODO: For certain shapes and stroke params we could ignore the scale. (e. g. miter or bevel |
189 // stroke of a rect). | 191 // stroke of a rect). |
190 if (!parent.style().applies() || | 192 if (!parent.style().applies() || |
191 (GrStyle::Apply::kPathEffectOnly == apply && !parent.style().pathEffect( ))) { | 193 (GrStyle::Apply::kPathEffectOnly == apply && !parent.style().pathEffect( ))) { |
192 fType = Type::kEmpty; | 194 fType = Type::kEmpty; |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
308 fType = Type::kRRect; | 310 fType = Type::kRRect; |
309 } | 311 } |
310 } | 312 } |
311 } | 313 } |
312 if (Type::kPath != fType) { | 314 if (Type::kPath != fType) { |
313 fPath.reset(); | 315 fPath.reset(); |
314 fInheritedKey.reset(0); | 316 fInheritedKey.reset(0); |
315 if (Type::kRRect == fType) { | 317 if (Type::kRRect == fType) { |
316 this->attemptToSimplifyRRect(); | 318 this->attemptToSimplifyRRect(); |
317 } | 319 } |
320 } else { | |
321 if (fInheritedKey.count() || fPath.get()->isVolatile()) { | |
322 fPathGenID = 0; | |
323 } else { | |
324 fPathGenID = fPath.get()->getGenerationID(); | |
325 } | |
326 if (this->style().isSimpleFill()) { | |
327 // Filled paths are treated as though all their contours were closed . | |
328 // Since SkPath doesn't track individual contours, this will only cl ose the last. :( | |
329 // There is no point in closing lines, though, since they loose thei r line-ness. | |
bsalomon
2016/06/20 20:18:58
In the future we'll extract the line during simpli
| |
330 if (!fPath.get()->isLine(nullptr)) { | |
331 fPath.get()->close(); | |
332 fPath.get()->setIsVolatile(true); | |
333 } | |
334 } | |
335 if (fPath.get()->isConvex()) { | |
336 // There is no distinction between even/odd and non-zero winding cou nt for convex | |
337 // paths. | |
338 if (fPath.get()->isInverseFillType()) { | |
339 fPath.get()->setFillType(SkPath::kInverseEvenOdd_FillType); | |
340 } else { | |
341 fPath.get()->setFillType(SkPath::kEvenOdd_FillType); | |
342 } | |
343 } | |
344 if (this->style().isDashed()) { | |
345 // Dashing ignores inverseness (skbug.com/5421) | |
346 switch (fPath.get()->getFillType()) { | |
347 case SkPath::kWinding_FillType: | |
348 case SkPath::kEvenOdd_FillType: | |
349 break; | |
350 case SkPath::kInverseWinding_FillType: | |
351 fPath.get()->setFillType(SkPath::kWinding_FillType); | |
352 break; | |
353 case SkPath::kInverseEvenOdd_FillType: | |
354 fPath.get()->setFillType(SkPath::kEvenOdd_FillType); | |
355 break; | |
356 } | |
357 } | |
318 } | 358 } |
319 } | 359 } |
320 | 360 |
321 void GrShape::attemptToSimplifyRRect() { | 361 void GrShape::attemptToSimplifyRRect() { |
322 SkASSERT(Type::kRRect == fType); | 362 SkASSERT(Type::kRRect == fType); |
323 SkASSERT(!fInheritedKey.count()); | 363 SkASSERT(!fInheritedKey.count()); |
324 if (fRRect.isEmpty()) { | 364 if (fRRect.isEmpty()) { |
325 fType = Type::kEmpty; | 365 fType = Type::kEmpty; |
326 return; | 366 return; |
327 } | 367 } |
328 if (!this->style().hasPathEffect()) { | 368 if (!this->style().hasPathEffect()) { |
329 fRRectDir = kDefaultRRectDir; | 369 fRRectDir = kDefaultRRectDir; |
330 fRRectStart = kDefaultRRectStart; | 370 fRRectStart = kDefaultRRectStart; |
331 } else if (fStyle.isDashed()) { | 371 } else if (fStyle.isDashed()) { |
332 // Dashing ignores the inverseness (currently). skbug.com/5421 | 372 // Dashing ignores the inverseness (currently). skbug.com/5421 |
333 fRRectIsInverted = false; | 373 fRRectIsInverted = false; |
334 } | 374 } |
335 } | 375 } |
OLD | NEW |