| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 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 "GrPathUtils.h" | 8 #include "GrPathUtils.h" |
| 9 | 9 |
| 10 #include "GrPoint.h" | 10 #include "GrPoint.h" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 } | 34 } |
| 35 | 35 |
| 36 static const int MAX_POINTS_PER_CURVE = 1 << 10; | 36 static const int MAX_POINTS_PER_CURVE = 1 << 10; |
| 37 static const SkScalar gMinCurveTol = SkFloatToScalar(0.0001f); | 37 static const SkScalar gMinCurveTol = SkFloatToScalar(0.0001f); |
| 38 | 38 |
| 39 uint32_t GrPathUtils::quadraticPointCount(const GrPoint points[], | 39 uint32_t GrPathUtils::quadraticPointCount(const GrPoint points[], |
| 40 SkScalar tol) { | 40 SkScalar tol) { |
| 41 if (tol < gMinCurveTol) { | 41 if (tol < gMinCurveTol) { |
| 42 tol = gMinCurveTol; | 42 tol = gMinCurveTol; |
| 43 } | 43 } |
| 44 GrAssert(tol > 0); | 44 SkASSERT(tol > 0); |
| 45 | 45 |
| 46 SkScalar d = points[1].distanceToLineSegmentBetween(points[0], points[2]); | 46 SkScalar d = points[1].distanceToLineSegmentBetween(points[0], points[2]); |
| 47 if (d <= tol) { | 47 if (d <= tol) { |
| 48 return 1; | 48 return 1; |
| 49 } else { | 49 } else { |
| 50 // Each time we subdivide, d should be cut in 4. So we need to | 50 // Each time we subdivide, d should be cut in 4. So we need to |
| 51 // subdivide x = log4(d/tol) times. x subdivisions creates 2^(x) | 51 // subdivide x = log4(d/tol) times. x subdivisions creates 2^(x) |
| 52 // points. | 52 // points. |
| 53 // 2^(log4(x)) = sqrt(x); | 53 // 2^(log4(x)) = sqrt(x); |
| 54 int temp = SkScalarCeil(SkScalarSqrt(SkScalarDiv(d, tol))); | 54 int temp = SkScalarCeil(SkScalarSqrt(SkScalarDiv(d, tol))); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 uint32_t a = generateQuadraticPoints(p0, q[0], r, tolSqd, points, pointsLeft
); | 86 uint32_t a = generateQuadraticPoints(p0, q[0], r, tolSqd, points, pointsLeft
); |
| 87 uint32_t b = generateQuadraticPoints(r, q[1], p2, tolSqd, points, pointsLeft
); | 87 uint32_t b = generateQuadraticPoints(r, q[1], p2, tolSqd, points, pointsLeft
); |
| 88 return a + b; | 88 return a + b; |
| 89 } | 89 } |
| 90 | 90 |
| 91 uint32_t GrPathUtils::cubicPointCount(const GrPoint points[], | 91 uint32_t GrPathUtils::cubicPointCount(const GrPoint points[], |
| 92 SkScalar tol) { | 92 SkScalar tol) { |
| 93 if (tol < gMinCurveTol) { | 93 if (tol < gMinCurveTol) { |
| 94 tol = gMinCurveTol; | 94 tol = gMinCurveTol; |
| 95 } | 95 } |
| 96 GrAssert(tol > 0); | 96 SkASSERT(tol > 0); |
| 97 | 97 |
| 98 SkScalar d = GrMax( | 98 SkScalar d = GrMax( |
| 99 points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]), | 99 points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]), |
| 100 points[2].distanceToLineSegmentBetweenSqd(points[0], points[3])); | 100 points[2].distanceToLineSegmentBetweenSqd(points[0], points[3])); |
| 101 d = SkScalarSqrt(d); | 101 d = SkScalarSqrt(d); |
| 102 if (d <= tol) { | 102 if (d <= tol) { |
| 103 return 1; | 103 return 1; |
| 104 } else { | 104 } else { |
| 105 int temp = SkScalarCeil(SkScalarSqrt(SkScalarDiv(d, tol))); | 105 int temp = SkScalarCeil(SkScalarSqrt(SkScalarDiv(d, tol))); |
| 106 int pow2 = GrNextPow2(temp); | 106 int pow2 = GrNextPow2(temp); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 uint32_t a = generateCubicPoints(p0, q[0], r[0], s, tolSqd, points, pointsLe
ft); | 142 uint32_t a = generateCubicPoints(p0, q[0], r[0], s, tolSqd, points, pointsLe
ft); |
| 143 uint32_t b = generateCubicPoints(s, r[1], q[2], p3, tolSqd, points, pointsLe
ft); | 143 uint32_t b = generateCubicPoints(s, r[1], q[2], p3, tolSqd, points, pointsLe
ft); |
| 144 return a + b; | 144 return a + b; |
| 145 } | 145 } |
| 146 | 146 |
| 147 int GrPathUtils::worstCasePointCount(const SkPath& path, int* subpaths, | 147 int GrPathUtils::worstCasePointCount(const SkPath& path, int* subpaths, |
| 148 SkScalar tol) { | 148 SkScalar tol) { |
| 149 if (tol < gMinCurveTol) { | 149 if (tol < gMinCurveTol) { |
| 150 tol = gMinCurveTol; | 150 tol = gMinCurveTol; |
| 151 } | 151 } |
| 152 GrAssert(tol > 0); | 152 SkASSERT(tol > 0); |
| 153 | 153 |
| 154 int pointCount = 0; | 154 int pointCount = 0; |
| 155 *subpaths = 1; | 155 *subpaths = 1; |
| 156 | 156 |
| 157 bool first = true; | 157 bool first = true; |
| 158 | 158 |
| 159 SkPath::Iter iter(path, false); | 159 SkPath::Iter iter(path, false); |
| 160 SkPath::Verb verb; | 160 SkPath::Verb verb; |
| 161 | 161 |
| 162 GrPoint pts[4]; | 162 GrPoint pts[4]; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 // It's a point. It should cover zero area. Just set the matrix such | 244 // It's a point. It should cover zero area. Just set the matrix such |
| 245 // that (u, v) will always be far away from the quad. | 245 // that (u, v) will always be far away from the quad. |
| 246 fM[0] = 0; fM[1] = 0; fM[2] = 100.f; | 246 fM[0] = 0; fM[1] = 0; fM[2] = 100.f; |
| 247 fM[3] = 0; fM[4] = 0; fM[5] = 100.f; | 247 fM[3] = 0; fM[4] = 0; fM[5] = 100.f; |
| 248 } | 248 } |
| 249 } else { | 249 } else { |
| 250 m.postConcat(UVpts); | 250 m.postConcat(UVpts); |
| 251 | 251 |
| 252 // The matrix should not have perspective. | 252 // The matrix should not have perspective. |
| 253 SkDEBUGCODE(static const SkScalar gTOL = SkFloatToScalar(1.f / 100.f)); | 253 SkDEBUGCODE(static const SkScalar gTOL = SkFloatToScalar(1.f / 100.f)); |
| 254 GrAssert(SkScalarAbs(m.get(SkMatrix::kMPersp0)) < gTOL); | 254 SkASSERT(SkScalarAbs(m.get(SkMatrix::kMPersp0)) < gTOL); |
| 255 GrAssert(SkScalarAbs(m.get(SkMatrix::kMPersp1)) < gTOL); | 255 SkASSERT(SkScalarAbs(m.get(SkMatrix::kMPersp1)) < gTOL); |
| 256 | 256 |
| 257 // It may not be normalized to have 1.0 in the bottom right | 257 // It may not be normalized to have 1.0 in the bottom right |
| 258 float m33 = m.get(SkMatrix::kMPersp2); | 258 float m33 = m.get(SkMatrix::kMPersp2); |
| 259 if (1.f != m33) { | 259 if (1.f != m33) { |
| 260 m33 = 1.f / m33; | 260 m33 = 1.f / m33; |
| 261 fM[0] = m33 * m.get(SkMatrix::kMScaleX); | 261 fM[0] = m33 * m.get(SkMatrix::kMScaleX); |
| 262 fM[1] = m33 * m.get(SkMatrix::kMSkewX); | 262 fM[1] = m33 * m.get(SkMatrix::kMSkewX); |
| 263 fM[2] = m33 * m.get(SkMatrix::kMTransX); | 263 fM[2] = m33 * m.get(SkMatrix::kMTransX); |
| 264 fM[3] = m33 * m.get(SkMatrix::kMSkewY); | 264 fM[3] = m33 * m.get(SkMatrix::kMSkewY); |
| 265 fM[4] = m33 * m.get(SkMatrix::kMScaleY); | 265 fM[4] = m33 * m.get(SkMatrix::kMScaleY); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 289 const SkPoint& d, | 289 const SkPoint& d, |
| 290 SkPath::Direction dir, | 290 SkPath::Direction dir, |
| 291 const SkPoint p) { | 291 const SkPoint p) { |
| 292 SkVector ap = p - a; | 292 SkVector ap = p - a; |
| 293 SkScalar apXab = ap.cross(ab); | 293 SkScalar apXab = ap.cross(ab); |
| 294 if (SkPath::kCW_Direction == dir) { | 294 if (SkPath::kCW_Direction == dir) { |
| 295 if (apXab > 0) { | 295 if (apXab > 0) { |
| 296 return false; | 296 return false; |
| 297 } | 297 } |
| 298 } else { | 298 } else { |
| 299 GrAssert(SkPath::kCCW_Direction == dir); | 299 SkASSERT(SkPath::kCCW_Direction == dir); |
| 300 if (apXab < 0) { | 300 if (apXab < 0) { |
| 301 return false; | 301 return false; |
| 302 } | 302 } |
| 303 } | 303 } |
| 304 | 304 |
| 305 SkVector dp = p - d; | 305 SkVector dp = p - d; |
| 306 SkScalar dpXdc = dp.cross(dc); | 306 SkScalar dpXdc = dp.cross(dc); |
| 307 if (SkPath::kCW_Direction == dir) { | 307 if (SkPath::kCW_Direction == dir) { |
| 308 if (dpXdc < 0) { | 308 if (dpXdc < 0) { |
| 309 return false; | 309 return false; |
| 310 } | 310 } |
| 311 } else { | 311 } else { |
| 312 GrAssert(SkPath::kCCW_Direction == dir); | 312 SkASSERT(SkPath::kCCW_Direction == dir); |
| 313 if (dpXdc > 0) { | 313 if (dpXdc > 0) { |
| 314 return false; | 314 return false; |
| 315 } | 315 } |
| 316 } | 316 } |
| 317 return true; | 317 return true; |
| 318 } | 318 } |
| 319 | 319 |
| 320 void convert_noninflect_cubic_to_quads(const SkPoint p[4], | 320 void convert_noninflect_cubic_to_quads(const SkPoint p[4], |
| 321 SkScalar toleranceSqd, | 321 SkScalar toleranceSqd, |
| 322 bool constrainWithinTangents, | 322 bool constrainWithinTangents, |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 // base tolerance is 1 pixel. | 469 // base tolerance is 1 pixel. |
| 470 static const SkScalar kTolerance = SK_Scalar1; | 470 static const SkScalar kTolerance = SK_Scalar1; |
| 471 const SkScalar tolSqd = SkScalarSquare(SkScalarMul(tolScale, kTolerance)); | 471 const SkScalar tolSqd = SkScalarSquare(SkScalarMul(tolScale, kTolerance)); |
| 472 | 472 |
| 473 for (int i = 0; i < count; ++i) { | 473 for (int i = 0; i < count; ++i) { |
| 474 SkPoint* cubic = chopped + 3*i; | 474 SkPoint* cubic = chopped + 3*i; |
| 475 convert_noninflect_cubic_to_quads(cubic, tolSqd, constrainWithinTangents
, dir, quads); | 475 convert_noninflect_cubic_to_quads(cubic, tolSqd, constrainWithinTangents
, dir, quads); |
| 476 } | 476 } |
| 477 | 477 |
| 478 } | 478 } |
| OLD | NEW |