[Impeller] Change Path::CreatePolyline from tolerance to scale, and make it required (#39917)

[Impeller] Change Path::CreatePolyline from tolerance to scale, and make it required
diff --git a/impeller/entity/contents/texture_contents.cc b/impeller/entity/contents/texture_contents.cc
index 7375922..7375598 100644
--- a/impeller/entity/contents/texture_contents.cc
+++ b/impeller/entity/contents/texture_contents.cc
@@ -123,7 +123,7 @@
   VertexBufferBuilder<VS::PerVertexData> vertex_builder;
   {
     const auto tess_result = renderer.GetTessellator()->Tessellate(
-        path_.GetFillType(), path_.CreatePolyline(),
+        path_.GetFillType(), path_.CreatePolyline(1.0f),
         [this, &vertex_builder, &coverage_rect, &texture_size](
             const float* vertices, size_t vertices_size,
             const uint16_t* indices, size_t indices_size) {
diff --git a/impeller/entity/geometry.cc b/impeller/entity/geometry.cc
index fa3f201..c86eaa6 100644
--- a/impeller/entity/geometry.cc
+++ b/impeller/entity/geometry.cc
@@ -53,13 +53,11 @@
     const ContentContext& renderer,
     const Entity& entity,
     RenderPass& pass) {
-  auto tolerance =
-      kDefaultCurveTolerance / entity.GetTransformation().GetMaxBasisLength();
-
   VertexBuffer vertex_buffer;
   auto& host_buffer = pass.GetTransientsBuffer();
   auto tesselation_result = renderer.GetTessellator()->Tessellate(
-      path_.GetFillType(), path_.CreatePolyline(tolerance),
+      path_.GetFillType(),
+      path_.CreatePolyline(entity.GetTransformation().GetMaxBasisLength()),
       [&vertex_buffer, &host_buffer](
           const float* vertices, size_t vertices_count, const uint16_t* indices,
           size_t indices_count) {
@@ -151,7 +149,7 @@
       join_proc = [](VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
                      const Point& position, const Point& start_offset,
                      const Point& end_offset, Scalar miter_limit,
-                     Scalar tolerance) {
+                     Scalar scale) {
         CreateBevelAndGetDirection(vtx_builder, position, start_offset,
                                    end_offset);
       };
@@ -160,7 +158,7 @@
       join_proc = [](VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
                      const Point& position, const Point& start_offset,
                      const Point& end_offset, Scalar miter_limit,
-                     Scalar tolerance) {
+                     Scalar scale) {
         Point start_normal = start_offset.Normalize();
         Point end_normal = end_offset.Normalize();
 
@@ -189,7 +187,7 @@
       join_proc = [](VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
                      const Point& position, const Point& start_offset,
                      const Point& end_offset, Scalar miter_limit,
-                     Scalar tolerance) {
+                     Scalar scale) {
         Point start_normal = start_offset.Normalize();
         Point end_normal = end_offset.Normalize();
 
@@ -216,7 +214,7 @@
 
         auto arc_points = CubicPathComponent(start_offset, start_handle,
                                              middle_handle, middle)
-                              .CreatePolyline(tolerance);
+                              .CreatePolyline(scale);
 
         VS::PerVertexData vtx;
         for (const auto& point : arc_points) {
@@ -238,8 +236,7 @@
   switch (stroke_cap) {
     case Cap::kButt:
       cap_proc = [](VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
-                    const Point& position, const Point& offset,
-                    Scalar tolerance) {
+                    const Point& position, const Point& offset, Scalar scale) {
         VS::PerVertexData vtx;
         vtx.position = position + offset;
         vtx_builder.AppendVertex(vtx);
@@ -249,8 +246,7 @@
       break;
     case Cap::kRound:
       cap_proc = [](VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
-                    const Point& position, const Point& offset,
-                    Scalar tolerance) {
+                    const Point& position, const Point& offset, Scalar scale) {
         VS::PerVertexData vtx;
 
         Point forward(offset.y, -offset.x);
@@ -260,7 +256,7 @@
             CubicPathComponent(
                 offset, offset + forward * PathBuilder::kArcApproximationMagic,
                 forward + offset * PathBuilder::kArcApproximationMagic, forward)
-                .CreatePolyline(tolerance);
+                .CreatePolyline(scale);
 
         vtx.position = position + offset;
         vtx_builder.AppendVertex(vtx);
@@ -276,8 +272,7 @@
       break;
     case Cap::kSquare:
       cap_proc = [](VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
-                    const Point& position, const Point& offset,
-                    Scalar tolerance) {
+                    const Point& position, const Point& offset, Scalar scale) {
         VS::PerVertexData vtx;
 
         Point forward(offset.y, -offset.x);
@@ -305,9 +300,9 @@
     Cap cap,
     const StrokePathGeometry::JoinProc& join_proc,
     const StrokePathGeometry::CapProc& cap_proc,
-    Scalar tolerance) {
+    Scalar scale) {
   VertexBufferBuilder<VS::PerVertexData> vtx_builder;
-  auto polyline = path.CreatePolyline();
+  auto polyline = path.CreatePolyline(scale);
 
   VS::PerVertexData vtx;
 
@@ -333,8 +328,8 @@
     switch (contour_end_point_i - contour_start_point_i) {
       case 1: {
         Point p = polyline.points[contour_start_point_i];
-        cap_proc(vtx_builder, p, {-stroke_width * 0.5f, 0}, tolerance);
-        cap_proc(vtx_builder, p, {stroke_width * 0.5f, 0}, tolerance);
+        cap_proc(vtx_builder, p, {-stroke_width * 0.5f, 0}, scale);
+        cap_proc(vtx_builder, p, {stroke_width * 0.5f, 0}, scale);
         continue;
       }
       case 0:
@@ -381,7 +376,7 @@
       }
       auto cap_offset = direction * stroke_width * 0.5;
       cap_proc(vtx_builder, polyline.points[contour_start_point_i], cap_offset,
-               tolerance);
+               scale);
     }
 
     // Generate contour geometry.
@@ -402,7 +397,7 @@
 
         // Generate join from the current line to the next line.
         join_proc(vtx_builder, polyline.points[point_i], previous_offset,
-                  offset, scaled_miter_limit, tolerance);
+                  offset, scaled_miter_limit, scale);
       }
     }
 
@@ -412,10 +407,10 @@
           Vector2(-contour.end_direction.y, contour.end_direction.x) *
           stroke_width * 0.5;
       cap_proc(vtx_builder, polyline.points[contour_end_point_i - 1],
-               cap_offset, tolerance);
+               cap_offset, scale);
     } else {
       join_proc(vtx_builder, polyline.points[contour_start_point_i], offset,
-                contour_first_offset, scaled_miter_limit, tolerance);
+                contour_first_offset, scaled_miter_limit, scale);
     }
   }
 
@@ -437,15 +432,11 @@
   Scalar min_size = 1.0f / sqrt(std::abs(determinant));
   Scalar stroke_width = std::max(stroke_width_, min_size);
 
-  auto tolerance =
-      kDefaultCurveTolerance /
-      (stroke_width_ * entity.GetTransformation().GetMaxBasisLength());
-
   auto& host_buffer = pass.GetTransientsBuffer();
   auto vertex_buffer = CreateSolidStrokeVertices(
       path_, host_buffer, stroke_width, miter_limit_ * stroke_width_ * 0.5,
       stroke_cap_, GetJoinProc(stroke_join_), GetCapProc(stroke_cap_),
-      tolerance);
+      entity.GetTransformation().GetMaxBasisLength());
 
   return GeometryResult{
       .type = PrimitiveType::kTriangleStrip,
diff --git a/impeller/entity/geometry.h b/impeller/entity/geometry.h
index d5eb6af..f595eee 100644
--- a/impeller/entity/geometry.h
+++ b/impeller/entity/geometry.h
@@ -134,14 +134,14 @@
       std::function<void(VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
                          const Point& position,
                          const Point& offset,
-                         Scalar tolerance)>;
+                         Scalar scale)>;
   using JoinProc =
       std::function<void(VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
                          const Point& position,
                          const Point& start_offset,
                          const Point& end_offset,
                          Scalar miter_limit,
-                         Scalar tolerance)>;
+                         Scalar scale)>;
 
   // |Geometry|
   GeometryResult GetPositionBuffer(const ContentContext& renderer,
@@ -167,7 +167,7 @@
                                                 Cap cap,
                                                 const JoinProc& join_proc,
                                                 const CapProc& cap_proc,
-                                                Scalar tolerance);
+                                                Scalar scale);
 
   static StrokePathGeometry::JoinProc GetJoinProc(Join stroke_join);
 
diff --git a/impeller/geometry/geometry_benchmarks.cc b/impeller/geometry/geometry_benchmarks.cc
index 06b514b..d3c1f9e 100644
--- a/impeller/geometry/geometry_benchmarks.cc
+++ b/impeller/geometry/geometry_benchmarks.cc
@@ -29,7 +29,7 @@
   size_t point_count = 0u;
   size_t single_point_count = 0u;
   while (state.KeepRunning()) {
-    auto polyline = path.CreatePolyline();
+    auto polyline = path.CreatePolyline(1.0f);
     single_point_count = polyline.points.size();
     point_count += single_point_count;
     if (tessellate) {
diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc
index 8edada6..1e3db56 100644
--- a/impeller/geometry/geometry_unittests.cc
+++ b/impeller/geometry/geometry_unittests.cc
@@ -17,7 +17,6 @@
 #include "impeller/geometry/rect.h"
 #include "impeller/geometry/scalar.h"
 #include "impeller/geometry/size.h"
-#include "path_component.h"
 
 namespace impeller {
 namespace testing {
@@ -577,7 +576,7 @@
   path.GetContourComponentAtIndex(0, c);
   ASSERT_POINT_NEAR(c.destination, Point());
 
-  Path::Polyline polyline = path.CreatePolyline();
+  Path::Polyline polyline = path.CreatePolyline(1.0f);
   ASSERT_TRUE(polyline.points.empty());
   ASSERT_TRUE(polyline.contours.empty());
 }
@@ -1596,7 +1595,7 @@
   path.AddContourComponent({40, 40});
   path.AddLinearComponent({40, 40}, {50, 50});
 
-  auto polyline = path.CreatePolyline();
+  auto polyline = path.CreatePolyline(1.0f);
 
   ASSERT_EQ(polyline.contours.size(), 2u);
   ASSERT_EQ(polyline.points.size(), 5u);
@@ -1682,7 +1681,7 @@
                                 .LineTo({200, 200})
                                 .Close()
                                 .TakePath()
-                                .CreatePolyline();
+                                .CreatePolyline(1.0f);
   ASSERT_EQ(polyline.points.size(), 6u);
   ASSERT_EQ(polyline.contours.size(), 2u);
   ASSERT_EQ(polyline.contours[0].is_closed, false);
@@ -1699,7 +1698,7 @@
                                 .LineTo({200, 200})
                                 .Close()
                                 .TakePath()
-                                .CreatePolyline();
+                                .CreatePolyline(1.0f);
   size_t a1, a2, b1, b2;
   std::tie(a1, a2) = polyline.GetContourPointBounds(0);
   std::tie(b1, b2) = polyline.GetContourPointBounds(1);
@@ -1713,7 +1712,7 @@
   Path::Polyline polyline = PathBuilder{}
                                 .AddRect(Rect::MakeLTRB(50, 60, 70, 80))
                                 .TakePath()
-                                .CreatePolyline();
+                                .CreatePolyline(1.0f);
   ASSERT_EQ(polyline.contours.size(), 1u);
   ASSERT_TRUE(polyline.contours[0].is_closed);
   ASSERT_EQ(polyline.contours[0].start_index, 0u);
@@ -1738,7 +1737,7 @@
           .LineTo({0, 100})
           .LineTo({0, 100})  // Insert duplicate at end of contour.
           .TakePath()
-          .CreatePolyline();
+          .CreatePolyline(1.0f);
   ASSERT_EQ(polyline.contours.size(), 2u);
   ASSERT_EQ(polyline.contours[0].start_index, 0u);
   ASSERT_TRUE(polyline.contours[0].is_closed);
diff --git a/impeller/geometry/path.cc b/impeller/geometry/path.cc
index cad3774..b5f2693 100644
--- a/impeller/geometry/path.cc
+++ b/impeller/geometry/path.cc
@@ -7,6 +7,7 @@
 #include <optional>
 
 #include "impeller/geometry/path_component.h"
+#include "path_component.h"
 
 namespace impeller {
 
@@ -221,8 +222,9 @@
   return true;
 }
 
-Path::Polyline Path::CreatePolyline(Scalar tolerance) const {
+Path::Polyline Path::CreatePolyline(Scalar scale) const {
   Polyline polyline;
+  auto tolerance = kDefaultCurveTolerance / scale;
 
   std::optional<Point> previous_contour_point;
   auto collect_points = [&polyline, &previous_contour_point](
diff --git a/impeller/geometry/path.h b/impeller/geometry/path.h
index 9e348cd..0c4cf69 100644
--- a/impeller/geometry/path.h
+++ b/impeller/geometry/path.h
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "impeller/geometry/path_component.h"
+#include "path_component.h"
 
 namespace impeller {
 
@@ -122,7 +123,12 @@
   bool UpdateContourComponentAtIndex(size_t index,
                                      const ContourComponent& contour);
 
-  Polyline CreatePolyline(Scalar tolerance = kDefaultCurveTolerance) const;
+  /// Callers must provide the scale factor for how this path will be
+  /// transformed.
+  ///
+  /// It is suitable to use the max basis length of the matrix used to transform
+  /// the path. If the provided scale is 0, curves will revert to lines.
+  Polyline CreatePolyline(Scalar scale) const;
 
   std::optional<Rect> GetBoundingBox() const;
 
diff --git a/impeller/renderer/renderer_unittests.cc b/impeller/renderer/renderer_unittests.cc
index 79c79cb..aec9c77 100644
--- a/impeller/renderer/renderer_unittests.cc
+++ b/impeller/renderer/renderer_unittests.cc
@@ -396,7 +396,7 @@
                 PathBuilder{}
                     .AddRect(Rect::MakeXYWH(10, 10, 100, 100))
                     .TakePath()
-                    .CreatePolyline(),
+                    .CreatePolyline(1.0f),
                 [&builder](const float* vertices, size_t vertices_size,
                            const uint16_t* indices, size_t indices_size) {
                   for (auto i = 0u; i < vertices_size; i += 2) {
diff --git a/impeller/tessellator/tessellator_unittests.cc b/impeller/tessellator/tessellator_unittests.cc
index 56c2478..0b943d1 100644
--- a/impeller/tessellator/tessellator_unittests.cc
+++ b/impeller/tessellator/tessellator_unittests.cc
@@ -14,7 +14,7 @@
   // Zero points.
   {
     Tessellator t;
-    auto polyline = PathBuilder{}.TakePath().CreatePolyline();
+    auto polyline = PathBuilder{}.TakePath().CreatePolyline(1.0f);
     Tessellator::Result result = t.Tessellate(
         FillType::kPositive, polyline,
         [](const float* vertices, size_t vertices_size, const uint16_t* indices,
@@ -27,7 +27,8 @@
   // One point.
   {
     Tessellator t;
-    auto polyline = PathBuilder{}.LineTo({0, 0}).TakePath().CreatePolyline();
+    auto polyline =
+        PathBuilder{}.LineTo({0, 0}).TakePath().CreatePolyline(1.0f);
     Tessellator::Result result = t.Tessellate(
         FillType::kPositive, polyline,
         [](const float* vertices, size_t vertices_size, const uint16_t* indices,
@@ -40,7 +41,7 @@
   {
     Tessellator t;
     auto polyline =
-        PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline();
+        PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline(1.0f);
     Tessellator::Result result = t.Tessellate(
         FillType::kPositive, polyline,
         [](const float* vertices, size_t vertices_size, const uint16_t* indices,
@@ -58,7 +59,7 @@
       auto coord = i * 1.0f;
       builder.AddLine({coord, coord}, {coord + 1, coord + 1});
     }
-    auto polyline = builder.TakePath().CreatePolyline();
+    auto polyline = builder.TakePath().CreatePolyline(1.0f);
     Tessellator::Result result = t.Tessellate(
         FillType::kPositive, polyline,
         [](const float* vertices, size_t vertices_size, const uint16_t* indices,
@@ -72,7 +73,7 @@
   {
     Tessellator t;
     auto polyline =
-        PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline();
+        PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline(1.0f);
     Tessellator::Result result = t.Tessellate(
         FillType::kPositive, polyline,
         [](const float* vertices, size_t vertices_size, const uint16_t* indices,