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

Side by Side Diff: src/core/SkPathMeasure.cpp

Issue 455043002: use conics (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: address comments Created 6 years 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 | « src/core/SkPath.cpp ('k') | src/utils/SkParsePath.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 /* 2 /*
3 * Copyright 2008 The Android Open Source Project 3 * Copyright 2008 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #include "SkPathMeasure.h" 10 #include "SkPathMeasure.h"
11 #include "SkGeometry.h" 11 #include "SkGeometry.h"
12 #include "SkPath.h" 12 #include "SkPath.h"
13 #include "SkTSearch.h" 13 #include "SkTSearch.h"
14 14
15 // these must be 0,1,2 since they are in our 2-bit field 15 // these must be 0,1,2,3 since they are in our 2-bit field
16 enum { 16 enum {
17 kLine_SegType, 17 kLine_SegType,
18 kQuad_SegType, 18 kQuad_SegType,
19 kCubic_SegType 19 kCubic_SegType,
20 kConic_SegType,
20 }; 21 };
21 22
22 #define kMaxTValue 32767 23 #define kMaxTValue 32767
23 24
24 static inline SkScalar tValue2Scalar(int t) { 25 static inline SkScalar tValue2Scalar(int t) {
25 SkASSERT((unsigned)t <= kMaxTValue); 26 SkASSERT((unsigned)t <= kMaxTValue);
26 return t * 3.05185e-5f; // t / 32767 27 return t * 3.05185e-5f; // t / 32767
27 } 28 }
28 29
29 SkScalar SkPathMeasure::Segment::getScalarT() const { 30 SkScalar SkPathMeasure::Segment::getScalarT() const {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 Segment* seg = fSegments.append(); 98 Segment* seg = fSegments.append();
98 seg->fDistance = distance; 99 seg->fDistance = distance;
99 seg->fPtIndex = ptIndex; 100 seg->fPtIndex = ptIndex;
100 seg->fType = kQuad_SegType; 101 seg->fType = kQuad_SegType;
101 seg->fTValue = maxt; 102 seg->fTValue = maxt;
102 } 103 }
103 } 104 }
104 return distance; 105 return distance;
105 } 106 }
106 107
108 SkScalar SkPathMeasure::compute_conic_segs(const SkConic& conic,
109 SkScalar distance, int mint, int maxt , int ptIndex) {
110 if (tspan_big_enough(maxt - mint) && quad_too_curvy(conic.fPts)) {
111 SkConic tmp[2];
112 conic.chop(tmp);
113
114 int halft = (mint + maxt) >> 1;
115 distance = this->compute_conic_segs(tmp[0], distance, mint, halft, ptInd ex);
116 distance = this->compute_conic_segs(tmp[1], distance, halft, maxt, ptInd ex);
117 } else {
118 SkScalar d = SkPoint::Distance(conic.fPts[0], conic.fPts[2]);
119 SkScalar prevD = distance;
120 distance += d;
121 if (distance > prevD) {
122 Segment* seg = fSegments.append();
123 seg->fDistance = distance;
124 seg->fPtIndex = ptIndex;
125 seg->fType = kConic_SegType;
126 seg->fTValue = maxt;
127 }
128 }
129 return distance;
130 }
131
107 SkScalar SkPathMeasure::compute_cubic_segs(const SkPoint pts[4], 132 SkScalar SkPathMeasure::compute_cubic_segs(const SkPoint pts[4],
108 SkScalar distance, int mint, int maxt, int ptIndex) { 133 SkScalar distance, int mint, int maxt, int ptIndex) {
109 if (tspan_big_enough(maxt - mint) && cubic_too_curvy(pts)) { 134 if (tspan_big_enough(maxt - mint) && cubic_too_curvy(pts)) {
110 SkPoint tmp[7]; 135 SkPoint tmp[7];
111 int halft = (mint + maxt) >> 1; 136 int halft = (mint + maxt) >> 1;
112 137
113 SkChopCubicAtHalf(pts, tmp); 138 SkChopCubicAtHalf(pts, tmp);
114 distance = this->compute_cubic_segs(tmp, distance, mint, halft, ptIndex) ; 139 distance = this->compute_cubic_segs(tmp, distance, mint, halft, ptIndex) ;
115 distance = this->compute_cubic_segs(&tmp[3], distance, halft, maxt, ptIn dex); 140 distance = this->compute_cubic_segs(&tmp[3], distance, halft, maxt, ptIn dex);
116 } else { 141 } else {
(...skipping 23 matching lines...) Expand all
140 * as we accumulate distance, we have to check that the result of += 165 * as we accumulate distance, we have to check that the result of +=
141 * actually made it larger, since a very small delta might be > 0, but 166 * actually made it larger, since a very small delta might be > 0, but
142 * still have no effect on distance (if distance >>> delta). 167 * still have no effect on distance (if distance >>> delta).
143 * 168 *
144 * We do this check below, and in compute_quad_segs and compute_cubic_segs 169 * We do this check below, and in compute_quad_segs and compute_cubic_segs
145 */ 170 */
146 fSegments.reset(); 171 fSegments.reset();
147 bool done = false; 172 bool done = false;
148 do { 173 do {
149 switch (fIter.next(pts)) { 174 switch (fIter.next(pts)) {
150 case SkPath::kConic_Verb:
151 SkASSERT(0);
152 break;
153 case SkPath::kMove_Verb: 175 case SkPath::kMove_Verb:
154 ptIndex += 1; 176 ptIndex += 1;
155 fPts.append(1, pts); 177 fPts.append(1, pts);
156 if (!firstMoveTo) { 178 if (!firstMoveTo) {
157 done = true; 179 done = true;
158 break; 180 break;
159 } 181 }
160 firstMoveTo = false; 182 firstMoveTo = false;
161 break; 183 break;
162 184
163 case SkPath::kLine_Verb: { 185 case SkPath::kLine_Verb: {
164 SkScalar d = SkPoint::Distance(pts[0], pts[1]); 186 SkScalar d = SkPoint::Distance(pts[0], pts[1]);
165 SkASSERT(d >= 0); 187 SkASSERT(d >= 0);
166 SkScalar prevD = distance; 188 SkScalar prevD = distance;
167 distance += d; 189 distance += d;
168 if (distance > prevD) { 190 if (distance > prevD) {
169 seg = fSegments.append(); 191 seg = fSegments.append();
170 seg->fDistance = distance; 192 seg->fDistance = distance;
171 seg->fPtIndex = ptIndex; 193 seg->fPtIndex = ptIndex;
172 seg->fType = kLine_SegType; 194 seg->fType = kLine_SegType;
173 seg->fTValue = kMaxTValue; 195 seg->fTValue = kMaxTValue;
174 fPts.append(1, pts + 1); 196 fPts.append(1, pts + 1);
175 ptIndex++; 197 ptIndex++;
176 } 198 }
177 } break; 199 } break;
178 200
179 case SkPath::kQuad_Verb: { 201 case SkPath::kQuad_Verb: {
180 SkScalar prevD = distance; 202 SkScalar prevD = distance;
181 distance = this->compute_quad_segs(pts, distance, 0, 203 distance = this->compute_quad_segs(pts, distance, 0, kMaxTValue, ptIndex);
182 kMaxTValue, ptIndex);
183 if (distance > prevD) { 204 if (distance > prevD) {
184 fPts.append(2, pts + 1); 205 fPts.append(2, pts + 1);
185 ptIndex += 2; 206 ptIndex += 2;
186 } 207 }
187 } break; 208 } break;
188 209
210 case SkPath::kConic_Verb: {
211 const SkConic conic(pts, fIter.conicWeight());
212 SkScalar prevD = distance;
213 distance = this->compute_conic_segs(conic, distance, 0, kMaxTVal ue, ptIndex);
214 if (distance > prevD) {
215 // we store the conic weight in our next point, followed by the last 2 pts
216 // thus to reconstitue a conic, you'd need to say
217 // SkConic(pts[0], pts[2], pts[3], weight = pts[1].fX)
218 fPts.append()->set(conic.fW, 0);
219 fPts.append(2, pts + 1);
220 ptIndex += 3;
221 }
222 } break;
223
189 case SkPath::kCubic_Verb: { 224 case SkPath::kCubic_Verb: {
190 SkScalar prevD = distance; 225 SkScalar prevD = distance;
191 distance = this->compute_cubic_segs(pts, distance, 0, 226 distance = this->compute_cubic_segs(pts, distance, 0, kMaxTValue , ptIndex);
192 kMaxTValue, ptIndex);
193 if (distance > prevD) { 227 if (distance > prevD) {
194 fPts.append(3, pts + 1); 228 fPts.append(3, pts + 1);
195 ptIndex += 3; 229 ptIndex += 3;
196 } 230 }
197 } break; 231 } break;
198 232
199 case SkPath::kClose_Verb: 233 case SkPath::kClose_Verb:
200 isClosed = true; 234 isClosed = true;
201 break; 235 break;
202 236
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 if (tangent) { 283 if (tangent) {
250 tangent->setNormalize(pts[1].fX - pts[0].fX, pts[1].fY - pts[0]. fY); 284 tangent->setNormalize(pts[1].fX - pts[0].fX, pts[1].fY - pts[0]. fY);
251 } 285 }
252 break; 286 break;
253 case kQuad_SegType: 287 case kQuad_SegType:
254 SkEvalQuadAt(pts, t, pos, tangent); 288 SkEvalQuadAt(pts, t, pos, tangent);
255 if (tangent) { 289 if (tangent) {
256 tangent->normalize(); 290 tangent->normalize();
257 } 291 }
258 break; 292 break;
293 case kConic_SegType: {
294 SkConic(pts[0], pts[2], pts[3], pts[1].fX).evalAt(t, pos, tangent);
295 if (tangent) {
296 tangent->normalize();
297 }
298 } break;
259 case kCubic_SegType: 299 case kCubic_SegType:
260 SkEvalCubicAt(pts, t, pos, tangent, NULL); 300 SkEvalCubicAt(pts, t, pos, tangent, NULL);
261 if (tangent) { 301 if (tangent) {
262 tangent->normalize(); 302 tangent->normalize();
263 } 303 }
264 break; 304 break;
265 default: 305 default:
266 SkDEBUGFAIL("unknown segType"); 306 SkDEBUGFAIL("unknown segType");
267 } 307 }
268 } 308 }
269 309
270 static void seg_to(const SkPoint pts[], int segType, 310 static void seg_to(const SkPoint pts[], int segType,
271 SkScalar startT, SkScalar stopT, SkPath* dst) { 311 SkScalar startT, SkScalar stopT, SkPath* dst) {
272 SkASSERT(startT >= 0 && startT <= SK_Scalar1); 312 SkASSERT(startT >= 0 && startT <= SK_Scalar1);
273 SkASSERT(stopT >= 0 && stopT <= SK_Scalar1); 313 SkASSERT(stopT >= 0 && stopT <= SK_Scalar1);
274 SkASSERT(startT <= stopT); 314 SkASSERT(startT <= stopT);
275 315
276 if (startT == stopT) { 316 if (startT == stopT) {
277 return; // should we report this, to undo a moveTo? 317 return; // should we report this, to undo a moveTo?
278 } 318 }
279 319
280 SkPoint tmp0[7], tmp1[7]; 320 SkPoint tmp0[7], tmp1[7];
281 321
282 switch (segType) { 322 switch (segType) {
283 case kLine_SegType: 323 case kLine_SegType:
284 if (SK_Scalar1 == stopT) { 324 if (SK_Scalar1 == stopT) {
285 dst->lineTo(pts[1]); 325 dst->lineTo(pts[1]);
286 } else { 326 } else {
287 dst->lineTo(SkScalarInterp(pts[0].fX, pts[1].fX, stopT), 327 dst->lineTo(SkScalarInterp(pts[0].fX, pts[1].fX, stopT),
288 SkScalarInterp(pts[0].fY, pts[1].fY, stopT)); 328 SkScalarInterp(pts[0].fY, pts[1].fY, stopT));
289 } 329 }
290 break; 330 break;
291 case kQuad_SegType: 331 case kQuad_SegType:
292 if (0 == startT) { 332 if (0 == startT) {
293 if (SK_Scalar1 == stopT) { 333 if (SK_Scalar1 == stopT) {
294 dst->quadTo(pts[1], pts[2]); 334 dst->quadTo(pts[1], pts[2]);
295 } else { 335 } else {
296 SkChopQuadAt(pts, tmp0, stopT); 336 SkChopQuadAt(pts, tmp0, stopT);
297 dst->quadTo(tmp0[1], tmp0[2]); 337 dst->quadTo(tmp0[1], tmp0[2]);
298 } 338 }
299 } else { 339 } else {
300 SkChopQuadAt(pts, tmp0, startT); 340 SkChopQuadAt(pts, tmp0, startT);
301 if (SK_Scalar1 == stopT) { 341 if (SK_Scalar1 == stopT) {
302 dst->quadTo(tmp0[3], tmp0[4]); 342 dst->quadTo(tmp0[3], tmp0[4]);
303 } else { 343 } else {
304 SkChopQuadAt(&tmp0[2], tmp1, SkScalarDiv(stopT - startT, 344 SkChopQuadAt(&tmp0[2], tmp1, SkScalarDiv(stopT - startT,
305 SK_Scalar1 - startT)); 345 SK_Scalar1 - startT));
306 dst->quadTo(tmp1[1], tmp1[2]); 346 dst->quadTo(tmp1[1], tmp1[2]);
307 } 347 }
308 } 348 }
309 break; 349 break;
350 case kConic_SegType: {
351 SkConic conic(pts[0], pts[2], pts[3], pts[1].fX);
352
353 if (0 == startT) {
354 if (SK_Scalar1 == stopT) {
355 dst->conicTo(conic.fPts[1], conic.fPts[2], conic.fW);
356 } else {
357 SkConic tmp[2];
358 conic.chopAt(stopT, tmp);
359 dst->conicTo(tmp[0].fPts[1], tmp[0].fPts[2], tmp[0].fW);
360 }
361 } else {
362 SkConic tmp1[2];
363 conic.chopAt(startT, tmp1);
364 if (SK_Scalar1 == stopT) {
365 dst->conicTo(tmp1[1].fPts[1], tmp1[1].fPts[2], tmp1[1].fW);
366 } else {
367 SkConic tmp2[2];
368 tmp1[1].chopAt((stopT - startT) / (SK_Scalar1 - startT), tmp 2);
369 dst->conicTo(tmp2[0].fPts[1], tmp2[0].fPts[2], tmp2[0].fW);
370 }
371 }
372 } break;
310 case kCubic_SegType: 373 case kCubic_SegType:
311 if (0 == startT) { 374 if (0 == startT) {
312 if (SK_Scalar1 == stopT) { 375 if (SK_Scalar1 == stopT) {
313 dst->cubicTo(pts[1], pts[2], pts[3]); 376 dst->cubicTo(pts[1], pts[2], pts[3]);
314 } else { 377 } else {
315 SkChopCubicAt(pts, tmp0, stopT); 378 SkChopCubicAt(pts, tmp0, stopT);
316 dst->cubicTo(tmp0[1], tmp0[2], tmp0[3]); 379 dst->cubicTo(tmp0[1], tmp0[2], tmp0[3]);
317 } 380 }
318 } else { 381 } else {
319 SkChopCubicAt(pts, tmp0, startT); 382 SkChopCubicAt(pts, tmp0, startT);
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 591
529 for (int i = 0; i < fSegments.count(); i++) { 592 for (int i = 0; i < fSegments.count(); i++) {
530 const Segment* seg = &fSegments[i]; 593 const Segment* seg = &fSegments[i];
531 SkDebugf("pathmeas: seg[%d] distance=%g, point=%d, t=%g, type=%d\n", 594 SkDebugf("pathmeas: seg[%d] distance=%g, point=%d, t=%g, type=%d\n",
532 i, seg->fDistance, seg->fPtIndex, seg->getScalarT(), 595 i, seg->fDistance, seg->fPtIndex, seg->getScalarT(),
533 seg->fType); 596 seg->fType);
534 } 597 }
535 } 598 }
536 599
537 #endif 600 #endif
OLDNEW
« no previous file with comments | « src/core/SkPath.cpp ('k') | src/utils/SkParsePath.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698