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 #ifndef GrShape_DEFINED | 8 #ifndef GrShape_DEFINED |
9 #define GrShape_DEFINED | 9 #define GrShape_DEFINED |
10 | 10 |
(...skipping 16 matching lines...) Expand all Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |