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 #include "GrShape.h" | 8 #include "GrShape.h" |
9 | 9 |
10 GrShape& GrShape::operator=(const GrShape& that) { | 10 GrShape& GrShape::operator=(const GrShape& that) { |
11 fStyle = that.fStyle; | 11 fStyle = that.fStyle; |
12 this->changeType(that.fType, Type::kPath == that.fType ? &that.path() : null
ptr); | 12 this->changeType(that.fType, Type::kPath == that.fType ? &that.path() : null
ptr); |
13 switch (fType) { | 13 switch (fType) { |
14 case Type::kEmpty: | 14 case Type::kEmpty: |
15 break; | 15 break; |
16 case Type::kRRect: | 16 case Type::kRRect: |
17 fRRectData.fRRect = that.fRRectData.fRRect; | 17 fRRectData = that.fRRectData; |
18 fRRectData.fDir = that.fRRectData.fDir; | 18 break; |
19 fRRectData.fStart = that.fRRectData.fStart; | 19 case Type::kLine: |
20 fRRectData.fInverted = that.fRRectData.fInverted; | 20 fLineData = that.fLineData; |
21 break; | 21 break; |
22 case Type::kPath: | 22 case Type::kPath: |
23 fPathData.fGenID = that.fPathData.fGenID; | 23 fPathData.fGenID = that.fPathData.fGenID; |
24 break; | 24 break; |
25 } | 25 } |
26 fInheritedKey.reset(that.fInheritedKey.count()); | 26 fInheritedKey.reset(that.fInheritedKey.count()); |
27 sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(), | 27 sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(), |
28 sizeof(uint32_t) * fInheritedKey.count()); | 28 sizeof(uint32_t) * fInheritedKey.count()); |
29 return *this; | 29 return *this; |
30 } | 30 } |
31 | 31 |
32 const SkRect& GrShape::bounds() const { | 32 SkRect GrShape::bounds() const { |
33 static constexpr SkRect kEmpty = SkRect::MakeEmpty(); | 33 static constexpr SkRect kEmpty = SkRect::MakeEmpty(); |
34 switch (fType) { | 34 switch (fType) { |
35 case Type::kEmpty: | 35 case Type::kEmpty: |
36 return kEmpty; | 36 return kEmpty; |
| 37 case Type::kLine: { |
| 38 SkRect bounds; |
| 39 if (fLineData.fPts[0].fX < fLineData.fPts[1].fX) { |
| 40 bounds.fLeft = fLineData.fPts[0].fX; |
| 41 bounds.fRight = fLineData.fPts[1].fX; |
| 42 } else { |
| 43 bounds.fLeft = fLineData.fPts[1].fX; |
| 44 bounds.fRight = fLineData.fPts[0].fX; |
| 45 } |
| 46 if (fLineData.fPts[0].fY < fLineData.fPts[1].fY) { |
| 47 bounds.fTop = fLineData.fPts[0].fY; |
| 48 bounds.fBottom = fLineData.fPts[1].fY; |
| 49 } else { |
| 50 bounds.fTop = fLineData.fPts[1].fY; |
| 51 bounds.fBottom = fLineData.fPts[0].fY; |
| 52 } |
| 53 return bounds; |
| 54 } |
37 case Type::kRRect: | 55 case Type::kRRect: |
38 return fRRectData.fRRect.getBounds(); | 56 return fRRectData.fRRect.getBounds(); |
39 case Type::kPath: | 57 case Type::kPath: |
40 return this->path().getBounds(); | 58 return this->path().getBounds(); |
41 } | 59 } |
42 SkFAIL("Unknown shape type"); | 60 SkFAIL("Unknown shape type"); |
43 return kEmpty; | 61 return kEmpty; |
44 } | 62 } |
45 | 63 |
46 void GrShape::styledBounds(SkRect* bounds) const { | 64 SkRect GrShape::styledBounds() const { |
47 if (Type::kEmpty == fType && !fStyle.hasNonDashPathEffect()) { | 65 if (Type::kEmpty == fType && !fStyle.hasNonDashPathEffect()) { |
48 *bounds = SkRect::MakeEmpty(); | 66 return SkRect::MakeEmpty(); |
49 } else { | |
50 fStyle.adjustBounds(bounds, this->bounds()); | |
51 } | 67 } |
| 68 SkRect bounds; |
| 69 fStyle.adjustBounds(&bounds, this->bounds()); |
| 70 return bounds; |
52 } | 71 } |
53 | 72 |
54 int GrShape::unstyledKeySize() const { | 73 int GrShape::unstyledKeySize() const { |
55 if (fInheritedKey.count()) { | 74 if (fInheritedKey.count()) { |
56 return fInheritedKey.count(); | 75 return fInheritedKey.count(); |
57 } | 76 } |
58 switch (fType) { | 77 switch (fType) { |
59 case Type::kEmpty: | 78 case Type::kEmpty: |
60 return 1; | 79 return 1; |
61 case Type::kRRect: | 80 case Type::kRRect: |
62 SkASSERT(!fInheritedKey.count()); | 81 SkASSERT(!fInheritedKey.count()); |
63 SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t)); | 82 SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t)); |
64 // + 1 for the direction, start index, and inverseness. | 83 // + 1 for the direction, start index, and inverseness. |
65 return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1; | 84 return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1; |
| 85 case Type::kLine: |
| 86 GR_STATIC_ASSERT(2 * sizeof(uint32_t) == sizeof(SkPoint)); |
| 87 // 4 for the end points and 1 for the inverseness |
| 88 return 5; |
66 case Type::kPath: | 89 case Type::kPath: |
67 if (0 == fPathData.fGenID) { | 90 if (0 == fPathData.fGenID) { |
68 return -1; | 91 return -1; |
69 } else { | 92 } else { |
70 // The key is the path ID and fill type. | 93 // The key is the path ID and fill type. |
71 return 2; | 94 return 2; |
72 } | 95 } |
73 } | 96 } |
74 SkFAIL("Should never get here."); | 97 SkFAIL("Should never get here."); |
75 return 0; | 98 return 0; |
(...skipping 11 matching lines...) Expand all Loading... |
87 *key++ = 1; | 110 *key++ = 1; |
88 break; | 111 break; |
89 case Type::kRRect: | 112 case Type::kRRect: |
90 fRRectData.fRRect.writeToMemory(key); | 113 fRRectData.fRRect.writeToMemory(key); |
91 key += SkRRect::kSizeInMemory / sizeof(uint32_t); | 114 key += SkRRect::kSizeInMemory / sizeof(uint32_t); |
92 *key = (fRRectData.fDir == SkPath::kCCW_Direction) ? (1 << 31) :
0; | 115 *key = (fRRectData.fDir == SkPath::kCCW_Direction) ? (1 << 31) :
0; |
93 *key |= fRRectData.fInverted ? (1 << 30) : 0; | 116 *key |= fRRectData.fInverted ? (1 << 30) : 0; |
94 *key++ |= fRRectData.fStart; | 117 *key++ |= fRRectData.fStart; |
95 SkASSERT(fRRectData.fStart < 8); | 118 SkASSERT(fRRectData.fStart < 8); |
96 break; | 119 break; |
| 120 case Type::kLine: |
| 121 memcpy(key, fLineData.fPts, 2 * sizeof(SkPoint)); |
| 122 key += 4; |
| 123 *key++ = fLineData.fInverted ? 1 : 0; |
| 124 break; |
97 case Type::kPath: | 125 case Type::kPath: |
98 SkASSERT(fPathData.fGenID); | 126 SkASSERT(fPathData.fGenID); |
99 *key++ = fPathData.fGenID; | 127 *key++ = fPathData.fGenID; |
100 // We could canonicalize the fill rule for paths that don't diff
erentiate between | 128 // We could canonicalize the fill rule for paths that don't diff
erentiate between |
101 // even/odd or winding fill (e.g. convex). | 129 // even/odd or winding fill (e.g. convex). |
102 *key++ = this->path().getFillType(); | 130 *key++ = this->path().getFillType(); |
103 break; | 131 break; |
104 } | 132 } |
105 } | 133 } |
106 SkASSERT(key - origKey == this->unstyledKeySize()); | 134 SkASSERT(key - origKey == this->unstyledKeySize()); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 } | 180 } |
153 } | 181 } |
154 | 182 |
155 GrShape::GrShape(const GrShape& that) : fStyle(that.fStyle) { | 183 GrShape::GrShape(const GrShape& that) : fStyle(that.fStyle) { |
156 const SkPath* thatPath = Type::kPath == that.fType ? &that.fPathData.fPath :
nullptr; | 184 const SkPath* thatPath = Type::kPath == that.fType ? &that.fPathData.fPath :
nullptr; |
157 this->initType(that.fType, thatPath); | 185 this->initType(that.fType, thatPath); |
158 switch (fType) { | 186 switch (fType) { |
159 case Type::kEmpty: | 187 case Type::kEmpty: |
160 break; | 188 break; |
161 case Type::kRRect: | 189 case Type::kRRect: |
162 fRRectData.fRRect = that.fRRectData.fRRect; | 190 fRRectData = that.fRRectData; |
163 fRRectData.fDir = that.fRRectData.fDir; | 191 break; |
164 fRRectData.fStart = that.fRRectData.fStart; | 192 case Type::kLine: |
165 fRRectData.fInverted = that.fRRectData.fInverted; | 193 fLineData = that.fLineData; |
166 break; | 194 break; |
167 case Type::kPath: | 195 case Type::kPath: |
168 fPathData.fGenID = that.fPathData.fGenID; | 196 fPathData.fGenID = that.fPathData.fGenID; |
169 break; | 197 break; |
170 } | 198 } |
171 fInheritedKey.reset(that.fInheritedKey.count()); | 199 fInheritedKey.reset(that.fInheritedKey.count()); |
172 sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(), | 200 sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(), |
173 sizeof(uint32_t) * fInheritedKey.count()); | 201 sizeof(uint32_t) * fInheritedKey.count()); |
174 } | 202 } |
175 | 203 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 this->attemptToSimplifyPath(); | 287 this->attemptToSimplifyPath(); |
260 this->setInheritedKey(*parentForKey, apply, scale); | 288 this->setInheritedKey(*parentForKey, apply, scale); |
261 } | 289 } |
262 | 290 |
263 void GrShape::attemptToSimplifyPath() { | 291 void GrShape::attemptToSimplifyPath() { |
264 SkRect rect; | 292 SkRect rect; |
265 SkRRect rrect; | 293 SkRRect rrect; |
266 SkPath::Direction rrectDir; | 294 SkPath::Direction rrectDir; |
267 unsigned rrectStart; | 295 unsigned rrectStart; |
268 bool inverted = this->path().isInverseFillType(); | 296 bool inverted = this->path().isInverseFillType(); |
| 297 SkPoint pts[2]; |
269 if (this->path().isEmpty()) { | 298 if (this->path().isEmpty()) { |
270 this->changeType(Type::kEmpty); | 299 this->changeType(Type::kEmpty); |
| 300 } else if (this->path().isLine(pts)) { |
| 301 this->changeType(Type::kLine); |
| 302 fLineData.fPts[0] = pts[0]; |
| 303 fLineData.fPts[1] = pts[1]; |
| 304 fLineData.fInverted = inverted; |
271 } else if (this->path().isRRect(&rrect, &rrectDir, &rrectStart)) { | 305 } else if (this->path().isRRect(&rrect, &rrectDir, &rrectStart)) { |
272 this->changeType(Type::kRRect); | 306 this->changeType(Type::kRRect); |
273 fRRectData.fRRect = rrect; | 307 fRRectData.fRRect = rrect; |
274 fRRectData.fDir = rrectDir; | 308 fRRectData.fDir = rrectDir; |
275 fRRectData.fStart = rrectStart; | 309 fRRectData.fStart = rrectStart; |
276 fRRectData.fInverted = inverted; | 310 fRRectData.fInverted = inverted; |
277 // Currently SkPath does not acknowledge that empty, rect, or oval subty
pes as rrects. | 311 // Currently SkPath does not acknowledge that empty, rect, or oval subty
pes as rrects. |
278 SkASSERT(!fRRectData.fRRect.isEmpty()); | 312 SkASSERT(!fRRectData.fRRect.isEmpty()); |
279 SkASSERT(fRRectData.fRRect.getType() != SkRRect::kRect_Type); | 313 SkASSERT(fRRectData.fRRect.getType() != SkRRect::kRect_Type); |
280 SkASSERT(fRRectData.fRRect.getType() != SkRRect::kOval_Type); | 314 SkASSERT(fRRectData.fRRect.getType() != SkRRect::kOval_Type); |
(...skipping 25 matching lines...) Expand all Loading... |
306 fRRectData.fStart = kDefaultRRectStart; | 340 fRRectData.fStart = kDefaultRRectStart; |
307 // There isn't dashing so we will have to preserver inverseness. | 341 // There isn't dashing so we will have to preserver inverseness. |
308 fRRectData.fInverted = inverted; | 342 fRRectData.fInverted = inverted; |
309 } | 343 } |
310 } | 344 } |
311 } | 345 } |
312 if (Type::kPath != fType) { | 346 if (Type::kPath != fType) { |
313 fInheritedKey.reset(0); | 347 fInheritedKey.reset(0); |
314 if (Type::kRRect == fType) { | 348 if (Type::kRRect == fType) { |
315 this->attemptToSimplifyRRect(); | 349 this->attemptToSimplifyRRect(); |
| 350 } else if (Type::kLine == fType) { |
| 351 this->attemptToSimplifyLine(); |
316 } | 352 } |
317 } else { | 353 } else { |
318 if (fInheritedKey.count() || this->path().isVolatile()) { | 354 if (fInheritedKey.count() || this->path().isVolatile()) { |
319 fPathData.fGenID = 0; | 355 fPathData.fGenID = 0; |
320 } else { | 356 } else { |
321 fPathData.fGenID = this->path().getGenerationID(); | 357 fPathData.fGenID = this->path().getGenerationID(); |
322 } | 358 } |
323 if (this->style().isSimpleFill()) { | 359 if (this->style().isSimpleFill()) { |
324 // Filled paths are treated as though all their contours were closed
. | 360 this->path().close(); |
325 // Since SkPath doesn't track individual contours, this will only cl
ose the last. :( | 361 this->path().setIsVolatile(true); |
326 // There is no point in closing lines, though, since they loose thei
r line-ness. | |
327 if (!this->path().isLine(nullptr)) { | |
328 this->path().close(); | |
329 this->path().setIsVolatile(true); | |
330 } | |
331 } | 362 } |
332 if (!this->style().hasNonDashPathEffect()) { | 363 if (!this->style().hasNonDashPathEffect()) { |
333 if (this->style().strokeRec().getStyle() == SkStrokeRec::kStroke_Sty
le || | 364 if (this->style().strokeRec().getStyle() == SkStrokeRec::kStroke_Sty
le || |
334 this->style().strokeRec().getStyle() == SkStrokeRec::kHairline_S
tyle) { | 365 this->style().strokeRec().getStyle() == SkStrokeRec::kHairline_S
tyle) { |
335 // Stroke styles don't differentiate between winding and even/od
d. | 366 // Stroke styles don't differentiate between winding and even/od
d. |
336 // Moreover, dashing ignores inverseness (skbug.com/5421) | 367 // Moreover, dashing ignores inverseness (skbug.com/5421) |
337 bool inverse = !this->style().isDashed() && this->path().isInver
seFillType(); | 368 bool inverse = !this->style().isDashed() && this->path().isInver
seFillType(); |
338 if (inverse) { | 369 if (inverse) { |
339 this->path().setFillType(kDefaultPathInverseFillType); | 370 this->path().setFillType(kDefaultPathInverseFillType); |
340 } else { | 371 } else { |
(...skipping 20 matching lines...) Expand all Loading... |
361 return; | 392 return; |
362 } | 393 } |
363 if (!this->style().hasPathEffect()) { | 394 if (!this->style().hasPathEffect()) { |
364 fRRectData.fDir = kDefaultRRectDir; | 395 fRRectData.fDir = kDefaultRRectDir; |
365 fRRectData.fStart = kDefaultRRectStart; | 396 fRRectData.fStart = kDefaultRRectStart; |
366 } else if (fStyle.isDashed()) { | 397 } else if (fStyle.isDashed()) { |
367 // Dashing ignores the inverseness (currently). skbug.com/5421 | 398 // Dashing ignores the inverseness (currently). skbug.com/5421 |
368 fRRectData.fInverted = false; | 399 fRRectData.fInverted = false; |
369 } | 400 } |
370 } | 401 } |
| 402 |
| 403 void GrShape::attemptToSimplifyLine() { |
| 404 if (fStyle.isSimpleFill() && !fLineData.fInverted) { |
| 405 this->changeType(Type::kEmpty); |
| 406 } else { |
| 407 // Only path effects could care about the order of the points. Otherwise
canonicalize |
| 408 // the point order |
| 409 if (!fStyle.hasPathEffect()) { |
| 410 SkPoint* pts = fLineData.fPts; |
| 411 if (pts[1].fY < pts[0].fY || (pts[1].fY == pts[0].fY && pts[1].fX <
pts[0].fX)) { |
| 412 SkTSwap(pts[0], pts[1]); |
| 413 } |
| 414 } else if (fStyle.isDashed()) { |
| 415 // Dashing ignores inverseness. |
| 416 fLineData.fInverted = false; |
| 417 } |
| 418 } |
| 419 } |
OLD | NEW |