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