| 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 957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 968 } | 968 } |
| 969 #endif | 969 #endif |
| 970 | 970 |
| 971 void SkPath::addRoundRect(const SkRect& rect, const SkScalar radii[], | 971 void SkPath::addRoundRect(const SkRect& rect, const SkScalar radii[], |
| 972 Direction dir) { | 972 Direction dir) { |
| 973 SkRRect rrect; | 973 SkRRect rrect; |
| 974 rrect.setRectRadii(rect, (const SkVector*) radii); | 974 rrect.setRectRadii(rect, (const SkVector*) radii); |
| 975 this->addRRect(rrect, dir); | 975 this->addRRect(rrect, dir); |
| 976 } | 976 } |
| 977 | 977 |
| 978 #ifdef SK_SUPPORT_LEGACY_ADDRRECT | |
| 979 /* The inline clockwise and counterclockwise round rect quad approximations | |
| 980 make it easier to see the symmetry patterns used by add corner quads. | |
| 981 Clockwise corner value | |
| 982 path->lineTo(rect.fLeft, rect.fTop + ry); 0 upper left | |
| 983 path->quadTo(rect.fLeft, rect.fTop + offPtY, | |
| 984 rect.fLeft + midPtX, rect.fTop + midPtY); | |
| 985 path->quadTo(rect.fLeft + offPtX, rect.fTop, | |
| 986 rect.fLeft + rx, rect.fTop); | |
| 987 | |
| 988 path->lineTo(rect.fRight - rx, rect.fTop); 1 upper right | |
| 989 path->quadTo(rect.fRight - offPtX, rect.fTop, | |
| 990 rect.fRight - midPtX, rect.fTop + midPtY); | |
| 991 path->quadTo(rect.fRight, rect.fTop + offPtY, | |
| 992 rect.fRight, rect.fTop + ry); | |
| 993 | |
| 994 path->lineTo(rect.fRight, rect.fBottom - ry); 2 lower right | |
| 995 path->quadTo(rect.fRight, rect.fBottom - offPtY, | |
| 996 rect.fRight - midPtX, rect.fBottom - midPtY); | |
| 997 path->quadTo(rect.fRight - offPtX, rect.fBottom, | |
| 998 rect.fRight - rx, rect.fBottom); | |
| 999 | |
| 1000 path->lineTo(rect.fLeft + rx, rect.fBottom); 3 lower left | |
| 1001 path->quadTo(rect.fLeft + offPtX, rect.fBottom, | |
| 1002 rect.fLeft + midPtX, rect.fBottom - midPtY); | |
| 1003 path->quadTo(rect.fLeft, rect.fBottom - offPtY, | |
| 1004 rect.fLeft, rect.fBottom - ry); | |
| 1005 | |
| 1006 Counterclockwise | |
| 1007 path->lineTo(rect.fLeft, rect.fBottom - ry); 3 lower left | |
| 1008 path->quadTo(rect.fLeft, rect.fBottom - offPtY, | |
| 1009 rect.fLeft + midPtX, rect.fBottom - midPtY); | |
| 1010 path->quadTo(rect.fLeft + offPtX, rect.fBottom, | |
| 1011 rect.fLeft + rx, rect.fBottom); | |
| 1012 | |
| 1013 path->lineTo(rect.fRight - rx, rect.fBottom); 2 lower right | |
| 1014 path->quadTo(rect.fRight - offPtX, rect.fBottom, | |
| 1015 rect.fRight - midPtX, rect.fBottom - midPtY); | |
| 1016 path->quadTo(rect.fRight, rect.fBottom - offPtY, | |
| 1017 rect.fRight, rect.fBottom - ry); | |
| 1018 | |
| 1019 path->lineTo(rect.fRight, rect.fTop + ry); 1 upper right | |
| 1020 path->quadTo(rect.fRight, rect.fTop + offPtY, | |
| 1021 rect.fRight - midPtX, rect.fTop + midPtY); | |
| 1022 path->quadTo(rect.fRight - offPtX, rect.fTop, | |
| 1023 rect.fRight - rx, rect.fTop); | |
| 1024 | |
| 1025 path->lineTo(rect.fLeft + rx, rect.fTop); 0 upper left | |
| 1026 path->quadTo(rect.fLeft + offPtX, rect.fTop, | |
| 1027 rect.fLeft + midPtX, rect.fTop + midPtY); | |
| 1028 path->quadTo(rect.fLeft, rect.fTop + offPtY, | |
| 1029 rect.fLeft, rect.fTop + ry); | |
| 1030 */ | |
| 1031 static void add_corner_quads(SkPath* path, const SkRRect& rrect, | |
| 1032 SkRRect::Corner corner, SkPath::Direction dir) { | |
| 1033 const SkRect& rect = rrect.rect(); | |
| 1034 const SkVector& radii = rrect.radii(corner); | |
| 1035 SkScalar rx = radii.fX; | |
| 1036 SkScalar ry = radii.fY; | |
| 1037 // The mid point of the quadratic arc approximation is half way between the
two | |
| 1038 // control points. | |
| 1039 const SkScalar mid = 1 - (SK_Scalar1 + SK_ScalarTanPIOver8) / 2; | |
| 1040 SkScalar midPtX = rx * mid; | |
| 1041 SkScalar midPtY = ry * mid; | |
| 1042 const SkScalar control = 1 - SK_ScalarTanPIOver8; | |
| 1043 SkScalar offPtX = rx * control; | |
| 1044 SkScalar offPtY = ry * control; | |
| 1045 static const int kCornerPts = 5; | |
| 1046 SkScalar xOff[kCornerPts]; | |
| 1047 SkScalar yOff[kCornerPts]; | |
| 1048 | |
| 1049 if ((corner & 1) == (dir == SkPath::kCCW_Direction)) { // corners always al
ternate direction | |
| 1050 SkASSERT(dir == SkPath::kCCW_Direction | |
| 1051 ? corner == SkRRect::kLowerLeft_Corner || corner == SkRRect::kUpper
Right_Corner | |
| 1052 : corner == SkRRect::kUpperLeft_Corner || corner == SkRRect::kLower
Right_Corner); | |
| 1053 xOff[0] = xOff[1] = 0; | |
| 1054 xOff[2] = midPtX; | |
| 1055 xOff[3] = offPtX; | |
| 1056 xOff[4] = rx; | |
| 1057 yOff[0] = ry; | |
| 1058 yOff[1] = offPtY; | |
| 1059 yOff[2] = midPtY; | |
| 1060 yOff[3] = yOff[4] = 0; | |
| 1061 } else { | |
| 1062 xOff[0] = rx; | |
| 1063 xOff[1] = offPtX; | |
| 1064 xOff[2] = midPtX; | |
| 1065 xOff[3] = xOff[4] = 0; | |
| 1066 yOff[0] = yOff[1] = 0; | |
| 1067 yOff[2] = midPtY; | |
| 1068 yOff[3] = offPtY; | |
| 1069 yOff[4] = ry; | |
| 1070 } | |
| 1071 if ((corner - 1) & 2) { | |
| 1072 SkASSERT(corner == SkRRect::kLowerLeft_Corner || corner == SkRRect::kUpp
erLeft_Corner); | |
| 1073 for (int i = 0; i < kCornerPts; ++i) { | |
| 1074 xOff[i] = rect.fLeft + xOff[i]; | |
| 1075 } | |
| 1076 } else { | |
| 1077 SkASSERT(corner == SkRRect::kLowerRight_Corner || corner == SkRRect::kUp
perRight_Corner); | |
| 1078 for (int i = 0; i < kCornerPts; ++i) { | |
| 1079 xOff[i] = rect.fRight - xOff[i]; | |
| 1080 } | |
| 1081 } | |
| 1082 if (corner < SkRRect::kLowerRight_Corner) { | |
| 1083 for (int i = 0; i < kCornerPts; ++i) { | |
| 1084 yOff[i] = rect.fTop + yOff[i]; | |
| 1085 } | |
| 1086 } else { | |
| 1087 for (int i = 0; i < kCornerPts; ++i) { | |
| 1088 yOff[i] = rect.fBottom - yOff[i]; | |
| 1089 } | |
| 1090 } | |
| 1091 | |
| 1092 SkPoint lastPt; | |
| 1093 SkAssertResult(path->getLastPt(&lastPt)); | |
| 1094 if (lastPt.fX != xOff[0] || lastPt.fY != yOff[0]) { | |
| 1095 path->lineTo(xOff[0], yOff[0]); | |
| 1096 } | |
| 1097 if (rx || ry) { | |
| 1098 path->quadTo(xOff[1], yOff[1], xOff[2], yOff[2]); | |
| 1099 path->quadTo(xOff[3], yOff[3], xOff[4], yOff[4]); | |
| 1100 } else { | |
| 1101 path->lineTo(xOff[2], yOff[2]); | |
| 1102 path->lineTo(xOff[4], yOff[4]); | |
| 1103 } | |
| 1104 } | |
| 1105 #endif | |
| 1106 | |
| 1107 void SkPath::addRRect(const SkRRect& rrect, Direction dir) { | 978 void SkPath::addRRect(const SkRRect& rrect, Direction dir) { |
| 1108 assert_known_direction(dir); | 979 assert_known_direction(dir); |
| 1109 | 980 |
| 1110 if (rrect.isEmpty()) { | 981 if (rrect.isEmpty()) { |
| 1111 return; | 982 return; |
| 1112 } | 983 } |
| 1113 | 984 |
| 1114 const SkRect& bounds = rrect.getBounds(); | 985 const SkRect& bounds = rrect.getBounds(); |
| 1115 | 986 |
| 1116 if (rrect.isRect()) { | 987 if (rrect.isRect()) { |
| 1117 this->addRect(bounds, dir); | 988 this->addRect(bounds, dir); |
| 1118 } else if (rrect.isOval()) { | 989 } else if (rrect.isOval()) { |
| 1119 this->addOval(bounds, dir); | 990 this->addOval(bounds, dir); |
| 1120 } else { | 991 } else { |
| 1121 fDirection = this->hasOnlyMoveTos() ? dir : kUnknown_Direction; | 992 fDirection = this->hasOnlyMoveTos() ? dir : kUnknown_Direction; |
| 1122 | 993 |
| 1123 SkAutoPathBoundsUpdate apbu(this, bounds); | 994 SkAutoPathBoundsUpdate apbu(this, bounds); |
| 1124 SkAutoDisableDirectionCheck addc(this); | 995 SkAutoDisableDirectionCheck addc(this); |
| 1125 | 996 |
| 1126 #ifdef SK_SUPPORT_LEGACY_ADDRRECT | |
| 1127 this->incReserve(21); | |
| 1128 if (kCW_Direction == dir) { | |
| 1129 this->moveTo(bounds.fLeft, | |
| 1130 bounds.fBottom - rrect.fRadii[SkRRect::kLowerLeft_Corne
r].fY); | |
| 1131 add_corner_quads(this, rrect, SkRRect::kUpperLeft_Corner, dir); | |
| 1132 add_corner_quads(this, rrect, SkRRect::kUpperRight_Corner, dir); | |
| 1133 add_corner_quads(this, rrect, SkRRect::kLowerRight_Corner, dir); | |
| 1134 add_corner_quads(this, rrect, SkRRect::kLowerLeft_Corner, dir); | |
| 1135 } else { | |
| 1136 this->moveTo(bounds.fLeft, | |
| 1137 bounds.fTop + rrect.fRadii[SkRRect::kUpperLeft_Corner].
fY); | |
| 1138 add_corner_quads(this, rrect, SkRRect::kLowerLeft_Corner, dir); | |
| 1139 add_corner_quads(this, rrect, SkRRect::kLowerRight_Corner, dir); | |
| 1140 add_corner_quads(this, rrect, SkRRect::kUpperRight_Corner, dir); | |
| 1141 add_corner_quads(this, rrect, SkRRect::kUpperLeft_Corner, dir); | |
| 1142 } | |
| 1143 #else | |
| 1144 const SkScalar L = bounds.fLeft; | 997 const SkScalar L = bounds.fLeft; |
| 1145 const SkScalar T = bounds.fTop; | 998 const SkScalar T = bounds.fTop; |
| 1146 const SkScalar R = bounds.fRight; | 999 const SkScalar R = bounds.fRight; |
| 1147 const SkScalar B = bounds.fBottom; | 1000 const SkScalar B = bounds.fBottom; |
| 1148 const SkScalar W = SK_ScalarRoot2Over2; | 1001 const SkScalar W = SK_ScalarRoot2Over2; |
| 1149 | 1002 |
| 1150 this->incReserve(13); | 1003 this->incReserve(13); |
| 1151 if (kCW_Direction == dir) { | 1004 if (kCW_Direction == dir) { |
| 1152 this->moveTo(L, B - rrect.fRadii[SkRRect::kLowerLeft_Corner].fY); | 1005 this->moveTo(L, B - rrect.fRadii[SkRRect::kLowerLeft_Corner].fY); |
| 1153 | 1006 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1170 | 1023 |
| 1171 this->lineTo(R - rrect.fRadii[SkRRect::kLowerRight_Corner].fX, B); | 1024 this->lineTo(R - rrect.fRadii[SkRRect::kLowerRight_Corner].fX, B); |
| 1172 this->conicTo(R, B, R, B - rrect.fRadii[SkRRect::kLowerRight_Corner]
.fY, W); | 1025 this->conicTo(R, B, R, B - rrect.fRadii[SkRRect::kLowerRight_Corner]
.fY, W); |
| 1173 | 1026 |
| 1174 this->lineTo(R, T + rrect.fRadii[SkRRect::kUpperRight_Corner].fY); | 1027 this->lineTo(R, T + rrect.fRadii[SkRRect::kUpperRight_Corner].fY); |
| 1175 this->conicTo(R, T, R - rrect.fRadii[SkRRect::kUpperRight_Corner].fX
, T, W); | 1028 this->conicTo(R, T, R - rrect.fRadii[SkRRect::kUpperRight_Corner].fX
, T, W); |
| 1176 | 1029 |
| 1177 this->lineTo(L + rrect.fRadii[SkRRect::kUpperLeft_Corner].fX, T); | 1030 this->lineTo(L + rrect.fRadii[SkRRect::kUpperLeft_Corner].fX, T); |
| 1178 this->conicTo(L, T, L, T + rrect.fRadii[SkRRect::kUpperLeft_Corner].
fY, W); | 1031 this->conicTo(L, T, L, T + rrect.fRadii[SkRRect::kUpperLeft_Corner].
fY, W); |
| 1179 } | 1032 } |
| 1180 #endif | |
| 1181 this->close(); | 1033 this->close(); |
| 1182 } | 1034 } |
| 1183 SkDEBUGCODE(fPathRef->validate();) | 1035 SkDEBUGCODE(fPathRef->validate();) |
| 1184 } | 1036 } |
| 1185 | 1037 |
| 1186 bool SkPath::hasOnlyMoveTos() const { | 1038 bool SkPath::hasOnlyMoveTos() const { |
| 1187 int count = fPathRef->countVerbs(); | 1039 int count = fPathRef->countVerbs(); |
| 1188 const uint8_t* verbs = const_cast<const SkPathRef*>(fPathRef.get())->verbsMe
mBegin(); | 1040 const uint8_t* verbs = const_cast<const SkPathRef*>(fPathRef.get())->verbsMe
mBegin(); |
| 1189 for (int i = 0; i < count; ++i) { | 1041 for (int i = 0; i < count; ++i) { |
| 1190 if (*verbs == kLine_Verb || | 1042 if (*verbs == kLine_Verb || |
| (...skipping 1754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2945 switch (this->getFillType()) { | 2797 switch (this->getFillType()) { |
| 2946 case SkPath::kEvenOdd_FillType: | 2798 case SkPath::kEvenOdd_FillType: |
| 2947 case SkPath::kInverseEvenOdd_FillType: | 2799 case SkPath::kInverseEvenOdd_FillType: |
| 2948 w &= 1; | 2800 w &= 1; |
| 2949 break; | 2801 break; |
| 2950 default: | 2802 default: |
| 2951 break; | 2803 break; |
| 2952 } | 2804 } |
| 2953 return SkToBool(w); | 2805 return SkToBool(w); |
| 2954 } | 2806 } |
| OLD | NEW |