| 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 |