| OLD | NEW |
| 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 "SkBuffer.h" | 8 #include "SkBuffer.h" |
| 9 #include "SkErrorInternals.h" | 9 #include "SkErrorInternals.h" |
| 10 #include "SkGeometry.h" | 10 #include "SkGeometry.h" |
| (...skipping 876 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 887 if (close) { | 887 if (close) { |
| 888 ed.growForVerb(kClose_Verb); | 888 ed.growForVerb(kClose_Verb); |
| 889 } | 889 } |
| 890 | 890 |
| 891 DIRTY_AFTER_EDIT; | 891 DIRTY_AFTER_EDIT; |
| 892 SkDEBUGCODE(this->validate();) | 892 SkDEBUGCODE(this->validate();) |
| 893 } | 893 } |
| 894 | 894 |
| 895 #include "SkGeometry.h" | 895 #include "SkGeometry.h" |
| 896 | 896 |
| 897 static int build_arc_points(const SkRect& oval, SkScalar startAngle, | 897 static bool arc_is_lone_point(const SkRect& oval, SkScalar startAngle, SkScalar
sweepAngle, |
| 898 SkScalar sweepAngle, | 898 SkPoint* pt) { |
| 899 SkPoint pts[kSkBuildQuadArcStorage]) { | 899 if (0 == sweepAngle && (0 == startAngle || SkIntToScalar(360) == startAngle)
) { |
| 900 | |
| 901 if (0 == sweepAngle && | |
| 902 (0 == startAngle || SkIntToScalar(360) == startAngle)) { | |
| 903 // Chrome uses this path to move into and out of ovals. If not | 900 // Chrome uses this path to move into and out of ovals. If not |
| 904 // treated as a special case the moves can distort the oval's | 901 // treated as a special case the moves can distort the oval's |
| 905 // bounding box (and break the circle special case). | 902 // bounding box (and break the circle special case). |
| 906 pts[0].set(oval.fRight, oval.centerY()); | 903 pt->set(oval.fRight, oval.centerY()); |
| 907 return 1; | 904 return true; |
| 908 } else if (0 == oval.width() && 0 == oval.height()) { | 905 } else if (0 == oval.width() && 0 == oval.height()) { |
| 909 // Chrome will sometimes create 0 radius round rects. Having degenerate | 906 // Chrome will sometimes create 0 radius round rects. Having degenerate |
| 910 // quad segments in the path prevents the path from being recognized as | 907 // quad segments in the path prevents the path from being recognized as |
| 911 // a rect. | 908 // a rect. |
| 912 // TODO: optimizing the case where only one of width or height is zero | 909 // TODO: optimizing the case where only one of width or height is zero |
| 913 // should also be considered. This case, however, doesn't seem to be | 910 // should also be considered. This case, however, doesn't seem to be |
| 914 // as common as the single point case. | 911 // as common as the single point case. |
| 915 pts[0].set(oval.fRight, oval.fTop); | 912 pt->set(oval.fRight, oval.fTop); |
| 916 return 1; | 913 return true; |
| 917 } | 914 } |
| 915 return false; |
| 916 } |
| 918 | 917 |
| 918 static int build_arc_points(const SkRect& oval, SkScalar startAngle, SkScalar sw
eepAngle, |
| 919 SkPoint pts[kSkBuildQuadArcStorage]) { |
| 919 SkVector start, stop; | 920 SkVector start, stop; |
| 920 | 921 |
| 921 start.fY = SkScalarSinCos(SkDegreesToRadians(startAngle), &start.fX); | 922 start.fY = SkScalarSinCos(SkDegreesToRadians(startAngle), &start.fX); |
| 922 stop.fY = SkScalarSinCos(SkDegreesToRadians(startAngle + sweepAngle), | 923 stop.fY = SkScalarSinCos(SkDegreesToRadians(startAngle + sweepAngle), |
| 923 &stop.fX); | 924 &stop.fX); |
| 924 | 925 |
| 925 /* If the sweep angle is nearly (but less than) 360, then due to precision | 926 /* If the sweep angle is nearly (but less than) 360, then due to precision |
| 926 loss in radians-conversion and/or sin/cos, we may end up with coincident | 927 loss in radians-conversion and/or sin/cos, we may end up with coincident |
| 927 vectors, which will fool SkBuildQuadArc into doing nothing (bad) instead | 928 vectors, which will fool SkBuildQuadArc into doing nothing (bad) instead |
| 928 of drawing a nearly complete circle (good). | 929 of drawing a nearly complete circle (good). |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1302 this->addOval(rect, dir); | 1303 this->addOval(rect, dir); |
| 1303 } | 1304 } |
| 1304 } | 1305 } |
| 1305 | 1306 |
| 1306 void SkPath::arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, | 1307 void SkPath::arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, |
| 1307 bool forceMoveTo) { | 1308 bool forceMoveTo) { |
| 1308 if (oval.width() < 0 || oval.height() < 0) { | 1309 if (oval.width() < 0 || oval.height() < 0) { |
| 1309 return; | 1310 return; |
| 1310 } | 1311 } |
| 1311 | 1312 |
| 1313 if (fPathRef->countVerbs() == 0) { |
| 1314 forceMoveTo = true; |
| 1315 } |
| 1316 |
| 1317 SkPoint lonePt; |
| 1318 if (arc_is_lone_point(oval, startAngle, sweepAngle, &lonePt)) { |
| 1319 forceMoveTo ? this->moveTo(lonePt) : this->lineTo(lonePt); |
| 1320 return; |
| 1321 } |
| 1322 |
| 1312 SkPoint pts[kSkBuildQuadArcStorage]; | 1323 SkPoint pts[kSkBuildQuadArcStorage]; |
| 1313 int count = build_arc_points(oval, startAngle, sweepAngle, pts); | 1324 int count = build_arc_points(oval, startAngle, sweepAngle, pts); |
| 1314 SkASSERT((count & 1) == 1); | 1325 SkASSERT((count & 1) == 1); |
| 1315 | 1326 |
| 1316 if (fPathRef->countVerbs() == 0) { | |
| 1317 forceMoveTo = true; | |
| 1318 } | |
| 1319 this->incReserve(count); | 1327 this->incReserve(count); |
| 1320 forceMoveTo ? this->moveTo(pts[0]) : this->lineTo(pts[0]); | 1328 forceMoveTo ? this->moveTo(pts[0]) : this->lineTo(pts[0]); |
| 1321 for (int i = 1; i < count; i += 2) { | 1329 for (int i = 1; i < count; i += 2) { |
| 1322 this->quadTo(pts[i], pts[i+1]); | 1330 this->quadTo(pts[i], pts[i+1]); |
| 1323 } | 1331 } |
| 1324 } | 1332 } |
| 1325 | 1333 |
| 1326 void SkPath::addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle
) { | 1334 void SkPath::addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle
) { |
| 1327 if (oval.isEmpty() || 0 == sweepAngle) { | 1335 if (oval.isEmpty() || 0 == sweepAngle) { |
| 1328 return; | 1336 return; |
| 1329 } | 1337 } |
| 1330 | 1338 |
| 1331 const SkScalar kFullCircleAngle = SkIntToScalar(360); | 1339 const SkScalar kFullCircleAngle = SkIntToScalar(360); |
| 1332 | 1340 |
| 1333 if (sweepAngle >= kFullCircleAngle || sweepAngle <= -kFullCircleAngle) { | 1341 if (sweepAngle >= kFullCircleAngle || sweepAngle <= -kFullCircleAngle) { |
| 1334 this->addOval(oval, sweepAngle > 0 ? kCW_Direction : kCCW_Direction); | 1342 this->addOval(oval, sweepAngle > 0 ? kCW_Direction : kCCW_Direction); |
| 1335 return; | 1343 return; |
| 1336 } | 1344 } |
| 1337 | 1345 |
| 1346 SkPoint lonePt; |
| 1347 if (arc_is_lone_point(oval, startAngle, sweepAngle, &lonePt)) { |
| 1348 this->moveTo(lonePt); |
| 1349 return; |
| 1350 } |
| 1351 |
| 1338 SkPoint pts[kSkBuildQuadArcStorage]; | 1352 SkPoint pts[kSkBuildQuadArcStorage]; |
| 1339 int count = build_arc_points(oval, startAngle, sweepAngle, pts); | 1353 int count = build_arc_points(oval, startAngle, sweepAngle, pts); |
| 1340 | 1354 |
| 1341 SkDEBUGCODE(this->validate();) | 1355 SkDEBUGCODE(this->validate();) |
| 1342 SkASSERT(count & 1); | 1356 SkASSERT(count & 1); |
| 1343 | 1357 |
| 1344 fLastMoveToIndex = fPathRef->countPoints(); | 1358 fLastMoveToIndex = fPathRef->countPoints(); |
| 1345 | 1359 |
| 1346 SkPathRef::Editor ed(&fPathRef, 1+(count-1)/2, count); | 1360 SkPathRef::Editor ed(&fPathRef, 1+(count-1)/2, count); |
| 1347 | 1361 |
| (...skipping 1579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2927 switch (this->getFillType()) { | 2941 switch (this->getFillType()) { |
| 2928 case SkPath::kEvenOdd_FillType: | 2942 case SkPath::kEvenOdd_FillType: |
| 2929 case SkPath::kInverseEvenOdd_FillType: | 2943 case SkPath::kInverseEvenOdd_FillType: |
| 2930 w &= 1; | 2944 w &= 1; |
| 2931 break; | 2945 break; |
| 2932 default: | 2946 default: |
| 2933 break; | 2947 break; |
| 2934 } | 2948 } |
| 2935 return SkToBool(w); | 2949 return SkToBool(w); |
| 2936 } | 2950 } |
| OLD | NEW |