Improve generated content stream data in cpdf_generateap.cpp

Change more operator<< usage in cpdf_generateap.cpp that takes a float
to use Write functions from cpdf_contentstream_write_utils.h instead.
This avoids creating illegal content stream data where floats are in the
exponential format.

Change-Id: Id9bd4e491c64bb171a9d4662a2884ba545374d85
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/117470
Reviewed-by: Thomas Sepez <tsepez@google.com>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfdoc/cpdf_generateap.cpp b/core/fpdfdoc/cpdf_generateap.cpp
index 005f253..a67c7f1 100644
--- a/core/fpdfdoc/cpdf_generateap.cpp
+++ b/core/fpdfdoc/cpdf_generateap.cpp
@@ -90,8 +90,10 @@
   fxcrt::ostringstream sRet;
   if (pFontMap) {
     ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex);
-    if (sFontAlias.GetLength() > 0 && fFontSize > 0)
-      sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n";
+    if (sFontAlias.GetLength() > 0 && fFontSize > 0) {
+      sRet << "/" << sFontAlias << " ";
+      WriteFloat(sRet, fFontSize) << " Tf\n";
+    }
   }
   return ByteString(sRet);
 }
@@ -130,8 +132,7 @@
                              line.ptLine.y + ptOffset.y);
         }
         if (ptNew != ptOld) {
-          sLineStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y
-                      << " Td\n";
+          WritePoint(sLineStream, ptNew - ptOld) << " Td\n";
           ptOld = ptNew;
         }
       }
@@ -155,8 +156,7 @@
         ptNew =
             CFX_PointF(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y);
         if (ptNew != ptOld) {
-          sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y
-                      << " Td\n";
+          WritePoint(sEditStream, ptNew - ptOld) << " Td\n";
           ptOld = ptNew;
         }
         if (word.nFontIndex != nCurFontIndex) {
@@ -181,20 +181,23 @@
   fxcrt::ostringstream sColorStream;
   switch (color.nColorType) {
     case CFX_Color::Type::kRGB:
-      sColorStream << color.fColor1 << " " << color.fColor2 << " "
-                   << color.fColor3 << " "
-                   << (nOperation == PaintOperation::kStroke ? "RG" : "rg")
+      WriteFloat(sColorStream, color.fColor1) << " ";
+      WriteFloat(sColorStream, color.fColor2) << " ";
+      WriteFloat(sColorStream, color.fColor3) << " ";
+      sColorStream << (nOperation == PaintOperation::kStroke ? "RG" : "rg")
                    << "\n";
       break;
     case CFX_Color::Type::kGray:
-      sColorStream << color.fColor1 << " "
-                   << (nOperation == PaintOperation::kStroke ? "G" : "g")
+      WriteFloat(sColorStream, color.fColor1) << " ";
+      sColorStream << (nOperation == PaintOperation::kStroke ? "G" : "g")
                    << "\n";
       break;
     case CFX_Color::Type::kCMYK:
-      sColorStream << color.fColor1 << " " << color.fColor2 << " "
-                   << color.fColor3 << " " << color.fColor4 << " "
-                   << (nOperation == PaintOperation::kStroke ? "K" : "k")
+      WriteFloat(sColorStream, color.fColor1) << " ";
+      WriteFloat(sColorStream, color.fColor2) << " ";
+      WriteFloat(sColorStream, color.fColor3) << " ";
+      WriteFloat(sColorStream, color.fColor4) << " ";
+      sColorStream << (nOperation == PaintOperation::kStroke ? "K" : "k")
                    << "\n";
       break;
     case CFX_Color::Type::kTransparent:
@@ -212,10 +215,10 @@
                             const CPVT_Dash& dash) {
   fxcrt::ostringstream sAppStream;
   ByteString sColor;
-  float fLeft = rect.left;
-  float fRight = rect.right;
-  float fTop = rect.top;
-  float fBottom = rect.bottom;
+  const float fLeft = rect.left;
+  const float fRight = rect.right;
+  const float fTop = rect.top;
+  const float fBottom = rect.bottom;
   if (fWidth > 0.0f) {
     float fHalfWidth = fWidth / 2.0f;
     switch (nStyle) {
@@ -223,12 +226,10 @@
         sColor = GenerateColorAP(color, PaintOperation::kFill);
         if (sColor.GetLength() > 0) {
           sAppStream << sColor;
-          sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " "
-                     << fTop - fBottom << " re\n";
-          sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " "
-                     << fRight - fLeft - fWidth * 2 << " "
-                     << fTop - fBottom - fWidth * 2 << " re\n";
-          sAppStream << "f*\n";
+          WriteRect(sAppStream, rect) << " re\n";
+          CFX_FloatRect inner_rect = rect;
+          inner_rect.Deflate(fWidth, fWidth);
+          WriteRect(sAppStream, inner_rect) << " re f*\n";
         }
         break;
       case BorderStyle::kDash:
@@ -238,16 +239,16 @@
           sAppStream << fWidth << " w"
                      << " [" << dash.nDash << " " << dash.nGap << "] "
                      << dash.nPhase << " d\n";
-          sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2
-                     << " m\n";
-          sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2
-                     << " l\n";
-          sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2
-                     << " l\n";
-          sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2
-                     << " l\n";
-          sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2
-                     << " l S\n";
+          WritePoint(sAppStream, {fLeft + fWidth / 2, fBottom + fWidth / 2})
+              << " m\n";
+          WritePoint(sAppStream, {fLeft + fWidth / 2, fTop - fWidth / 2})
+              << " l\n";
+          WritePoint(sAppStream, {fRight - fWidth / 2, fTop - fWidth / 2})
+              << " l\n";
+          WritePoint(sAppStream, {fRight - fWidth / 2, fBottom + fWidth / 2})
+              << " l\n";
+          WritePoint(sAppStream, {fLeft + fWidth / 2, fBottom + fWidth / 2})
+              << " l S\n";
         }
         break;
       case BorderStyle::kBeveled:
@@ -255,43 +256,48 @@
         sColor = GenerateColorAP(crLeftTop, PaintOperation::kFill);
         if (sColor.GetLength() > 0) {
           sAppStream << sColor;
-          sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth
-                     << " m\n";
-          sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth
-                     << " l\n";
-          sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth
-                     << " l\n";
-          sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
-                     << " l\n";
-          sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
-                     << " l\n";
-          sAppStream << fLeft + fHalfWidth * 2 << " "
-                     << fBottom + fHalfWidth * 2 << " l f\n";
+          WritePoint(sAppStream, {fLeft + fHalfWidth, fBottom + fHalfWidth})
+              << " m\n";
+          WritePoint(sAppStream, {fLeft + fHalfWidth, fTop - fHalfWidth})
+              << " l\n";
+          WritePoint(sAppStream, {fRight - fHalfWidth, fTop - fHalfWidth})
+              << " l\n";
+          WritePoint(sAppStream,
+                     {fRight - fHalfWidth * 2, fTop - fHalfWidth * 2})
+              << " l\n";
+          WritePoint(sAppStream,
+                     {fLeft + fHalfWidth * 2, fTop - fHalfWidth * 2})
+              << " l\n";
+          WritePoint(sAppStream,
+                     {fLeft + fHalfWidth * 2, fBottom + fHalfWidth * 2})
+              << " l f\n";
         }
         sColor = GenerateColorAP(crRightBottom, PaintOperation::kFill);
         if (sColor.GetLength() > 0) {
           sAppStream << sColor;
-          sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth
-                     << " m\n";
-          sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth
-                     << " l\n";
-          sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth
-                     << " l\n";
-          sAppStream << fLeft + fHalfWidth * 2 << " "
-                     << fBottom + fHalfWidth * 2 << " l\n";
-          sAppStream << fRight - fHalfWidth * 2 << " "
-                     << fBottom + fHalfWidth * 2 << " l\n";
-          sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
-                     << " l f\n";
+          WritePoint(sAppStream, {fRight - fHalfWidth, fTop - fHalfWidth})
+              << " m\n";
+          WritePoint(sAppStream, {fRight - fHalfWidth, fBottom + fHalfWidth})
+              << " l\n";
+          WritePoint(sAppStream, {fLeft + fHalfWidth, fBottom + fHalfWidth})
+              << " l\n";
+          WritePoint(sAppStream,
+                     {fLeft + fHalfWidth * 2, fBottom + fHalfWidth * 2})
+              << " l\n";
+          WritePoint(sAppStream,
+                     {fRight - fHalfWidth * 2, fBottom + fHalfWidth * 2})
+              << " l\n";
+          WritePoint(sAppStream,
+                     {fRight - fHalfWidth * 2, fTop - fHalfWidth * 2})
+              << " l f\n";
         }
         sColor = GenerateColorAP(color, PaintOperation::kFill);
         if (sColor.GetLength() > 0) {
           sAppStream << sColor;
-          sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " "
-                     << fTop - fBottom << " re\n";
-          sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " "
-                     << fRight - fLeft - fHalfWidth * 2 << " "
-                     << fTop - fBottom - fHalfWidth * 2 << " re f*\n";
+          WriteRect(sAppStream, rect) << " re\n";
+          CFX_FloatRect inner_rect = rect;
+          inner_rect.Deflate(fHalfWidth, fHalfWidth);
+          WriteRect(sAppStream, inner_rect) << " re f*\n";
         }
         break;
       case BorderStyle::kUnderline:
@@ -299,8 +305,8 @@
         if (sColor.GetLength() > 0) {
           sAppStream << sColor;
           sAppStream << fWidth << " w\n";
-          sAppStream << fLeft << " " << fBottom + fWidth / 2 << " m\n";
-          sAppStream << fRight << " " << fBottom + fWidth / 2 << " l S\n";
+          WritePoint(sAppStream, {fLeft, fBottom + fWidth / 2}) << " m\n";
+          WritePoint(sAppStream, {fRight, fBottom + fWidth / 2}) << " l S\n";
         }
         break;
     }
@@ -355,7 +361,7 @@
 
   sDashStream << "[";
   for (size_t i = 0; i < pDashArrayCount; ++i)
-    sDashStream << pDashArray->GetFloatAt(i) << " ";
+    WriteFloat(sDashStream, pDashArray->GetFloatAt(i)) << " ";
   sDashStream << "] 0 d\n";
 
   return ByteString(sDashStream);
@@ -427,31 +433,31 @@
   sAppStream << GenerateColorAP(CFX_Color(CFX_Color::Type::kRGB, 0, 0, 0),
                                 PaintOperation::kStroke);
 
-  const float fBorderWidth = 1;
-  sAppStream << fBorderWidth << " w\n";
+  constexpr float kBorderWidth = 1;
+  WriteFloat(sAppStream, kBorderWidth) << " w\n";
 
-  const float fHalfWidth = fBorderWidth / 2;
-  const float fTipDelta = 4;
+  constexpr float kHalfWidth = kBorderWidth / 2;
+  constexpr float kTipDelta = 4;
 
   CFX_FloatRect outerRect1 = rect;
-  outerRect1.Deflate(fHalfWidth, fHalfWidth);
-  outerRect1.bottom += fTipDelta;
+  outerRect1.Deflate(kHalfWidth, kHalfWidth);
+  outerRect1.bottom += kTipDelta;
 
   CFX_FloatRect outerRect2 = outerRect1;
-  outerRect2.left += fTipDelta;
-  outerRect2.right = outerRect2.left + fTipDelta;
-  outerRect2.top = outerRect2.bottom - fTipDelta;
+  outerRect2.left += kTipDelta;
+  outerRect2.right = outerRect2.left + kTipDelta;
+  outerRect2.top = outerRect2.bottom - kTipDelta;
   float outerRect2Middle = (outerRect2.left + outerRect2.right) / 2;
 
   // Draw outer boxes.
-  sAppStream << outerRect1.left << " " << outerRect1.bottom << " m\n"
-             << outerRect1.left << " " << outerRect1.top << " l\n"
-             << outerRect1.right << " " << outerRect1.top << " l\n"
-             << outerRect1.right << " " << outerRect1.bottom << " l\n"
-             << outerRect2.right << " " << outerRect2.bottom << " l\n"
-             << outerRect2Middle << " " << outerRect2.top << " l\n"
-             << outerRect2.left << " " << outerRect2.bottom << " l\n"
-             << outerRect1.left << " " << outerRect1.bottom << " l\n";
+  WritePoint(sAppStream, {outerRect1.left, outerRect1.bottom}) << " m\n";
+  WritePoint(sAppStream, {outerRect1.left, outerRect1.top}) << " l\n";
+  WritePoint(sAppStream, {outerRect1.right, outerRect1.top}) << " l\n";
+  WritePoint(sAppStream, {outerRect1.right, outerRect1.bottom}) << " l\n";
+  WritePoint(sAppStream, {outerRect2.right, outerRect2.bottom}) << " l\n";
+  WritePoint(sAppStream, {outerRect2Middle, outerRect2.top}) << " l\n";
+  WritePoint(sAppStream, {outerRect2.left, outerRect2.bottom}) << " l\n";
+  WritePoint(sAppStream, {outerRect1.left, outerRect1.bottom}) << " l\n";
 
   // Draw inner lines.
   CFX_FloatRect lineRect = outerRect1;
@@ -462,8 +468,8 @@
   lineRect.right -= fXDelta;
   for (int i = 0; i < 3; ++i) {
     lineRect.top -= fYDelta;
-    sAppStream << lineRect.left << " " << lineRect.top << " m\n"
-               << lineRect.right << " " << lineRect.top << " l\n";
+    WritePoint(sAppStream, {lineRect.left, lineRect.top}) << " m\n";
+    WritePoint(sAppStream, {lineRect.right, lineRect.top}) << " l\n";
   }
   sAppStream << "B*\n";