@@ -1005,6 +1005,10 @@ SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, const SkMat
10051005 // get rotated quad in 3D
10061006 SkPoint pts[4 ];
10071007 ctm.mapRectToQuad (pts, pathBounds);
1008+ // No shadows for bowties or other degenerate cases
1009+ if (!SkIsConvexPolygon (pts, 4 )) {
1010+ return ;
1011+ }
10081012 SkPoint3 pts3D[4 ];
10091013 SkScalar z = this ->heightFunc (pathBounds.fLeft , pathBounds.fTop );
10101014 pts3D[0 ].set (pts[0 ].fX , pts[0 ].fY , z);
@@ -1017,20 +1021,30 @@ SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, const SkMat
10171021
10181022 // project from light through corners to z=0 plane
10191023 for (int i = 0 ; i < 4 ; ++i) {
1020- SkScalar zRatio = pts3D[i].fZ / (lightPos.fZ - pts3D[i].fZ );
1024+ SkScalar dz = lightPos.fZ - pts3D[i].fZ ;
1025+ // light shouldn't be below or at a corner's z-location
1026+ if (dz <= SK_ScalarNearlyZero) {
1027+ return ;
1028+ }
1029+ SkScalar zRatio = pts3D[i].fZ / dz;
10211030 pts3D[i].fX -= (lightPos.fX - pts3D[i].fX )*zRatio;
10221031 pts3D[i].fY -= (lightPos.fY - pts3D[i].fY )*zRatio;
10231032 pts3D[i].fZ = SK_Scalar1;
10241033 }
10251034
10261035 // Generate matrix that projects from [-1,1]x[-1,1] square to projected quad
10271036 SkPoint3 h0, h1, h2;
1028- // Compute crossing point between top and bottom edges (gives new x-axis).
1037+ // Compute homogenous crossing point between top and bottom edges (gives new x-axis).
10291038 h0 = (pts3D[1 ].cross (pts3D[0 ])).cross (pts3D[2 ].cross (pts3D[3 ]));
1030- // Compute crossing point between left and right edges (gives new y-axis).
1039+ // Compute homogenous crossing point between left and right edges (gives new y-axis).
10311040 h1 = (pts3D[0 ].cross (pts3D[3 ])).cross (pts3D[1 ].cross (pts3D[2 ]));
1032- // Compute crossing point between diagonals (gives new origin).
1041+ // Compute homogenous crossing point between diagonals (gives new origin).
10331042 h2 = (pts3D[0 ].cross (pts3D[2 ])).cross (pts3D[1 ].cross (pts3D[3 ]));
1043+ // If h2 is a vector (z=0 in 2D homogeneous space), that means that at least
1044+ // two of the quad corners are coincident and we don't have a realistic projection
1045+ if (SkScalarNearlyZero (h2.fZ )) {
1046+ return ;
1047+ }
10341048 // In some cases the crossing points are in the wrong direction
10351049 // to map (-1,-1) to pts3D[0], so we need to correct for that.
10361050 // Want h0 to be to the right of the left edge.
0 commit comments