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

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

Issue 784593002: add convexity logic and tests for scalar max, Inf, and NaN (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years 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 2197 matching lines...) Expand 10 before | Expand all | Expand 10 after
2208 } 2208 }
2209 2209
2210 return kStraight_DirChange; 2210 return kStraight_DirChange;
2211 } 2211 }
2212 2212
2213 // only valid for a single contour 2213 // only valid for a single contour
2214 struct Convexicator { 2214 struct Convexicator {
2215 Convexicator() 2215 Convexicator()
2216 : fPtCount(0) 2216 : fPtCount(0)
2217 , fConvexity(SkPath::kConvex_Convexity) 2217 , fConvexity(SkPath::kConvex_Convexity)
2218 , fDirection(SkPath::kUnknown_Direction) { 2218 , fDirection(SkPath::kUnknown_Direction)
2219 , fIsFinite(true) {
2219 fExpectedDir = kInvalid_DirChange; 2220 fExpectedDir = kInvalid_DirChange;
2220 // warnings 2221 // warnings
2221 fLastPt.set(0, 0); 2222 fLastPt.set(0, 0);
2222 fCurrPt.set(0, 0); 2223 fCurrPt.set(0, 0);
2223 fLastVec.set(0, 0); 2224 fLastVec.set(0, 0);
2224 fFirstVec.set(0, 0); 2225 fFirstVec.set(0, 0);
2225 2226
2226 fDx = fDy = 0; 2227 fDx = fDy = 0;
2227 fSx = fSy = kValueNeverReturnedBySign; 2228 fSx = fSy = kValueNeverReturnedBySign;
2228 } 2229 }
2229 2230
2230 SkPath::Convexity getConvexity() const { return fConvexity; } 2231 SkPath::Convexity getConvexity() const { return fConvexity; }
2231 2232
2232 /** The direction returned is only valid if the path is determined convex */ 2233 /** The direction returned is only valid if the path is determined convex */
2233 SkPath::Direction getDirection() const { return fDirection; } 2234 SkPath::Direction getDirection() const { return fDirection; }
2234 2235
2235 void addPt(const SkPoint& pt) { 2236 void addPt(const SkPoint& pt) {
2236 if (SkPath::kConcave_Convexity == fConvexity) { 2237 if (SkPath::kConcave_Convexity == fConvexity || !fIsFinite) {
2237 return; 2238 return;
2238 } 2239 }
2239 2240
2240 if (0 == fPtCount) { 2241 if (0 == fPtCount) {
2241 fCurrPt = pt; 2242 fCurrPt = pt;
2242 ++fPtCount; 2243 ++fPtCount;
2243 } else { 2244 } else {
2244 SkVector vec = pt - fCurrPt; 2245 SkVector vec = pt - fCurrPt;
2245 if (!SkScalarNearlyZero(vec.lengthSqd(), SK_ScalarNearlyZero*SK_Scal arNearlyZero)) { 2246 SkScalar lengthSqd = vec.lengthSqd();
2247 if (!SkScalarIsFinite(lengthSqd)) {
2248 fIsFinite = false;
bsalomon 2014/12/05 20:23:46 Do we need to track fIsFinite or can this just be
2249 } else if (!SkScalarNearlyZero(lengthSqd, SK_ScalarNearlyZero*SK_Sca larNearlyZero)) {
2246 fLastPt = fCurrPt; 2250 fLastPt = fCurrPt;
2247 fCurrPt = pt; 2251 fCurrPt = pt;
2248 if (++fPtCount == 2) { 2252 if (++fPtCount == 2) {
2249 fFirstVec = fLastVec = vec; 2253 fFirstVec = fLastVec = vec;
2250 } else { 2254 } else {
2251 SkASSERT(fPtCount > 2); 2255 SkASSERT(fPtCount > 2);
2252 this->addVec(vec); 2256 this->addVec(vec);
2253 } 2257 }
2254 2258
2255 int sx = sign(vec.fX); 2259 int sx = sign(vec.fX);
2256 int sy = sign(vec.fY); 2260 int sy = sign(vec.fY);
2257 fDx += (sx != fSx); 2261 fDx += (sx != fSx);
2258 fDy += (sy != fSy); 2262 fDy += (sy != fSy);
2259 fSx = sx; 2263 fSx = sx;
2260 fSy = sy; 2264 fSy = sy;
2261 2265
2262 if (fDx > 3 || fDy > 3) { 2266 if (fDx > 3 || fDy > 3) {
2263 fConvexity = SkPath::kConcave_Convexity; 2267 fConvexity = SkPath::kConcave_Convexity;
2264 } 2268 }
2265 } 2269 }
2266 } 2270 }
2267 } 2271 }
2268 2272
2269 void close() { 2273 void close() {
2270 if (fPtCount > 2) { 2274 if (fPtCount > 2) {
2271 this->addVec(fFirstVec); 2275 this->addVec(fFirstVec);
2272 } 2276 }
2273 } 2277 }
2274 2278
2279 bool isFinite() const {
2280 return fIsFinite;
2281 }
2282
2275 private: 2283 private:
2276 void addVec(const SkVector& vec) { 2284 void addVec(const SkVector& vec) {
2277 SkASSERT(vec.fX || vec.fY); 2285 SkASSERT(vec.fX || vec.fY);
2278 DirChange dir = direction_change(fLastPt, fCurrPt, fLastVec, vec); 2286 DirChange dir = direction_change(fLastPt, fCurrPt, fLastVec, vec);
2279 switch (dir) { 2287 switch (dir) {
2280 case kLeft_DirChange: // fall through 2288 case kLeft_DirChange: // fall through
2281 case kRight_DirChange: 2289 case kRight_DirChange:
2282 if (kInvalid_DirChange == fExpectedDir) { 2290 if (kInvalid_DirChange == fExpectedDir) {
2283 fExpectedDir = dir; 2291 fExpectedDir = dir;
2284 fDirection = (kRight_DirChange == dir) ? SkPath::kCW_Directi on 2292 fDirection = (kRight_DirChange == dir) ? SkPath::kCW_Directi on
(...skipping 18 matching lines...) Expand all
2303 SkPoint fLastPt; 2311 SkPoint fLastPt;
2304 SkPoint fCurrPt; 2312 SkPoint fCurrPt;
2305 // fLastVec does not necessarily start at fLastPt. We only advance it when t he cross product 2313 // fLastVec does not necessarily start at fLastPt. We only advance it when t he cross product
2306 // value with the current vec is deemed to be of a significant value. 2314 // value with the current vec is deemed to be of a significant value.
2307 SkVector fLastVec, fFirstVec; 2315 SkVector fLastVec, fFirstVec;
2308 int fPtCount; // non-degenerate points 2316 int fPtCount; // non-degenerate points
2309 DirChange fExpectedDir; 2317 DirChange fExpectedDir;
2310 SkPath::Convexity fConvexity; 2318 SkPath::Convexity fConvexity;
2311 SkPath::Direction fDirection; 2319 SkPath::Direction fDirection;
2312 int fDx, fDy, fSx, fSy; 2320 int fDx, fDy, fSx, fSy;
2321 bool fIsFinite;
2313 }; 2322 };
2314 2323
2315 SkPath::Convexity SkPath::internalGetConvexity() const { 2324 SkPath::Convexity SkPath::internalGetConvexity() const {
2316 SkASSERT(kUnknown_Convexity == fConvexity); 2325 SkASSERT(kUnknown_Convexity == fConvexity);
2317 SkPoint pts[4]; 2326 SkPoint pts[4];
2318 SkPath::Verb verb; 2327 SkPath::Verb verb;
2319 SkPath::Iter iter(*this, true); 2328 SkPath::Iter iter(*this, true);
2320 2329
2321 int contourCount = 0; 2330 int contourCount = 0;
2322 int count; 2331 int count;
2323 Convexicator state; 2332 Convexicator state;
2324 2333
2334 if (!isFinite()) {
2335 return kUnknown_Convexity;
2336 }
2325 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 2337 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
2326 switch (verb) { 2338 switch (verb) {
2327 case kMove_Verb: 2339 case kMove_Verb:
2328 if (++contourCount > 1) { 2340 if (++contourCount > 1) {
2329 fConvexity = kConcave_Convexity; 2341 fConvexity = kConcave_Convexity;
2330 return kConcave_Convexity; 2342 return kConcave_Convexity;
2331 } 2343 }
2332 pts[1] = pts[0]; 2344 pts[1] = pts[0];
2333 count = 1; 2345 count = 1;
2334 break; 2346 break;
2335 case kLine_Verb: count = 1; break; 2347 case kLine_Verb: count = 1; break;
2336 case kQuad_Verb: count = 2; break; 2348 case kQuad_Verb: count = 2; break;
2337 case kConic_Verb: count = 2; break; 2349 case kConic_Verb: count = 2; break;
2338 case kCubic_Verb: count = 3; break; 2350 case kCubic_Verb: count = 3; break;
2339 case kClose_Verb: 2351 case kClose_Verb:
2340 state.close(); 2352 state.close();
2341 count = 0; 2353 count = 0;
2342 break; 2354 break;
2343 default: 2355 default:
2344 SkDEBUGFAIL("bad verb"); 2356 SkDEBUGFAIL("bad verb");
2345 fConvexity = kConcave_Convexity; 2357 fConvexity = kConcave_Convexity;
2346 return kConcave_Convexity; 2358 return kConcave_Convexity;
2347 } 2359 }
2348 2360
2349 for (int i = 1; i <= count; i++) { 2361 for (int i = 1; i <= count; i++) {
2350 state.addPt(pts[i]); 2362 state.addPt(pts[i]);
2351 } 2363 }
2352 // early exit 2364 // early exit
2365 if (!state.isFinite()) {
2366 return kUnknown_Convexity;
2367 }
2353 if (kConcave_Convexity == state.getConvexity()) { 2368 if (kConcave_Convexity == state.getConvexity()) {
2354 fConvexity = kConcave_Convexity; 2369 fConvexity = kConcave_Convexity;
2355 return kConcave_Convexity; 2370 return kConcave_Convexity;
2356 } 2371 }
2357 } 2372 }
2358 fConvexity = state.getConvexity(); 2373 fConvexity = state.getConvexity();
2359 if (kConvex_Convexity == fConvexity && kUnknown_Direction == fDirection) { 2374 if (kConvex_Convexity == fConvexity && kUnknown_Direction == fDirection) {
2360 fDirection = state.getDirection(); 2375 fDirection = state.getDirection();
2361 } 2376 }
2362 return static_cast<Convexity>(fConvexity); 2377 return static_cast<Convexity>(fConvexity);
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after
2864 switch (this->getFillType()) { 2879 switch (this->getFillType()) {
2865 case SkPath::kEvenOdd_FillType: 2880 case SkPath::kEvenOdd_FillType:
2866 case SkPath::kInverseEvenOdd_FillType: 2881 case SkPath::kInverseEvenOdd_FillType:
2867 w &= 1; 2882 w &= 1;
2868 break; 2883 break;
2869 default: 2884 default:
2870 break; 2885 break;
2871 } 2886 }
2872 return SkToBool(w); 2887 return SkToBool(w);
2873 } 2888 }
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