| 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 |