Reland Cleanup CPDF_MeshStream

This CL fixes up the bits of the CPDF_MeshStream CL that depended on the Origin
CL and integrates the fixes for the Skia bots.

Change-Id: I470e49c35b809f00fecbaeb303de15c0db3fe590
Reviewed-on: https://pdfium-review.googlesource.com/2698
Reviewed-by: Nicolás Peña <npm@chromium.org>
Commit-Queue: dsinclair <dsinclair@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_meshstream.cpp b/core/fpdfapi/page/cpdf_meshstream.cpp
index b852901..fbbd222 100644
--- a/core/fpdfapi/page/cpdf_meshstream.cpp
+++ b/core/fpdfapi/page/cpdf_meshstream.cpp
@@ -83,6 +83,12 @@
 
 }  // namespace
 
+CPDF_MeshVertex::CPDF_MeshVertex() = default;
+
+CPDF_MeshVertex::CPDF_MeshVertex(const CPDF_MeshVertex&) = default;
+
+CPDF_MeshVertex::~CPDF_MeshVertex() = default;
+
 CPDF_MeshStream::CPDF_MeshStream(
     ShadingType type,
     const std::vector<std::unique_ptr<CPDF_Function>>& funcs,
@@ -148,37 +154,47 @@
   return true;
 }
 
-uint32_t CPDF_MeshStream::GetFlag() {
+uint32_t CPDF_MeshStream::ReadFlag() {
   ASSERT(ShouldCheckBitsPerFlag(m_type));
   return m_BitStream.GetBits(m_nFlagBits) & 0x03;
 }
 
-void CPDF_MeshStream::GetCoords(FX_FLOAT& x, FX_FLOAT& y) {
+CFX_PointF CPDF_MeshStream::ReadCoords() {
   ASSERT(ShouldCheckBPC(m_type));
+
+  CFX_PointF pos;
   if (m_nCoordBits == 32) {
-    x = m_xmin + (FX_FLOAT)(m_BitStream.GetBits(m_nCoordBits) *
-                            (m_xmax - m_xmin) / (double)m_CoordMax);
-    y = m_ymin + (FX_FLOAT)(m_BitStream.GetBits(m_nCoordBits) *
-                            (m_ymax - m_ymin) / (double)m_CoordMax);
+    pos.x = m_xmin +
+            m_BitStream.GetBits(m_nCoordBits) * (m_xmax - m_xmin) /
+                static_cast<double>(m_CoordMax);
+    pos.y = m_ymin +
+            m_BitStream.GetBits(m_nCoordBits) * (m_ymax - m_ymin) /
+                static_cast<double>(m_CoordMax);
   } else {
-    x = m_xmin +
-        m_BitStream.GetBits(m_nCoordBits) * (m_xmax - m_xmin) / m_CoordMax;
-    y = m_ymin +
-        m_BitStream.GetBits(m_nCoordBits) * (m_ymax - m_ymin) / m_CoordMax;
+    pos.x = m_xmin +
+            m_BitStream.GetBits(m_nCoordBits) * (m_xmax - m_xmin) / m_CoordMax;
+    pos.y = m_ymin +
+            m_BitStream.GetBits(m_nCoordBits) * (m_ymax - m_ymin) / m_CoordMax;
   }
+  return pos;
 }
 
-void CPDF_MeshStream::GetColor(FX_FLOAT& r, FX_FLOAT& g, FX_FLOAT& b) {
+std::tuple<FX_FLOAT, FX_FLOAT, FX_FLOAT> CPDF_MeshStream::ReadColor() {
   ASSERT(ShouldCheckBPC(m_type));
+
   FX_FLOAT color_value[kMaxComponents];
   for (uint32_t i = 0; i < m_nComponents; ++i) {
     color_value[i] = m_ColorMin[i] +
                      m_BitStream.GetBits(m_nComponentBits) *
                          (m_ColorMax[i] - m_ColorMin[i]) / m_ComponentMax;
   }
+
+  FX_FLOAT r;
+  FX_FLOAT g;
+  FX_FLOAT b;
   if (m_funcs.empty()) {
     m_pCS->GetRGB(color_value, r, g, b);
-    return;
+    return std::tuple<FX_FLOAT, FX_FLOAT, FX_FLOAT>(r, g, b);
   }
 
   FX_FLOAT result[kMaxComponents];
@@ -188,29 +204,34 @@
     if (func && func->CountOutputs() <= kMaxComponents)
       func->Call(color_value, 1, result, nResults);
   }
+
   m_pCS->GetRGB(result, r, g, b);
+  return std::tuple<FX_FLOAT, FX_FLOAT, FX_FLOAT>(r, g, b);
 }
 
-uint32_t CPDF_MeshStream::GetVertex(CPDF_MeshVertex& vertex,
-                                    CFX_Matrix* pObject2Bitmap) {
-  uint32_t flag = GetFlag();
-  GetCoords(vertex.x, vertex.y);
-  pObject2Bitmap->TransformPoint(vertex.x, vertex.y);
-  GetColor(vertex.r, vertex.g, vertex.b);
+CPDF_MeshVertex CPDF_MeshStream::ReadVertex(const CFX_Matrix& pObject2Bitmap,
+                                            uint32_t* flag) {
+  *flag = ReadFlag();
+
+  CPDF_MeshVertex vertex;
+  vertex.position = ReadCoords();
+  pObject2Bitmap.TransformPoint(vertex.position.x, vertex.position.y);
+  std::tie(vertex.r, vertex.g, vertex.b) = ReadColor();
   m_BitStream.ByteAlign();
-  return flag;
+
+  return vertex;
 }
 
-bool CPDF_MeshStream::GetVertexRow(CPDF_MeshVertex* vertex,
-                                   int count,
-                                   CFX_Matrix* pObject2Bitmap) {
+bool CPDF_MeshStream::ReadVertexRow(const CFX_Matrix& pObject2Bitmap,
+                                    int count,
+                                    CPDF_MeshVertex* vertex) {
   for (int i = 0; i < count; i++) {
     if (m_BitStream.IsEOF())
       return false;
 
-    GetCoords(vertex[i].x, vertex[i].y);
-    pObject2Bitmap->TransformPoint(vertex[i].x, vertex[i].y);
-    GetColor(vertex[i].r, vertex[i].g, vertex[i].b);
+    vertex[i].position = ReadCoords();
+    pObject2Bitmap.TransformPoint(vertex[i].position.x, vertex[i].position.y);
+    std::tie(vertex[i].r, vertex[i].g, vertex[i].b) = ReadColor();
     m_BitStream.ByteAlign();
   }
   return true;
diff --git a/core/fpdfapi/page/cpdf_meshstream.h b/core/fpdfapi/page/cpdf_meshstream.h
index 21a6c2f..24f1d66 100644
--- a/core/fpdfapi/page/cpdf_meshstream.h
+++ b/core/fpdfapi/page/cpdf_meshstream.h
@@ -8,6 +8,7 @@
 #define CORE_FPDFAPI_PAGE_CPDF_MESHSTREAM_H_
 
 #include <memory>
+#include <tuple>
 #include <vector>
 
 #include "core/fpdfapi/page/cpdf_shadingpattern.h"
@@ -15,9 +16,13 @@
 #include "core/fxcrt/fx_basic.h"
 #include "core/fxcrt/fx_system.h"
 
-struct CPDF_MeshVertex {
-  FX_FLOAT x;
-  FX_FLOAT y;
+class CPDF_MeshVertex {
+ public:
+  CPDF_MeshVertex();
+  CPDF_MeshVertex(const CPDF_MeshVertex&);
+  ~CPDF_MeshVertex();
+
+  CFX_PointF position;
   FX_FLOAT r;
   FX_FLOAT g;
   FX_FLOAT b;
@@ -37,14 +42,14 @@
 
   bool Load();
 
-  uint32_t GetFlag();
-  void GetCoords(FX_FLOAT& x, FX_FLOAT& y);
-  void GetColor(FX_FLOAT& r, FX_FLOAT& g, FX_FLOAT& b);
+  uint32_t ReadFlag();
+  CFX_PointF ReadCoords();
+  std::tuple<FX_FLOAT, FX_FLOAT, FX_FLOAT> ReadColor();
 
-  uint32_t GetVertex(CPDF_MeshVertex& vertex, CFX_Matrix* pObject2Bitmap);
-  bool GetVertexRow(CPDF_MeshVertex* vertex,
-                    int count,
-                    CFX_Matrix* pObject2Bitmap);
+  CPDF_MeshVertex ReadVertex(const CFX_Matrix& pObject2Bitmap, uint32_t* flag);
+  bool ReadVertexRow(const CFX_Matrix& pObject2Bitmap,
+                     int count,
+                     CPDF_MeshVertex* vertex);
 
   CFX_BitStream* BitStream() { return &m_BitStream; }
   uint32_t ComponentBits() const { return m_nComponentBits; }
diff --git a/core/fpdfapi/page/cpdf_streamcontentparser.cpp b/core/fpdfapi/page/cpdf_streamcontentparser.cpp
index 61efb48..0af43d0 100644
--- a/core/fpdfapi/page/cpdf_streamcontentparser.cpp
+++ b/core/fpdfapi/page/cpdf_streamcontentparser.cpp
@@ -99,7 +99,7 @@
   while (!stream.BitStream()->IsEOF()) {
     uint32_t flag = 0;
     if (type != kLatticeFormGouraudTriangleMeshShading)
-      flag = stream.GetFlag();
+      flag = stream.ReadFlag();
 
     if (!bGouraud && flag) {
       point_count -= 4;
@@ -107,13 +107,11 @@
     }
 
     for (int i = 0; i < point_count; i++) {
-      FX_FLOAT x;
-      FX_FLOAT y;
-      stream.GetCoords(x, y);
+      CFX_PointF origin = stream.ReadCoords();
       if (bStarted) {
-        rect.UpdateRect(x, y);
+        rect.UpdateRect(origin.x, origin.y);
       } else {
-        rect.InitRect(x, y);
+        rect.InitRect(origin.x, origin.y);
         bStarted = true;
       }
     }
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index 60b7a49..4f2638f 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -369,67 +369,65 @@
 }
 
 bool GetScanlineIntersect(int y,
-                          FX_FLOAT x1,
-                          FX_FLOAT y1,
-                          FX_FLOAT x2,
-                          FX_FLOAT y2,
+                          const CFX_PointF& first,
+                          const CFX_PointF& second,
                           FX_FLOAT* x) {
-  if (y1 == y2)
+  if (first.y == second.y)
     return false;
 
-  if (y1 < y2) {
-    if (y < y1 || y > y2)
+  if (first.y < second.y) {
+    if (y < first.y || y > second.y)
       return false;
-  } else {
-    if (y < y2 || y > y1)
-      return false;
+  } else if (y < second.y || y > first.y) {
+    return false;
   }
-  *x = x1 + ((x2 - x1) * (y - y1) / (y2 - y1));
+  *x = first.x + ((second.x - first.x) * (y - first.y) / (second.y - first.y));
   return true;
 }
 
 void DrawGouraud(CFX_DIBitmap* pBitmap,
                  int alpha,
                  CPDF_MeshVertex triangle[3]) {
-  FX_FLOAT min_y = triangle[0].y, max_y = triangle[0].y;
+  FX_FLOAT min_y = triangle[0].position.y;
+  FX_FLOAT max_y = triangle[0].position.y;
   for (int i = 1; i < 3; i++) {
-    if (min_y > triangle[i].y) {
-      min_y = triangle[i].y;
-    }
-    if (max_y < triangle[i].y) {
-      max_y = triangle[i].y;
-    }
+    min_y = std::min(min_y, triangle[i].position.y);
+    max_y = std::max(max_y, triangle[i].position.y);
   }
-  if (min_y == max_y) {
+  if (min_y == max_y)
     return;
-  }
-  int min_yi = (int)FXSYS_floor(min_y), max_yi = (int)FXSYS_ceil(max_y);
-  if (min_yi < 0) {
-    min_yi = 0;
-  }
-  if (max_yi >= pBitmap->GetHeight()) {
+
+  int min_yi = std::max(static_cast<int>(FXSYS_floor(min_y)), 0);
+  int max_yi = static_cast<int>(FXSYS_ceil(max_y));
+
+  if (max_yi >= pBitmap->GetHeight())
     max_yi = pBitmap->GetHeight() - 1;
-  }
+
   for (int y = min_yi; y <= max_yi; y++) {
     int nIntersects = 0;
-    FX_FLOAT inter_x[3], r[3], g[3], b[3];
+    FX_FLOAT inter_x[3];
+    FX_FLOAT r[3];
+    FX_FLOAT g[3];
+    FX_FLOAT b[3];
     for (int i = 0; i < 3; i++) {
       CPDF_MeshVertex& vertex1 = triangle[i];
       CPDF_MeshVertex& vertex2 = triangle[(i + 1) % 3];
-      bool bIntersect = GetScanlineIntersect(y, vertex1.x, vertex1.y, vertex2.x,
-                                             vertex2.y, &inter_x[nIntersects]);
+      CFX_PointF& position1 = vertex1.position;
+      CFX_PointF& position2 = vertex2.position;
+      bool bIntersect =
+          GetScanlineIntersect(y, position1, position2, &inter_x[nIntersects]);
       if (!bIntersect)
         continue;
 
-      FX_FLOAT y_dist = (y - vertex1.y) / (vertex2.y - vertex1.y);
+      FX_FLOAT y_dist = (y - position1.y) / (position2.y - position1.y);
       r[nIntersects] = vertex1.r + ((vertex2.r - vertex1.r) * y_dist);
       g[nIntersects] = vertex1.g + ((vertex2.g - vertex1.g) * y_dist);
       b[nIntersects] = vertex1.b + ((vertex2.b - vertex1.b) * y_dist);
       nIntersects++;
     }
-    if (nIntersects != 2) {
+    if (nIntersects != 2)
       continue;
-    }
+
     int min_x, max_x, start_index, end_index;
     if (inter_x[0] < inter_x[1]) {
       min_x = (int)FXSYS_floor(inter_x[0]);
@@ -442,13 +440,12 @@
       start_index = 1;
       end_index = 0;
     }
-    int start_x = min_x, end_x = max_x;
-    if (start_x < 0) {
-      start_x = 0;
-    }
-    if (end_x > pBitmap->GetWidth()) {
+
+    int start_x = std::max(min_x, 0);
+    int end_x = max_x;
+    if (end_x > pBitmap->GetWidth())
       end_x = pBitmap->GetWidth();
-    }
+
     uint8_t* dib_buf =
         pBitmap->GetBuffer() + y * pBitmap->GetPitch() + start_x * 4;
     FX_FLOAT r_unit = (r[end_index] - r[start_index]) / (max_x - min_x);
@@ -487,17 +484,18 @@
   FXSYS_memset(triangle, 0, sizeof(triangle));
 
   while (!stream.BitStream()->IsEOF()) {
-    CPDF_MeshVertex vertex;
-    uint32_t flag = stream.GetVertex(vertex, pObject2Bitmap);
+    uint32_t flag;
+    CPDF_MeshVertex vertex = stream.ReadVertex(*pObject2Bitmap, &flag);
     if (flag == 0) {
       triangle[0] = vertex;
       for (int j = 1; j < 3; j++) {
-        stream.GetVertex(triangle[j], pObject2Bitmap);
+        uint32_t tflag;
+        triangle[j] = stream.ReadVertex(*pObject2Bitmap, &tflag);
       }
     } else {
-      if (flag == 1) {
+      if (flag == 1)
         triangle[0] = triangle[1];
-      }
+
       triangle[1] = triangle[2];
       triangle[2] = vertex;
     }
@@ -525,14 +523,14 @@
 
   std::unique_ptr<CPDF_MeshVertex, FxFreeDeleter> vertex(
       FX_Alloc2D(CPDF_MeshVertex, row_verts, 2));
-  if (!stream.GetVertexRow(vertex.get(), row_verts, pObject2Bitmap))
+  if (!stream.ReadVertexRow(*pObject2Bitmap, row_verts, vertex.get()))
     return;
 
   int last_index = 0;
   while (1) {
     CPDF_MeshVertex* last_row = vertex.get() + last_index * row_verts;
     CPDF_MeshVertex* this_row = vertex.get() + (1 - last_index) * row_verts;
-    if (!stream.GetVertexRow(this_row, row_verts, pObject2Bitmap))
+    if (!stream.ReadVertexRow(*pObject2Bitmap, row_verts, this_row))
       return;
 
     CPDF_MeshVertex triangle[3];
@@ -827,7 +825,7 @@
   CFX_PointF coords[16];
   int point_count = type == kTensorProductPatchMeshShading ? 16 : 12;
   while (!stream.BitStream()->IsEOF()) {
-    uint32_t flag = stream.GetFlag();
+    uint32_t flag = stream.ReadFlag();
     int iStartPoint = 0, iStartColor = 0, i = 0;
     if (flag) {
       iStartPoint = 4;
@@ -843,12 +841,16 @@
       FXSYS_memcpy(patch.patch_colors, tempColors, sizeof(Coon_Color) * 2);
     }
     for (i = iStartPoint; i < point_count; i++) {
-      stream.GetCoords(coords[i].x, coords[i].y);
+      coords[i] = stream.ReadCoords();
       pObject2Bitmap->TransformPoint(coords[i].x, coords[i].y);
     }
+
     for (i = iStartColor; i < 4; i++) {
-      FX_FLOAT r = 0.0f, g = 0.0f, b = 0.0f;
-      stream.GetColor(r, g, b);
+      FX_FLOAT r;
+      FX_FLOAT g;
+      FX_FLOAT b;
+      std::tie(r, g, b) = stream.ReadColor();
+
       patch.patch_colors[i].comp[0] = (int32_t)(r * 255);
       patch.patch_colors[i].comp[1] = (int32_t)(g * 255);
       patch.patch_colors[i].comp[2] = (int32_t)(b * 255);
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index 40bd321..c8b16f5 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -1749,7 +1749,7 @@
       m_pCanvas->clipPath(skClip, SkClipOp::kIntersect, true);
     m_pCanvas->concat(skMatrix);
     while (!stream.BitStream()->IsEOF()) {
-      uint32_t flag = stream.GetFlag();
+      uint32_t flag = stream.ReadFlag();
       int iStartPoint = flag ? 4 : 0;
       int iStartColor = flag ? 2 : 0;
       if (flag) {
@@ -1762,11 +1762,16 @@
         tempColors[1] = colors[(flag + 1) % 4];
         FXSYS_memcpy(colors, tempColors, sizeof(tempColors));
       }
-      for (int i = iStartPoint; i < (int)SK_ARRAY_COUNT(cubics); i++)
-        stream.GetCoords(cubics[i].fX, cubics[i].fY);
+      for (int i = iStartPoint; i < (int)SK_ARRAY_COUNT(cubics); i++) {
+        CFX_PointF point = stream.ReadCoords();
+        cubics[i].fX = point.x;
+        cubics[i].fY = point.y;
+      }
       for (int i = iStartColor; i < (int)SK_ARRAY_COUNT(colors); i++) {
-        FX_FLOAT r = 0.0f, g = 0.0f, b = 0.0f;
-        stream.GetColor(r, g, b);
+        FX_FLOAT r;
+        FX_FLOAT g;
+        FX_FLOAT b;
+        std::tie(r, g, b) = stream.ReadColor();
         colors[i] = SkColorSetARGBInline(0xFF, (U8CPU)(r * 255),
                                          (U8CPU)(g * 255), (U8CPU)(b * 255));
       }
diff --git a/core/fxge/skia/fx_skia_device_unittest.cpp b/core/fxge/skia/fx_skia_device_unittest.cpp
index 693cf1b..3b799e6 100644
--- a/core/fxge/skia/fx_skia_device_unittest.cpp
+++ b/core/fxge/skia/fx_skia_device_unittest.cpp
@@ -35,7 +35,12 @@
 }
 
 void CommonTest(CFX_SkiaDeviceDriver* driver, const State& state) {
-  FXTEXT_CHARPOS charPos[] = {{{0, 0, 0, 0}, 0, 1, 1, 4, false, false}};
+  FXTEXT_CHARPOS charPos[1];
+  charPos[0].m_OriginX = 0;
+  charPos[0].m_OriginY = 1;
+  charPos[0].m_GlyphIndex = 1;
+  charPos[0].m_FontCharWidth = 4;
+
   CFX_Font font;
   FX_FLOAT fontSize = 1;
   CFX_PathData clipPath, clipPath2;