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 2114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2125 } | 2125 } |
2126 #endif // SK_DEBUG_PATH | 2126 #endif // SK_DEBUG_PATH |
2127 } | 2127 } |
2128 #endif // SK_DEBUG | 2128 #endif // SK_DEBUG |
2129 | 2129 |
2130 /////////////////////////////////////////////////////////////////////////////// | 2130 /////////////////////////////////////////////////////////////////////////////// |
2131 | 2131 |
2132 static int sign(SkScalar x) { return x < 0; } | 2132 static int sign(SkScalar x) { return x < 0; } |
2133 #define kValueNeverReturnedBySign 2 | 2133 #define kValueNeverReturnedBySign 2 |
2134 | 2134 |
| 2135 enum DirChange { |
| 2136 kLeft_DirChange, |
| 2137 kRight_DirChange, |
| 2138 kStraight_DirChange, |
| 2139 kBackwards_DirChange, |
| 2140 |
| 2141 kInvalid_DirChange |
| 2142 }; |
| 2143 |
| 2144 |
2135 static bool almost_equal(SkScalar compA, SkScalar compB) { | 2145 static bool almost_equal(SkScalar compA, SkScalar compB) { |
2136 // The error epsilon was empirically derived; worse case round rects | 2146 // The error epsilon was empirically derived; worse case round rects |
2137 // with a mid point outset by 2x float epsilon in tests had an error | 2147 // with a mid point outset by 2x float epsilon in tests had an error |
2138 // of 12. | 2148 // of 12. |
2139 const int epsilon = 16; | 2149 const int epsilon = 16; |
2140 if (!SkScalarIsFinite(compA) || !SkScalarIsFinite(compB)) { | 2150 if (!SkScalarIsFinite(compA) || !SkScalarIsFinite(compB)) { |
2141 return false; | 2151 return false; |
2142 } | 2152 } |
2143 // no need to check for small numbers because SkPath::Iter has removed degen
erate values | 2153 // no need to check for small numbers because SkPath::Iter has removed degen
erate values |
2144 int aBits = SkFloatAs2sCompliment(compA); | 2154 int aBits = SkFloatAs2sCompliment(compA); |
2145 int bBits = SkFloatAs2sCompliment(compB); | 2155 int bBits = SkFloatAs2sCompliment(compB); |
2146 return aBits < bBits + epsilon && bBits < aBits + epsilon; | 2156 return aBits < bBits + epsilon && bBits < aBits + epsilon; |
2147 } | 2157 } |
2148 | 2158 |
| 2159 static DirChange direction_change(const SkPoint& lastPt, const SkVector& curPt, |
| 2160 const SkVector& lastVec, const SkVector& curVe
c) { |
| 2161 SkScalar cross = SkPoint::CrossProduct(lastVec, curVec); |
| 2162 |
| 2163 SkScalar smallest = SkTMin(curPt.fX, SkTMin(curPt.fY, SkTMin(lastPt.fX, last
Pt.fY))); |
| 2164 SkScalar largest = SkTMax(curPt.fX, SkTMax(curPt.fY, SkTMax(lastPt.fX, lastP
t.fY))); |
| 2165 largest = SkTMax(largest, -smallest); |
| 2166 |
| 2167 if (!almost_equal(largest, largest + cross)) { |
| 2168 int sign = SkScalarSignAsInt(cross); |
| 2169 if (sign) { |
| 2170 return (1 == sign) ? kRight_DirChange : kLeft_DirChange; |
| 2171 } |
| 2172 } |
| 2173 |
| 2174 if (!SkScalarNearlyZero(lastVec.lengthSqd(), SK_ScalarNearlyZero*SK_ScalarNe
arlyZero) && |
| 2175 !SkScalarNearlyZero(curVec.lengthSqd(), SK_ScalarNearlyZero*SK_ScalarNea
rlyZero) && |
| 2176 lastVec.dot(curVec) < 0.0f) { |
| 2177 return kBackwards_DirChange; |
| 2178 } |
| 2179 |
| 2180 return kStraight_DirChange; |
| 2181 } |
| 2182 |
2149 // only valid for a single contour | 2183 // only valid for a single contour |
2150 struct Convexicator { | 2184 struct Convexicator { |
2151 Convexicator() | 2185 Convexicator() |
2152 : fPtCount(0) | 2186 : fPtCount(0) |
2153 , fConvexity(SkPath::kConvex_Convexity) | 2187 , fConvexity(SkPath::kConvex_Convexity) |
2154 , fDirection(SkPath::kUnknown_Direction) { | 2188 , fDirection(SkPath::kUnknown_Direction) { |
2155 fSign = 0; | 2189 fExpectedDir = kInvalid_DirChange; |
2156 // warnings | 2190 // warnings |
2157 fLastPt.set(0, 0); | 2191 fLastPt.set(0, 0); |
2158 fCurrPt.set(0, 0); | 2192 fCurrPt.set(0, 0); |
2159 fLastVec.set(0, 0); | 2193 fLastVec.set(0, 0); |
2160 fFirstVec.set(0, 0); | 2194 fFirstVec.set(0, 0); |
2161 | 2195 |
2162 fDx = fDy = 0; | 2196 fDx = fDy = 0; |
2163 fSx = fSy = kValueNeverReturnedBySign; | 2197 fSx = fSy = kValueNeverReturnedBySign; |
2164 } | 2198 } |
2165 | 2199 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2204 | 2238 |
2205 void close() { | 2239 void close() { |
2206 if (fPtCount > 2) { | 2240 if (fPtCount > 2) { |
2207 this->addVec(fFirstVec); | 2241 this->addVec(fFirstVec); |
2208 } | 2242 } |
2209 } | 2243 } |
2210 | 2244 |
2211 private: | 2245 private: |
2212 void addVec(const SkVector& vec) { | 2246 void addVec(const SkVector& vec) { |
2213 SkASSERT(vec.fX || vec.fY); | 2247 SkASSERT(vec.fX || vec.fY); |
2214 SkScalar cross = SkPoint::CrossProduct(fLastVec, vec); | 2248 DirChange dir = direction_change(fLastPt, fCurrPt, fLastVec, vec); |
2215 SkScalar smallest = SkTMin(fCurrPt.fX, SkTMin(fCurrPt.fY, SkTMin(fLastPt
.fX, fLastPt.fY))); | 2249 switch (dir) { |
2216 SkScalar largest = SkTMax(fCurrPt.fX, SkTMax(fCurrPt.fY, SkTMax(fLastPt.
fX, fLastPt.fY))); | 2250 case kLeft_DirChange: // fall through |
2217 largest = SkTMax(largest, -smallest); | 2251 case kRight_DirChange: |
2218 if (!almost_equal(largest, largest + cross)) { | 2252 if (kInvalid_DirChange == fExpectedDir) { |
2219 int sign = SkScalarSignAsInt(cross); | 2253 fExpectedDir = dir; |
2220 if (0 == fSign) { | 2254 fDirection = (kRight_DirChange == dir) ? SkPath::kCW_Directi
on |
2221 fSign = sign; | 2255 : SkPath::kCCW_Direct
ion; |
2222 fDirection = (1 == sign) ? SkPath::kCW_Direction : SkPath::kCCW_
Direction; | 2256 } else if (dir != fExpectedDir) { |
2223 } else if (sign && fSign != sign) { | 2257 fConvexity = SkPath::kConcave_Convexity; |
2224 fConvexity = SkPath::kConcave_Convexity; | 2258 fDirection = SkPath::kUnknown_Direction; |
2225 fDirection = SkPath::kUnknown_Direction; | 2259 } |
2226 } | 2260 fLastVec = vec; |
2227 fLastVec = vec; | 2261 break; |
| 2262 case kStraight_DirChange: |
| 2263 break; |
| 2264 case kBackwards_DirChange: |
| 2265 fLastVec = vec; |
| 2266 break; |
| 2267 case kInvalid_DirChange: |
| 2268 SkFAIL("Use of invalid direction change flag"); |
| 2269 break; |
2228 } | 2270 } |
2229 } | 2271 } |
2230 | 2272 |
2231 SkPoint fLastPt; | 2273 SkPoint fLastPt; |
2232 SkPoint fCurrPt; | 2274 SkPoint fCurrPt; |
2233 // fLastVec does not necessarily start at fLastPt. We only advance it when t
he cross product | 2275 // fLastVec does not necessarily start at fLastPt. We only advance it when t
he cross product |
2234 // value with the current vec is deemed to be of a significant value. | 2276 // value with the current vec is deemed to be of a significant value. |
2235 SkVector fLastVec, fFirstVec; | 2277 SkVector fLastVec, fFirstVec; |
2236 int fPtCount; // non-degenerate points | 2278 int fPtCount; // non-degenerate points |
2237 int fSign; | 2279 DirChange fExpectedDir; |
2238 SkPath::Convexity fConvexity; | 2280 SkPath::Convexity fConvexity; |
2239 SkPath::Direction fDirection; | 2281 SkPath::Direction fDirection; |
2240 int fDx, fDy, fSx, fSy; | 2282 int fDx, fDy, fSx, fSy; |
2241 }; | 2283 }; |
2242 | 2284 |
2243 SkPath::Convexity SkPath::internalGetConvexity() const { | 2285 SkPath::Convexity SkPath::internalGetConvexity() const { |
2244 SkASSERT(kUnknown_Convexity == fConvexity); | 2286 SkASSERT(kUnknown_Convexity == fConvexity); |
2245 SkPoint pts[4]; | 2287 SkPoint pts[4]; |
2246 SkPath::Verb verb; | 2288 SkPath::Verb verb; |
2247 SkPath::Iter iter(*this, true); | 2289 SkPath::Iter iter(*this, true); |
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2792 switch (this->getFillType()) { | 2834 switch (this->getFillType()) { |
2793 case SkPath::kEvenOdd_FillType: | 2835 case SkPath::kEvenOdd_FillType: |
2794 case SkPath::kInverseEvenOdd_FillType: | 2836 case SkPath::kInverseEvenOdd_FillType: |
2795 w &= 1; | 2837 w &= 1; |
2796 break; | 2838 break; |
2797 default: | 2839 default: |
2798 break; | 2840 break; |
2799 } | 2841 } |
2800 return SkToBool(w); | 2842 return SkToBool(w); |
2801 } | 2843 } |
OLD | NEW |