| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |