More polyutils fixes

Bug: chromium:954891, oss-fuzz:14079
Change-Id: Ia1ee0a15ab4bfc93e67188ff02e6aa436432a3be
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/211602
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/utils/SkPolyUtils.cpp b/src/utils/SkPolyUtils.cpp
index ee1ae1e..86212f1 100644
--- a/src/utils/SkPolyUtils.cpp
+++ b/src/utils/SkPolyUtils.cpp
@@ -1052,16 +1052,16 @@
         return false;
     }
 
-    // need to be able to represent all the vertices in the 16-bit indices
-    if (polygonSize > std::numeric_limits<uint16_t>::max()) {
-        return false;
-    }
-
     // If it's convex, it's simple
     if (SkIsConvexPolygon(polygon, polygonSize)) {
         return true;
     }
 
+    // practically speaking, it takes too long to process large polygons
+    if (polygonSize > 2048) {
+        return false;
+    }
+
     SkTDPQueue <Vertex, Vertex::Left> vertexQueue(polygonSize);
     for (int i = 0; i < polygonSize; ++i) {
         Vertex newVertex;
@@ -1146,7 +1146,8 @@
     return (side*winding*offset < 0);
 }
 
-bool SkOffsetSimplePolygon(const SkPoint* inputPolygonVerts, int inputPolygonSize, SkScalar offset,
+bool SkOffsetSimplePolygon(const SkPoint* inputPolygonVerts, int inputPolygonSize,
+                           const SkRect& bounds, SkScalar offset,
                            SkTDArray<SkPoint>* offsetPolygon, SkTDArray<int>* polygonIndices) {
     if (inputPolygonSize < 3) {
         return false;
@@ -1161,6 +1162,12 @@
         return false;
     }
 
+    // can't inset more than the half bounds of the polygon
+    if (offset > SkTMin(SkTAbs(SK_ScalarHalf*bounds.width()),
+                        SkTAbs(SK_ScalarHalf*bounds.height()))) {
+        return false;
+    }
+
     // offsetting close to zero just returns the original poly
     if (SkScalarNearlyZero(offset)) {
         for (int i = 0; i < inputPolygonSize; ++i) {
diff --git a/src/utils/SkPolyUtils.h b/src/utils/SkPolyUtils.h
index a7b3b79..6c3403e 100644
--- a/src/utils/SkPolyUtils.h
+++ b/src/utils/SkPolyUtils.h
@@ -13,6 +13,8 @@
 #include "include/core/SkPoint.h"
 #include "include/private/SkTDArray.h"
 
+struct SkRect;
+
 /**
  * Generates a polygon that is inset a constant from the boundary of a given convex polygon.
  *
@@ -33,6 +35,7 @@
  *
  * @param inputPolygonVerts  Array of points representing the vertices of the original polygon.
  * @param inputPolygonSize  Number of vertices in the original polygon.
+ * @param bounds Bounding rectangle for the original polygon.
  * @param offset How far we wish to offset the polygon.
  *   Positive values indicate insetting, negative values outsetting.
  * @param offsetPolgon  The resulting offset polygon, if any.
@@ -40,7 +43,7 @@
  * @return true if an offset simple polygon exists, false otherwise.
  */
 bool SkOffsetSimplePolygon(const SkPoint* inputPolygonVerts, int inputPolygonSize,
-                           SkScalar offset, SkTDArray<SkPoint>* offsetPolygon,
+                           const SkRect& bounds, SkScalar offset, SkTDArray<SkPoint>* offsetPolygon,
                            SkTDArray<int>* polygonIndices = nullptr);
 
 /**
diff --git a/src/utils/SkShadowTessellator.cpp b/src/utils/SkShadowTessellator.cpp
index a43a337..6dc7a75 100644
--- a/src/utils/SkShadowTessellator.cpp
+++ b/src/utils/SkShadowTessellator.cpp
@@ -25,7 +25,7 @@
  */
 class SkBaseShadowTessellator {
 public:
-    SkBaseShadowTessellator(const SkPoint3& zPlaneParams, bool transparent);
+    SkBaseShadowTessellator(const SkPoint3& zPlaneParams, const SkRect& bounds, bool transparent);
     virtual ~SkBaseShadowTessellator() {}
 
     sk_sp<SkVertices> releaseVertices() {
@@ -99,6 +99,7 @@
     SkTDArray<SkPoint>   fClipPolygon;
     SkTDArray<SkVector>  fClipVectors;
 
+    SkRect              fPathBounds;
     SkPoint             fCentroid;
     SkScalar            fArea;
     SkScalar            fLastArea;
@@ -155,8 +156,10 @@
     return v0.cross(v1);
 }
 
-SkBaseShadowTessellator::SkBaseShadowTessellator(const SkPoint3& zPlaneParams, bool transparent)
+SkBaseShadowTessellator::SkBaseShadowTessellator(const SkPoint3& zPlaneParams, const SkRect& bounds,
+                                                 bool transparent)
         : fZPlaneParams(zPlaneParams)
+        , fPathBounds(bounds)
         , fCentroid({0, 0})
         , fArea(0)
         , fLastArea(0)
@@ -559,7 +562,7 @@
     SkTDArray<SkPoint> umbraPolygon;
     SkTDArray<int> umbraIndices;
     umbraIndices.setReserve(fPathPolygon.count());
-    if (!SkOffsetSimplePolygon(&fPathPolygon[0], fPathPolygon.count(), inset,
+    if (!SkOffsetSimplePolygon(&fPathPolygon[0], fPathPolygon.count(), fPathBounds, inset,
                                &umbraPolygon, &umbraIndices)) {
         // TODO: figure out how to handle this case
         return false;
@@ -570,7 +573,7 @@
     SkTDArray<int> penumbraIndices;
     penumbraPolygon.setReserve(umbraPolygon.count());
     penumbraIndices.setReserve(umbraPolygon.count());
-    if (!SkOffsetSimplePolygon(&fPathPolygon[0], fPathPolygon.count(), -outset,
+    if (!SkOffsetSimplePolygon(&fPathPolygon[0], fPathPolygon.count(), fPathBounds, -outset,
                                &penumbraPolygon, &penumbraIndices)) {
         // TODO: figure out how to handle this case
         return false;
@@ -904,12 +907,14 @@
                                                        const SkMatrix& ctm,
                                                        const SkPoint3& zPlaneParams,
                                                        bool transparent)
-        : INHERITED(zPlaneParams, transparent) {
+        : INHERITED(zPlaneParams, path.getBounds(), transparent) {
     // Set base colors
-    auto baseZ = heightFunc(path.getBounds().centerX(), path.getBounds().centerY());
+    auto baseZ = heightFunc(fPathBounds.centerX(), fPathBounds.centerY());
     // umbraColor is the interior value, penumbraColor the exterior value.
     auto outset = SkDrawShadowMetrics::AmbientBlurRadius(baseZ);
     auto inset = outset * SkDrawShadowMetrics::AmbientRecipAlpha(baseZ) - outset;
+    inset = SkScalarPin(inset, 0, SkTMin(path.getBounds().width(),
+                                         path.getBounds().height()));
 
     if (!this->computePathPolygon(path, ctm)) {
         return;
@@ -999,7 +1004,7 @@
                                                  const SkPoint3& zPlaneParams,
                                                  const SkPoint3& lightPos, SkScalar lightRadius,
                                                  bool transparent)
-    : INHERITED(zPlaneParams, transparent) {
+    : INHERITED(zPlaneParams, path.getBounds(), transparent) {
 
     // Compute the blur radius, scale and translation for the spot shadow.
     SkMatrix shadowTransform;