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 |