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

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: 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') | no next file » | 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 22 matching lines...) Expand all
33 33
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
robertphillips 2014/11/03 21:20:07 This code was adapted from src\utils\SkDashPath.cp
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 // Only handles lines for now. If returns true, dstPath is the new (smaller)
56 // path. If returns false, then dstPath parameter is ignored.
57 static bool cull_path(const SkPath& srcPath, const SkStrokeRec& rec,
58 const SkRect* cullRect, SkScalar intervalLength,
59 SkPath* dstPath) {
60 if (NULL == cullRect) {
61 return false;
62 }
63
64 SkPoint pts[2];
65 if (!srcPath.isLine(pts)) {
66 return false;
67 }
68
69 SkRect bounds = *cullRect;
70 outset_for_stroke(&bounds, rec);
71
72 SkScalar dx = pts[1].x() - pts[0].x();
73 SkScalar dy = pts[1].y() - pts[0].y();
74
75 if (dx && dy) {
76 return false;
77 }
78
79 if (dx) {
80 SkASSERT(dx && !dy);
81 SkScalar minX = pts[0].fX;
82 SkScalar maxX = pts[1].fX;
83
84 if (dx < 0) {
85 SkTSwap(minX, maxX);
86 }
87
88 SkASSERT(minX < maxX);
89 if (maxX < bounds.fLeft || minX > bounds.fRight) {
90 return false;
91 }
92
93 // Now we actually perform the chop, removing the excess to the left and
94 // right of the bounds (keeping our new line "in phase" with the dash,
95 // hence the (mod intervalLength).
96
97 if (minX < bounds.fLeft) {
98 minX = bounds.fLeft - SkScalarMod(bounds.fLeft - minX, intervalLengt h);
egdaniel 2014/11/03 22:03:31 This moding thing to get "in phase" seems off to m
99 }
100 if (maxX > bounds.fRight) {
101 maxX = bounds.fRight + SkScalarMod(maxX - bounds.fRight, intervalLen gth);
102 }
103
104 SkASSERT(maxX >= minX);
105 if (dx < 0) {
106 SkTSwap(minX, maxX);
107 }
108 pts[0].fX = minX;
109 pts[1].fX = maxX;
110
111 dstPath->moveTo(pts[0]);
112 dstPath->lineTo(pts[1]);
113 } else {
114 SkASSERT(dy && !dx);
115 SkScalar minY = pts[0].fY;
116 SkScalar maxY = pts[1].fY;
117
118 if (dy < 0) {
119 SkTSwap(minY, maxY);
120 }
121
122 SkASSERT(minY < maxY);
123 if (maxY < bounds.fTop || minY > bounds.fBottom) {
124 return false;
125 }
126
127 // Now we actually perform the chop, removing the excess to the top and
128 // bottom of the bounds (keeping our new line "in phase" with the dash,
129 // hence the (mod intervalLength).
130
131 if (minY < bounds.fTop) {
132 minY = bounds.fTop - SkScalarMod(bounds.fTop - minY, intervalLength) ;
133 }
134 if (maxY > bounds.fBottom) {
135 maxY = bounds.fBottom + SkScalarMod(maxY - bounds.fBottom, intervalL ength);
136 }
137
138 SkASSERT(maxY >= minY);
139 if (dy < 0) {
140 SkTSwap(minY, maxY);
141 }
142 pts[0].fY = minY;
143 pts[1].fY = maxY;
144
145 dstPath->moveTo(pts[0]);
146 dstPath->lineTo(pts[1]);
147 }
148
149 return true;
150 }
151
44 // Currently asPoints is more restrictive then it needs to be. In the future 152 // Currently asPoints is more restrictive then it needs to be. In the future
45 // we need to: 153 // we need to:
46 // allow kRound_Cap capping (could allow rotations in the matrix with this) 154 // allow kRound_Cap capping (could allow rotations in the matrix with this)
47 // allow paths to be returned 155 // allow paths to be returned
48 bool SkDashPathEffect::asPoints(PointData* results, 156 bool SkDashPathEffect::asPoints(PointData* results,
49 const SkPath& src, 157 const SkPath& src,
50 const SkStrokeRec& rec, 158 const SkStrokeRec& rec,
51 const SkMatrix& matrix, 159 const SkMatrix& matrix,
52 const SkRect* cullRect) const { 160 const SkRect* cullRect) const {
53 // width < 0 -> fill && width == 0 -> hairline so requiring width > 0 rules both out 161 // width < 0 -> fill && width == 0 -> hairline so requiring width > 0 rules both out
54 if (fInitialDashLength < 0 || 0 >= rec.getWidth()) { 162 if (fInitialDashLength < 0 || 0 >= rec.getWidth()) {
55 return false; 163 return false;
56 } 164 }
57 165
58 // TODO: this next test could be eased up. We could allow any number of 166 // TODO: this next test could be eased up. We could allow any number of
59 // intervals as long as all the ons match and all the offs match. 167 // intervals as long as all the ons match and all the offs match.
60 // Additionally, they do not necessarily need to be integers. 168 // Additionally, they do not necessarily need to be integers.
61 // We cannot allow arbitrary intervals since we want the returned points 169 // We cannot allow arbitrary intervals since we want the returned points
62 // to be uniformly sized. 170 // to be uniformly sized.
63 if (fCount != 2 || 171 if (fCount != 2 ||
64 !SkScalarNearlyEqual(fIntervals[0], fIntervals[1]) || 172 !SkScalarNearlyEqual(fIntervals[0], fIntervals[1]) ||
65 !SkScalarIsInt(fIntervals[0]) || 173 !SkScalarIsInt(fIntervals[0]) ||
66 !SkScalarIsInt(fIntervals[1])) { 174 !SkScalarIsInt(fIntervals[1])) {
67 return false; 175 return false;
68 } 176 }
69 177
178 SkPath cullPathStorage;
179 const SkPath* srcPtr = &src;
180 if (cull_path(src, rec, cullRect, fIntervalLength, &cullPathStorage)) {
181 srcPtr = &cullPathStorage;
182 }
183
70 SkPoint pts[2]; 184 SkPoint pts[2];
71 185
72 if (!src.isLine(pts)) { 186 if (!srcPtr->isLine(pts)) {
73 return false; 187 return false;
74 } 188 }
75 189
76 // TODO: this test could be eased up to allow circles 190 // TODO: this test could be eased up to allow circles
77 if (SkPaint::kButt_Cap != rec.getCap()) { 191 if (SkPaint::kButt_Cap != rec.getCap()) {
78 return false; 192 return false;
79 } 193 }
80 194
81 // TODO: this test could be eased up for circles. Rotations could be allowed . 195 // TODO: this test could be eased up for circles. Rotations could be allowed .
82 if (!matrix.rectStaysRect()) { 196 if (!matrix.rectStaysRect()) {
83 return false; 197 return false;
84 } 198 }
85 199
86 SkScalar length = SkPoint::Distance(pts[1], pts[0]); 200 SkScalar length = SkPoint::Distance(pts[1], pts[0]);
87 201
88 SkVector tangent = pts[1] - pts[0]; 202 SkVector tangent = pts[1] - pts[0];
89 if (tangent.isZero()) { 203 if (tangent.isZero()) {
90 return false; 204 return false;
91 } 205 }
92 206
93 tangent.scale(SkScalarInvert(length)); 207 tangent.scale(SkScalarInvert(length));
94 208
95 // TODO: make this test for horizontal & vertical lines more robust 209 // TODO: make this test for horizontal & vertical lines more robust
96 bool isXAxis = true; 210 bool isXAxis = true;
97 if (SK_Scalar1 == tangent.fX || -SK_Scalar1 == tangent.fX) { 211 if (SkScalarNearlyEqual(SK_Scalar1, tangent.fX) ||
212 SkScalarNearlyEqual(-SK_Scalar1, tangent.fX)) {
98 results->fSize.set(SkScalarHalf(fIntervals[0]), SkScalarHalf(rec.getWidt h())); 213 results->fSize.set(SkScalarHalf(fIntervals[0]), SkScalarHalf(rec.getWidt h()));
99 } else if (SK_Scalar1 == tangent.fY || -SK_Scalar1 == tangent.fY) { 214 } else if (SkScalarNearlyEqual(SK_Scalar1, tangent.fY) ||
215 SkScalarNearlyEqual(-SK_Scalar1, tangent.fY)) {
100 results->fSize.set(SkScalarHalf(rec.getWidth()), SkScalarHalf(fIntervals [0])); 216 results->fSize.set(SkScalarHalf(rec.getWidth()), SkScalarHalf(fIntervals [0]));
101 isXAxis = false; 217 isXAxis = false;
102 } else if (SkPaint::kRound_Cap != rec.getCap()) { 218 } else if (SkPaint::kRound_Cap != rec.getCap()) {
103 // Angled lines don't have axis-aligned boxes. 219 // Angled lines don't have axis-aligned boxes.
104 return false; 220 return false;
105 } 221 }
106 222
107 if (results) { 223 if (results) {
108 results->fFlags = 0; 224 results->fFlags = 0;
109 SkScalar clampedInitialDashLength = SkMinScalar(length, fInitialDashLeng th); 225 SkScalar clampedInitialDashLength = SkMinScalar(length, fInitialDashLeng th);
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 } 405 }
290 } else { 406 } else {
291 // set the internal data members, fPhase should have been between 0 and intervalLength 407 // set the internal data members, fPhase should have been between 0 and intervalLength
292 // when written to buffer so no need to adjust it 408 // when written to buffer so no need to adjust it
293 SkDashPath::CalcDashParameters(fPhase, fIntervals, fCount, 409 SkDashPath::CalcDashParameters(fPhase, fIntervals, fCount,
294 &fInitialDashLength, &fInitialDashIndex, &fIntervalLength); 410 &fInitialDashLength, &fInitialDashIndex, &fIntervalLength);
295 } 411 }
296 } 412 }
297 #endif 413 #endif
298 414
OLDNEW
« no previous file with comments | « gm/dashing.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698