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

Side by Side Diff: src/core/SkPath.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/SkGeometry.cpp ('k') | src/core/SkPathMeasure.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
2 /* 1 /*
3 * Copyright 2006 The Android Open Source Project 2 * Copyright 2006 The Android Open Source Project
4 * 3 *
5 * 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
6 * found in the LICENSE file. 5 * found in the LICENSE file.
7 */ 6 */
8 7
9
10 #include "SkBuffer.h" 8 #include "SkBuffer.h"
11 #include "SkErrorInternals.h" 9 #include "SkErrorInternals.h"
10 #include "SkGeometry.h"
12 #include "SkMath.h" 11 #include "SkMath.h"
13 #include "SkPath.h" 12 #include "SkPath.h"
14 #include "SkPathRef.h" 13 #include "SkPathRef.h"
15 #include "SkRRect.h" 14 #include "SkRRect.h"
16 #include "SkThread.h" 15 #include "SkThread.h"
17 16
17 #define SK_SUPPORT_LEGACY_ADDOVAL
18
18 //////////////////////////////////////////////////////////////////////////// 19 ////////////////////////////////////////////////////////////////////////////
19 20
20 /** 21 /**
21 * Path.bounds is defined to be the bounds of all the control points. 22 * Path.bounds is defined to be the bounds of all the control points.
22 * If we called bounds.join(r) we would skip r if r was empty, which breaks 23 * If we called bounds.join(r) we would skip r if r was empty, which breaks
23 * our promise. Hence we have a custom joiner that doesn't look at emptiness 24 * our promise. Hence we have a custom joiner that doesn't look at emptiness
24 */ 25 */
25 static void joinNoEmptyChecks(SkRect* dst, const SkRect& src) { 26 static void joinNoEmptyChecks(SkRect* dst, const SkRect& src) {
26 dst->fLeft = SkMinScalar(dst->fLeft, src.fLeft); 27 dst->fLeft = SkMinScalar(dst->fLeft, src.fLeft);
27 dst->fTop = SkMinScalar(dst->fTop, src.fTop); 28 dst->fTop = SkMinScalar(dst->fTop, src.fTop);
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 SkDEBUGCODE(++segmentCount); 276 SkDEBUGCODE(++segmentCount);
276 nextPt = 3; 277 nextPt = 3;
277 break; 278 break;
278 case kClose_Verb: 279 case kClose_Verb:
279 SkDEBUGCODE(++closeCount;) 280 SkDEBUGCODE(++closeCount;)
280 break; 281 break;
281 default: 282 default:
282 SkDEBUGFAIL("unknown verb"); 283 SkDEBUGFAIL("unknown verb");
283 } 284 }
284 if (-1 != nextPt) { 285 if (-1 != nextPt) {
285 if (!check_edge_against_rect(prevPt, pts[nextPt], rect, direction)) { 286 if (SkPath::kConic_Verb == verb) {
286 return false; 287 SkConic orig;
288 orig.set(pts, iter.conicWeight());
289 SkPoint quadPts[5];
290 int count = orig.chopIntoQuadsPOW2(quadPts, 1);
291 SK_ALWAYSBREAK(2 == count);
292
293 if (!check_edge_against_rect(quadPts[0], quadPts[2], rect, direc tion)) {
294 return false;
295 }
296 if (!check_edge_against_rect(quadPts[2], quadPts[4], rect, direc tion)) {
297 return false;
298 }
299 } else {
300 if (!check_edge_against_rect(prevPt, pts[nextPt], rect, directio n)) {
301 return false;
302 }
287 } 303 }
288 prevPt = pts[nextPt]; 304 prevPt = pts[nextPt];
289 } 305 }
290 } 306 }
291 307
292 return check_edge_against_rect(prevPt, firstPt, rect, direction); 308 return check_edge_against_rect(prevPt, firstPt, rect, direction);
293 } 309 }
294 310
295 uint32_t SkPath::getGenerationID() const { 311 uint32_t SkPath::getGenerationID() const {
296 uint32_t genID = fPathRef->genID(); 312 uint32_t genID = fPathRef->genID();
(...skipping 869 matching lines...) Expand 10 before | Expand all | Expand 10 after
1166 if (isOval) { 1182 if (isOval) {
1167 fDirection = dir; 1183 fDirection = dir;
1168 } else { 1184 } else {
1169 fDirection = kUnknown_Direction; 1185 fDirection = kUnknown_Direction;
1170 } 1186 }
1171 1187
1172 SkAutoDisableDirectionCheck addc(this); 1188 SkAutoDisableDirectionCheck addc(this);
1173 1189
1174 SkAutoPathBoundsUpdate apbu(this, oval); 1190 SkAutoPathBoundsUpdate apbu(this, oval);
1175 1191
1192 #ifdef SK_SUPPORT_LEGACY_ADDOVAL
1176 SkScalar cx = oval.centerX(); 1193 SkScalar cx = oval.centerX();
1177 SkScalar cy = oval.centerY(); 1194 SkScalar cy = oval.centerY();
1178 SkScalar rx = SkScalarHalf(oval.width()); 1195 SkScalar rx = SkScalarHalf(oval.width());
1179 SkScalar ry = SkScalarHalf(oval.height()); 1196 SkScalar ry = SkScalarHalf(oval.height());
1180 1197
1181 SkScalar sx = SkScalarMul(rx, SK_ScalarTanPIOver8); 1198 SkScalar sx = SkScalarMul(rx, SK_ScalarTanPIOver8);
1182 SkScalar sy = SkScalarMul(ry, SK_ScalarTanPIOver8); 1199 SkScalar sy = SkScalarMul(ry, SK_ScalarTanPIOver8);
1183 SkScalar mx = SkScalarMul(rx, SK_ScalarRoot2Over2); 1200 SkScalar mx = SkScalarMul(rx, SK_ScalarRoot2Over2);
1184 SkScalar my = SkScalarMul(ry, SK_ScalarRoot2Over2); 1201 SkScalar my = SkScalarMul(ry, SK_ScalarRoot2Over2);
1185 1202
1186 /* 1203 /*
1187 To handle imprecision in computing the center and radii, we revert to 1204 To handle imprecision in computing the center and radii, we revert to
1188 the provided bounds when we can (i.e. use oval.fLeft instead of cx-rx) 1205 the provided bounds when we can (i.e. use oval.fLeft instead of cx-rx)
1189 to ensure that we don't exceed the oval's bounds *ever*, since we want 1206 to ensure that we don't exceed the oval's bounds *ever*, since we want
1190 to use oval for our fast-bounds, rather than have to recompute it. 1207 to use oval for our fast-bounds, rather than have to recompute it.
1191 */ 1208 */
1192 const SkScalar L = oval.fLeft; // cx - rx 1209 const SkScalar L = oval.fLeft; // cx - rx
1193 const SkScalar T = oval.fTop; // cy - ry 1210 const SkScalar T = oval.fTop; // cy - ry
1194 const SkScalar R = oval.fRight; // cx + rx 1211 const SkScalar R = oval.fRight; // cx + rx
1195 const SkScalar B = oval.fBottom; // cy + ry 1212 const SkScalar B = oval.fBottom; // cy + ry
1196 1213
1197 this->incReserve(17); // 8 quads + close 1214 this->incReserve(17); // 8 quads + close
1198 this->moveTo(R, cy); 1215 this->moveTo(R, cy);
1199 if (dir == kCCW_Direction) { 1216 if (dir == kCCW_Direction) {
1200 this->quadTo( R, cy - sy, cx + mx, cy - my); 1217 this->quadTo( R, cy - sy, cx + mx, cy - my);
1201 this->quadTo(cx + sx, T, cx , T); 1218 this->quadTo(cx + sx, T, cx , T);
1202 this->quadTo(cx - sx, T, cx - mx, cy - my); 1219 this->quadTo(cx - sx, T, cx - mx, cy - my);
1203 this->quadTo( L, cy - sy, L, cy ); 1220 this->quadTo( L, cy - sy, L, cy );
1204 this->quadTo( L, cy + sy, cx - mx, cy + my); 1221 this->quadTo( L, cy + sy, cx - mx, cy + my);
1205 this->quadTo(cx - sx, B, cx , B); 1222 this->quadTo(cx - sx, B, cx , B);
1206 this->quadTo(cx + sx, B, cx + mx, cy + my); 1223 this->quadTo(cx + sx, B, cx + mx, cy + my);
1207 this->quadTo( R, cy + sy, R, cy ); 1224 this->quadTo( R, cy + sy, R, cy );
1208 } else { 1225 } else {
1209 this->quadTo( R, cy + sy, cx + mx, cy + my); 1226 this->quadTo( R, cy + sy, cx + mx, cy + my);
1210 this->quadTo(cx + sx, B, cx , B); 1227 this->quadTo(cx + sx, B, cx , B);
1211 this->quadTo(cx - sx, B, cx - mx, cy + my); 1228 this->quadTo(cx - sx, B, cx - mx, cy + my);
1212 this->quadTo( L, cy + sy, L, cy ); 1229 this->quadTo( L, cy + sy, L, cy );
1213 this->quadTo( L, cy - sy, cx - mx, cy - my); 1230 this->quadTo( L, cy - sy, cx - mx, cy - my);
1214 this->quadTo(cx - sx, T, cx , T); 1231 this->quadTo(cx - sx, T, cx , T);
1215 this->quadTo(cx + sx, T, cx + mx, cy - my); 1232 this->quadTo(cx + sx, T, cx + mx, cy - my);
1216 this->quadTo( R, cy - sy, R, cy ); 1233 this->quadTo( R, cy - sy, R, cy );
1217 } 1234 }
1235 #else
1236 const SkScalar L = oval.fLeft;
1237 const SkScalar T = oval.fTop;
1238 const SkScalar R = oval.fRight;
1239 const SkScalar B = oval.fBottom;
1240 const SkScalar cx = oval.centerX();
1241 const SkScalar cy = oval.centerY();
1242 const SkScalar weight = SK_ScalarRoot2Over2;
1243
1244 this->incReserve(9); // move + 4 conics
1245 this->moveTo(R, cy);
1246 if (dir == kCCW_Direction) {
1247 this->conicTo(R, T, cx, T, weight);
1248 this->conicTo(L, T, L, cy, weight);
1249 this->conicTo(L, B, cx, B, weight);
1250 this->conicTo(R, B, R, cy, weight);
1251 } else {
1252 this->conicTo(R, B, cx, B, weight);
1253 this->conicTo(L, B, L, cy, weight);
1254 this->conicTo(L, T, cx, T, weight);
1255 this->conicTo(R, T, R, cy, weight);
1256 }
1257 #endif
1218 this->close(); 1258 this->close();
1219 1259
1220 SkPathRef::Editor ed(&fPathRef); 1260 SkPathRef::Editor ed(&fPathRef);
1221 1261
1222 ed.setIsOval(isOval); 1262 ed.setIsOval(isOval);
1223 } 1263 }
1224 1264
1225 void SkPath::addCircle(SkScalar x, SkScalar y, SkScalar r, Direction dir) { 1265 void SkPath::addCircle(SkScalar x, SkScalar y, SkScalar r, Direction dir) {
1226 if (r > 0) { 1266 if (r > 0) {
1227 SkRect rect; 1267 SkRect rect;
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
1523 1563
1524 /////////////////////////////////////////////////////////////////////////////// 1564 ///////////////////////////////////////////////////////////////////////////////
1525 1565
1526 void SkPath::offset(SkScalar dx, SkScalar dy, SkPath* dst) const { 1566 void SkPath::offset(SkScalar dx, SkScalar dy, SkPath* dst) const {
1527 SkMatrix matrix; 1567 SkMatrix matrix;
1528 1568
1529 matrix.setTranslate(dx, dy); 1569 matrix.setTranslate(dx, dy);
1530 this->transform(matrix, dst); 1570 this->transform(matrix, dst);
1531 } 1571 }
1532 1572
1533 #include "SkGeometry.h"
1534
1535 static void subdivide_quad_to(SkPath* path, const SkPoint pts[3],
1536 int level = 2) {
1537 if (--level >= 0) {
1538 SkPoint tmp[5];
1539
1540 SkChopQuadAtHalf(pts, tmp);
1541 subdivide_quad_to(path, &tmp[0], level);
1542 subdivide_quad_to(path, &tmp[2], level);
1543 } else {
1544 path->quadTo(pts[1], pts[2]);
1545 }
1546 }
1547
1548 static void subdivide_cubic_to(SkPath* path, const SkPoint pts[4], 1573 static void subdivide_cubic_to(SkPath* path, const SkPoint pts[4],
1549 int level = 2) { 1574 int level = 2) {
1550 if (--level >= 0) { 1575 if (--level >= 0) {
1551 SkPoint tmp[7]; 1576 SkPoint tmp[7];
1552 1577
1553 SkChopCubicAtHalf(pts, tmp); 1578 SkChopCubicAtHalf(pts, tmp);
1554 subdivide_cubic_to(path, &tmp[0], level); 1579 subdivide_cubic_to(path, &tmp[0], level);
1555 subdivide_cubic_to(path, &tmp[3], level); 1580 subdivide_cubic_to(path, &tmp[3], level);
1556 } else { 1581 } else {
1557 path->cubicTo(pts[1], pts[2], pts[3]); 1582 path->cubicTo(pts[1], pts[2], pts[3]);
(...skipping 16 matching lines...) Expand all
1574 1599
1575 while ((verb = iter.next(pts, false)) != kDone_Verb) { 1600 while ((verb = iter.next(pts, false)) != kDone_Verb) {
1576 switch (verb) { 1601 switch (verb) {
1577 case kMove_Verb: 1602 case kMove_Verb:
1578 tmp.moveTo(pts[0]); 1603 tmp.moveTo(pts[0]);
1579 break; 1604 break;
1580 case kLine_Verb: 1605 case kLine_Verb:
1581 tmp.lineTo(pts[1]); 1606 tmp.lineTo(pts[1]);
1582 break; 1607 break;
1583 case kQuad_Verb: 1608 case kQuad_Verb:
1584 subdivide_quad_to(&tmp, pts); 1609 // promote the quad to a conic
1610 tmp.conicTo(pts[1], pts[2],
1611 SkConic::TransformW(pts, SK_Scalar1, matrix));
1585 break; 1612 break;
1586 case kConic_Verb: 1613 case kConic_Verb:
1587 SkDEBUGFAIL("TODO: compute new weight"); 1614 tmp.conicTo(pts[1], pts[2],
1588 tmp.conicTo(pts[1], pts[2], iter.conicWeight()); 1615 SkConic::TransformW(pts, iter.conicWeight(), mat rix));
1589 break; 1616 break;
1590 case kCubic_Verb: 1617 case kCubic_Verb:
1591 subdivide_cubic_to(&tmp, pts); 1618 subdivide_cubic_to(&tmp, pts);
1592 break; 1619 break;
1593 case kClose_Verb: 1620 case kClose_Verb:
1594 tmp.close(); 1621 tmp.close();
1595 break; 1622 break;
1596 default: 1623 default:
1597 SkDEBUGFAIL("unknown verb"); 1624 SkDEBUGFAIL("unknown verb");
1598 break; 1625 break;
(...skipping 1268 matching lines...) Expand 10 before | Expand all | Expand 10 after
2867 switch (this->getFillType()) { 2894 switch (this->getFillType()) {
2868 case SkPath::kEvenOdd_FillType: 2895 case SkPath::kEvenOdd_FillType:
2869 case SkPath::kInverseEvenOdd_FillType: 2896 case SkPath::kInverseEvenOdd_FillType:
2870 w &= 1; 2897 w &= 1;
2871 break; 2898 break;
2872 default: 2899 default:
2873 break; 2900 break;
2874 } 2901 }
2875 return SkToBool(w); 2902 return SkToBool(w);
2876 } 2903 }
OLDNEW
« no previous file with comments | « src/core/SkGeometry.cpp ('k') | src/core/SkPathMeasure.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698