| 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 |