OLD | NEW |
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 1071 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1082 if (rrect.isEmpty()) { | 1082 if (rrect.isEmpty()) { |
1083 return; | 1083 return; |
1084 } | 1084 } |
1085 | 1085 |
1086 const SkRect& bounds = rrect.getBounds(); | 1086 const SkRect& bounds = rrect.getBounds(); |
1087 | 1087 |
1088 if (rrect.isRect()) { | 1088 if (rrect.isRect()) { |
1089 this->addRect(bounds, dir); | 1089 this->addRect(bounds, dir); |
1090 } else if (rrect.isOval()) { | 1090 } else if (rrect.isOval()) { |
1091 this->addOval(bounds, dir); | 1091 this->addOval(bounds, dir); |
1092 #ifdef SK_IGNORE_QUAD_RR_CORNERS_OPT | |
1093 } else if (rrect.isSimple()) { | |
1094 const SkVector& rad = rrect.getSimpleRadii(); | |
1095 this->addRoundRect(bounds, rad.x(), rad.y(), dir); | |
1096 #endif | |
1097 } else { | 1092 } else { |
1098 fDirection = this->hasOnlyMoveTos() ? dir : kUnknown_Direction; | 1093 fDirection = this->hasOnlyMoveTos() ? dir : kUnknown_Direction; |
1099 | 1094 |
1100 SkAutoPathBoundsUpdate apbu(this, bounds); | 1095 SkAutoPathBoundsUpdate apbu(this, bounds); |
1101 SkAutoDisableDirectionCheck addc(this); | 1096 SkAutoDisableDirectionCheck addc(this); |
1102 | 1097 |
1103 this->incReserve(21); | 1098 this->incReserve(21); |
1104 if (kCW_Direction == dir) { | 1099 if (kCW_Direction == dir) { |
1105 this->moveTo(bounds.fLeft, | 1100 this->moveTo(bounds.fLeft, |
1106 bounds.fBottom - rrect.fRadii[SkRRect::kLowerLeft_Corne
r].fY); | 1101 bounds.fBottom - rrect.fRadii[SkRRect::kLowerLeft_Corne
r].fY); |
(...skipping 21 matching lines...) Expand all Loading... |
1128 *verbs == kQuad_Verb || | 1123 *verbs == kQuad_Verb || |
1129 *verbs == kConic_Verb || | 1124 *verbs == kConic_Verb || |
1130 *verbs == kCubic_Verb) { | 1125 *verbs == kCubic_Verb) { |
1131 return false; | 1126 return false; |
1132 } | 1127 } |
1133 ++verbs; | 1128 ++verbs; |
1134 } | 1129 } |
1135 return true; | 1130 return true; |
1136 } | 1131 } |
1137 | 1132 |
1138 #ifdef SK_IGNORE_QUAD_RR_CORNERS_OPT | |
1139 #define CUBIC_ARC_FACTOR ((SK_ScalarSqrt2 - SK_Scalar1) * 4 / 3) | |
1140 #endif | |
1141 | |
1142 void SkPath::addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, | 1133 void SkPath::addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, |
1143 Direction dir) { | 1134 Direction dir) { |
1144 assert_known_direction(dir); | 1135 assert_known_direction(dir); |
1145 | 1136 |
1146 if (rx < 0 || ry < 0) { | 1137 if (rx < 0 || ry < 0) { |
1147 SkErrorInternals::SetError( kInvalidArgument_SkError, | 1138 SkErrorInternals::SetError( kInvalidArgument_SkError, |
1148 "I got %f and %f as radii to SkPath::AddRoun
dRect, " | 1139 "I got %f and %f as radii to SkPath::AddRoun
dRect, " |
1149 "but negative radii are not allowed.", | 1140 "but negative radii are not allowed.", |
1150 SkScalarToDouble(rx), SkScalarToDouble(ry) )
; | 1141 SkScalarToDouble(rx), SkScalarToDouble(ry) )
; |
1151 return; | 1142 return; |
1152 } | 1143 } |
1153 | 1144 |
1154 #ifdef SK_IGNORE_QUAD_RR_CORNERS_OPT | |
1155 SkScalar w = rect.width(); | |
1156 SkScalar halfW = SkScalarHalf(w); | |
1157 SkScalar h = rect.height(); | |
1158 SkScalar halfH = SkScalarHalf(h); | |
1159 | |
1160 if (halfW <= 0 || halfH <= 0) { | |
1161 return; | |
1162 } | |
1163 | |
1164 bool skip_hori = rx >= halfW; | |
1165 bool skip_vert = ry >= halfH; | |
1166 | |
1167 if (skip_hori && skip_vert) { | |
1168 this->addOval(rect, dir); | |
1169 return; | |
1170 } | |
1171 | |
1172 fDirection = this->hasOnlyMoveTos() ? dir : kUnknown_Direction; | |
1173 | |
1174 SkAutoPathBoundsUpdate apbu(this, rect); | |
1175 SkAutoDisableDirectionCheck addc(this); | |
1176 | |
1177 if (skip_hori) { | |
1178 rx = halfW; | |
1179 } else if (skip_vert) { | |
1180 ry = halfH; | |
1181 } | |
1182 SkScalar sx = SkScalarMul(rx, CUBIC_ARC_FACTOR); | |
1183 SkScalar sy = SkScalarMul(ry, CUBIC_ARC_FACTOR); | |
1184 | |
1185 this->incReserve(17); | |
1186 this->moveTo(rect.fRight - rx, rect.fTop); // top-right | |
1187 if (dir == kCCW_Direction) { | |
1188 if (!skip_hori) { | |
1189 this->lineTo(rect.fLeft + rx, rect.fTop); // top | |
1190 } | |
1191 this->cubicTo(rect.fLeft + rx - sx, rect.fTop, | |
1192 rect.fLeft, rect.fTop + ry - sy, | |
1193 rect.fLeft, rect.fTop + ry); // top-left | |
1194 if (!skip_vert) { | |
1195 this->lineTo(rect.fLeft, rect.fBottom - ry); // left | |
1196 } | |
1197 this->cubicTo(rect.fLeft, rect.fBottom - ry + sy, | |
1198 rect.fLeft + rx - sx, rect.fBottom, | |
1199 rect.fLeft + rx, rect.fBottom); // bot-left | |
1200 if (!skip_hori) { | |
1201 this->lineTo(rect.fRight - rx, rect.fBottom); // bottom | |
1202 } | |
1203 this->cubicTo(rect.fRight - rx + sx, rect.fBottom, | |
1204 rect.fRight, rect.fBottom - ry + sy, | |
1205 rect.fRight, rect.fBottom - ry); // bot-right | |
1206 if (!skip_vert) { | |
1207 this->lineTo(rect.fRight, rect.fTop + ry); // right | |
1208 } | |
1209 this->cubicTo(rect.fRight, rect.fTop + ry - sy, | |
1210 rect.fRight - rx + sx, rect.fTop, | |
1211 rect.fRight - rx, rect.fTop); // top-right | |
1212 } else { | |
1213 this->cubicTo(rect.fRight - rx + sx, rect.fTop, | |
1214 rect.fRight, rect.fTop + ry - sy, | |
1215 rect.fRight, rect.fTop + ry); // top-right | |
1216 if (!skip_vert) { | |
1217 this->lineTo(rect.fRight, rect.fBottom - ry); // right | |
1218 } | |
1219 this->cubicTo(rect.fRight, rect.fBottom - ry + sy, | |
1220 rect.fRight - rx + sx, rect.fBottom, | |
1221 rect.fRight - rx, rect.fBottom); // bot-right | |
1222 if (!skip_hori) { | |
1223 this->lineTo(rect.fLeft + rx, rect.fBottom); // bottom | |
1224 } | |
1225 this->cubicTo(rect.fLeft + rx - sx, rect.fBottom, | |
1226 rect.fLeft, rect.fBottom - ry + sy, | |
1227 rect.fLeft, rect.fBottom - ry); // bot-left | |
1228 if (!skip_vert) { | |
1229 this->lineTo(rect.fLeft, rect.fTop + ry); // left | |
1230 } | |
1231 this->cubicTo(rect.fLeft, rect.fTop + ry - sy, | |
1232 rect.fLeft + rx - sx, rect.fTop, | |
1233 rect.fLeft + rx, rect.fTop); // top-left | |
1234 if (!skip_hori) { | |
1235 this->lineTo(rect.fRight - rx, rect.fTop); // top | |
1236 } | |
1237 } | |
1238 this->close(); | |
1239 #else | |
1240 SkRRect rrect; | 1145 SkRRect rrect; |
1241 rrect.setRectXY(rect, rx, ry); | 1146 rrect.setRectXY(rect, rx, ry); |
1242 this->addRRect(rrect, dir); | 1147 this->addRRect(rrect, dir); |
1243 #endif | |
1244 } | 1148 } |
1245 | 1149 |
1246 void SkPath::addOval(const SkRect& oval, Direction dir) { | 1150 void SkPath::addOval(const SkRect& oval, Direction dir) { |
1247 assert_known_direction(dir); | 1151 assert_known_direction(dir); |
1248 | 1152 |
1249 /* If addOval() is called after previous moveTo(), | 1153 /* If addOval() is called after previous moveTo(), |
1250 this path is still marked as an oval. This is used to | 1154 this path is still marked as an oval. This is used to |
1251 fit into WebKit's calling sequences. | 1155 fit into WebKit's calling sequences. |
1252 We can't simply check isEmpty() in this case, as additional | 1156 We can't simply check isEmpty() in this case, as additional |
1253 moveTo() would mark the path non empty. | 1157 moveTo() would mark the path non empty. |
(...skipping 1634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2888 switch (this->getFillType()) { | 2792 switch (this->getFillType()) { |
2889 case SkPath::kEvenOdd_FillType: | 2793 case SkPath::kEvenOdd_FillType: |
2890 case SkPath::kInverseEvenOdd_FillType: | 2794 case SkPath::kInverseEvenOdd_FillType: |
2891 w &= 1; | 2795 w &= 1; |
2892 break; | 2796 break; |
2893 default: | 2797 default: |
2894 break; | 2798 break; |
2895 } | 2799 } |
2896 return SkToBool(w); | 2800 return SkToBool(w); |
2897 } | 2801 } |
OLD | NEW |