Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(710)

Side by Side Diff: src/gpu/GrShape.cpp

Issue 1951613002: Expand GrStyle's interface. (Closed) Base URL: https://chromium.googlesource.com/skia.git@style
Patch Set: Don't use temp for stroke in GrShape::GrShape() Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrShape.h ('k') | src/gpu/GrStyle.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 int GrShape::StyleKeySize(const GrStyle& style, bool stopAfterPE) { 86 void GrShape::setInheritedKey(const GrShape &parent, GrStyle::Apply apply) {
87 GR_STATIC_ASSERT(sizeof(uint32_t) == sizeof(SkScalar));
88 int size = 0;
89 if (style.isDashed()) {
90 // One scalar for dash phase and one for each dash value.
91 size += 1 + style.dashIntervalCnt();
92 } else if (style.pathEffect()) {
93 // No key for a generic path effect.
94 return -1;
95 }
96
97 if (stopAfterPE) {
98 return size;
99 }
100
101 if (style.strokeRec().needToApply()) {
102 // One for style/cap/join, 2 for miter and width.
103 size += 3;
104 }
105 return size;
106 }
107
108 void GrShape::StyleKey(uint32_t* key, const GrStyle& style, bool stopAfterPE) {
109 SkASSERT(key);
110 SkASSERT(StyleKeySize(style, stopAfterPE) >= 0);
111 GR_STATIC_ASSERT(sizeof(uint32_t) == sizeof(SkScalar));
112
113 int i = 0;
114 if (style.isDashed()) {
115 GR_STATIC_ASSERT(sizeof(style.dashPhase()) == sizeof(uint32_t));
116 SkScalar phase = style.dashPhase();
117 memcpy(&key[i++], &phase, sizeof(SkScalar));
118
119 int32_t count = style.dashIntervalCnt();
120 // Dash count should always be even.
121 SkASSERT(0 == (count & 0x1));
122 const SkScalar* intervals = style.dashIntervals();
123 int intervalByteCnt = count * sizeof(SkScalar);
124 memcpy(&key[i], intervals, intervalByteCnt);
125 i += count;
126 } else {
127 SkASSERT(!style.pathEffect());
128 }
129
130 if (!stopAfterPE && style.strokeRec().needToApply()) {
131 enum {
132 kStyleBits = 2,
133 kJoinBits = 2,
134 kCapBits = 32 - kStyleBits - kJoinBits,
135
136 kJoinShift = kStyleBits,
137 kCapShift = kJoinShift + kJoinBits,
138 };
139 GR_STATIC_ASSERT(SkStrokeRec::kStyleCount <= (1 << kStyleBits));
140 GR_STATIC_ASSERT(SkPaint::kJoinCount <= (1 << kJoinBits));
141 GR_STATIC_ASSERT(SkPaint::kCapCount <= (1 << kCapBits));
142 key[i++] = style.strokeRec().getStyle() |
143 style.strokeRec().getJoin() << kJoinShift |
144 style.strokeRec().getCap() << kCapShift;
145
146 SkScalar scalar;
147 // Miter limit only affects miter joins
148 scalar = SkPaint::kMiter_Join == style.strokeRec().getJoin()
149 ? style.strokeRec().getMiter()
150 : -1.f;
151 memcpy(&key[i++], &scalar, sizeof(scalar));
152
153 scalar = style.strokeRec().getWidth();
154 memcpy(&key[i++], &scalar, sizeof(scalar));
155 }
156 SkASSERT(StyleKeySize(style, stopAfterPE) == i);
157 }
158
159 void GrShape::setInheritedKey(const GrShape &parent, bool stopAfterPE) {
160 SkASSERT(!fInheritedKey.count()); 87 SkASSERT(!fInheritedKey.count());
161 // 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
162 if (Type::kPath == fType) { 89 if (Type::kPath == fType) {
163 // 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
164 // ApplyFullStyle(shape). 91 // ApplyFullStyle(shape).
165 // The full key is structured as (geo,path_effect,stroke). 92 // The full key is structured as (geo,path_effect,stroke).
166 // 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
167 // 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
168 // 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.
169 int parentCnt = parent.fInheritedKey.count(); 96 int parentCnt = parent.fInheritedKey.count();
170 bool useParentGeoKey = !parentCnt; 97 bool useParentGeoKey = !parentCnt;
171 if (useParentGeoKey) { 98 if (useParentGeoKey) {
172 parentCnt = parent.unstyledKeySize(); 99 parentCnt = parent.unstyledKeySize();
173 if (parentCnt < 0) { 100 if (parentCnt < 0) {
174 // The parent's geometry has no key so we will have no key. 101 // The parent's geometry has no key so we will have no key.
175 fPath.get()->setIsVolatile(true); 102 fPath.get()->setIsVolatile(true);
176 return; 103 return;
177 } 104 }
178 } 105 }
179 int styleCnt = StyleKeySize(parent.fStyle, stopAfterPE); 106 int styleCnt = GrStyle::KeySize(parent.fStyle, apply);
180 if (styleCnt < 0) { 107 if (styleCnt < 0) {
181 // The style doesn't allow a key, set the path to volatile so that w e fail when 108 // The style doesn't allow a key, set the path to volatile so that w e fail when
182 // we try to get a key for the shape. 109 // we try to get a key for the shape.
183 fPath.get()->setIsVolatile(true); 110 fPath.get()->setIsVolatile(true);
184 return; 111 return;
185 } 112 }
186 fInheritedKey.reset(parentCnt + styleCnt); 113 fInheritedKey.reset(parentCnt + styleCnt);
187 if (useParentGeoKey) { 114 if (useParentGeoKey) {
188 // This will be the geo key. 115 // This will be the geo key.
189 parent.writeUnstyledKey(fInheritedKey.get()); 116 parent.writeUnstyledKey(fInheritedKey.get());
190 } else { 117 } else {
191 // This should be (geo,path_effect). 118 // This should be (geo,path_effect).
192 memcpy(fInheritedKey.get(), parent.fInheritedKey.get(), 119 memcpy(fInheritedKey.get(), parent.fInheritedKey.get(),
193 parentCnt * sizeof(uint32_t)); 120 parentCnt * sizeof(uint32_t));
194 } 121 }
195 // Now turn (geo,path_effect) or (geo) into (geo,path_effect,stroke) 122 // Now turn (geo,path_effect) or (geo) into (geo,path_effect,stroke)
196 StyleKey(fInheritedKey.get() + parentCnt, parent.fStyle, stopAfterPE); 123 GrStyle::WriteKey(fInheritedKey.get() + parentCnt, parent.fStyle, apply) ;
197 } 124 }
198 } 125 }
199 126
200 GrShape::GrShape(const GrShape& that) : fType(that.fType), fStyle(that.fStyle) { 127 GrShape::GrShape(const GrShape& that) : fType(that.fType), fStyle(that.fStyle) {
201 switch (fType) { 128 switch (fType) {
202 case Type::kEmpty: 129 case Type::kEmpty:
203 return; 130 return;
204 case Type::kRRect: 131 case Type::kRRect:
205 fRRect = that.fRRect; 132 fRRect = that.fRRect;
206 return; 133 return;
207 case Type::kPath: 134 case Type::kPath:
208 fPath.set(*that.fPath.get()); 135 fPath.set(*that.fPath.get());
209 return; 136 return;
210 } 137 }
211 fInheritedKey.reset(that.fInheritedKey.count()); 138 fInheritedKey.reset(that.fInheritedKey.count());
212 memcpy(fInheritedKey.get(), that.fInheritedKey.get(), 139 memcpy(fInheritedKey.get(), that.fInheritedKey.get(),
213 sizeof(uint32_t) * fInheritedKey.count()); 140 sizeof(uint32_t) * fInheritedKey.count());
214 } 141 }
215 142
216 GrShape::GrShape(const GrShape& parent, bool stopAfterPE) { 143 GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply) {
217 fType = Type::kEmpty; 144 if (!parent.style().applies() ||
145 (GrStyle::Apply::kPathEffectOnly == apply && !parent.style().pathEffect( ))) {
146 fType = Type::kEmpty;
147 *this = parent;
148 return;
149 }
150
218 SkPathEffect* pe = parent.fStyle.pathEffect(); 151 SkPathEffect* pe = parent.fStyle.pathEffect();
219 const SkPath* inPath; 152 SkTLazy<SkPath> tmpPath;
220 SkStrokeRec strokeRec = parent.fStyle.strokeRec(); 153 const GrShape* parentForKey = &parent;
221 bool appliedPE = false; 154 SkTLazy<GrShape> tmpParent;
155 fType = Type::kPath;
156 fPath.init();
222 if (pe) { 157 if (pe) {
223 fType = Type::kPath; 158 SkPath* srcForPathEffect;
224 fPath.init();
225 if (parent.fType == Type::kPath) { 159 if (parent.fType == Type::kPath) {
226 inPath = parent.fPath.get(); 160 srcForPathEffect = parent.fPath.get();
227 } else { 161 } else {
228 inPath = fPath.get(); 162 srcForPathEffect = tmpPath.init();
229 parent.asPath(fPath.get()); 163 parent.asPath(tmpPath.get());
230 } 164 }
231 // Should we consider bounds? Would have to include in key, but it'd be nice to know 165 // Should we consider bounds? Would have to include in key, but it'd be nice to know
232 // if the bounds actually modified anything before including in key. 166 // if the bounds actually modified anything before including in key.
233 if (!pe->filterPath(fPath.get(), *inPath, &strokeRec, nullptr)) { 167 SkStrokeRec strokeRec = parent.fStyle.strokeRec();
168 if (!pe->filterPath(fPath.get(), *srcForPathEffect, &strokeRec, nullptr) ) {
234 // Make an empty unstyled shape if filtering fails. 169 // Make an empty unstyled shape if filtering fails.
235 fType = Type::kEmpty; 170 fType = Type::kEmpty;
236 fStyle = GrStyle(); 171 fStyle = GrStyle();
237 fPath.reset(); 172 fPath.reset();
238 return; 173 return;
239 } 174 }
240 appliedPE = true; 175 if (GrStyle::Apply::kPathEffectAndStrokeRec == apply) {
241 inPath = fPath.get(); 176 if (strokeRec.needToApply()) {
242 } else if (stopAfterPE || !strokeRec.needToApply()) { 177 // The intermediate shape may not be a general path. If we we're just applying
243 *this = parent; 178 // the path effect then attemptToReduceFromPath would catch it. This means that
244 return; 179 // when we subsequently applied the remaining strokeRec we would have a non-path
180 // parent shape that would be used to determine the the stroked path's key.
181 // We detect that case here and change parentForKey to a tempora ry that represents
182 // the simpler shape so that applying both path effect and the s trokerec all at
183 // once produces the same key.
184 SkRRect rrect;
185 Type parentType = AttemptToReduceFromPathImpl(*fPath.get(), &rre ct, nullptr,
186 strokeRec);
187 switch (parentType) {
188 case Type::kEmpty:
189 tmpParent.init();
190 parentForKey = tmpParent.get();
191 break;
192 case Type::kRRect:
193 tmpParent.init(rrect, GrStyle(strokeRec, nullptr));
194 parentForKey = tmpParent.get();
195 case Type::kPath:
196 break;
197 }
198 SkAssertResult(strokeRec.applyToPath(fPath.get(), *fPath.get())) ;
199 } else {
200 fStyle = GrStyle(strokeRec, nullptr);
201 }
202 } else {
203 fStyle = GrStyle(strokeRec, nullptr);
204 }
245 } else { 205 } else {
246 fType = Type::kPath; 206 const SkPath* srcForStrokeRec;
247 fPath.init();
248 if (parent.fType == Type::kPath) { 207 if (parent.fType == Type::kPath) {
249 inPath = parent.fPath.get(); 208 srcForStrokeRec = parent.fPath.get();
250 } else { 209 } else {
251 inPath = fPath.get(); 210 srcForStrokeRec = tmpPath.init();
252 parent.asPath(fPath.get()); 211 parent.asPath(tmpPath.get());
253 } 212 }
254 } 213 SkASSERT(parent.fStyle.strokeRec().needToApply());
255 const GrShape* effectiveParent = &parent; 214 SkAssertResult(parent.fStyle.strokeRec().applyToPath(fPath.get(), *srcFo rStrokeRec));
256 SkTLazy<GrShape> tmpParent; 215 fStyle.resetToInitStyle(SkStrokeRec::kFill_InitStyle);
257 if (!stopAfterPE) {
258 if (appliedPE) {
259 // If the intermediate shape from just the PE is not a path then we capture that here
260 // so that we can pass the non-path parent to setInheritedKey.
261 SkRRect rrect;
262 Type parentType = AttemptToReduceFromPathImpl(*fPath.get(), &rrect, nullptr, strokeRec);
263 switch (parentType) {
264 case Type::kEmpty:
265 tmpParent.init();
266 effectiveParent = tmpParent.get();
267 break;
268 case Type::kRRect:
269 tmpParent.init(rrect, GrStyle(strokeRec, nullptr));
270 effectiveParent = tmpParent.get();
271 case Type::kPath:
272 break;
273 }
274 }
275 strokeRec.applyToPath(fPath.get(), *inPath);
276 } else {
277 fStyle = GrStyle(strokeRec, nullptr);
278 } 216 }
279 this->attemptToReduceFromPath(); 217 this->attemptToReduceFromPath();
280 this->setInheritedKey(*effectiveParent, stopAfterPE); 218 this->setInheritedKey(*parentForKey, apply);
281 } 219 }
OLDNEW
« no previous file with comments | « src/gpu/GrShape.h ('k') | src/gpu/GrStyle.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698