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

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

Issue 2042813002: Make GrShape track the winding direction and starting point for rrect types. (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Fix more MSVS warnings Created 4 years, 6 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 | « include/core/SkRRect.h ('k') | 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
11 #include "GrStyle.h" 11 #include "GrStyle.h"
12 #include "SkPath.h" 12 #include "SkPath.h"
13 #include "SkPathPriv.h"
13 #include "SkRRect.h" 14 #include "SkRRect.h"
14 #include "SkTemplates.h" 15 #include "SkTemplates.h"
15 #include "SkTLazy.h" 16 #include "SkTLazy.h"
16 17
17 /** 18 /**
18 * Represents a geometric shape (rrect or path) and the GrStyle that it should b e rendered with. 19 * Represents a geometric shape (rrect or path) and the GrStyle that it should b e rendered with.
19 * It is possible to apply the style to the GrShape to produce a new GrShape whe re the geometry 20 * It is possible to apply the style to the GrShape to produce a new GrShape whe re the geometry
20 * reflects the styling information (e.g. is stroked). It is also possible to ap ply just the 21 * reflects the styling information (e.g. is stroked). It is also possible to ap ply just the
21 * path effect from the style. In this case the resulting shape will include any remaining 22 * path effect from the style. In this case the resulting shape will include any remaining
22 * stroking information that is to be applied after the path effect. 23 * stroking information that is to be applied after the path effect.
23 * 24 *
24 * Shapes can produce keys that represent only the geometry information, not the style. Note that 25 * Shapes can produce keys that represent only the geometry information, not the style. Note that
25 * when styling information is applied to produce a new shape then the style has been converted 26 * when styling information is applied to produce a new shape then the style has been converted
26 * 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
27 * 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
28 * will be the same. 29 * will be the same.
29 * 30 *
30 * Currently this can only be constructed from a rrect, though it can become a p ath by applying 31 * Currently this can only be constructed from a path, rect, or rrect though it can become a path
31 * style to the geometry. The idea is to expand this to cover most or all of the geometries that 32 * applying style to the geometry. The idea is to expand this to cover most or a ll of the geometries
32 * have SkCanvas::draw APIs. 33 * that have SkCanvas::draw APIs.
33 */ 34 */
34 class GrShape { 35 class GrShape {
35 public: 36 public:
36 GrShape() : fType(Type::kEmpty) {} 37 GrShape() : fType(Type::kEmpty) {}
37 38
38 explicit GrShape(const SkPath& path) 39 explicit GrShape(const SkPath& path)
39 : fType(Type::kPath) 40 : fType(Type::kPath)
40 , fPath(&path) { 41 , fPath(&path) {
41 this->attemptToReduceFromPath(); 42 this->attemptToReduceFromPath();
42 } 43 }
43 44
44 explicit GrShape(const SkRRect& rrect) 45 explicit GrShape(const SkRRect& rrect)
45 : fType(Type::kRRect) 46 : fType(Type::kRRect)
46 , fRRect(rrect) { 47 , fRRect(rrect) {
48 fRRectStart = DefaultRRectDirAndStartIndex(rrect, false, &fRRectDir);
47 this->attemptToReduceFromRRect(); 49 this->attemptToReduceFromRRect();
48 } 50 }
49 51
50 explicit GrShape(const SkRect& rect) 52 explicit GrShape(const SkRect& rect)
51 : fType(Type::kRRect) 53 : fType(Type::kRRect)
52 , fRRect(SkRRect::MakeRect(rect)) { 54 , fRRect(SkRRect::MakeRect(rect)) {
55 fRRectStart = DefaultRectDirAndStartIndex(rect, false, &fRRectDir);
53 this->attemptToReduceFromRRect(); 56 this->attemptToReduceFromRRect();
54 } 57 }
55 58
56 GrShape(const SkPath& path, const GrStyle& style) 59 GrShape(const SkPath& path, const GrStyle& style)
57 : fType(Type::kPath) 60 : fType(Type::kPath)
58 , fPath(&path) 61 , fPath(&path)
59 , fStyle(style) { 62 , fStyle(style) {
60 this->attemptToReduceFromPath(); 63 this->attemptToReduceFromPath();
61 } 64 }
62 65
63 GrShape(const SkRRect& rrect, const GrStyle& style) 66 GrShape(const SkRRect& rrect, const GrStyle& style)
64 : fType(Type::kRRect) 67 : fType(Type::kRRect)
65 , fRRect(rrect) 68 , fRRect(rrect)
66 , fStyle(style) { 69 , fStyle(style) {
70 fRRectStart = DefaultRRectDirAndStartIndex(rrect, style.hasPathEffect(), &fRRectDir);
67 this->attemptToReduceFromRRect(); 71 this->attemptToReduceFromRRect();
68 } 72 }
69 73
74 GrShape(const SkRRect& rrect, SkPath::Direction dir, unsigned start, const G rStyle& style)
75 : fType(Type::kRRect)
76 , fRRect(rrect)
77 , fStyle(style) {
78 if (style.pathEffect()) {
79 fRRectDir = dir;
80 fRRectStart = start;
81 } else {
82 fRRectStart = DefaultRRectDirAndStartIndex(rrect, false, &fRRectDir) ;
83 }
84 this->attemptToReduceFromRRect();
85 }
86
70 GrShape(const SkRect& rect, const GrStyle& style) 87 GrShape(const SkRect& rect, const GrStyle& style)
71 : fType(Type::kRRect) 88 : fType(Type::kRRect)
72 , fRRect(SkRRect::MakeRect(rect)) 89 , fRRect(SkRRect::MakeRect(rect))
73 , fStyle(style) { 90 , fStyle(style) {
91 fRRectStart = DefaultRectDirAndStartIndex(rect, style.hasPathEffect(), & fRRectDir);
74 this->attemptToReduceFromRRect(); 92 this->attemptToReduceFromRRect();
75 } 93 }
76 94
77 GrShape(const SkPath& path, const SkPaint& paint) 95 GrShape(const SkPath& path, const SkPaint& paint)
78 : fType(Type::kPath) 96 : fType(Type::kPath)
79 , fPath(&path) 97 , fPath(&path)
80 , fStyle(paint) { 98 , fStyle(paint) {
81 this->attemptToReduceFromPath(); 99 this->attemptToReduceFromPath();
82 } 100 }
83 101
84 GrShape(const SkRRect& rrect, const SkPaint& paint) 102 GrShape(const SkRRect& rrect, const SkPaint& paint)
85 : fType(Type::kRRect) 103 : fType(Type::kRRect)
86 , fRRect(rrect) 104 , fRRect(rrect)
87 , fStyle(paint) { 105 , fStyle(paint) {
106 fRRectStart = DefaultRRectDirAndStartIndex(rrect, fStyle.hasPathEffect() , &fRRectDir);
88 this->attemptToReduceFromRRect(); 107 this->attemptToReduceFromRRect();
89 } 108 }
90 109
91 GrShape(const SkRect& rect, const SkPaint& paint) 110 GrShape(const SkRect& rect, const SkPaint& paint)
92 : fType(Type::kRRect) 111 : fType(Type::kRRect)
93 , fRRect(SkRRect::MakeRect(rect)) 112 , fRRect(SkRRect::MakeRect(rect))
94 , fStyle(paint) { 113 , fStyle(paint) {
114 fRRectStart = DefaultRectDirAndStartIndex(rect, fStyle.hasPathEffect(), &fRRectDir);
95 this->attemptToReduceFromRRect(); 115 this->attemptToReduceFromRRect();
96 } 116 }
97 117
98 GrShape(const GrShape&); 118 GrShape(const GrShape&);
99 GrShape& operator=(const GrShape& that); 119 GrShape& operator=(const GrShape& that);
100 120
101 ~GrShape() { 121 ~GrShape() {
102 if (Type::kPath == fType) { 122 if (Type::kPath == fType) {
103 fPath.reset(); 123 fPath.reset();
104 } 124 }
105 } 125 }
106 126
107 const GrStyle& style() const { return fStyle; } 127 const GrStyle& style() const { return fStyle; }
108 128
109 /** 129 /**
110 * Returns a shape that has either applied the path effect or path effect an d stroking 130 * Returns a shape that has either applied the path effect or path effect an d stroking
111 * information from this shape's style to its geometry. Scale is used when a pproximating the 131 * information from this shape's style to its geometry. Scale is used when a pproximating the
112 * output geometry and typically is computed from the view matrix 132 * output geometry and typically is computed from the view matrix
113 */ 133 */
114 GrShape applyStyle(GrStyle::Apply apply, SkScalar scale) { 134 GrShape applyStyle(GrStyle::Apply apply, SkScalar scale) {
115 return GrShape(*this, apply, scale); 135 return GrShape(*this, apply, scale);
116 } 136 }
117 137
118 /** Returns the unstyled geometry as a rrect if possible. */ 138 /** Returns the unstyled geometry as a rrect if possible. */
119 bool asRRect(SkRRect* rrect) const { 139 bool asRRect(SkRRect* rrect, SkPath::Direction* dir, unsigned* start) const {
120 if (Type::kRRect != fType) { 140 if (Type::kRRect != fType) {
121 return false; 141 return false;
122 } 142 }
123 if (rrect) { 143 if (rrect) {
124 *rrect = fRRect; 144 *rrect = fRRect;
125 } 145 }
146 if (dir) {
147 *dir = fRRectDir;
148 }
149 if (start) {
150 *start = fRRectStart;
151 }
126 return true; 152 return true;
127 } 153 }
128 154
129 /** Returns the unstyled geometry as a path. */ 155 /** Returns the unstyled geometry as a path. */
130 void asPath(SkPath* out) const { 156 void asPath(SkPath* out) const {
131 switch (fType) { 157 switch (fType) {
132 case Type::kEmpty: 158 case Type::kEmpty:
133 out->reset(); 159 out->reset();
134 break; 160 break;
135 case Type::kRRect: 161 case Type::kRRect:
136 out->reset(); 162 out->reset();
137 out->addRRect(fRRect); 163 out->addRRect(fRRect, fRRectDir, fRRectStart);
138 break; 164 break;
139 case Type::kPath: 165 case Type::kPath:
140 *out = *fPath.get(); 166 *out = *fPath.get();
141 break; 167 break;
142 } 168 }
143 } 169 }
144 170
145 /** 171 /**
146 * Returns whether the geometry is empty. Note that applying the style could produce a 172 * Returns whether the geometry is empty. Note that applying the style could produce a
147 * non-empty shape. 173 * non-empty shape.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 */ 209 */
184 void writeUnstyledKey(uint32_t* key) const; 210 void writeUnstyledKey(uint32_t* key) const;
185 211
186 private: 212 private:
187 enum class Type { 213 enum class Type {
188 kEmpty, 214 kEmpty,
189 kRRect, 215 kRRect,
190 kPath, 216 kPath,
191 }; 217 };
192 218
193
194 /** Constructor used by the applyStyle() function */ 219 /** Constructor used by the applyStyle() function */
195 GrShape(const GrShape& parentShape, GrStyle::Apply, SkScalar scale); 220 GrShape(const GrShape& parentShape, GrStyle::Apply, SkScalar scale);
196 221
197 /** 222 /**
198 * Determines the key we should inherit from the input shape's geometry and style when 223 * Determines the key we should inherit from the input shape's geometry and style when
199 * we are applying the style to create a new shape. 224 * we are applying the style to create a new shape.
200 */ 225 */
201 void setInheritedKey(const GrShape& parentShape, GrStyle::Apply, SkScalar sc ale); 226 void setInheritedKey(const GrShape& parentShape, GrStyle::Apply, SkScalar sc ale);
202 227
203 void attemptToReduceFromPath() { 228 void attemptToReduceFromPath() {
204 SkASSERT(Type::kPath == fType); 229 SkASSERT(Type::kPath == fType);
205 fType = AttemptToReduceFromPathImpl(*fPath.get(), &fRRect, fStyle.pathEf fect(), 230 fType = AttemptToReduceFromPathImpl(*fPath.get(), &fRRect, &fRRectDir, & fRRectStart,
206 fStyle.strokeRec()); 231 fStyle.pathEffect(), fStyle.strokeRe c());
207 if (Type::kPath != fType) { 232 if (Type::kPath != fType) {
208 fPath.reset(); 233 fPath.reset();
209 fInheritedKey.reset(0); 234 fInheritedKey.reset(0);
210 } 235 }
211 } 236 }
212 237
213 void attemptToReduceFromRRect() { 238 void attemptToReduceFromRRect() {
214 SkASSERT(Type::kRRect == fType); 239 SkASSERT(Type::kRRect == fType);
215 SkASSERT(!fInheritedKey.count()); 240 SkASSERT(!fInheritedKey.count());
216 if (fRRect.isEmpty()) { 241 if (fRRect.isEmpty()) {
217 fType = Type::kEmpty; 242 fType = Type::kEmpty;
218 } 243 }
219 } 244 }
220 245
221 static Type AttemptToReduceFromPathImpl(const SkPath& path, SkRRect* rrect, 246 static Type AttemptToReduceFromPathImpl(const SkPath& path, SkRRect* rrect,
222 const SkPathEffect* pe, const SkStro keRec& strokeRec) { 247 SkPath::Direction* rrectDir, unsigne d* rrectStart,
223 if (path.isEmpty()) { 248 const SkPathEffect* pe, const SkStro keRec& strokeRec);
224 return Type::kEmpty; 249
250 static constexpr SkPath::Direction kDefaultRRectDir = SkPath::kCW_Direction;
251 static constexpr unsigned kDefaultRRectStart = 0;
252
253 static unsigned DefaultRectDirAndStartIndex(const SkRect& rect, bool hasPath Effect,
254 SkPath::Direction* dir) {
255 *dir = kDefaultRRectDir;
256 // This comes from SkPath's interface. The default for adding a SkRect i s counter clockwise
257 // beginning at index 0 (which happens to correspond to rrect index 0 or 7).
258 if (!hasPathEffect) {
259 // It doesn't matter what start we use, just be consistent to avoid redundant keys.
260 return kDefaultRRectStart;
225 } 261 }
226 if (path.isRRect(rrect)) { 262 // In SkPath a rect starts at index 0 by default. This is the top left c orner. However,
227 SkASSERT(!rrect->isEmpty()); 263 // we store rects as rrects. RRects don't preserve the invertedness, but rather sort the
228 return Type::kRRect; 264 // rect edges. Thus, we may need to modify the rrect's start index to ac count for the sort.
265 bool swapX = rect.fLeft > rect.fRight;
266 bool swapY = rect.fTop > rect.fBottom;
267 if (swapX && swapY) {
268 // 0 becomes start index 2 and times 2 to convert from rect the rrec t indices.
269 return 2 * 2;
270 } else if (swapX) {
271 *dir = SkPath::kCCW_Direction;
272 // 0 becomes start index 1 and times 2 to convert from rect the rrec t indices.
273 return 2 * 1;
274 } else if (swapY) {
275 *dir = SkPath::kCCW_Direction;
276 // 0 becomes start index 3 and times 2 to convert from rect the rrec t indices.
277 return 2 * 3;
229 } 278 }
230 SkRect rect; 279 return 0;
231 if (path.isOval(&rect)) { 280 }
232 rrect->setOval(rect); 281
233 return Type::kRRect; 282 static unsigned DefaultRRectDirAndStartIndex(const SkRRect& rrect, bool hasP athEffect,
283 SkPath::Direction* dir) {
284 // This comes from SkPath's interface. The default for adding a SkRRect to a path is
285 // clockwise beginning at starting index 6.
286 static constexpr unsigned kPathRRectStartIdx = 6;
287 *dir = kDefaultRRectDir;
288 if (!hasPathEffect) {
289 // It doesn't matter what start we use, just be consistent to avoid redundant keys.
290 return kDefaultRRectStart;
234 } 291 }
235 bool closed; 292 return kPathRRectStartIdx;
236 if (path.isRect(&rect, &closed, nullptr)) {
237 if (closed || (!pe && strokeRec.isFillStyle())) {
238 rrect->setRect(rect);
239 return Type::kRRect;
240 }
241 }
242 return Type::kPath;
243 } 293 }
244 294
245 Type fType; 295 Type fType;
246 SkRRect fRRect; 296 SkRRect fRRect;
297 SkPath::Direction fRRectDir;
298 unsigned fRRectStart;
247 SkTLazy<SkPath> fPath; 299 SkTLazy<SkPath> fPath;
248 GrStyle fStyle; 300 GrStyle fStyle;
249 SkAutoSTArray<8, uint32_t> fInheritedKey; 301 SkAutoSTArray<8, uint32_t> fInheritedKey;
250 }; 302 };
251 #endif 303 #endif
OLDNEW
« no previous file with comments | « include/core/SkRRect.h ('k') | src/gpu/GrShape.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698