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