diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-01-31 20:46:32 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-01-31 20:46:32 +0000 |
commit | dc3c78076ea279d4f6d502b3b42471e9b2bba48e (patch) | |
tree | 37464c0f73b20b65e1e964e444c4b9d1e49e776a /src | |
parent | fb6f0f6f18cd515af85bb71e688e8530edd92827 (diff) |
[GPU]: Handle degenerate quads when computing UV matrix from control points
Review URL: http://codereview.appspot.com/5602045/
git-svn-id: http://skia.googlecode.com/svn/trunk@3125 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrPathUtils.cpp | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/src/gpu/GrPathUtils.cpp b/src/gpu/GrPathUtils.cpp index 349b887e1c..2951e1f72c 100644 --- a/src/gpu/GrPathUtils.cpp +++ b/src/gpu/GrPathUtils.cpp @@ -225,16 +225,52 @@ void GrPathUtils::quadDesignSpaceToUVCoordsMatrix(const SkPoint qPts[3], #ifndef SK_SCALAR_IS_FLOAT GrCrash("Expected scalar is float."); #endif - + // We want M such that M * xy_pt = uv_pt + // We know M * control_pts = [0 1/2 1] + // [0 0 1] + // [1 1 1] + // We invert the control pt matrix and post concat to both sides to get M. UVpts.setAll(0, 0.5f, 1.f, 0, 0, 1.f, 1.f, 1.f, 1.f); matrix->setAll(qPts[0].fX, qPts[1].fX, qPts[2].fX, qPts[0].fY, qPts[1].fY, qPts[2].fY, 1.f, 1.f, 1.f); - matrix->invert(matrix); - matrix->postConcat(UVpts); - fixup_matrix(matrix); + if (!matrix->invert(matrix)) { + // The quad is degenerate. Hopefully this is rare. Find the pts that are + // farthest apart to compute a line (unless it is really a pt). + SkScalar maxD = qPts[0].distanceToSqd(qPts[1]); + int maxEdge = 0; + SkScalar d = qPts[1].distanceToSqd(qPts[2]); + if (d > maxD) { + maxD = d; + maxEdge = 1; + } + d = qPts[2].distanceToSqd(qPts[0]); + if (d > maxD) { + maxD = d; + maxEdge = 2; + } + // We could have a tolerance here, not sure if it would improve anything + if (maxD > 0) { + // Set the matrix to give (u = 0, v = distance_to_line) + GrVec lineVec = qPts[maxEdge] - qPts[(maxEdge + 1)%3]; + lineVec.setOrthog(lineVec); + lineVec.dot(qPts[0]); + matrix->setAll(0, 0, 0, + lineVec.fX, lineVec.fY, -lineVec.dot(qPts[maxEdge]), + 0, 0, 1.f); + } else { + // It's a point. It should cover zero area. Just set the matrix such + // that (u, v) will always be far away from the quad. + matrix->setAll(0, 0, 100 * SK_Scalar1, + 0, 0, 100 * SK_Scalar1, + 0, 0, 1.f); + } + } else { + matrix->postConcat(UVpts); + fixup_matrix(matrix); + } } namespace { |