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

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

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 | « no previous file | src/gpu/GrShape.cpp » ('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 #ifndef GrShape_DEFINED 8 #ifndef GrShape_DEFINED
9 #define GrShape_DEFINED 9 #define GrShape_DEFINED
10 10
(...skipping 16 matching lines...) Expand all
27 * to geometric information and is included in the new shape's key. When the sam e style is applied 27 * to geometric information and is included in the new shape's key. When the sam e style is applied
28 * to two shapes that reflect the same underlying geometry the computed keys of the stylized shapes 28 * to two shapes that reflect the same underlying geometry the computed keys of the stylized shapes
29 * will be the same. 29 * will be the same.
30 * 30 *
31 * Currently this can only be constructed from a path, rect, or rrect though it can become a path 31 * Currently this can only be constructed from a path, rect, or rrect though it can become a path
32 * applying style to the geometry. The idea is to expand this to cover most or a ll of the geometries 32 * applying style to the geometry. The idea is to expand this to cover most or a ll of the geometries
33 * that have SkCanvas::draw APIs. 33 * that have SkCanvas::draw APIs.
34 */ 34 */
35 class GrShape { 35 class GrShape {
36 public: 36 public:
37 GrShape() : fType(Type::kEmpty) {} 37 GrShape() { this->initType(Type::kEmpty); }
38 38
39 explicit GrShape(const SkPath& path) 39 explicit GrShape(const SkPath& path) : GrShape(path, GrStyle::SimpleFill()) {}
40 : fType(Type::kPath)
41 , fPath(&path) {
42 this->attemptToSimplifyPath();
43 }
44 40
45 explicit GrShape(const SkRRect& rrect) 41 explicit GrShape(const SkRRect& rrect) : GrShape(rrect, GrStyle::SimpleFill( )) {}
46 : fType(Type::kRRect)
47 , fRRect(rrect)
48 , fRRectIsInverted(false) {
49 fRRectStart = DefaultRRectDirAndStartIndex(rrect, false, &fRRectDir);
50 this->attemptToSimplifyRRect();
51 }
52 42
53 explicit GrShape(const SkRect& rect) 43 explicit GrShape(const SkRect& rect) : GrShape(rect, GrStyle::SimpleFill()) {}
54 : fType(Type::kRRect)
55 , fRRect(SkRRect::MakeRect(rect))
56 , fRRectIsInverted(false) {
57 fRRectStart = DefaultRectDirAndStartIndex(rect, false, &fRRectDir);
58 this->attemptToSimplifyRRect();
59 }
60 44
61 GrShape(const SkPath& path, const GrStyle& style) 45 GrShape(const SkPath& path, const GrStyle& style) : fStyle(style) {
62 : fType(Type::kPath) 46 this->initType(Type::kPath, &path);
63 , fPath(&path)
64 , fStyle(style) {
65 this->attemptToSimplifyPath(); 47 this->attemptToSimplifyPath();
66 } 48 }
67 49
68 GrShape(const SkRRect& rrect, const GrStyle& style) 50 GrShape(const SkRRect& rrect, const GrStyle& style)
69 : fType(Type::kRRect) 51 : fStyle(style) {
70 , fRRect(rrect) 52 this->initType(Type::kRRect);
71 , fRRectIsInverted(false) 53 fRRectData.fRRect = rrect;
72 , fStyle(style) { 54 fRRectData.fInverted = false;
73 fRRectStart = DefaultRRectDirAndStartIndex(rrect, style.hasPathEffect(), &fRRectDir); 55 fRRectData.fStart = DefaultRRectDirAndStartIndex(rrect, style.hasPathEff ect(),
56 &fRRectData.fDir);
74 this->attemptToSimplifyRRect(); 57 this->attemptToSimplifyRRect();
75 } 58 }
76 59
77 GrShape(const SkRRect& rrect, SkPath::Direction dir, unsigned start, bool in verted, 60 GrShape(const SkRRect& rrect, SkPath::Direction dir, unsigned start, bool in verted,
78 const GrStyle& style) 61 const GrStyle& style)
79 : fType(Type::kRRect) 62 : fStyle(style) {
80 , fRRect(rrect) 63 this->initType(Type::kRRect);
81 , fRRectIsInverted(inverted) 64 fRRectData.fRRect = rrect;
82 , fStyle(style) { 65 fRRectData.fInverted = inverted;
83 if (style.pathEffect()) { 66 if (style.pathEffect()) {
84 fRRectDir = dir; 67 fRRectData.fDir = dir;
85 fRRectStart = start; 68 fRRectData.fStart = start;
86 if (fRRect.getType() == SkRRect::kRect_Type) { 69 if (fRRectData.fRRect.getType() == SkRRect::kRect_Type) {
87 fRRectStart = (fRRectStart + 1) & 0b110; 70 fRRectData.fStart = (fRRectData.fStart + 1) & 0b110;
88 } else if (fRRect.getType() == SkRRect::kOval_Type) { 71 } else if (fRRectData.fRRect.getType() == SkRRect::kOval_Type) {
89 fRRectStart &= 0b110; 72 fRRectData.fStart &= 0b110;
90 } 73 }
91 } else { 74 } else {
92 fRRectStart = DefaultRRectDirAndStartIndex(rrect, false, &fRRectDir) ; 75 fRRectData.fStart = DefaultRRectDirAndStartIndex(rrect, false, &fRRe ctData.fDir);
93 } 76 }
94 this->attemptToSimplifyRRect(); 77 this->attemptToSimplifyRRect();
95 } 78 }
96 79
97 GrShape(const SkRect& rect, const GrStyle& style) 80 GrShape(const SkRect& rect, const GrStyle& style)
98 : fType(Type::kRRect) 81 : fStyle(style) {
99 , fRRect(SkRRect::MakeRect(rect)) 82 this->initType(Type::kRRect);
100 , fRRectIsInverted(false) 83 fRRectData.fRRect = SkRRect::MakeRect(rect);
101 , fStyle(style) { 84 fRRectData.fInverted = false;
102 fRRectStart = DefaultRectDirAndStartIndex(rect, style.hasPathEffect(), & fRRectDir); 85 fRRectData.fStart = DefaultRectDirAndStartIndex(rect, style.hasPathEffec t(),
86 &fRRectData.fDir);
103 this->attemptToSimplifyRRect(); 87 this->attemptToSimplifyRRect();
104 } 88 }
105 89
106 GrShape(const SkPath& path, const SkPaint& paint) 90 GrShape(const SkPath& path, const SkPaint& paint) : fStyle(paint) {
107 : fType(Type::kPath) 91 this->initType(Type::kPath, &path);
108 , fPath(&path)
109 , fStyle(paint) {
110 this->attemptToSimplifyPath(); 92 this->attemptToSimplifyPath();
111 } 93 }
112 94
113 GrShape(const SkRRect& rrect, const SkPaint& paint) 95 GrShape(const SkRRect& rrect, const SkPaint& paint)
114 : fType(Type::kRRect) 96 : fStyle(paint) {
115 , fRRect(rrect) 97 this->initType(Type::kRRect);
116 , fRRectIsInverted(false) 98 fRRectData.fRRect = rrect;
117 , fStyle(paint) { 99 fRRectData.fInverted = false;
118 fRRectStart = DefaultRRectDirAndStartIndex(rrect, fStyle.hasPathEffect() , &fRRectDir); 100 fRRectData.fStart = DefaultRRectDirAndStartIndex(rrect, fStyle.hasPathEf fect(),
101 &fRRectData.fDir);
119 this->attemptToSimplifyRRect(); 102 this->attemptToSimplifyRRect();
120 } 103 }
121 104
122 GrShape(const SkRect& rect, const SkPaint& paint) 105 GrShape(const SkRect& rect, const SkPaint& paint)
123 : fType(Type::kRRect) 106 : fStyle(paint) {
124 , fRRect(SkRRect::MakeRect(rect)) 107 this->initType(Type::kRRect);
125 , fRRectIsInverted(false) 108 fRRectData.fRRect = SkRRect::MakeRect(rect);
126 , fStyle(paint) { 109 fRRectData.fInverted = false;
127 fRRectStart = DefaultRectDirAndStartIndex(rect, fStyle.hasPathEffect(), &fRRectDir); 110 fRRectData.fStart = DefaultRectDirAndStartIndex(rect, fStyle.hasPathEffe ct(),
111 &fRRectData.fDir);
128 this->attemptToSimplifyRRect(); 112 this->attemptToSimplifyRRect();
129 } 113 }
130 114
131 GrShape(const GrShape&); 115 GrShape(const GrShape&);
132 GrShape& operator=(const GrShape& that); 116 GrShape& operator=(const GrShape& that);
133 117
134 ~GrShape() { 118 ~GrShape() { this->changeType(Type::kEmpty); }
135 if (Type::kPath == fType) {
136 fPath.reset();
137 }
138 }
139 119
140 const GrStyle& style() const { return fStyle; } 120 const GrStyle& style() const { return fStyle; }
141 121
142 /** 122 /**
143 * Returns a shape that has either applied the path effect or path effect an d stroking 123 * Returns a shape that has either applied the path effect or path effect an d stroking
144 * information from this shape's style to its geometry. Scale is used when a pproximating the 124 * information from this shape's style to its geometry. Scale is used when a pproximating the
145 * output geometry and typically is computed from the view matrix 125 * output geometry and typically is computed from the view matrix
146 */ 126 */
147 GrShape applyStyle(GrStyle::Apply apply, SkScalar scale) const { 127 GrShape applyStyle(GrStyle::Apply apply, SkScalar scale) const {
148 return GrShape(*this, apply, scale); 128 return GrShape(*this, apply, scale);
149 } 129 }
150 130
151 /** Returns the unstyled geometry as a rrect if possible. */ 131 /** Returns the unstyled geometry as a rrect if possible. */
152 bool asRRect(SkRRect* rrect, SkPath::Direction* dir, unsigned* start, bool* inverted) const { 132 bool asRRect(SkRRect* rrect, SkPath::Direction* dir, unsigned* start, bool* inverted) const {
153 if (Type::kRRect != fType) { 133 if (Type::kRRect != fType) {
154 return false; 134 return false;
155 } 135 }
156 if (rrect) { 136 if (rrect) {
157 *rrect = fRRect; 137 *rrect = fRRectData.fRRect;
158 } 138 }
159 if (dir) { 139 if (dir) {
160 *dir = fRRectDir; 140 *dir = fRRectData.fDir;
161 } 141 }
162 if (start) { 142 if (start) {
163 *start = fRRectStart; 143 *start = fRRectData.fStart;
164 } 144 }
165 if (inverted) { 145 if (inverted) {
166 *inverted = fRRectIsInverted; 146 *inverted = fRRectData.fInverted;
167 } 147 }
168 return true; 148 return true;
169 } 149 }
170 150
171 /** 151 /**
172 * If the unstyled shape is a straight line segment, returns true and sets p ts to the endpoints. 152 * If the unstyled shape is a straight line segment, returns true and sets p ts to the endpoints.
173 * An inverse filled line path is still considered a line. 153 * An inverse filled line path is still considered a line.
174 */ 154 */
175 bool asLine(SkPoint pts[2]) const { 155 bool asLine(SkPoint pts[2]) const {
176 if (fType != Type::kPath) { 156 if (fType != Type::kPath) {
177 return false; 157 return false;
178 } 158 }
179 return fPath.get()->isLine(pts); 159 return this->path().isLine(pts);
180 } 160 }
181 161
182 /** Returns the unstyled geometry as a path. */ 162 /** Returns the unstyled geometry as a path. */
183 void asPath(SkPath* out) const { 163 void asPath(SkPath* out) const {
184 switch (fType) { 164 switch (fType) {
185 case Type::kEmpty: 165 case Type::kEmpty:
186 out->reset(); 166 out->reset();
187 break; 167 break;
188 case Type::kRRect: 168 case Type::kRRect:
189 out->reset(); 169 out->reset();
190 out->addRRect(fRRect, fRRectDir, fRRectStart); 170 out->addRRect(fRRectData.fRRect, fRRectData.fDir, fRRectData.fSt art);
191 // Below matches the fill type that attemptToSimplifyPath uses. 171 // Below matches the fill type that attemptToSimplifyPath uses.
192 if (fRRectIsInverted) { 172 if (fRRectData.fInverted) {
193 out->setFillType(kDefaultPathInverseFillType); 173 out->setFillType(kDefaultPathInverseFillType);
194 } else { 174 } else {
195 out->setFillType(kDefaultPathFillType); 175 out->setFillType(kDefaultPathFillType);
196 } 176 }
197 break; 177 break;
198 case Type::kPath: 178 case Type::kPath:
199 *out = *fPath.get(); 179 *out = this->path();
200 break; 180 break;
201 } 181 }
202 } 182 }
203 183
204 /** 184 /**
205 * Returns whether the geometry is empty. Note that applying the style could produce a 185 * Returns whether the geometry is empty. Note that applying the style could produce a
206 * non-empty shape. 186 * non-empty shape.
207 */ 187 */
208 bool isEmpty() const { return Type::kEmpty == fType; } 188 bool isEmpty() const { return Type::kEmpty == fType; }
209 189
(...skipping 18 matching lines...) Expand all
228 switch (fType) { 208 switch (fType) {
229 case Type::kEmpty: 209 case Type::kEmpty:
230 return true; 210 return true;
231 case Type::kRRect: 211 case Type::kRRect:
232 return true; 212 return true;
233 case Type::kPath: 213 case Type::kPath:
234 // SkPath.isConvex() really means "is this path convex were it t o be closed" and 214 // SkPath.isConvex() really means "is this path convex were it t o be closed" and
235 // thus doesn't give the correct answer for stroked paths, hence we also check 215 // thus doesn't give the correct answer for stroked paths, hence we also check
236 // whether the path is either filled or closed. Convex paths may only have one 216 // whether the path is either filled or closed. Convex paths may only have one
237 // contour hence isLastContourClosed() is a sufficient for a con vex path. 217 // contour hence isLastContourClosed() is a sufficient for a con vex path.
238 return (this->style().isSimpleFill() || fPath.get()->isLastConto urClosed()) && 218 return (this->style().isSimpleFill() || this->path().isLastConto urClosed()) &&
239 fPath.get()->isConvex(); 219 this->path().isConvex();
240 } 220 }
241 return false; 221 return false;
242 } 222 }
243 223
244 /** Is the pre-styled geometry inverse filled? */ 224 /** Is the pre-styled geometry inverse filled? */
245 bool inverseFilled() const { 225 bool inverseFilled() const {
246 bool ret = false; 226 bool ret = false;
247 switch (fType) { 227 switch (fType) {
248 case Type::kEmpty: 228 case Type::kEmpty:
249 ret = false; 229 ret = false;
250 break; 230 break;
251 case Type::kRRect: 231 case Type::kRRect:
252 ret = fRRectIsInverted; 232 ret = fRRectData.fInverted;
253 break; 233 break;
254 case Type::kPath: 234 case Type::kPath:
255 ret = this->fPath.get()->isInverseFillType(); 235 ret = this->path().isInverseFillType();
256 break; 236 break;
257 } 237 }
258 // Dashing ignores inverseness. We should have caught this earlier. skbu g.com/5421 238 // Dashing ignores inverseness. We should have caught this earlier. skbu g.com/5421
259 SkASSERT(!(ret && this->style().isDashed())); 239 SkASSERT(!(ret && this->style().isDashed()));
260 return ret; 240 return ret;
261 } 241 }
262 242
263 /** 243 /**
264 * Might applying the styling to the geometry produce an inverse fill. The " may" part comes in 244 * Might applying the styling to the geometry produce an inverse fill. The " may" part comes in
265 * because an arbitrary path effect could produce an inverse filled path. In other cases this 245 * because an arbitrary path effect could produce an inverse filled path. In other cases this
(...skipping 13 matching lines...) Expand all
279 * not have any caps if stroked (modulo the effect of any path effect). 259 * not have any caps if stroked (modulo the effect of any path effect).
280 */ 260 */
281 bool knownToBeClosed() const { 261 bool knownToBeClosed() const {
282 switch (fType) { 262 switch (fType) {
283 case Type::kEmpty: 263 case Type::kEmpty:
284 return true; 264 return true;
285 case Type::kRRect: 265 case Type::kRRect:
286 return true; 266 return true;
287 case Type::kPath: 267 case Type::kPath:
288 // SkPath doesn't keep track of the closed status of each contou r. 268 // SkPath doesn't keep track of the closed status of each contou r.
289 return SkPathPriv::IsClosedSingleContour(*fPath.get()); 269 return SkPathPriv::IsClosedSingleContour(this->path());
290 } 270 }
291 return false; 271 return false;
292 } 272 }
293 273
294 uint32_t segmentMask() const { 274 uint32_t segmentMask() const {
295 switch (fType) { 275 switch (fType) {
296 case Type::kEmpty: 276 case Type::kEmpty:
297 return 0; 277 return 0;
298 case Type::kRRect: 278 case Type::kRRect:
299 if (fRRect.getType() == SkRRect::kOval_Type) { 279 if (fRRectData.fRRect.getType() == SkRRect::kOval_Type) {
300 return SkPath::kConic_SegmentMask; 280 return SkPath::kConic_SegmentMask;
301 } else if (fRRect.getType() == SkRRect::kRect_Type) { 281 } else if (fRRectData.fRRect.getType() == SkRRect::kRect_Type) {
302 return SkPath::kLine_SegmentMask; 282 return SkPath::kLine_SegmentMask;
303 } 283 }
304 return SkPath::kLine_SegmentMask | SkPath::kConic_SegmentMask; 284 return SkPath::kLine_SegmentMask | SkPath::kConic_SegmentMask;
305 case Type::kPath: 285 case Type::kPath:
306 return fPath.get()->getSegmentMasks(); 286 return this->path().getSegmentMasks();
307 } 287 }
308 return 0; 288 return 0;
309 } 289 }
310 290
311 /** 291 /**
312 * Gets the size of the key for the shape represented by this GrShape (ignor ing its styling). 292 * Gets the size of the key for the shape represented by this GrShape (ignor ing its styling).
313 * A negative value is returned if the shape has no key (shouldn't be cached ). 293 * A negative value is returned if the shape has no key (shouldn't be cached ).
314 */ 294 */
315 int unstyledKeySize() const; 295 int unstyledKeySize() const;
316 296
317 bool hasUnstyledKey() const { return this->unstyledKeySize() >= 0; } 297 bool hasUnstyledKey() const { return this->unstyledKeySize() >= 0; }
318 298
319 /** 299 /**
320 * Writes unstyledKeySize() bytes into the provided pointer. Assumes that th ere is enough 300 * Writes unstyledKeySize() bytes into the provided pointer. Assumes that th ere is enough
321 * space allocated for the key and that unstyledKeySize() does not return a negative value 301 * space allocated for the key and that unstyledKeySize() does not return a negative value
322 * for this shape. 302 * for this shape.
323 */ 303 */
324 void writeUnstyledKey(uint32_t* key) const; 304 void writeUnstyledKey(uint32_t* key) const;
325 305
326 private: 306 private:
327 enum class Type { 307 enum class Type {
328 kEmpty, 308 kEmpty,
329 kRRect, 309 kRRect,
330 kPath, 310 kPath,
331 }; 311 };
332 312
313 void initType(Type type, const SkPath* path = nullptr) {
314 fType = Type::kEmpty;
315 this->changeType(type, path);
316 }
317
318 void changeType(Type type, const SkPath* path = nullptr) {
319 bool wasPath = Type::kPath == fType;
320 fType = type;
321 bool isPath = Type::kPath == type;
322 SkASSERT(!path || isPath);
323 if (wasPath && !isPath) {
324 fPathData.fPath.~SkPath();
325 } else if (!wasPath && isPath) {
326 if (path) {
327 new (&fPathData.fPath) SkPath(*path);
328 } else {
329 new (&fPathData.fPath) SkPath();
330 }
331 } else if (isPath && path) {
332 fPathData.fPath = *path;
333 }
334 // Whether or not we use the path's gen ID is decided in attemptToSimpli fyPath.
335 fPathData.fGenID = 0;
336 }
337
338 SkPath& path() {
339 SkASSERT(Type::kPath == fType);
340 return fPathData.fPath;
341 }
342
343 const SkPath& path() const {
344 SkASSERT(Type::kPath == fType);
345 return fPathData.fPath;
346 }
347
333 /** Constructor used by the applyStyle() function */ 348 /** Constructor used by the applyStyle() function */
334 GrShape(const GrShape& parentShape, GrStyle::Apply, SkScalar scale); 349 GrShape(const GrShape& parentShape, GrStyle::Apply, SkScalar scale);
335 350
336 /** 351 /**
337 * Determines the key we should inherit from the input shape's geometry and style when 352 * Determines the key we should inherit from the input shape's geometry and style when
338 * we are applying the style to create a new shape. 353 * we are applying the style to create a new shape.
339 */ 354 */
340 void setInheritedKey(const GrShape& parentShape, GrStyle::Apply, SkScalar sc ale); 355 void setInheritedKey(const GrShape& parentShape, GrStyle::Apply, SkScalar sc ale);
341 356
342 void attemptToSimplifyPath(); 357 void attemptToSimplifyPath();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 static constexpr unsigned kPathRRectStartIdx = 6; 401 static constexpr unsigned kPathRRectStartIdx = 6;
387 *dir = kDefaultRRectDir; 402 *dir = kDefaultRRectDir;
388 if (!hasPathEffect) { 403 if (!hasPathEffect) {
389 // It doesn't matter what start we use, just be consistent to avoid redundant keys. 404 // It doesn't matter what start we use, just be consistent to avoid redundant keys.
390 return kDefaultRRectStart; 405 return kDefaultRRectStart;
391 } 406 }
392 return kPathRRectStartIdx; 407 return kPathRRectStartIdx;
393 } 408 }
394 409
395 Type fType; 410 Type fType;
396 SkRRect fRRect; 411 union {
397 SkPath::Direction fRRectDir; 412 struct {
398 unsigned fRRectStart; 413 SkRRect fRRect;
399 bool fRRectIsInverted; 414 SkPath::Direction fDir;
400 SkTLazy<SkPath> fPath; 415 unsigned fStart;
401 // Gen ID of the original path (fPath may be modified) 416 bool fInverted;
402 int32_t fPathGenID = 0; 417 } fRRectData;
418 struct {
419 SkPath fPath;
420 // Gen ID of the original path (fPath may be modified)
421 int32_t fGenID;
422 } fPathData;
423 };
403 GrStyle fStyle; 424 GrStyle fStyle;
404 SkAutoSTArray<8, uint32_t> fInheritedKey; 425 SkAutoSTArray<8, uint32_t> fInheritedKey;
405 }; 426 };
406 #endif 427 #endif
OLDNEW
« no previous file with comments | « no previous file | src/gpu/GrShape.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698