Remove manual memory allocation in CGdiplusExt::DrawPath().

Use a vector instead. Use more span and fix nits along the way.

Change-Id: I40b16d8d32dc57b3e79f88f2f5c387a8ed56191b
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/67655
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxge/win32/fx_win32_gdipext.cpp b/core/fxge/win32/fx_win32_gdipext.cpp
index 272e408..a4ce59e 100644
--- a/core/fxge/win32/fx_win32_gdipext.cpp
+++ b/core/fxge/win32/fx_win32_gdipext.cpp
@@ -12,6 +12,7 @@
 #include <memory>
 #include <sstream>
 #include <utility>
+#include <vector>
 
 #include "core/fxcrt/fx_system.h"
 #include "core/fxge/cfx_gemodule.h"
@@ -19,6 +20,7 @@
 #include "core/fxge/cfx_pathdata.h"
 #include "core/fxge/win32/cfx_windowsdib.h"
 #include "core/fxge/win32/win32_int.h"
+#include "third_party/base/span.h"
 
 // Has to come before gdiplus.h
 namespace Gdiplus {
@@ -483,12 +485,13 @@
   return pPen;
 }
 
-Optional<std::pair<size_t, size_t>> IsSmallTriangle(Gdiplus::PointF* points,
-                                                    const CFX_Matrix* pMatrix) {
-  size_t pairs[] = {1, 2, 0, 2, 0, 1};
-  for (size_t i = 0; i < FX_ArraySize(pairs) / 2; i++) {
-    size_t pair1 = pairs[i * 2];
-    size_t pair2 = pairs[i * 2 + 1];
+Optional<std::pair<size_t, size_t>> IsSmallTriangle(
+    pdfium::span<const Gdiplus::PointF> points,
+    const CFX_Matrix* pMatrix) {
+  static constexpr size_t kPairs[3][2] = {{1, 2}, {0, 2}, {0, 1}};
+  for (size_t i = 0; i < FX_ArraySize(kPairs); ++i) {
+    size_t pair1 = kPairs[i][0];
+    size_t pair2 = kPairs[i][1];
 
     CFX_PointF p1(points[pair1].X, points[pair1].Y);
     CFX_PointF p2(points[pair2].X, points[pair2].Y);
@@ -499,7 +502,7 @@
 
     CFX_PointF diff = p1 - p2;
     float distance_square = (diff.x * diff.x) + (diff.y * diff.y);
-    if (distance_square < (1.0f * 2 + 1.0f / 4))
+    if (distance_square < 2.25f)
       return std::make_pair(i, pair1);
   }
   return {};
@@ -827,62 +830,65 @@
                                 pObject2Device->e, pObject2Device->f, &pMatrix);
     CallFunc(GdipSetWorldTransform)(pGraphics, pMatrix);
   }
-  Gdiplus::PointF* points = FX_Alloc(Gdiplus::PointF, pPoints.size());
-  BYTE* types = FX_Alloc(BYTE, pPoints.size());
+  std::vector<Gdiplus::PointF> gp_points(pPoints.size());
+  std::vector<BYTE> gp_types(pPoints.size());
   int nSubPathes = 0;
   bool bSubClose = false;
   int pos_subclose = 0;
   bool bSmooth = false;
   int startpoint = 0;
   for (size_t i = 0; i < pPoints.size(); i++) {
-    points[i].X = pPoints[i].m_Point.x;
-    points[i].Y = pPoints[i].m_Point.y;
+    gp_points[i].X = pPoints[i].m_Point.x;
+    gp_points[i].Y = pPoints[i].m_Point.y;
 
     CFX_PointF pos = pPoints[i].m_Point;
     if (pObject2Device)
       pos = pObject2Device->Transform(pos);
 
-    if (pos.x > 50000 * 1.0f)
-      points[i].X = 50000 * 1.0f;
-    if (pos.x < -50000 * 1.0f)
-      points[i].X = -50000 * 1.0f;
-    if (pos.y > 50000 * 1.0f)
-      points[i].Y = 50000 * 1.0f;
-    if (pos.y < -50000 * 1.0f)
-      points[i].Y = -50000 * 1.0f;
+    if (pos.x > 50000.0f)
+      gp_points[i].X = 50000.0f;
+    if (pos.x < -50000.0f)
+      gp_points[i].X = -50000.0f;
+    if (pos.y > 50000.0f)
+      gp_points[i].Y = 50000.0f;
+    if (pos.y < -50000.0f)
+      gp_points[i].Y = -50000.0f;
 
     FXPT_TYPE point_type = pPoints[i].m_Type;
     if (point_type == FXPT_TYPE::MoveTo) {
-      types[i] = Gdiplus::PathPointTypeStart;
+      gp_types[i] = Gdiplus::PathPointTypeStart;
       nSubPathes++;
       bSubClose = false;
       startpoint = i;
     } else if (point_type == FXPT_TYPE::LineTo) {
-      types[i] = Gdiplus::PathPointTypeLine;
+      gp_types[i] = Gdiplus::PathPointTypeLine;
       if (pPoints[i - 1].IsTypeAndOpen(FXPT_TYPE::MoveTo) &&
           (i == pPoints.size() - 1 ||
            pPoints[i + 1].IsTypeAndOpen(FXPT_TYPE::MoveTo)) &&
-          points[i].Y == points[i - 1].Y && points[i].X == points[i - 1].X) {
-        points[i].X += 0.01f;
+          gp_points[i].Y == gp_points[i - 1].Y &&
+          gp_points[i].X == gp_points[i - 1].X) {
+        gp_points[i].X += 0.01f;
         continue;
       }
-      if (!bSmooth && points[i].X != points[i - 1].X &&
-          points[i].Y != points[i - 1].Y)
+      if (!bSmooth && gp_points[i].X != gp_points[i - 1].X &&
+          gp_points[i].Y != gp_points[i - 1].Y) {
         bSmooth = true;
+      }
     } else if (point_type == FXPT_TYPE::BezierTo) {
-      types[i] = Gdiplus::PathPointTypeBezier;
+      gp_types[i] = Gdiplus::PathPointTypeBezier;
       bSmooth = true;
     }
     if (pPoints[i].m_CloseFigure) {
       if (bSubClose)
-        types[pos_subclose] &= ~Gdiplus::PathPointTypeCloseSubpath;
+        gp_types[pos_subclose] &= ~Gdiplus::PathPointTypeCloseSubpath;
       else
         bSubClose = true;
       pos_subclose = i;
-      types[i] |= Gdiplus::PathPointTypeCloseSubpath;
-      if (!bSmooth && points[i].X != points[startpoint].X &&
-          points[i].Y != points[startpoint].Y)
+      gp_types[i] |= Gdiplus::PathPointTypeCloseSubpath;
+      if (!bSmooth && gp_points[i].X != gp_points[startpoint].X &&
+          gp_points[i].Y != gp_points[startpoint].Y) {
         bSmooth = true;
+      }
     }
   }
   if (fill_mode & FXFILL_NOPATHSMOOTH) {
@@ -899,30 +905,28 @@
   }
   int new_fill_mode = fill_mode & 3;
   if (pPoints.size() == 4 && !pGraphState) {
-    auto indices = IsSmallTriangle(points, pObject2Device);
+    auto indices = IsSmallTriangle(gp_points, pObject2Device);
     if (indices.has_value()) {
       size_t v1;
       size_t v2;
       std::tie(v1, v2) = indices.value();
       Gdiplus::GpPen* pPen = nullptr;
       CallFunc(GdipCreatePen1)(fill_argb, 1.0f, Gdiplus::UnitPixel, &pPen);
-      CallFunc(GdipDrawLineI)(pGraphics, pPen, FXSYS_roundf(points[v1].X),
-                              FXSYS_roundf(points[v1].Y),
-                              FXSYS_roundf(points[v2].X),
-                              FXSYS_roundf(points[v2].Y));
+      CallFunc(GdipDrawLineI)(pGraphics, pPen, FXSYS_roundf(gp_points[v1].X),
+                              FXSYS_roundf(gp_points[v1].Y),
+                              FXSYS_roundf(gp_points[v2].X),
+                              FXSYS_roundf(gp_points[v2].Y));
       CallFunc(GdipDeletePen)(pPen);
       return true;
     }
   }
   Gdiplus::GpPath* pGpPath = nullptr;
-  CallFunc(GdipCreatePath2)(points, types, pPoints.size(),
+  CallFunc(GdipCreatePath2)(gp_points.data(), gp_types.data(), pPoints.size(),
                             GdiFillType2Gdip(new_fill_mode), &pGpPath);
   if (!pGpPath) {
     if (pMatrix)
       CallFunc(GdipDeleteMatrix)(pMatrix);
 
-    FX_Free(points);
-    FX_Free(types);
     CallFunc(GdipDeleteGraphics)(pGraphics);
     return false;
   }
@@ -942,9 +946,9 @@
       int iStart = 0;
       for (size_t i = 0; i < pPoints.size(); i++) {
         if (i == pPoints.size() - 1 ||
-            types[i + 1] == Gdiplus::PathPointTypeStart) {
+            gp_types[i + 1] == Gdiplus::PathPointTypeStart) {
           Gdiplus::GpPath* pSubPath;
-          CallFunc(GdipCreatePath2)(points + iStart, types + iStart,
+          CallFunc(GdipCreatePath2)(&gp_points[iStart], &gp_types[iStart],
                                     i - iStart + 1,
                                     GdiFillType2Gdip(new_fill_mode), &pSubPath);
           iStart = i + 1;
@@ -957,8 +961,6 @@
   }
   if (pMatrix)
     CallFunc(GdipDeleteMatrix)(pMatrix);
-  FX_Free(points);
-  FX_Free(types);
   CallFunc(GdipDeletePath)(pGpPath);
   CallFunc(GdipDeleteGraphics)(pGraphics);
   return true;