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

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

Issue 2151313002: In GrShape detect that stroked axis-aligned lines are rrects. (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Add accidentally delete semicolon back 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 | « include/core/SkRect.h ('k') | src/gpu/GrStyle.h » ('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 #include "GrShape.h" 8 #include "GrShape.h"
9 9
10 GrShape& GrShape::operator=(const GrShape& that) { 10 GrShape& GrShape::operator=(const GrShape& that) {
(...skipping 12 matching lines...) Expand all
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 SkRect GrShape::bounds() const {
33 static constexpr SkRect kEmpty = SkRect::MakeEmpty(); 33 // Bounds where left == bottom or top == right can indicate a line or point shape. We return
34 // inverted bounds for a truly empty shape.
35 static constexpr SkRect kInverted = SkRect::MakeLTRB(1, 1, -1, -1);
34 switch (fType) { 36 switch (fType) {
35 case Type::kEmpty: 37 case Type::kEmpty:
36 return kEmpty; 38 return kInverted;
37 case Type::kLine: { 39 case Type::kLine: {
38 SkRect bounds; 40 SkRect bounds;
39 if (fLineData.fPts[0].fX < fLineData.fPts[1].fX) { 41 if (fLineData.fPts[0].fX < fLineData.fPts[1].fX) {
40 bounds.fLeft = fLineData.fPts[0].fX; 42 bounds.fLeft = fLineData.fPts[0].fX;
41 bounds.fRight = fLineData.fPts[1].fX; 43 bounds.fRight = fLineData.fPts[1].fX;
42 } else { 44 } else {
43 bounds.fLeft = fLineData.fPts[1].fX; 45 bounds.fLeft = fLineData.fPts[1].fX;
44 bounds.fRight = fLineData.fPts[0].fX; 46 bounds.fRight = fLineData.fPts[0].fX;
45 } 47 }
46 if (fLineData.fPts[0].fY < fLineData.fPts[1].fY) { 48 if (fLineData.fPts[0].fY < fLineData.fPts[1].fY) {
47 bounds.fTop = fLineData.fPts[0].fY; 49 bounds.fTop = fLineData.fPts[0].fY;
48 bounds.fBottom = fLineData.fPts[1].fY; 50 bounds.fBottom = fLineData.fPts[1].fY;
49 } else { 51 } else {
50 bounds.fTop = fLineData.fPts[1].fY; 52 bounds.fTop = fLineData.fPts[1].fY;
51 bounds.fBottom = fLineData.fPts[0].fY; 53 bounds.fBottom = fLineData.fPts[0].fY;
52 } 54 }
53 return bounds; 55 return bounds;
54 } 56 }
55 case Type::kRRect: 57 case Type::kRRect:
56 return fRRectData.fRRect.getBounds(); 58 return fRRectData.fRRect.getBounds();
57 case Type::kPath: 59 case Type::kPath:
58 return this->path().getBounds(); 60 return this->path().getBounds();
59 } 61 }
60 SkFAIL("Unknown shape type"); 62 SkFAIL("Unknown shape type");
61 return kEmpty; 63 return kInverted;
62 } 64 }
63 65
64 SkRect GrShape::styledBounds() const { 66 SkRect GrShape::styledBounds() const {
65 if (Type::kEmpty == fType && !fStyle.hasNonDashPathEffect()) { 67 if (Type::kEmpty == fType && !fStyle.hasNonDashPathEffect()) {
66 return SkRect::MakeEmpty(); 68 return SkRect::MakeEmpty();
67 } 69 }
68 SkRect bounds; 70 SkRect bounds;
69 fStyle.adjustBounds(&bounds, this->bounds()); 71 fStyle.adjustBounds(&bounds, this->bounds());
70 return bounds; 72 return bounds;
71 } 73 }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 if (parentCnt < 0) { 153 if (parentCnt < 0) {
152 // The parent's geometry has no key so we will have no key. 154 // The parent's geometry has no key so we will have no key.
153 fPathData.fGenID = 0; 155 fPathData.fGenID = 0;
154 return; 156 return;
155 } 157 }
156 } 158 }
157 uint32_t styleKeyFlags = 0; 159 uint32_t styleKeyFlags = 0;
158 if (parent.knownToBeClosed()) { 160 if (parent.knownToBeClosed()) {
159 styleKeyFlags |= GrStyle::kClosed_KeyFlag; 161 styleKeyFlags |= GrStyle::kClosed_KeyFlag;
160 } 162 }
163 if (parent.asLine(nullptr, nullptr)) {
164 styleKeyFlags |= GrStyle::kNoJoins_KeyFlag;
165 }
161 int styleCnt = GrStyle::KeySize(parent.fStyle, apply, styleKeyFlags); 166 int styleCnt = GrStyle::KeySize(parent.fStyle, apply, styleKeyFlags);
162 if (styleCnt < 0) { 167 if (styleCnt < 0) {
163 // The style doesn't allow a key, set the path gen ID to 0 so that w e fail when 168 // The style doesn't allow a key, set the path gen ID to 0 so that w e fail when
164 // we try to get a key for the shape. 169 // we try to get a key for the shape.
165 fPathData.fGenID = 0; 170 fPathData.fGenID = 0;
166 return; 171 return;
167 } 172 }
168 fInheritedKey.reset(parentCnt + styleCnt); 173 fInheritedKey.reset(parentCnt + styleCnt);
169 if (useParentGeoKey) { 174 if (useParentGeoKey) {
170 // This will be the geo key. 175 // This will be the geo key.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 srcForPathEffect = &parent.path(); 230 srcForPathEffect = &parent.path();
226 } else { 231 } else {
227 srcForPathEffect = tmpPath.init(); 232 srcForPathEffect = tmpPath.init();
228 parent.asPath(tmpPath.get()); 233 parent.asPath(tmpPath.get());
229 } 234 }
230 // Should we consider bounds? Would have to include in key, but it'd be nice to know 235 // Should we consider bounds? Would have to include in key, but it'd be nice to know
231 // if the bounds actually modified anything before including in key. 236 // if the bounds actually modified anything before including in key.
232 SkStrokeRec strokeRec = parent.fStyle.strokeRec(); 237 SkStrokeRec strokeRec = parent.fStyle.strokeRec();
233 if (!parent.fStyle.applyPathEffectToPath(&this->path(), &strokeRec, *src ForPathEffect, 238 if (!parent.fStyle.applyPathEffectToPath(&this->path(), &strokeRec, *src ForPathEffect,
234 scale)) { 239 scale)) {
235 // If the path effect fails then we continue as though there was no path effect. 240 tmpParent.init(*srcForPathEffect, GrStyle(strokeRec, nullptr));
236 // If the original was a rrect that we couldn't canonicalize because of the path 241 *this = tmpParent.get()->applyStyle(apply, scale);
237 // effect, then do so now. 242 return;
238 if (parent.fType == Type::kRRect && (parent.fRRectData.fDir != kDefa ultRRectDir ||
239 parent.fRRectData.fStart != kDe faultRRectStart)) {
240 SkASSERT(srcForPathEffect == tmpPath.get());
241 tmpPath.get()->reset();
242 tmpPath.get()->addRRect(parent.fRRectData.fRRect, kDefaultRRectD ir,
243 kDefaultRRectDir);
244 }
245 this->path() = *srcForPathEffect;
246 } 243 }
247 // A path effect has access to change the res scale but we aren't expect ing it to and it 244 // A path effect has access to change the res scale but we aren't expect ing it to and it
248 // would mess up our key computation. 245 // would mess up our key computation.
249 SkASSERT(scale == strokeRec.getResScale()); 246 SkASSERT(scale == strokeRec.getResScale());
250 if (GrStyle::Apply::kPathEffectAndStrokeRec == apply && strokeRec.needTo Apply()) { 247 if (GrStyle::Apply::kPathEffectAndStrokeRec == apply && strokeRec.needTo Apply()) {
251 // The intermediate shape may not be a general path. If we we're jus t applying 248 // The intermediate shape may not be a general path. If we we're jus t applying
252 // the path effect then attemptToReduceFromPath would catch it. This means that 249 // the path effect then attemptToReduceFromPath would catch it. This means that
253 // when we subsequently applied the remaining strokeRec we would hav e a non-path 250 // when we subsequently applied the remaining strokeRec we would hav e a non-path
254 // parent shape that would be used to determine the the stroked path 's key. 251 // parent shape that would be used to determine the the stroked path 's key.
255 // We detect that case here and change parentForKey to a temporary t hat represents 252 // We detect that case here and change parentForKey to a temporary t hat represents
256 // the simpler shape so that applying both path effect and the strok erec all at 253 // the simpler shape so that applying both path effect and the strok erec all at
257 // once produces the same key. 254 // once produces the same key.
258 tmpParent.init(this->path(), GrStyle(strokeRec, nullptr)); 255 tmpParent.init(this->path(), GrStyle(strokeRec, nullptr));
259 tmpParent.get()->setInheritedKey(parent, GrStyle::Apply::kPathEffect Only, scale); 256 tmpParent.get()->setInheritedKey(parent, GrStyle::Apply::kPathEffect Only, scale);
260 if (!tmpPath.isValid()) { 257 if (!tmpPath.isValid()) {
261 tmpPath.init(); 258 tmpPath.init();
262 } 259 }
263 tmpParent.get()->asPath(tmpPath.get()); 260 tmpParent.get()->asPath(tmpPath.get());
264 SkStrokeRec::InitStyle fillOrHairline; 261 SkStrokeRec::InitStyle fillOrHairline;
265 SkAssertResult(tmpParent.get()->style().applyToPath(&this->path(), & fillOrHairline, 262 // The parent shape may have simplified away the strokeRec, check fo r that here.
266 *tmpPath.get(), scale)); 263 if (tmpParent.get()->style().applies()) {
264 SkAssertResult(tmpParent.get()->style().applyToPath(&this->path( ), &fillOrHairline,
265 *tmpPath.get (), scale));
266 } else if (tmpParent.get()->style().isSimpleFill()) {
267 fillOrHairline = SkStrokeRec::kFill_InitStyle;
268 } else {
269 SkASSERT(tmpParent.get()->style().isSimpleHairline());
270 fillOrHairline = SkStrokeRec::kHairline_InitStyle;
271 }
267 fStyle.resetToInitStyle(fillOrHairline); 272 fStyle.resetToInitStyle(fillOrHairline);
268 parentForKey = tmpParent.get(); 273 parentForKey = tmpParent.get();
269 } else { 274 } else {
270 fStyle = GrStyle(strokeRec, nullptr); 275 fStyle = GrStyle(strokeRec, nullptr);
271 } 276 }
272 } else { 277 } else {
273 const SkPath* srcForParentStyle; 278 const SkPath* srcForParentStyle;
274 if (parent.fType == Type::kPath) { 279 if (parent.fType == Type::kPath) {
275 srcForParentStyle = &parent.path(); 280 srcForParentStyle = &parent.path();
276 } else { 281 } else {
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 if (!this->style().hasPathEffect()) { 399 if (!this->style().hasPathEffect()) {
395 fRRectData.fDir = kDefaultRRectDir; 400 fRRectData.fDir = kDefaultRRectDir;
396 fRRectData.fStart = kDefaultRRectStart; 401 fRRectData.fStart = kDefaultRRectStart;
397 } else if (fStyle.isDashed()) { 402 } else if (fStyle.isDashed()) {
398 // Dashing ignores the inverseness (currently). skbug.com/5421 403 // Dashing ignores the inverseness (currently). skbug.com/5421
399 fRRectData.fInverted = false; 404 fRRectData.fInverted = false;
400 } 405 }
401 } 406 }
402 407
403 void GrShape::attemptToSimplifyLine() { 408 void GrShape::attemptToSimplifyLine() {
409 SkASSERT(Type::kLine == fType);
410 SkASSERT(!fInheritedKey.count());
411 if (fStyle.isDashed()) {
412 // Dashing ignores inverseness.
413 fLineData.fInverted = false;
414 return;
415 } else if (fStyle.hasPathEffect()) {
416 return;
417 }
418 if (fStyle.strokeRec().getStyle() == SkStrokeRec::kStrokeAndFill_Style) {
419 // Make stroke + fill be stroke since the fill is empty.
420 SkStrokeRec rec = fStyle.strokeRec();
421 rec.setStrokeStyle(fStyle.strokeRec().getWidth(), false);
422 fStyle = GrStyle(rec, nullptr);
423 }
404 if (fStyle.isSimpleFill() && !fLineData.fInverted) { 424 if (fStyle.isSimpleFill() && !fLineData.fInverted) {
405 this->changeType(Type::kEmpty); 425 this->changeType(Type::kEmpty);
406 } else { 426 return;
407 // Only path effects could care about the order of the points. Otherwise canonicalize 427 }
408 // the point order 428 SkPoint* pts = fLineData.fPts;
409 if (!fStyle.hasPathEffect()) { 429 if (fStyle.strokeRec().getStyle() == SkStrokeRec::kStroke_Style) {
410 SkPoint* pts = fLineData.fPts; 430 // If it is horizontal or vertical we will turn it into a filled rrect.
411 if (pts[1].fY < pts[0].fY || (pts[1].fY == pts[0].fY && pts[1].fX < pts[0].fX)) { 431 SkRect rect;
412 SkTSwap(pts[0], pts[1]); 432 rect.fLeft = SkTMin(pts[0].fX, pts[1].fX);
433 rect.fRight = SkTMax(pts[0].fX, pts[1].fX);
434 rect.fTop = SkTMin(pts[0].fY, pts[1].fY);
435 rect.fBottom = SkTMax(pts[0].fY, pts[1].fY);
436 bool eqX = rect.fLeft == rect.fRight;
437 bool eqY = rect.fTop == rect.fBottom;
438 if (eqX || eqY) {
439 SkScalar r = fStyle.strokeRec().getWidth() / 2;
440 bool inverted = fLineData.fInverted;
441 this->changeType(Type::kRRect);
442 switch (fStyle.strokeRec().getCap()) {
443 case SkPaint::kButt_Cap:
444 if (eqX && eqY) {
445 this->changeType(Type::kEmpty);
446 return;
447 }
448 if (eqX) {
449 rect.outset(r, 0);
450 } else {
451 rect.outset(0, r);
452 }
453 fRRectData.fRRect = SkRRect::MakeRect(rect);
454 break;
455 case SkPaint::kSquare_Cap:
456 rect.outset(r, r);
457 fRRectData.fRRect = SkRRect::MakeRect(rect);
458 break;
459 case SkPaint::kRound_Cap:
460 rect.outset(r, r);
461 fRRectData.fRRect = SkRRect::MakeRectXY(rect, r, r);
462 break;
413 } 463 }
414 } else if (fStyle.isDashed()) { 464 fRRectData.fInverted = inverted;
415 // Dashing ignores inverseness. 465 fRRectData.fDir = kDefaultRRectDir;
416 fLineData.fInverted = false; 466 fRRectData.fStart = kDefaultRRectStart;
467 if (fRRectData.fRRect.isEmpty()) {
468 // This can happen when r is very small relative to the rect edg es.
469 this->changeType(Type::kEmpty);
470 return;
471 }
472 fStyle = GrStyle::SimpleFill();
473 return;
417 } 474 }
418 } 475 }
476 // Only path effects could care about the order of the points. Otherwise can onicalize
477 // the point order.
478 if (pts[1].fY < pts[0].fY || (pts[1].fY == pts[0].fY && pts[1].fX < pts[0].f X)) {
479 SkTSwap(pts[0], pts[1]);
480 }
419 } 481 }
OLDNEW
« no previous file with comments | « include/core/SkRect.h ('k') | src/gpu/GrStyle.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698