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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 break; | 76 break; |
77 case Type::kPath: | 77 case Type::kPath: |
78 SkASSERT(!fPath.get()->isVolatile()); | 78 SkASSERT(!fPath.get()->isVolatile()); |
79 *key++ = fPath.get()->getGenerationID(); | 79 *key++ = fPath.get()->getGenerationID(); |
80 break; | 80 break; |
81 } | 81 } |
82 } | 82 } |
83 SkASSERT(key - origKey == this->unstyledKeySize()); | 83 SkASSERT(key - origKey == this->unstyledKeySize()); |
84 } | 84 } |
85 | 85 |
86 void GrShape::setInheritedKey(const GrShape &parent, GrStyle::Apply apply) { | 86 void GrShape::setInheritedKey(const GrShape &parent, GrStyle::Apply apply, SkSca
lar scale) { |
87 SkASSERT(!fInheritedKey.count()); | 87 SkASSERT(!fInheritedKey.count()); |
88 // If the output shape turns out to be simple, then we will just use its geo
metric key | 88 // If the output shape turns out to be simple, then we will just use its geo
metric key |
89 if (Type::kPath == fType) { | 89 if (Type::kPath == fType) { |
90 // We want ApplyFullStyle(ApplyPathEffect(shape)) to have the same key a
s | 90 // We want ApplyFullStyle(ApplyPathEffect(shape)) to have the same key a
s |
91 // ApplyFullStyle(shape). | 91 // ApplyFullStyle(shape). |
92 // The full key is structured as (geo,path_effect,stroke). | 92 // The full key is structured as (geo,path_effect,stroke). |
93 // If we do ApplyPathEffect we get get,path_effect as the inherited key.
If we then | 93 // If we do ApplyPathEffect we get get,path_effect as the inherited key.
If we then |
94 // do ApplyFullStyle we'll memcpy geo,path_effect into the new inherited
key | 94 // do ApplyFullStyle we'll memcpy geo,path_effect into the new inherited
key |
95 // and then append the style key (which should now be stroke only) at th
e end. | 95 // and then append the style key (which should now be stroke only) at th
e end. |
96 int parentCnt = parent.fInheritedKey.count(); | 96 int parentCnt = parent.fInheritedKey.count(); |
(...skipping 20 matching lines...) Expand all Loading... |
117 fInheritedKey.reset(parentCnt + styleCnt); | 117 fInheritedKey.reset(parentCnt + styleCnt); |
118 if (useParentGeoKey) { | 118 if (useParentGeoKey) { |
119 // This will be the geo key. | 119 // This will be the geo key. |
120 parent.writeUnstyledKey(fInheritedKey.get()); | 120 parent.writeUnstyledKey(fInheritedKey.get()); |
121 } else { | 121 } else { |
122 // This should be (geo,path_effect). | 122 // This should be (geo,path_effect). |
123 memcpy(fInheritedKey.get(), parent.fInheritedKey.get(), | 123 memcpy(fInheritedKey.get(), parent.fInheritedKey.get(), |
124 parentCnt * sizeof(uint32_t)); | 124 parentCnt * sizeof(uint32_t)); |
125 } | 125 } |
126 // Now turn (geo,path_effect) or (geo) into (geo,path_effect,stroke) | 126 // Now turn (geo,path_effect) or (geo) into (geo,path_effect,stroke) |
127 GrStyle::WriteKey(fInheritedKey.get() + parentCnt, parent.fStyle, apply,
styleKeyFlags); | 127 GrStyle::WriteKey(fInheritedKey.get() + parentCnt, parent.fStyle, apply,
scale, |
| 128 styleKeyFlags); |
128 } | 129 } |
129 } | 130 } |
130 | 131 |
131 GrShape::GrShape(const GrShape& that) : fType(that.fType), fStyle(that.fStyle) { | 132 GrShape::GrShape(const GrShape& that) : fType(that.fType), fStyle(that.fStyle) { |
132 switch (fType) { | 133 switch (fType) { |
133 case Type::kEmpty: | 134 case Type::kEmpty: |
134 return; | 135 return; |
135 case Type::kRRect: | 136 case Type::kRRect: |
136 fRRect = that.fRRect; | 137 fRRect = that.fRRect; |
137 return; | 138 return; |
138 case Type::kPath: | 139 case Type::kPath: |
139 fPath.set(*that.fPath.get()); | 140 fPath.set(*that.fPath.get()); |
140 return; | 141 return; |
141 } | 142 } |
142 fInheritedKey.reset(that.fInheritedKey.count()); | 143 fInheritedKey.reset(that.fInheritedKey.count()); |
143 memcpy(fInheritedKey.get(), that.fInheritedKey.get(), | 144 memcpy(fInheritedKey.get(), that.fInheritedKey.get(), |
144 sizeof(uint32_t) * fInheritedKey.count()); | 145 sizeof(uint32_t) * fInheritedKey.count()); |
145 } | 146 } |
146 | 147 |
147 GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply) { | 148 GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { |
| 149 // TODO: Add some quantization of scale for better cache performance here or
leave that up |
| 150 // to caller? |
| 151 // TODO: For certain shapes and stroke params we could ignore the scale. (e.
g. miter or bevel |
| 152 // stroke of a rect). |
148 if (!parent.style().applies() || | 153 if (!parent.style().applies() || |
149 (GrStyle::Apply::kPathEffectOnly == apply && !parent.style().pathEffect(
))) { | 154 (GrStyle::Apply::kPathEffectOnly == apply && !parent.style().pathEffect(
))) { |
150 fType = Type::kEmpty; | 155 fType = Type::kEmpty; |
151 *this = parent; | 156 *this = parent; |
152 return; | 157 return; |
153 } | 158 } |
154 | 159 |
155 SkPathEffect* pe = parent.fStyle.pathEffect(); | 160 SkPathEffect* pe = parent.fStyle.pathEffect(); |
156 SkTLazy<SkPath> tmpPath; | 161 SkTLazy<SkPath> tmpPath; |
157 const GrShape* parentForKey = &parent; | 162 const GrShape* parentForKey = &parent; |
158 SkTLazy<GrShape> tmpParent; | 163 SkTLazy<GrShape> tmpParent; |
159 fType = Type::kPath; | 164 fType = Type::kPath; |
160 fPath.init(); | 165 fPath.init(); |
161 if (pe) { | 166 if (pe) { |
162 SkPath* srcForPathEffect; | 167 SkPath* srcForPathEffect; |
163 if (parent.fType == Type::kPath) { | 168 if (parent.fType == Type::kPath) { |
164 srcForPathEffect = parent.fPath.get(); | 169 srcForPathEffect = parent.fPath.get(); |
165 } else { | 170 } else { |
166 srcForPathEffect = tmpPath.init(); | 171 srcForPathEffect = tmpPath.init(); |
167 parent.asPath(tmpPath.get()); | 172 parent.asPath(tmpPath.get()); |
168 } | 173 } |
169 // Should we consider bounds? Would have to include in key, but it'd be
nice to know | 174 // Should we consider bounds? Would have to include in key, but it'd be
nice to know |
170 // if the bounds actually modified anything before including in key. | 175 // if the bounds actually modified anything before including in key. |
171 SkStrokeRec strokeRec = parent.fStyle.strokeRec(); | 176 SkStrokeRec strokeRec = parent.fStyle.strokeRec(); |
| 177 strokeRec.setResScale(scale); |
172 if (!pe->filterPath(fPath.get(), *srcForPathEffect, &strokeRec, nullptr)
) { | 178 if (!pe->filterPath(fPath.get(), *srcForPathEffect, &strokeRec, nullptr)
) { |
173 // Make an empty unstyled shape if filtering fails. | 179 // Make an empty unstyled shape if filtering fails. |
174 fType = Type::kEmpty; | 180 fType = Type::kEmpty; |
175 fStyle = GrStyle(); | 181 fStyle = GrStyle(); |
176 fPath.reset(); | 182 fPath.reset(); |
177 return; | 183 return; |
178 } | 184 } |
| 185 // A path effect has access to change the res scale but we aren't expect
ing it to and it |
| 186 // would mess up our key computation. |
| 187 SkASSERT(scale == strokeRec.getResScale()); |
179 if (GrStyle::Apply::kPathEffectAndStrokeRec == apply) { | 188 if (GrStyle::Apply::kPathEffectAndStrokeRec == apply) { |
180 if (strokeRec.needToApply()) { | 189 if (strokeRec.needToApply()) { |
181 // The intermediate shape may not be a general path. If we we're
just applying | 190 // The intermediate shape may not be a general path. If we we're
just applying |
182 // the path effect then attemptToReduceFromPath would catch it.
This means that | 191 // the path effect then attemptToReduceFromPath would catch it.
This means that |
183 // when we subsequently applied the remaining strokeRec we would
have a non-path | 192 // when we subsequently applied the remaining strokeRec we would
have a non-path |
184 // parent shape that would be used to determine the the stroked
path's key. | 193 // parent shape that would be used to determine the the stroked
path's key. |
185 // We detect that case here and change parentForKey to a tempora
ry that represents | 194 // We detect that case here and change parentForKey to a tempora
ry that represents |
186 // the simpler shape so that applying both path effect and the s
trokerec all at | 195 // the simpler shape so that applying both path effect and the s
trokerec all at |
187 // once produces the same key. | 196 // once produces the same key. |
188 SkRRect rrect; | 197 SkRRect rrect; |
(...skipping 11 matching lines...) Expand all Loading... |
200 break; | 209 break; |
201 } | 210 } |
202 SkAssertResult(strokeRec.applyToPath(fPath.get(), *fPath.get()))
; | 211 SkAssertResult(strokeRec.applyToPath(fPath.get(), *fPath.get()))
; |
203 } else { | 212 } else { |
204 fStyle = GrStyle(strokeRec, nullptr); | 213 fStyle = GrStyle(strokeRec, nullptr); |
205 } | 214 } |
206 } else { | 215 } else { |
207 fStyle = GrStyle(strokeRec, nullptr); | 216 fStyle = GrStyle(strokeRec, nullptr); |
208 } | 217 } |
209 } else { | 218 } else { |
210 const SkPath* srcForStrokeRec; | 219 const SkPath* srcForParentStyle; |
211 if (parent.fType == Type::kPath) { | 220 if (parent.fType == Type::kPath) { |
212 srcForStrokeRec = parent.fPath.get(); | 221 srcForParentStyle = parent.fPath.get(); |
213 } else { | 222 } else { |
214 srcForStrokeRec = tmpPath.init(); | 223 srcForParentStyle = tmpPath.init(); |
215 parent.asPath(tmpPath.get()); | 224 parent.asPath(tmpPath.get()); |
216 } | 225 } |
217 SkASSERT(parent.fStyle.strokeRec().needToApply()); | 226 SkStrokeRec::InitStyle fillOrHairline; |
218 SkAssertResult(parent.fStyle.strokeRec().applyToPath(fPath.get(), *srcFo
rStrokeRec)); | 227 SkASSERT(parent.fStyle.applies()); |
219 fStyle.resetToInitStyle(SkStrokeRec::kFill_InitStyle); | 228 SkASSERT(!parent.fStyle.pathEffect()); |
| 229 SkAssertResult(parent.fStyle.applyToPath(fPath.get(), &fillOrHairline, *
srcForParentStyle, |
| 230 scale)); |
| 231 fStyle.resetToInitStyle(fillOrHairline); |
220 } | 232 } |
221 this->attemptToReduceFromPath(); | 233 this->attemptToReduceFromPath(); |
222 this->setInheritedKey(*parentForKey, apply); | 234 this->setInheritedKey(*parentForKey, apply, scale); |
223 } | 235 } |
OLD | NEW |