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

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

Issue 2094023002: Use a union inside GrShape to hold geometry (Closed) Base URL: https://chromium.googlesource.com/skia.git@noprkey
Patch Set: move comment Created 4 years, 5 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') | no next file » | 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) {
11 bool wasPath = Type::kPath == fType;
12 fStyle = that.fStyle; 11 fStyle = that.fStyle;
13 fType = that.fType; 12 this->changeType(that.fType, Type::kPath == that.fType ? &that.path() : null ptr);
14 switch (fType) { 13 switch (fType) {
15 case Type::kEmpty: 14 case Type::kEmpty:
16 if (wasPath) {
17 fPath.reset();
18 }
19 break; 15 break;
20 case Type::kRRect: 16 case Type::kRRect:
21 if (wasPath) { 17 fRRectData.fRRect = that.fRRectData.fRRect;
22 fPath.reset(); 18 fRRectData.fDir = that.fRRectData.fDir;
23 } 19 fRRectData.fStart = that.fRRectData.fStart;
24 fRRect = that.fRRect; 20 fRRectData.fInverted = that.fRRectData.fInverted;
25 fRRectDir = that.fRRectDir;
26 fRRectStart = that.fRRectStart;
27 fRRectIsInverted = that.fRRectIsInverted;
28 break; 21 break;
29 case Type::kPath: 22 case Type::kPath:
30 if (wasPath) { 23 fPathData.fGenID = that.fPathData.fGenID;
31 *fPath.get() = *that.fPath.get();
32 } else {
33 fPath.set(*that.fPath.get());
34 }
35 fPathGenID = that.fPathGenID;
36 break; 24 break;
37 } 25 }
38 fInheritedKey.reset(that.fInheritedKey.count()); 26 fInheritedKey.reset(that.fInheritedKey.count());
39 sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(), 27 sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(),
40 sizeof(uint32_t) * fInheritedKey.count()); 28 sizeof(uint32_t) * fInheritedKey.count());
41 return *this; 29 return *this;
42 } 30 }
43 31
44 const SkRect& GrShape::bounds() const { 32 const SkRect& GrShape::bounds() const {
45 static constexpr SkRect kEmpty = SkRect::MakeEmpty(); 33 static constexpr SkRect kEmpty = SkRect::MakeEmpty();
46 switch (fType) { 34 switch (fType) {
47 case Type::kEmpty: 35 case Type::kEmpty:
48 return kEmpty; 36 return kEmpty;
49 case Type::kRRect: 37 case Type::kRRect:
50 return fRRect.getBounds(); 38 return fRRectData.fRRect.getBounds();
51 case Type::kPath: 39 case Type::kPath:
52 return fPath.get()->getBounds(); 40 return this->path().getBounds();
53 } 41 }
54 SkFAIL("Unknown shape type"); 42 SkFAIL("Unknown shape type");
55 return kEmpty; 43 return kEmpty;
56 } 44 }
57 45
58 void GrShape::styledBounds(SkRect* bounds) const { 46 void GrShape::styledBounds(SkRect* bounds) const {
59 if (Type::kEmpty == fType && !fStyle.hasNonDashPathEffect()) { 47 if (Type::kEmpty == fType && !fStyle.hasNonDashPathEffect()) {
60 *bounds = SkRect::MakeEmpty(); 48 *bounds = SkRect::MakeEmpty();
61 } else { 49 } else {
62 fStyle.adjustBounds(bounds, this->bounds()); 50 fStyle.adjustBounds(bounds, this->bounds());
63 } 51 }
64 } 52 }
65 53
66 int GrShape::unstyledKeySize() const { 54 int GrShape::unstyledKeySize() const {
67 if (fInheritedKey.count()) { 55 if (fInheritedKey.count()) {
68 return fInheritedKey.count(); 56 return fInheritedKey.count();
69 } 57 }
70 switch (fType) { 58 switch (fType) {
71 case Type::kEmpty: 59 case Type::kEmpty:
72 return 1; 60 return 1;
73 case Type::kRRect: 61 case Type::kRRect:
74 SkASSERT(!fInheritedKey.count()); 62 SkASSERT(!fInheritedKey.count());
75 SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t)); 63 SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t));
76 // + 1 for the direction, start index, and inverseness. 64 // + 1 for the direction, start index, and inverseness.
77 return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1; 65 return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1;
78 case Type::kPath: 66 case Type::kPath:
79 if (0 == fPathGenID) { 67 if (0 == fPathData.fGenID) {
80 return -1; 68 return -1;
81 } else { 69 } else {
82 // The key is the path ID and fill type. 70 // The key is the path ID and fill type.
83 return 2; 71 return 2;
84 } 72 }
85 } 73 }
86 SkFAIL("Should never get here."); 74 SkFAIL("Should never get here.");
87 return 0; 75 return 0;
88 } 76 }
89 77
90 void GrShape::writeUnstyledKey(uint32_t* key) const { 78 void GrShape::writeUnstyledKey(uint32_t* key) const {
91 SkASSERT(this->unstyledKeySize()); 79 SkASSERT(this->unstyledKeySize());
92 SkDEBUGCODE(uint32_t* origKey = key;) 80 SkDEBUGCODE(uint32_t* origKey = key;)
93 if (fInheritedKey.count()) { 81 if (fInheritedKey.count()) {
94 memcpy(key, fInheritedKey.get(), sizeof(uint32_t) * fInheritedKey.count( )); 82 memcpy(key, fInheritedKey.get(), sizeof(uint32_t) * fInheritedKey.count( ));
95 SkDEBUGCODE(key += fInheritedKey.count();) 83 SkDEBUGCODE(key += fInheritedKey.count();)
96 } else { 84 } else {
97 switch (fType) { 85 switch (fType) {
98 case Type::kEmpty: 86 case Type::kEmpty:
99 *key++ = 1; 87 *key++ = 1;
100 break; 88 break;
101 case Type::kRRect: 89 case Type::kRRect:
102 fRRect.writeToMemory(key); 90 fRRectData.fRRect.writeToMemory(key);
103 key += SkRRect::kSizeInMemory / sizeof(uint32_t); 91 key += SkRRect::kSizeInMemory / sizeof(uint32_t);
104 *key = (fRRectDir == SkPath::kCCW_Direction) ? (1 << 31) : 0; 92 *key = (fRRectData.fDir == SkPath::kCCW_Direction) ? (1 << 31) : 0;
105 *key |= fRRectIsInverted ? (1 << 30) : 0; 93 *key |= fRRectData.fInverted ? (1 << 30) : 0;
106 *key++ |= fRRectStart; 94 *key++ |= fRRectData.fStart;
107 SkASSERT(fRRectStart < 8); 95 SkASSERT(fRRectData.fStart < 8);
108 break; 96 break;
109 case Type::kPath: 97 case Type::kPath:
110 SkASSERT(fPathGenID); 98 SkASSERT(fPathData.fGenID);
111 *key++ = fPathGenID; 99 *key++ = fPathData.fGenID;
112 // We could canonicalize the fill rule for paths that don't diff erentiate between 100 // We could canonicalize the fill rule for paths that don't diff erentiate between
113 // even/odd or winding fill (e.g. convex). 101 // even/odd or winding fill (e.g. convex).
114 *key++ = fPath.get()->getFillType(); 102 *key++ = this->path().getFillType();
115 break; 103 break;
116 } 104 }
117 } 105 }
118 SkASSERT(key - origKey == this->unstyledKeySize()); 106 SkASSERT(key - origKey == this->unstyledKeySize());
119 } 107 }
120 108
121 void GrShape::setInheritedKey(const GrShape &parent, GrStyle::Apply apply, SkSca lar scale) { 109 void GrShape::setInheritedKey(const GrShape &parent, GrStyle::Apply apply, SkSca lar scale) {
122 SkASSERT(!fInheritedKey.count()); 110 SkASSERT(!fInheritedKey.count());
123 // If the output shape turns out to be simple, then we will just use its geo metric key 111 // If the output shape turns out to be simple, then we will just use its geo metric key
124 if (Type::kPath == fType) { 112 if (Type::kPath == fType) {
125 // We want ApplyFullStyle(ApplyPathEffect(shape)) to have the same key a s 113 // We want ApplyFullStyle(ApplyPathEffect(shape)) to have the same key a s
126 // ApplyFullStyle(shape). 114 // ApplyFullStyle(shape).
127 // The full key is structured as (geo,path_effect,stroke). 115 // The full key is structured as (geo,path_effect,stroke).
128 // If we do ApplyPathEffect we get get,path_effect as the inherited key. If we then 116 // If we do ApplyPathEffect we get get,path_effect as the inherited key. If we then
129 // do ApplyFullStyle we'll memcpy geo,path_effect into the new inherited key 117 // do ApplyFullStyle we'll memcpy geo,path_effect into the new inherited key
130 // and then append the style key (which should now be stroke only) at th e end. 118 // and then append the style key (which should now be stroke only) at th e end.
131 int parentCnt = parent.fInheritedKey.count(); 119 int parentCnt = parent.fInheritedKey.count();
132 bool useParentGeoKey = !parentCnt; 120 bool useParentGeoKey = !parentCnt;
133 if (useParentGeoKey) { 121 if (useParentGeoKey) {
134 parentCnt = parent.unstyledKeySize(); 122 parentCnt = parent.unstyledKeySize();
135 if (parentCnt < 0) { 123 if (parentCnt < 0) {
136 // The parent's geometry has no key so we will have no key. 124 // The parent's geometry has no key so we will have no key.
137 fPathGenID = 0; 125 fPathData.fGenID = 0;
138 return; 126 return;
139 } 127 }
140 } 128 }
141 uint32_t styleKeyFlags = 0; 129 uint32_t styleKeyFlags = 0;
142 if (parent.knownToBeClosed()) { 130 if (parent.knownToBeClosed()) {
143 styleKeyFlags |= GrStyle::kClosed_KeyFlag; 131 styleKeyFlags |= GrStyle::kClosed_KeyFlag;
144 } 132 }
145 int styleCnt = GrStyle::KeySize(parent.fStyle, apply, styleKeyFlags); 133 int styleCnt = GrStyle::KeySize(parent.fStyle, apply, styleKeyFlags);
146 if (styleCnt < 0) { 134 if (styleCnt < 0) {
147 // The style doesn't allow a key, set the path gen ID to 0 so that w e fail when 135 // The style doesn't allow a key, set the path gen ID to 0 so that w e fail when
148 // we try to get a key for the shape. 136 // we try to get a key for the shape.
149 fPathGenID = 0; 137 fPathData.fGenID = 0;
150 return; 138 return;
151 } 139 }
152 fInheritedKey.reset(parentCnt + styleCnt); 140 fInheritedKey.reset(parentCnt + styleCnt);
153 if (useParentGeoKey) { 141 if (useParentGeoKey) {
154 // This will be the geo key. 142 // This will be the geo key.
155 parent.writeUnstyledKey(fInheritedKey.get()); 143 parent.writeUnstyledKey(fInheritedKey.get());
156 } else { 144 } else {
157 // This should be (geo,path_effect). 145 // This should be (geo,path_effect).
158 memcpy(fInheritedKey.get(), parent.fInheritedKey.get(), 146 memcpy(fInheritedKey.get(), parent.fInheritedKey.get(),
159 parentCnt * sizeof(uint32_t)); 147 parentCnt * sizeof(uint32_t));
160 } 148 }
161 // Now turn (geo,path_effect) or (geo) into (geo,path_effect,stroke) 149 // Now turn (geo,path_effect) or (geo) into (geo,path_effect,stroke)
162 GrStyle::WriteKey(fInheritedKey.get() + parentCnt, parent.fStyle, apply, scale, 150 GrStyle::WriteKey(fInheritedKey.get() + parentCnt, parent.fStyle, apply, scale,
163 styleKeyFlags); 151 styleKeyFlags);
164 } 152 }
165 } 153 }
166 154
167 GrShape::GrShape(const GrShape& that) : fType(that.fType), fStyle(that.fStyle) { 155 GrShape::GrShape(const GrShape& that) : fStyle(that.fStyle) {
156 const SkPath* thatPath = Type::kPath == that.fType ? &that.fPathData.fPath : nullptr;
157 this->initType(that.fType, thatPath);
168 switch (fType) { 158 switch (fType) {
169 case Type::kEmpty: 159 case Type::kEmpty:
170 break; 160 break;
171 case Type::kRRect: 161 case Type::kRRect:
172 fRRect = that.fRRect; 162 fRRectData.fRRect = that.fRRectData.fRRect;
173 fRRectDir = that.fRRectDir; 163 fRRectData.fDir = that.fRRectData.fDir;
174 fRRectStart = that.fRRectStart; 164 fRRectData.fStart = that.fRRectData.fStart;
175 fRRectIsInverted = that.fRRectIsInverted; 165 fRRectData.fInverted = that.fRRectData.fInverted;
176 break; 166 break;
177 case Type::kPath: 167 case Type::kPath:
178 fPath.set(*that.fPath.get()); 168 fPathData.fGenID = that.fPathData.fGenID;
179 fPathGenID = that.fPathGenID;
180 break; 169 break;
181 } 170 }
182 fInheritedKey.reset(that.fInheritedKey.count()); 171 fInheritedKey.reset(that.fInheritedKey.count());
183 sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(), 172 sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(),
184 sizeof(uint32_t) * fInheritedKey.count()); 173 sizeof(uint32_t) * fInheritedKey.count());
185 } 174 }
186 175
187 GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { 176 GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) {
188 // TODO: Add some quantization of scale for better cache performance here or leave that up 177 // TODO: Add some quantization of scale for better cache performance here or leave that up
189 // to caller? 178 // to caller?
190 // TODO: For certain shapes and stroke params we could ignore the scale. (e. g. miter or bevel 179 // TODO: For certain shapes and stroke params we could ignore the scale. (e. g. miter or bevel
191 // stroke of a rect). 180 // stroke of a rect).
192 if (!parent.style().applies() || 181 if (!parent.style().applies() ||
193 (GrStyle::Apply::kPathEffectOnly == apply && !parent.style().pathEffect( ))) { 182 (GrStyle::Apply::kPathEffectOnly == apply && !parent.style().pathEffect( ))) {
194 fType = Type::kEmpty; 183 this->initType(Type::kEmpty);
195 *this = parent; 184 *this = parent;
196 return; 185 return;
197 } 186 }
198 187
199 SkPathEffect* pe = parent.fStyle.pathEffect(); 188 SkPathEffect* pe = parent.fStyle.pathEffect();
200 SkTLazy<SkPath> tmpPath; 189 SkTLazy<SkPath> tmpPath;
201 const GrShape* parentForKey = &parent; 190 const GrShape* parentForKey = &parent;
202 SkTLazy<GrShape> tmpParent; 191 SkTLazy<GrShape> tmpParent;
203 fType = Type::kPath; 192 this->initType(Type::kPath);
204 fPath.init(); 193 fPathData.fGenID = 0;
205 if (pe) { 194 if (pe) {
206 SkPath* srcForPathEffect; 195 const SkPath* srcForPathEffect;
207 if (parent.fType == Type::kPath) { 196 if (parent.fType == Type::kPath) {
208 srcForPathEffect = parent.fPath.get(); 197 srcForPathEffect = &parent.path();
209 } else { 198 } else {
210 srcForPathEffect = tmpPath.init(); 199 srcForPathEffect = tmpPath.init();
211 parent.asPath(tmpPath.get()); 200 parent.asPath(tmpPath.get());
212 } 201 }
213 // Should we consider bounds? Would have to include in key, but it'd be nice to know 202 // Should we consider bounds? Would have to include in key, but it'd be nice to know
214 // if the bounds actually modified anything before including in key. 203 // if the bounds actually modified anything before including in key.
215 SkStrokeRec strokeRec = parent.fStyle.strokeRec(); 204 SkStrokeRec strokeRec = parent.fStyle.strokeRec();
216 if (!parent.fStyle.applyPathEffectToPath(fPath.get(), &strokeRec, *srcFo rPathEffect, 205 if (!parent.fStyle.applyPathEffectToPath(&this->path(), &strokeRec, *src ForPathEffect,
217 scale)) { 206 scale)) {
218 // If the path effect fails then we continue as though there was no path effect. 207 // If the path effect fails then we continue as though there was no path effect.
219 // If the original was a rrect that we couldn't canonicalize because of the path 208 // If the original was a rrect that we couldn't canonicalize because of the path
220 // effect, then do so now. 209 // effect, then do so now.
221 if (parent.fType == Type::kRRect && (parent.fRRectDir != kDefaultRRe ctDir || 210 if (parent.fType == Type::kRRect && (parent.fRRectData.fDir != kDefa ultRRectDir ||
222 parent.fRRectStart != kDefaultR RectStart)) { 211 parent.fRRectData.fStart != kDe faultRRectStart)) {
223 SkASSERT(srcForPathEffect == tmpPath.get()); 212 SkASSERT(srcForPathEffect == tmpPath.get());
224 tmpPath.get()->reset(); 213 tmpPath.get()->reset();
225 tmpPath.get()->addRRect(parent.fRRect, kDefaultRRectDir, kDefaul tRRectDir); 214 tmpPath.get()->addRRect(parent.fRRectData.fRRect, kDefaultRRectD ir,
215 kDefaultRRectDir);
226 } 216 }
227 *fPath.get() = *srcForPathEffect; 217 this->path() = *srcForPathEffect;
228 } 218 }
229 // A path effect has access to change the res scale but we aren't expect ing it to and it 219 // A path effect has access to change the res scale but we aren't expect ing it to and it
230 // would mess up our key computation. 220 // would mess up our key computation.
231 SkASSERT(scale == strokeRec.getResScale()); 221 SkASSERT(scale == strokeRec.getResScale());
232 if (GrStyle::Apply::kPathEffectAndStrokeRec == apply && strokeRec.needTo Apply()) { 222 if (GrStyle::Apply::kPathEffectAndStrokeRec == apply && strokeRec.needTo Apply()) {
233 // The intermediate shape may not be a general path. If we we're jus t applying 223 // The intermediate shape may not be a general path. If we we're jus t applying
234 // the path effect then attemptToReduceFromPath would catch it. This means that 224 // the path effect then attemptToReduceFromPath would catch it. This means that
235 // when we subsequently applied the remaining strokeRec we would hav e a non-path 225 // when we subsequently applied the remaining strokeRec we would hav e a non-path
236 // parent shape that would be used to determine the the stroked path 's key. 226 // parent shape that would be used to determine the the stroked path 's key.
237 // We detect that case here and change parentForKey to a temporary t hat represents 227 // We detect that case here and change parentForKey to a temporary t hat represents
238 // the simpler shape so that applying both path effect and the strok erec all at 228 // the simpler shape so that applying both path effect and the strok erec all at
239 // once produces the same key. 229 // once produces the same key.
240 tmpParent.init(*fPath.get(), GrStyle(strokeRec, nullptr)); 230 tmpParent.init(this->path(), GrStyle(strokeRec, nullptr));
241 tmpParent.get()->setInheritedKey(parent, GrStyle::Apply::kPathEffect Only, scale); 231 tmpParent.get()->setInheritedKey(parent, GrStyle::Apply::kPathEffect Only, scale);
242 if (!tmpPath.isValid()) { 232 if (!tmpPath.isValid()) {
243 tmpPath.init(); 233 tmpPath.init();
244 } 234 }
245 tmpParent.get()->asPath(tmpPath.get()); 235 tmpParent.get()->asPath(tmpPath.get());
246 SkStrokeRec::InitStyle fillOrHairline; 236 SkStrokeRec::InitStyle fillOrHairline;
247 SkAssertResult(tmpParent.get()->style().applyToPath(fPath.get(), &fi llOrHairline, 237 SkAssertResult(tmpParent.get()->style().applyToPath(&this->path(), & fillOrHairline,
248 *tmpPath.get(), scale)); 238 *tmpPath.get(), scale));
249 fStyle.resetToInitStyle(fillOrHairline); 239 fStyle.resetToInitStyle(fillOrHairline);
250 parentForKey = tmpParent.get(); 240 parentForKey = tmpParent.get();
251 } else { 241 } else {
252 fStyle = GrStyle(strokeRec, nullptr); 242 fStyle = GrStyle(strokeRec, nullptr);
253 } 243 }
254 } else { 244 } else {
255 const SkPath* srcForParentStyle; 245 const SkPath* srcForParentStyle;
256 if (parent.fType == Type::kPath) { 246 if (parent.fType == Type::kPath) {
257 srcForParentStyle = parent.fPath.get(); 247 srcForParentStyle = &parent.path();
258 } else { 248 } else {
259 srcForParentStyle = tmpPath.init(); 249 srcForParentStyle = tmpPath.init();
260 parent.asPath(tmpPath.get()); 250 parent.asPath(tmpPath.get());
261 } 251 }
262 SkStrokeRec::InitStyle fillOrHairline; 252 SkStrokeRec::InitStyle fillOrHairline;
263 SkASSERT(parent.fStyle.applies()); 253 SkASSERT(parent.fStyle.applies());
264 SkASSERT(!parent.fStyle.pathEffect()); 254 SkASSERT(!parent.fStyle.pathEffect());
265 SkAssertResult(parent.fStyle.applyToPath(fPath.get(), &fillOrHairline, * srcForParentStyle, 255 SkAssertResult(parent.fStyle.applyToPath(&this->path(), &fillOrHairline, *srcForParentStyle,
266 scale)); 256 scale));
267 fStyle.resetToInitStyle(fillOrHairline); 257 fStyle.resetToInitStyle(fillOrHairline);
268 } 258 }
269 this->attemptToSimplifyPath(); 259 this->attemptToSimplifyPath();
270 this->setInheritedKey(*parentForKey, apply, scale); 260 this->setInheritedKey(*parentForKey, apply, scale);
271 } 261 }
272 262
273 void GrShape::attemptToSimplifyPath() { 263 void GrShape::attemptToSimplifyPath() {
274 SkASSERT(Type::kPath == fType);
275 SkRect rect; 264 SkRect rect;
276 if (fPath.get()->isEmpty()) { 265 SkRRect rrect;
277 fType = Type::kEmpty; 266 SkPath::Direction rrectDir;
278 } else if (fPath.get()->isRRect(&fRRect, &fRRectDir, &fRRectStart)) { 267 unsigned rrectStart;
268 bool inverted = this->path().isInverseFillType();
269 if (this->path().isEmpty()) {
270 this->changeType(Type::kEmpty);
271 } else if (this->path().isRRect(&rrect, &rrectDir, &rrectStart)) {
272 this->changeType(Type::kRRect);
273 fRRectData.fRRect = rrect;
274 fRRectData.fDir = rrectDir;
275 fRRectData.fStart = rrectStart;
276 fRRectData.fInverted = inverted;
279 // Currently SkPath does not acknowledge that empty, rect, or oval subty pes as rrects. 277 // Currently SkPath does not acknowledge that empty, rect, or oval subty pes as rrects.
280 SkASSERT(!fRRect.isEmpty()); 278 SkASSERT(!fRRectData.fRRect.isEmpty());
281 SkASSERT(fRRect.getType() != SkRRect::kRect_Type); 279 SkASSERT(fRRectData.fRRect.getType() != SkRRect::kRect_Type);
282 SkASSERT(fRRect.getType() != SkRRect::kOval_Type); 280 SkASSERT(fRRectData.fRRect.getType() != SkRRect::kOval_Type);
283 fRRectIsInverted = fPath.get()->isInverseFillType(); 281 } else if (this->path().isOval(&rect, &rrectDir, &rrectStart)) {
284 fType = Type::kRRect; 282 this->changeType(Type::kRRect);
285 } else if (fPath.get()->isOval(&rect, &fRRectDir, &fRRectStart)) { 283 fRRectData.fRRect.setOval(rect);
286 fRRect.setOval(rect); 284 fRRectData.fDir = rrectDir;
287 fRRectIsInverted = fPath.get()->isInverseFillType(); 285 fRRectData.fInverted = inverted;
288 // convert from oval indexing to rrect indexiing. 286 // convert from oval indexing to rrect indexiing.
289 fRRectStart *= 2; 287 fRRectData.fStart = 2 * rrectStart;
290 fType = Type::kRRect; 288 } else if (SkPathPriv::IsSimpleClosedRect(this->path(), &rect, &rrectDir, &r rectStart)) {
291 } else if (SkPathPriv::IsSimpleClosedRect(*fPath.get(), &rect, &fRRectDir, & fRRectStart)) { 289 this->changeType(Type::kRRect);
292 // When there is a path effect we restrict rect detection to the narrowe r API that 290 // When there is a path effect we restrict rect detection to the narrowe r API that
293 // gives us the starting position. Otherwise, we will retry with the mor e aggressive 291 // gives us the starting position. Otherwise, we will retry with the mor e aggressive
294 // isRect(). 292 // isRect().
295 fRRect.setRect(rect); 293 fRRectData.fRRect.setRect(rect);
296 fRRectIsInverted = fPath.get()->isInverseFillType(); 294 fRRectData.fInverted = inverted;
295 fRRectData.fDir = rrectDir;
297 // convert from rect indexing to rrect indexiing. 296 // convert from rect indexing to rrect indexiing.
298 fRRectStart *= 2; 297 fRRectData.fStart = 2 * rrectStart;
299 fType = Type::kRRect;
300 } else if (!this->style().hasPathEffect()) { 298 } else if (!this->style().hasPathEffect()) {
301 bool closed; 299 bool closed;
302 if (fPath.get()->isRect(&rect, &closed, nullptr)) { 300 if (this->path().isRect(&rect, &closed, nullptr)) {
303 if (closed || this->style().isSimpleFill()) { 301 if (closed || this->style().isSimpleFill()) {
304 fRRect.setRect(rect); 302 this->changeType(Type::kRRect);
303 fRRectData.fRRect.setRect(rect);
305 // Since there is no path effect the dir and start index is imma terial. 304 // Since there is no path effect the dir and start index is imma terial.
306 fRRectDir = kDefaultRRectDir; 305 fRRectData.fDir = kDefaultRRectDir;
307 fRRectStart = kDefaultRRectStart; 306 fRRectData.fStart = kDefaultRRectStart;
308 // There isn't dashing so we will have to preserver inverseness. 307 // There isn't dashing so we will have to preserver inverseness.
309 fRRectIsInverted = fPath.get()->isInverseFillType(); 308 fRRectData.fInverted = inverted;
310 fType = Type::kRRect;
311 } 309 }
312 } 310 }
313 } 311 }
314 if (Type::kPath != fType) { 312 if (Type::kPath != fType) {
315 fPath.reset();
316 fInheritedKey.reset(0); 313 fInheritedKey.reset(0);
317 if (Type::kRRect == fType) { 314 if (Type::kRRect == fType) {
318 this->attemptToSimplifyRRect(); 315 this->attemptToSimplifyRRect();
319 } 316 }
320 } else { 317 } else {
321 if (fInheritedKey.count() || fPath.get()->isVolatile()) { 318 if (fInheritedKey.count() || this->path().isVolatile()) {
322 fPathGenID = 0; 319 fPathData.fGenID = 0;
323 } else { 320 } else {
324 fPathGenID = fPath.get()->getGenerationID(); 321 fPathData.fGenID = this->path().getGenerationID();
325 } 322 }
326 if (this->style().isSimpleFill()) { 323 if (this->style().isSimpleFill()) {
327 // Filled paths are treated as though all their contours were closed . 324 // 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. :( 325 // 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. 326 // There is no point in closing lines, though, since they loose thei r line-ness.
330 if (!fPath.get()->isLine(nullptr)) { 327 if (!this->path().isLine(nullptr)) {
331 fPath.get()->close(); 328 this->path().close();
332 fPath.get()->setIsVolatile(true); 329 this->path().setIsVolatile(true);
333 } 330 }
334 } 331 }
335 if (!this->style().hasNonDashPathEffect()) { 332 if (!this->style().hasNonDashPathEffect()) {
336 if (this->style().strokeRec().getStyle() == SkStrokeRec::kStroke_Sty le || 333 if (this->style().strokeRec().getStyle() == SkStrokeRec::kStroke_Sty le ||
337 this->style().strokeRec().getStyle() == SkStrokeRec::kHairline_S tyle) { 334 this->style().strokeRec().getStyle() == SkStrokeRec::kHairline_S tyle) {
338 // Stroke styles don't differentiate between winding and even/od d. 335 // Stroke styles don't differentiate between winding and even/od d.
339 // Moreover, dashing ignores inverseness (skbug.com/5421) 336 // Moreover, dashing ignores inverseness (skbug.com/5421)
340 bool inverse = !this->style().isDashed() && fPath.get()->isInver seFillType(); 337 bool inverse = !this->style().isDashed() && this->path().isInver seFillType();
341 if (inverse) { 338 if (inverse) {
342 fPath.get()->setFillType(kDefaultPathInverseFillType); 339 this->path().setFillType(kDefaultPathInverseFillType);
343 } else { 340 } else {
344 fPath.get()->setFillType(kDefaultPathFillType); 341 this->path().setFillType(kDefaultPathFillType);
345 } 342 }
346 } else if (fPath.get()->isConvex()) { 343 } else if (this->path().isConvex()) {
347 // There is no distinction between even/odd and non-zero winding count for convex 344 // There is no distinction between even/odd and non-zero winding count for convex
348 // paths. 345 // paths.
349 if (fPath.get()->isInverseFillType()) { 346 if (this->path().isInverseFillType()) {
350 fPath.get()->setFillType(kDefaultPathInverseFillType); 347 this->path().setFillType(kDefaultPathInverseFillType);
351 } else { 348 } else {
352 fPath.get()->setFillType(kDefaultPathFillType); 349 this->path().setFillType(kDefaultPathFillType);
353 } 350 }
354 } 351 }
355 } 352 }
356 } 353 }
357 } 354 }
358 355
359 void GrShape::attemptToSimplifyRRect() { 356 void GrShape::attemptToSimplifyRRect() {
360 SkASSERT(Type::kRRect == fType); 357 SkASSERT(Type::kRRect == fType);
361 SkASSERT(!fInheritedKey.count()); 358 SkASSERT(!fInheritedKey.count());
362 if (fRRect.isEmpty()) { 359 if (fRRectData.fRRect.isEmpty()) {
363 fType = Type::kEmpty; 360 fType = Type::kEmpty;
364 return; 361 return;
365 } 362 }
366 if (!this->style().hasPathEffect()) { 363 if (!this->style().hasPathEffect()) {
367 fRRectDir = kDefaultRRectDir; 364 fRRectData.fDir = kDefaultRRectDir;
368 fRRectStart = kDefaultRRectStart; 365 fRRectData.fStart = kDefaultRRectStart;
369 } else if (fStyle.isDashed()) { 366 } else if (fStyle.isDashed()) {
370 // Dashing ignores the inverseness (currently). skbug.com/5421 367 // Dashing ignores the inverseness (currently). skbug.com/5421
371 fRRectIsInverted = false; 368 fRRectData.fInverted = false;
372 } 369 }
373 } 370 }
OLDNEW
« no previous file with comments | « src/gpu/GrShape.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698