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

Side by Side Diff: src/effects/SkDashPathEffect.cpp

Issue 699623003: Crop the fast path dashed lines to the cull rect (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Address code review comments Created 6 years, 1 month 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 | « gm/dashing.cpp ('k') | src/utils/SkDashPath.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 2006 The Android Open Source Project 2 * Copyright 2006 The Android Open Source Project
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 "SkDashPathEffect.h" 8 #include "SkDashPathEffect.h"
9 9
10 #include "SkDashPathPriv.h" 10 #include "SkDashPathPriv.h"
(...skipping 23 matching lines...) Expand all
34 SkDashPathEffect::~SkDashPathEffect() { 34 SkDashPathEffect::~SkDashPathEffect() {
35 sk_free(fIntervals); 35 sk_free(fIntervals);
36 } 36 }
37 37
38 bool SkDashPathEffect::filterPath(SkPath* dst, const SkPath& src, 38 bool SkDashPathEffect::filterPath(SkPath* dst, const SkPath& src,
39 SkStrokeRec* rec, const SkRect* cullRect) const { 39 SkStrokeRec* rec, const SkRect* cullRect) const {
40 return SkDashPath::FilterDashPath(dst, src, rec, cullRect, fIntervals, fCoun t, 40 return SkDashPath::FilterDashPath(dst, src, rec, cullRect, fIntervals, fCoun t,
41 fInitialDashLength, fInitialDashIndex, fIn tervalLength); 41 fInitialDashLength, fInitialDashIndex, fIn tervalLength);
42 } 42 }
43 43
44 static void outset_for_stroke(SkRect* rect, const SkStrokeRec& rec) {
45 SkScalar radius = SkScalarHalf(rec.getWidth());
46 if (0 == radius) {
47 radius = SK_Scalar1; // hairlines
48 }
49 if (SkPaint::kMiter_Join == rec.getJoin()) {
50 radius = SkScalarMul(radius, rec.getMiter());
51 }
52 rect->outset(radius, radius);
53 }
54
55 // Attempt to trim the line to minimally cover the cull rect (currently
56 // only works for horizontal and vertical lines).
57 static void crop_line(SkPoint* pts, const SkStrokeRec& rec,
58 const SkRect* cullRect,
59 const SkScalar phase, const SkScalar intervalLength) {
60 SkASSERT(phase >= 0); // < 0 is used as a signal that the dash is invalid
61 SkASSERT(phase <= intervalLength);
62
63 if (NULL == cullRect) {
64 return;
65 }
66
67 SkRect bounds = *cullRect;
68 outset_for_stroke(&bounds, rec);
69
70 // By outsetting the cull rect by the phase we can ignore its effect in the
71 // followingr computations
72 bounds.outset(phase, phase);
73
74 SkScalar dx = pts[1].x() - pts[0].x();
75 SkScalar dy = pts[1].y() - pts[0].y();
76
77 if (dx && dy) {
reed1 2014/11/04 18:24:58 can/should we move this check earlier? seems like
robertphillips 2014/11/04 18:51:16 Done.
78 return;
79 }
80
81 if (dx) {
82 SkASSERT(dx && !dy);
83 SkScalar minX = pts[0].fX;
84 SkScalar maxX = pts[1].fX;
85
86 if (dx < 0) {
87 SkTSwap(minX, maxX);
88 }
89
90 SkASSERT(minX < maxX);
91 if (maxX < bounds.fLeft || minX > bounds.fRight) {
danakj 2014/11/04 18:30:04 This early out is causing us to miss the last tile
robertphillips 2014/11/04 18:51:16 Done.
92 return;
reed1 2014/11/04 18:24:58 If we're returning here, does that mean we're cull
robertphillips 2014/11/04 18:51:16 Done.
93 }
94
95 // Now we actually perform the chop, removing the excess to the left and
96 // right of the bounds (keeping our new line "in phase" with the dash,
97 // hence the (mod intervalLength).
98
99 if (minX < bounds.fLeft) {
100 minX = bounds.fLeft - SkScalarMod(bounds.fLeft - minX, intervalLengt h);
101 }
102 if (maxX > bounds.fRight) {
103 maxX = bounds.fRight + SkScalarMod(maxX - bounds.fRight, intervalLen gth);
104 }
105
106 SkASSERT(maxX > minX);
107 if (dx < 0) {
108 SkTSwap(minX, maxX);
109 }
110 pts[0].fX = minX;
111 pts[1].fX = maxX;
112 } else {
113 SkASSERT(dy && !dx);
114 SkScalar minY = pts[0].fY;
115 SkScalar maxY = pts[1].fY;
116
117 if (dy < 0) {
118 SkTSwap(minY, maxY);
119 }
120
121 SkASSERT(minY < maxY);
122 if (maxY < bounds.fTop || minY > bounds.fBottom) {
123 return;
124 }
125
126 // Now we actually perform the chop, removing the excess to the top and
127 // bottom of the bounds (keeping our new line "in phase" with the dash,
128 // hence the (mod intervalLength).
129
130 if (minY < bounds.fTop) {
131 minY = bounds.fTop - SkScalarMod(bounds.fTop - minY, intervalLength) ;
132 }
133 if (maxY > bounds.fBottom) {
134 maxY = bounds.fBottom + SkScalarMod(maxY - bounds.fBottom, intervalL ength);
135 }
136
137 SkASSERT(maxY > minY);
138 if (dy < 0) {
139 SkTSwap(minY, maxY);
140 }
141 pts[0].fY = minY;
142 pts[1].fY = maxY;
143 }
144 }
145
44 // Currently asPoints is more restrictive then it needs to be. In the future 146 // Currently asPoints is more restrictive then it needs to be. In the future
45 // we need to: 147 // we need to:
46 // allow kRound_Cap capping (could allow rotations in the matrix with this) 148 // allow kRound_Cap capping (could allow rotations in the matrix with this)
47 // allow paths to be returned 149 // allow paths to be returned
48 bool SkDashPathEffect::asPoints(PointData* results, 150 bool SkDashPathEffect::asPoints(PointData* results,
49 const SkPath& src, 151 const SkPath& src,
50 const SkStrokeRec& rec, 152 const SkStrokeRec& rec,
51 const SkMatrix& matrix, 153 const SkMatrix& matrix,
52 const SkRect* cullRect) const { 154 const SkRect* cullRect) const {
53 // width < 0 -> fill && width == 0 -> hairline so requiring width > 0 rules both out 155 // width < 0 -> fill && width == 0 -> hairline so requiring width > 0 rules both out
(...skipping 22 matching lines...) Expand all
76 // TODO: this test could be eased up to allow circles 178 // TODO: this test could be eased up to allow circles
77 if (SkPaint::kButt_Cap != rec.getCap()) { 179 if (SkPaint::kButt_Cap != rec.getCap()) {
78 return false; 180 return false;
79 } 181 }
80 182
81 // TODO: this test could be eased up for circles. Rotations could be allowed . 183 // TODO: this test could be eased up for circles. Rotations could be allowed .
82 if (!matrix.rectStaysRect()) { 184 if (!matrix.rectStaysRect()) {
83 return false; 185 return false;
84 } 186 }
85 187
86 SkScalar length = SkPoint::Distance(pts[1], pts[0]); 188 // crop the line to the cull rect
189 crop_line(pts, rec, cullRect, fPhase, fIntervalLength);
190
191 SkScalar length = SkPoint::Distance(pts[1], pts[0]);
87 192
88 SkVector tangent = pts[1] - pts[0]; 193 SkVector tangent = pts[1] - pts[0];
89 if (tangent.isZero()) { 194 if (tangent.isZero()) {
90 return false; 195 return false;
91 } 196 }
92 197
93 tangent.scale(SkScalarInvert(length)); 198 tangent.scale(SkScalarInvert(length));
94 199
95 // TODO: make this test for horizontal & vertical lines more robust 200 // TODO: make this test for horizontal & vertical lines more robust
96 bool isXAxis = true; 201 bool isXAxis = true;
97 if (SK_Scalar1 == tangent.fX || -SK_Scalar1 == tangent.fX) { 202 if (SkScalarNearlyEqual(SK_Scalar1, tangent.fX) ||
203 SkScalarNearlyEqual(-SK_Scalar1, tangent.fX)) {
98 results->fSize.set(SkScalarHalf(fIntervals[0]), SkScalarHalf(rec.getWidt h())); 204 results->fSize.set(SkScalarHalf(fIntervals[0]), SkScalarHalf(rec.getWidt h()));
99 } else if (SK_Scalar1 == tangent.fY || -SK_Scalar1 == tangent.fY) { 205 } else if (SkScalarNearlyEqual(SK_Scalar1, tangent.fY) ||
206 SkScalarNearlyEqual(-SK_Scalar1, tangent.fY)) {
100 results->fSize.set(SkScalarHalf(rec.getWidth()), SkScalarHalf(fIntervals [0])); 207 results->fSize.set(SkScalarHalf(rec.getWidth()), SkScalarHalf(fIntervals [0]));
101 isXAxis = false; 208 isXAxis = false;
102 } else if (SkPaint::kRound_Cap != rec.getCap()) { 209 } else if (SkPaint::kRound_Cap != rec.getCap()) {
103 // Angled lines don't have axis-aligned boxes. 210 // Angled lines don't have axis-aligned boxes.
104 return false; 211 return false;
105 } 212 }
106 213
107 if (results) { 214 if (results) {
108 results->fFlags = 0; 215 results->fFlags = 0;
109 SkScalar clampedInitialDashLength = SkMinScalar(length, fInitialDashLeng th); 216 SkScalar clampedInitialDashLength = SkMinScalar(length, fInitialDashLeng th);
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 } 396 }
290 } else { 397 } else {
291 // set the internal data members, fPhase should have been between 0 and intervalLength 398 // set the internal data members, fPhase should have been between 0 and intervalLength
292 // when written to buffer so no need to adjust it 399 // when written to buffer so no need to adjust it
293 SkDashPath::CalcDashParameters(fPhase, fIntervals, fCount, 400 SkDashPath::CalcDashParameters(fPhase, fIntervals, fCount,
294 &fInitialDashLength, &fInitialDashIndex, &fIntervalLength); 401 &fInitialDashLength, &fInitialDashIndex, &fIntervalLength);
295 } 402 }
296 } 403 }
297 #endif 404 #endif
298 405
OLDNEW
« no previous file with comments | « gm/dashing.cpp ('k') | src/utils/SkDashPath.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698