Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: src/core/SkPath.cpp

Issue 573763002: Fix convexicator bug (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Handle kInvalid_DirChange in switch statement Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tests/PathTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | tests/PathTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698