aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-01-31 20:46:32 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-01-31 20:46:32 +0000
commitdc3c78076ea279d4f6d502b3b42471e9b2bba48e (patch)
tree37464c0f73b20b65e1e964e444c4b9d1e49e776a /src
parentfb6f0f6f18cd515af85bb71e688e8530edd92827 (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.cpp44
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 {