OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |