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

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

Issue 975523002: add double precision convex test (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: add this-> for directionChange Created 5 years, 9 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 * Copyright 2006 The Android Open Source Project 2 * Copyright 2006 The Android Open Source Project
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkBuffer.h" 8 #include "SkBuffer.h"
9 #include "SkErrorInternals.h" 9 #include "SkErrorInternals.h"
10 #include "SkGeometry.h" 10 #include "SkGeometry.h"
(...skipping 2081 matching lines...) Expand 10 before | Expand all | Expand 10 after
2092 const int epsilon = 16; 2092 const int epsilon = 16;
2093 if (!SkScalarIsFinite(compA) || !SkScalarIsFinite(compB)) { 2093 if (!SkScalarIsFinite(compA) || !SkScalarIsFinite(compB)) {
2094 return false; 2094 return false;
2095 } 2095 }
2096 // no need to check for small numbers because SkPath::Iter has removed degen erate values 2096 // no need to check for small numbers because SkPath::Iter has removed degen erate values
2097 int aBits = SkFloatAs2sCompliment(compA); 2097 int aBits = SkFloatAs2sCompliment(compA);
2098 int bBits = SkFloatAs2sCompliment(compB); 2098 int bBits = SkFloatAs2sCompliment(compB);
2099 return aBits < bBits + epsilon && bBits < aBits + epsilon; 2099 return aBits < bBits + epsilon && bBits < aBits + epsilon;
2100 } 2100 }
2101 2101
2102 static DirChange direction_change(const SkPoint& lastPt, const SkVector& curPt, 2102 static bool approximately_zero_when_compared_to(double x, double y) {
2103 const SkVector& lastVec, const SkVector& curVe c) { 2103 return x == 0 || fabs(x) < fabs(y * FLT_EPSILON);
2104 SkScalar cross = SkPoint::CrossProduct(lastVec, curVec); 2104 }
2105 2105
2106 SkScalar smallest = SkTMin(curPt.fX, SkTMin(curPt.fY, SkTMin(lastPt.fX, last Pt.fY)));
2107 SkScalar largest = SkTMax(curPt.fX, SkTMax(curPt.fY, SkTMax(lastPt.fX, lastP t.fY)));
2108 largest = SkTMax(largest, -smallest);
2109
2110 if (!almost_equal(largest, largest + cross)) {
2111 int sign = SkScalarSignAsInt(cross);
2112 if (sign) {
2113 return (1 == sign) ? kRight_DirChange : kLeft_DirChange;
2114 }
2115 }
2116
2117 if (!SkScalarNearlyZero(lastVec.lengthSqd(), SK_ScalarNearlyZero*SK_ScalarNe arlyZero) &&
2118 !SkScalarNearlyZero(curVec.lengthSqd(), SK_ScalarNearlyZero*SK_ScalarNea rlyZero) &&
2119 lastVec.dot(curVec) < 0.0f) {
2120 return kBackwards_DirChange;
2121 }
2122
2123 return kStraight_DirChange;
2124 }
2125 2106
2126 // only valid for a single contour 2107 // only valid for a single contour
2127 struct Convexicator { 2108 struct Convexicator {
2128 Convexicator() 2109 Convexicator()
2129 : fPtCount(0) 2110 : fPtCount(0)
2130 , fConvexity(SkPath::kConvex_Convexity) 2111 , fConvexity(SkPath::kConvex_Convexity)
2131 , fDirection(SkPath::kUnknown_Direction) 2112 , fDirection(SkPath::kUnknown_Direction)
2132 , fIsFinite(true) 2113 , fIsFinite(true)
2133 , fIsCurve(false) { 2114 , fIsCurve(false) {
2134 fExpectedDir = kInvalid_DirChange; 2115 fExpectedDir = kInvalid_DirChange;
(...skipping 19 matching lines...) Expand all
2154 2135
2155 if (0 == fPtCount) { 2136 if (0 == fPtCount) {
2156 fCurrPt = pt; 2137 fCurrPt = pt;
2157 ++fPtCount; 2138 ++fPtCount;
2158 } else { 2139 } else {
2159 SkVector vec = pt - fCurrPt; 2140 SkVector vec = pt - fCurrPt;
2160 SkScalar lengthSqd = vec.lengthSqd(); 2141 SkScalar lengthSqd = vec.lengthSqd();
2161 if (!SkScalarIsFinite(lengthSqd)) { 2142 if (!SkScalarIsFinite(lengthSqd)) {
2162 fIsFinite = false; 2143 fIsFinite = false;
2163 } else if (!SkScalarNearlyZero(lengthSqd, SK_ScalarNearlyZero*SK_Sca larNearlyZero)) { 2144 } else if (!SkScalarNearlyZero(lengthSqd, SK_ScalarNearlyZero*SK_Sca larNearlyZero)) {
2145 fPriorPt = fLastPt;
2164 fLastPt = fCurrPt; 2146 fLastPt = fCurrPt;
2165 fCurrPt = pt; 2147 fCurrPt = pt;
2166 if (++fPtCount == 2) { 2148 if (++fPtCount == 2) {
2167 fFirstVec = fLastVec = vec; 2149 fFirstVec = fLastVec = vec;
2168 } else { 2150 } else {
2169 SkASSERT(fPtCount > 2); 2151 SkASSERT(fPtCount > 2);
2170 this->addVec(vec); 2152 this->addVec(vec);
2171 } 2153 }
2172 2154
2173 int sx = sign(vec.fX); 2155 int sx = sign(vec.fX);
2174 int sy = sign(vec.fY); 2156 int sy = sign(vec.fY);
2175 fDx += (sx != fSx); 2157 fDx += (sx != fSx);
2176 fDy += (sy != fSy); 2158 fDy += (sy != fSy);
2177 fSx = sx; 2159 fSx = sx;
2178 fSy = sy; 2160 fSy = sy;
2179 2161
2180 if (fDx > 3 || fDy > 3) { 2162 if (fDx > 3 || fDy > 3) {
2181 fConvexity = SkPath::kConcave_Convexity; 2163 fConvexity = SkPath::kConcave_Convexity;
2182 } 2164 }
2183 } 2165 }
2184 } 2166 }
2185 } 2167 }
2186 2168
2187 void close() { 2169 void close() {
2188 if (fPtCount > 2) { 2170 if (fPtCount > 2) {
2189 this->addVec(fFirstVec); 2171 this->addVec(fFirstVec);
2190 } 2172 }
2191 } 2173 }
2192 2174
2175 DirChange directionChange(const SkVector& curVec) {
2176 SkScalar cross = SkPoint::CrossProduct(fLastVec, curVec);
2177
2178 SkScalar smallest = SkTMin(fCurrPt.fX, SkTMin(fCurrPt.fY, SkTMin(fLastPt .fX, fLastPt.fY)));
2179 SkScalar largest = SkTMax(fCurrPt.fX, SkTMax(fCurrPt.fY, SkTMax(fLastPt. fX, fLastPt.fY)));
2180 largest = SkTMax(largest, -smallest);
2181
2182 if (!almost_equal(largest, largest + cross)) {
2183 int sign = SkScalarSignAsInt(cross);
2184 if (sign) {
2185 return (1 == sign) ? kRight_DirChange : kLeft_DirChange;
2186 }
2187 }
2188
2189 if (cross) {
2190 double dLastVecX = SkScalarToDouble(fLastPt.fX) - SkScalarToDouble(f PriorPt.fX);
2191 double dLastVecY = SkScalarToDouble(fLastPt.fY) - SkScalarToDouble(f PriorPt.fY);
2192 double dCurrVecX = SkScalarToDouble(fCurrPt.fX) - SkScalarToDouble(f LastPt.fX);
2193 double dCurrVecY = SkScalarToDouble(fCurrPt.fY) - SkScalarToDouble(f LastPt.fY);
2194 double dCross = dLastVecX * dCurrVecY - dLastVecY * dCurrVecX;
2195 if (!approximately_zero_when_compared_to(dCross, SkScalarToDouble(la rgest))) {
2196 int sign = SkScalarSignAsInt(SkDoubleToScalar(dCross));
2197 if (sign) {
2198 return (1 == sign) ? kRight_DirChange : kLeft_DirChange;
2199 }
2200 }
2201 }
2202
2203 if (!SkScalarNearlyZero(fLastVec.lengthSqd(), SK_ScalarNearlyZero*SK_Sca larNearlyZero) &&
2204 !SkScalarNearlyZero(curVec.lengthSqd(), SK_ScalarNearlyZero*SK_Scala rNearlyZero) &&
2205 fLastVec.dot(curVec) < 0.0f) {
2206 return kBackwards_DirChange;
2207 }
2208
2209 return kStraight_DirChange;
2210 }
2211
2212
2193 bool isFinite() const { 2213 bool isFinite() const {
2194 return fIsFinite; 2214 return fIsFinite;
2195 } 2215 }
2196 2216
2197 void setCurve(bool isCurve) { 2217 void setCurve(bool isCurve) {
2198 fIsCurve = isCurve; 2218 fIsCurve = isCurve;
2199 } 2219 }
2200 2220
2201 private: 2221 private:
2202 void addVec(const SkVector& vec) { 2222 void addVec(const SkVector& vec) {
2203 SkASSERT(vec.fX || vec.fY); 2223 SkASSERT(vec.fX || vec.fY);
2204 DirChange dir = direction_change(fLastPt, fCurrPt, fLastVec, vec); 2224 DirChange dir = this->directionChange(vec);
2205 switch (dir) { 2225 switch (dir) {
2206 case kLeft_DirChange: // fall through 2226 case kLeft_DirChange: // fall through
2207 case kRight_DirChange: 2227 case kRight_DirChange:
2208 if (kInvalid_DirChange == fExpectedDir) { 2228 if (kInvalid_DirChange == fExpectedDir) {
2209 fExpectedDir = dir; 2229 fExpectedDir = dir;
2210 fDirection = (kRight_DirChange == dir) ? SkPath::kCW_Directi on 2230 fDirection = (kRight_DirChange == dir) ? SkPath::kCW_Directi on
2211 : SkPath::kCCW_Direct ion; 2231 : SkPath::kCCW_Direct ion;
2212 } else if (dir != fExpectedDir) { 2232 } else if (dir != fExpectedDir) {
2213 fConvexity = SkPath::kConcave_Convexity; 2233 fConvexity = SkPath::kConcave_Convexity;
2214 fDirection = SkPath::kUnknown_Direction; 2234 fDirection = SkPath::kUnknown_Direction;
2215 } 2235 }
2216 fLastVec = vec; 2236 fLastVec = vec;
2217 break; 2237 break;
2218 case kStraight_DirChange: 2238 case kStraight_DirChange:
2219 break; 2239 break;
2220 case kBackwards_DirChange: 2240 case kBackwards_DirChange:
2221 if (fIsCurve) { 2241 if (fIsCurve) {
2222 fConvexity = SkPath::kConcave_Convexity; 2242 fConvexity = SkPath::kConcave_Convexity;
2223 fDirection = SkPath::kUnknown_Direction; 2243 fDirection = SkPath::kUnknown_Direction;
2224 } 2244 }
2225 fLastVec = vec; 2245 fLastVec = vec;
2226 break; 2246 break;
2227 case kInvalid_DirChange: 2247 case kInvalid_DirChange:
2228 SkFAIL("Use of invalid direction change flag"); 2248 SkFAIL("Use of invalid direction change flag");
2229 break; 2249 break;
2230 } 2250 }
2231 } 2251 }
2232 2252
2253 SkPoint fPriorPt;
2233 SkPoint fLastPt; 2254 SkPoint fLastPt;
2234 SkPoint fCurrPt; 2255 SkPoint fCurrPt;
2235 // fLastVec does not necessarily start at fLastPt. We only advance it when t he cross product 2256 // fLastVec does not necessarily start at fLastPt. We only advance it when t he cross product
2236 // value with the current vec is deemed to be of a significant value. 2257 // value with the current vec is deemed to be of a significant value.
2237 SkVector fLastVec, fFirstVec; 2258 SkVector fLastVec, fFirstVec;
2238 int fPtCount; // non-degenerate points 2259 int fPtCount; // non-degenerate points
2239 DirChange fExpectedDir; 2260 DirChange fExpectedDir;
2240 SkPath::Convexity fConvexity; 2261 SkPath::Convexity fConvexity;
2241 SkPath::Direction fDirection; 2262 SkPath::Direction fDirection;
2242 int fDx, fDy, fSx, fSy; 2263 int fDx, fDy, fSx, fSy;
(...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after
2812 switch (this->getFillType()) { 2833 switch (this->getFillType()) {
2813 case SkPath::kEvenOdd_FillType: 2834 case SkPath::kEvenOdd_FillType:
2814 case SkPath::kInverseEvenOdd_FillType: 2835 case SkPath::kInverseEvenOdd_FillType:
2815 w &= 1; 2836 w &= 1;
2816 break; 2837 break;
2817 default: 2838 default:
2818 break; 2839 break;
2819 } 2840 }
2820 return SkToBool(w); 2841 return SkToBool(w);
2821 } 2842 }
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