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

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

Issue 26372006: Replace cubic round rect corners with quads (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: cleaned up Created 7 years, 2 months 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | src/core/SkPathRef.cpp » ('j') | src/core/SkPathRef.cpp » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2006 The Android Open Source Project 3 * Copyright 2006 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 "SkBuffer.h" 10 #include "SkBuffer.h"
(...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after
891 fSegmentMask |= kLine_SegmentMask; 891 fSegmentMask |= kLine_SegmentMask;
892 } 892 }
893 if (close) { 893 if (close) {
894 vb[~count] = kClose_Verb; 894 vb[~count] = kClose_Verb;
895 } 895 }
896 896
897 GEN_ID_INC; 897 GEN_ID_INC;
898 DIRTY_AFTER_EDIT; 898 DIRTY_AFTER_EDIT;
899 SkDEBUGCODE(this->validate();) 899 SkDEBUGCODE(this->validate();)
900 } 900 }
901 901
robertphillips 2013/10/16 14:49:57 Just moved up from below
902 #include "SkGeometry.h"
903
904 static int build_arc_points(const SkRect& oval, SkScalar startAngle,
905 SkScalar sweepAngle,
906 SkPoint pts[kSkBuildQuadArcStorage]) {
907
908 if (0 == sweepAngle &&
909 (0 == startAngle || SkIntToScalar(360) == startAngle)) {
910 // Chrome uses this path to move into and out of ovals. If not
911 // treated as a special case the moves can distort the oval's
912 // bounding box (and break the circle special case).
913 pts[0].set(oval.fRight, oval.centerY());
914 return 1;
915 } else if (0 == oval.width() && 0 == oval.height()) {
916 // Chrome will sometimes create 0 radius round rects. Having degenerate
917 // quad segments in the path prevents the path from being recognized as
918 // a rect.
919 // TODO: optimizing the case where only one of width or height is zero
920 // should also be considered. This case, however, doesn't seem to be
921 // as common as the single point case.
922 pts[0].set(oval.fRight, oval.fTop);
923 return 1;
924 }
925
926 SkVector start, stop;
927
928 start.fY = SkScalarSinCos(SkDegreesToRadians(startAngle), &start.fX);
929 stop.fY = SkScalarSinCos(SkDegreesToRadians(startAngle + sweepAngle),
930 &stop.fX);
931
932 /* If the sweep angle is nearly (but less than) 360, then due to precision
933 loss in radians-conversion and/or sin/cos, we may end up with coincident
934 vectors, which will fool SkBuildQuadArc into doing nothing (bad) instead
935 of drawing a nearly complete circle (good).
936 e.g. canvas.drawArc(0, 359.99, ...)
937 -vs- canvas.drawArc(0, 359.9, ...)
938 We try to detect this edge case, and tweak the stop vector
939 */
940 if (start == stop) {
941 SkScalar sw = SkScalarAbs(sweepAngle);
942 if (sw < SkIntToScalar(360) && sw > SkIntToScalar(359)) {
943 SkScalar stopRad = SkDegreesToRadians(startAngle + sweepAngle);
944 // make a guess at a tiny angle (in radians) to tweak by
945 SkScalar deltaRad = SkScalarCopySign(SK_Scalar1/512, sweepAngle);
946 // not sure how much will be enough, so we use a loop
947 do {
948 stopRad -= deltaRad;
949 stop.fY = SkScalarSinCos(stopRad, &stop.fX);
950 } while (start == stop);
951 }
952 }
953
954 SkMatrix matrix;
955
956 matrix.setScale(SkScalarHalf(oval.width()), SkScalarHalf(oval.height()));
957 matrix.postTranslate(oval.centerX(), oval.centerY());
958
959 return SkBuildQuadArc(start, stop,
960 sweepAngle > 0 ? kCW_SkRotationDirection :
961 kCCW_SkRotationDirection,
962 &matrix, pts);
963 }
964
robertphillips 2013/10/16 14:49:57 Not overjoyed with these parameters.
902 static void add_corner_arc(SkPath* path, const SkRect& rect, 965 static void add_corner_arc(SkPath* path, const SkRect& rect,
903 SkScalar rx, SkScalar ry, int startAngle, 966 SkScalar rx, SkScalar ry, int startAngle,
904 SkPath::Direction dir, bool forceMoveTo) { 967 SkPath::Direction dir, bool addArcTo,
968 bool forceMoveTo = false) {
905 // These two asserts are not sufficient, since really we want to know 969 // These two asserts are not sufficient, since really we want to know
906 // that the pair of radii (e.g. left and right, or top and bottom) sum 970 // that the pair of radii (e.g. left and right, or top and bottom) sum
907 // to <= dimension, but we don't have that data here, so we just have 971 // to <= dimension, but we don't have that data here, so we just have
908 // these conservative asserts. 972 // these conservative asserts.
909 SkASSERT(0 <= rx && rx <= rect.width()); 973 SkASSERT(0 <= rx && rx <= rect.width());
910 SkASSERT(0 <= ry && ry <= rect.height()); 974 SkASSERT(0 <= ry && ry <= rect.height());
911 975
912 SkRect r; 976 SkRect r;
913 r.set(-rx, -ry, rx, ry); 977 r.set(-rx, -ry, rx, ry);
914 978
915 switch (startAngle) { 979 switch (startAngle) {
916 case 0: 980 case 0:
917 r.offset(rect.fRight - r.fRight, rect.fBottom - r.fBottom); 981 r.offset(rect.fRight - r.fRight, rect.fBottom - r.fBottom);
918 break; 982 break;
919 case 90: 983 case 90:
920 r.offset(rect.fLeft - r.fLeft, rect.fBottom - r.fBottom); 984 r.offset(rect.fLeft - r.fLeft, rect.fBottom - r.fBottom);
921 break; 985 break;
922 case 180: r.offset(rect.fLeft - r.fLeft, rect.fTop - r.fTop); break; 986 case 180: r.offset(rect.fLeft - r.fLeft, rect.fTop - r.fTop); break;
923 case 270: r.offset(rect.fRight - r.fRight, rect.fTop - r.fTop); break; 987 case 270: r.offset(rect.fRight - r.fRight, rect.fTop - r.fTop); break;
924 default: SkDEBUGFAIL("unexpected startAngle in add_corner_arc"); 988 default: SkDEBUGFAIL("unexpected startAngle in add_corner_arc");
925 } 989 }
926 990
927 SkScalar start = SkIntToScalar(startAngle); 991 SkScalar start = SkIntToScalar(startAngle);
928 SkScalar sweep = SkIntToScalar(90); 992 SkScalar sweep = SkIntToScalar(90);
929 if (SkPath::kCCW_Direction == dir) { 993 if (SkPath::kCCW_Direction == dir) {
930 start += sweep; 994 start += sweep;
931 sweep = -sweep; 995 sweep = -sweep;
932 } 996 }
933 997
934 path->arcTo(r, start, sweep, forceMoveTo); 998 if (addArcTo) {
999 path->arcTo(r, start, sweep, forceMoveTo);
1000 } else {
robertphillips 2013/10/16 14:49:57 Want to avoid the extra "move" addArc would add.
1001 SkPoint pts[kSkBuildQuadArcStorage];
1002 int count = build_arc_points(r, start, sweep, pts);
1003 for (int i = 1; i < count; i += 2) {
1004 path->quadTo(pts[i], pts[i+1]);
1005 }
1006 }
935 } 1007 }
936 1008
937 void SkPath::addRoundRect(const SkRect& rect, const SkScalar radii[], 1009 void SkPath::addRoundRect(const SkRect& rect, const SkScalar radii[],
938 Direction dir) { 1010 Direction dir) {
939 SkRRect rrect; 1011 SkRRect rrect;
940 rrect.setRectRadii(rect, (const SkVector*) radii); 1012 rrect.setRectRadii(rect, (const SkVector*) radii);
941 this->addRRect(rrect, dir); 1013 this->addRRect(rrect, dir);
942 } 1014 }
943 1015
944 void SkPath::addRRect(const SkRRect& rrect, Direction dir) { 1016 void SkPath::addRRect(const SkRRect& rrect, Direction dir) {
945 assert_known_direction(dir); 1017 assert_known_direction(dir);
946 1018
947 if (rrect.isEmpty()) { 1019 if (rrect.isEmpty()) {
948 return; 1020 return;
949 } 1021 }
950 1022
951 const SkRect& bounds = rrect.getBounds(); 1023 const SkRect& bounds = rrect.getBounds();
952 1024
953 if (rrect.isRect()) { 1025 if (rrect.isRect()) {
954 this->addRect(bounds, dir); 1026 this->addRect(bounds, dir);
955 } else if (rrect.isOval()) { 1027 } else if (rrect.isOval()) {
956 this->addOval(bounds, dir); 1028 this->addOval(bounds, dir);
957 } else if (rrect.isSimple()) { 1029 } else if (rrect.isSimple()) {
958 const SkVector& rad = rrect.getSimpleRadii(); 1030 const SkVector& rad = rrect.getSimpleRadii();
959 this->addRoundRect(bounds, rad.x(), rad.y(), dir); 1031 this->addRoundRect(bounds, rad.x(), rad.y(), dir);
960 } else { 1032 } else {
961 SkAutoPathBoundsUpdate apbu(this, bounds); 1033 SkAutoPathBoundsUpdate apbu(this, bounds);
962 1034
963 if (kCW_Direction == dir) { 1035 if (kCW_Direction == dir) {
964 add_corner_arc(this, bounds, rrect.fRadii[0].fX, rrect.fRadii[0].fY, 180, dir, true); 1036 add_corner_arc(this, bounds, rrect.fRadii[0].fX, rrect.fRadii[0].fY, 180, dir, true, true);
965 add_corner_arc(this, bounds, rrect.fRadii[1].fX, rrect.fRadii[1].fY, 270, dir, false); 1037 add_corner_arc(this, bounds, rrect.fRadii[1].fX, rrect.fRadii[1].fY, 270, dir, true);
966 add_corner_arc(this, bounds, rrect.fRadii[2].fX, rrect.fRadii[2].fY, 0, dir, false); 1038 add_corner_arc(this, bounds, rrect.fRadii[2].fX, rrect.fRadii[2].fY, 0, dir, true);
967 add_corner_arc(this, bounds, rrect.fRadii[3].fX, rrect.fRadii[3].fY, 90, dir, false); 1039 add_corner_arc(this, bounds, rrect.fRadii[3].fX, rrect.fRadii[3].fY, 90, dir, true);
968 } else { 1040 } else {
969 add_corner_arc(this, bounds, rrect.fRadii[0].fX, rrect.fRadii[0].fY, 180, dir, true); 1041 add_corner_arc(this, bounds, rrect.fRadii[0].fX, rrect.fRadii[0].fY, 180, dir, true, true);
970 add_corner_arc(this, bounds, rrect.fRadii[3].fX, rrect.fRadii[3].fY, 90, dir, false); 1042 add_corner_arc(this, bounds, rrect.fRadii[3].fX, rrect.fRadii[3].fY, 90, dir, true);
971 add_corner_arc(this, bounds, rrect.fRadii[2].fX, rrect.fRadii[2].fY, 0, dir, false); 1043 add_corner_arc(this, bounds, rrect.fRadii[2].fX, rrect.fRadii[2].fY, 0, dir, true);
972 add_corner_arc(this, bounds, rrect.fRadii[1].fX, rrect.fRadii[1].fY, 270, dir, false); 1044 add_corner_arc(this, bounds, rrect.fRadii[1].fX, rrect.fRadii[1].fY, 270, dir, true);
973 } 1045 }
974 this->close(); 1046 this->close();
975 } 1047 }
976 } 1048 }
977 1049
978 bool SkPath::hasOnlyMoveTos() const { 1050 bool SkPath::hasOnlyMoveTos() const {
979 int count = fPathRef->countVerbs(); 1051 int count = fPathRef->countVerbs();
980 const uint8_t* verbs = const_cast<const SkPathRef*>(fPathRef.get())->verbsMe mBegin(); 1052 const uint8_t* verbs = const_cast<const SkPathRef*>(fPathRef.get())->verbsMe mBegin();
981 for (int i = 0; i < count; ++i) { 1053 for (int i = 0; i < count; ++i) {
982 if (*verbs == kLine_Verb || 1054 if (*verbs == kLine_Verb ||
983 *verbs == kQuad_Verb || 1055 *verbs == kQuad_Verb ||
984 *verbs == kCubic_Verb) { 1056 *verbs == kCubic_Verb) {
985 return false; 1057 return false;
986 } 1058 }
987 ++verbs; 1059 ++verbs;
988 } 1060 }
989 return true; 1061 return true;
990 } 1062 }
991 1063
992 #define CUBIC_ARC_FACTOR ((SK_ScalarSqrt2 - SK_Scalar1) * 4 / 3)
993
994 void SkPath::addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, 1064 void SkPath::addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
995 Direction dir) { 1065 Direction dir) {
996 assert_known_direction(dir); 1066 assert_known_direction(dir);
997 1067
998 if (rx < 0 || ry < 0) { 1068 if (rx < 0 || ry < 0) {
999 SkErrorInternals::SetError( kInvalidArgument_SkError, 1069 SkErrorInternals::SetError( kInvalidArgument_SkError,
1000 "I got %f and %f as radii to SkPath::AddRoun dRect, " 1070 "I got %f and %f as radii to SkPath::AddRoun dRect, "
1001 "but negative radii are not allowed.", 1071 "but negative radii are not allowed.",
1002 SkScalarToDouble(rx), SkScalarToDouble(ry) ) ; 1072 SkScalarToDouble(rx), SkScalarToDouble(ry) ) ;
1003 return; 1073 return;
(...skipping 20 matching lines...) Expand all
1024 1094
1025 SkAutoPathBoundsUpdate apbu(this, rect); 1095 SkAutoPathBoundsUpdate apbu(this, rect);
1026 SkAutoDisableDirectionCheck(this); 1096 SkAutoDisableDirectionCheck(this);
1027 1097
1028 if (skip_hori) { 1098 if (skip_hori) {
1029 rx = halfW; 1099 rx = halfW;
1030 } else if (skip_vert) { 1100 } else if (skip_vert) {
1031 ry = halfH; 1101 ry = halfH;
1032 } 1102 }
1033 1103
1034 SkScalar sx = SkScalarMul(rx, CUBIC_ARC_FACTOR); 1104 this->incReserve(13);
1035 SkScalar sy = SkScalarMul(ry, CUBIC_ARC_FACTOR);
1036
1037 this->incReserve(17);
1038 this->moveTo(rect.fRight - rx, rect.fTop); 1105 this->moveTo(rect.fRight - rx, rect.fTop);
1039 if (dir == kCCW_Direction) { 1106 if (dir == kCCW_Direction) {
1040 if (!skip_hori) { 1107 if (!skip_hori) {
1041 this->lineTo(rect.fLeft + rx, rect.fTop); // top 1108 this->lineTo(rect.fLeft + rx, rect.fTop); // top
1042 } 1109 }
1043 this->cubicTo(rect.fLeft + rx - sx, rect.fTop, 1110 add_corner_arc(this, rect, rx, ry, 180, dir, false); // top-left
1044 rect.fLeft, rect.fTop + ry - sy,
1045 rect.fLeft, rect.fTop + ry); // top-left
1046 if (!skip_vert) { 1111 if (!skip_vert) {
1047 this->lineTo(rect.fLeft, rect.fBottom - ry); // left 1112 this->lineTo(rect.fLeft, rect.fBottom - ry); // left
1048 } 1113 }
1049 this->cubicTo(rect.fLeft, rect.fBottom - ry + sy, 1114 add_corner_arc(this, rect, rx, ry, 90, dir, false); // bot-left
1050 rect.fLeft + rx - sx, rect.fBottom,
1051 rect.fLeft + rx, rect.fBottom); // bot-left
1052 if (!skip_hori) { 1115 if (!skip_hori) {
1053 this->lineTo(rect.fRight - rx, rect.fBottom); // bottom 1116 this->lineTo(rect.fRight - rx, rect.fBottom); // bottom
1054 } 1117 }
1055 this->cubicTo(rect.fRight - rx + sx, rect.fBottom, 1118 add_corner_arc(this, rect, rx, ry, 0, dir, false); // bot-right
1056 rect.fRight, rect.fBottom - ry + sy,
1057 rect.fRight, rect.fBottom - ry); // bot-right
1058 if (!skip_vert) { 1119 if (!skip_vert) {
1059 this->lineTo(rect.fRight, rect.fTop + ry); 1120 this->lineTo(rect.fRight, rect.fTop + ry); // right
1060 } 1121 }
1061 this->cubicTo(rect.fRight, rect.fTop + ry - sy, 1122 add_corner_arc(this, rect, rx, ry, 270, dir, false); // top-right
1062 rect.fRight - rx + sx, rect.fTop,
1063 rect.fRight - rx, rect.fTop); // top-right
1064 } else { 1123 } else {
1065 this->cubicTo(rect.fRight - rx + sx, rect.fTop, 1124 add_corner_arc(this, rect, rx, ry, 270, dir, false); // top-right
1066 rect.fRight, rect.fTop + ry - sy,
1067 rect.fRight, rect.fTop + ry); // top-right
1068 if (!skip_vert) { 1125 if (!skip_vert) {
1069 this->lineTo(rect.fRight, rect.fBottom - ry); 1126 this->lineTo(rect.fRight, rect.fBottom - ry); // right
1070 } 1127 }
1071 this->cubicTo(rect.fRight, rect.fBottom - ry + sy, 1128 add_corner_arc(this, rect, rx, ry, 0, dir, false); // bot-right
1072 rect.fRight - rx + sx, rect.fBottom,
1073 rect.fRight - rx, rect.fBottom); // bot-right
1074 if (!skip_hori) { 1129 if (!skip_hori) {
1075 this->lineTo(rect.fLeft + rx, rect.fBottom); // bottom 1130 this->lineTo(rect.fLeft + rx, rect.fBottom); // bottom
1076 } 1131 }
1077 this->cubicTo(rect.fLeft + rx - sx, rect.fBottom, 1132 add_corner_arc(this, rect, rx, ry, 90, dir, false); // bot-left
1078 rect.fLeft, rect.fBottom - ry + sy,
1079 rect.fLeft, rect.fBottom - ry); // bot-left
1080 if (!skip_vert) { 1133 if (!skip_vert) {
1081 this->lineTo(rect.fLeft, rect.fTop + ry); // left 1134 this->lineTo(rect.fLeft, rect.fTop + ry); // left
1082 } 1135 }
1083 this->cubicTo(rect.fLeft, rect.fTop + ry - sy, 1136 add_corner_arc(this, rect, rx, ry, 180, dir, false); // top-left
1084 rect.fLeft + rx - sx, rect.fTop,
1085 rect.fLeft + rx, rect.fTop); // top-left
1086 if (!skip_hori) { 1137 if (!skip_hori) {
1087 this->lineTo(rect.fRight - rx, rect.fTop); // top 1138 this->lineTo(rect.fRight - rx, rect.fTop); // top
1088 } 1139 }
1089 } 1140 }
1090 this->close(); 1141 this->close();
1091 } 1142 }
1092 1143
1093 void SkPath::addOval(const SkRect& oval, Direction dir) { 1144 void SkPath::addOval(const SkRect& oval, Direction dir) {
1094 assert_known_direction(dir); 1145 assert_known_direction(dir);
1095 1146
1096 /* If addOval() is called after previous moveTo(), 1147 /* If addOval() is called after previous moveTo(),
1097 this path is still marked as an oval. This is used to 1148 this path is still marked as an oval. This is used to
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1165 } 1216 }
1166 1217
1167 void SkPath::addCircle(SkScalar x, SkScalar y, SkScalar r, Direction dir) { 1218 void SkPath::addCircle(SkScalar x, SkScalar y, SkScalar r, Direction dir) {
1168 if (r > 0) { 1219 if (r > 0) {
1169 SkRect rect; 1220 SkRect rect;
1170 rect.set(x - r, y - r, x + r, y + r); 1221 rect.set(x - r, y - r, x + r, y + r);
1171 this->addOval(rect, dir); 1222 this->addOval(rect, dir);
1172 } 1223 }
1173 } 1224 }
1174 1225
1175 #include "SkGeometry.h"
1176
1177 static int build_arc_points(const SkRect& oval, SkScalar startAngle,
1178 SkScalar sweepAngle,
1179 SkPoint pts[kSkBuildQuadArcStorage]) {
1180
1181 if (0 == sweepAngle &&
1182 (0 == startAngle || SkIntToScalar(360) == startAngle)) {
1183 // Chrome uses this path to move into and out of ovals. If not
1184 // treated as a special case the moves can distort the oval's
1185 // bounding box (and break the circle special case).
1186 pts[0].set(oval.fRight, oval.centerY());
1187 return 1;
1188 } else if (0 == oval.width() && 0 == oval.height()) {
1189 // Chrome will sometimes create 0 radius round rects. Having degenerate
1190 // quad segments in the path prevents the path from being recognized as
1191 // a rect.
1192 // TODO: optimizing the case where only one of width or height is zero
1193 // should also be considered. This case, however, doesn't seem to be
1194 // as common as the single point case.
1195 pts[0].set(oval.fRight, oval.fTop);
1196 return 1;
1197 }
1198
1199 SkVector start, stop;
1200
1201 start.fY = SkScalarSinCos(SkDegreesToRadians(startAngle), &start.fX);
1202 stop.fY = SkScalarSinCos(SkDegreesToRadians(startAngle + sweepAngle),
1203 &stop.fX);
1204
1205 /* If the sweep angle is nearly (but less than) 360, then due to precision
1206 loss in radians-conversion and/or sin/cos, we may end up with coincident
1207 vectors, which will fool SkBuildQuadArc into doing nothing (bad) instead
1208 of drawing a nearly complete circle (good).
1209 e.g. canvas.drawArc(0, 359.99, ...)
1210 -vs- canvas.drawArc(0, 359.9, ...)
1211 We try to detect this edge case, and tweak the stop vector
1212 */
1213 if (start == stop) {
1214 SkScalar sw = SkScalarAbs(sweepAngle);
1215 if (sw < SkIntToScalar(360) && sw > SkIntToScalar(359)) {
1216 SkScalar stopRad = SkDegreesToRadians(startAngle + sweepAngle);
1217 // make a guess at a tiny angle (in radians) to tweak by
1218 SkScalar deltaRad = SkScalarCopySign(SK_Scalar1/512, sweepAngle);
1219 // not sure how much will be enough, so we use a loop
1220 do {
1221 stopRad -= deltaRad;
1222 stop.fY = SkScalarSinCos(stopRad, &stop.fX);
1223 } while (start == stop);
1224 }
1225 }
1226
1227 SkMatrix matrix;
1228
1229 matrix.setScale(SkScalarHalf(oval.width()), SkScalarHalf(oval.height()));
1230 matrix.postTranslate(oval.centerX(), oval.centerY());
1231
1232 return SkBuildQuadArc(start, stop,
1233 sweepAngle > 0 ? kCW_SkRotationDirection :
1234 kCCW_SkRotationDirection,
1235 &matrix, pts);
1236 }
1237
1238 void SkPath::arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, 1226 void SkPath::arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
1239 bool forceMoveTo) { 1227 bool forceMoveTo) {
1240 if (oval.width() < 0 || oval.height() < 0) { 1228 if (oval.width() < 0 || oval.height() < 0) {
1241 return; 1229 return;
1242 } 1230 }
1243 1231
1244 SkPoint pts[kSkBuildQuadArcStorage]; 1232 SkPoint pts[kSkBuildQuadArcStorage];
1245 int count = build_arc_points(oval, startAngle, sweepAngle, pts); 1233 int count = build_arc_points(oval, startAngle, sweepAngle, pts);
1246 SkASSERT((count & 1) == 1); 1234 SkASSERT((count & 1) == 1);
1247 1235
1248 if (fPathRef->countVerbs() == 0) { 1236 if (fPathRef->countVerbs() == 0) {
1249 forceMoveTo = true; 1237 forceMoveTo = true;
1250 } 1238 }
1251 this->incReserve(count); 1239 this->incReserve(count);
1252 forceMoveTo ? this->moveTo(pts[0]) : this->lineTo(pts[0]); 1240 forceMoveTo ? this->moveTo(pts[0]) : this->lineTo(pts[0]);
1253 for (int i = 1; i < count; i += 2) { 1241 for (int i = 1; i < count; i += 2) {
1254 this->quadTo(pts[i], pts[i+1]); 1242 this->quadTo(pts[i], pts[i+1]);
1255 } 1243 }
1256 } 1244 }
1257 1245
1258 void SkPath::addArc(const SkRect& oval, SkScalar startAngle, 1246 void SkPath::addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle ) {
1259 SkScalar sweepAngle) {
1260 if (oval.isEmpty() || 0 == sweepAngle) { 1247 if (oval.isEmpty() || 0 == sweepAngle) {
1261 return; 1248 return;
1262 } 1249 }
1263 1250
1264 const SkScalar kFullCircleAngle = SkIntToScalar(360); 1251 const SkScalar kFullCircleAngle = SkIntToScalar(360);
1265 1252
1266 if (sweepAngle >= kFullCircleAngle || sweepAngle <= -kFullCircleAngle) { 1253 if (sweepAngle >= kFullCircleAngle || sweepAngle <= -kFullCircleAngle) {
1267 this->addOval(oval, sweepAngle > 0 ? kCW_Direction : kCCW_Direction); 1254 this->addOval(oval, sweepAngle > 0 ? kCW_Direction : kCCW_Direction);
1268 return; 1255 return;
1269 } 1256 }
(...skipping 1660 matching lines...) Expand 10 before | Expand all | Expand 10 after
2930 switch (this->getFillType()) { 2917 switch (this->getFillType()) {
2931 case SkPath::kEvenOdd_FillType: 2918 case SkPath::kEvenOdd_FillType:
2932 case SkPath::kInverseEvenOdd_FillType: 2919 case SkPath::kInverseEvenOdd_FillType:
2933 w &= 1; 2920 w &= 1;
2934 break; 2921 break;
2935 default: 2922 default:
2936 break; 2923 break;
2937 } 2924 }
2938 return SkToBool(w); 2925 return SkToBool(w);
2939 } 2926 }
OLDNEW
« no previous file with comments | « no previous file | src/core/SkPathRef.cpp » ('j') | src/core/SkPathRef.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698