Flush CFX_PSRenderer output when rendering ends.

This prepares CFX_PSRenderer for outputting a preamble in addition to
the normal output. Because there is no way to tell when drawing commands
that outputs to the preamble will occur, the normal output has to be
buffered until the end.

Bug: chromium:1232526
Change-Id: I38dd2af03986011676fd01102fde6584cb775763
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/84935
Reviewed-by: Hui Yingst <nigi@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxge/win32/cfx_psrenderer.cpp b/core/fxge/win32/cfx_psrenderer.cpp
index b704305..dd3b398 100644
--- a/core/fxge/win32/cfx_psrenderer.cpp
+++ b/core/fxge/win32/cfx_psrenderer.cpp
@@ -12,6 +12,7 @@
 #include <array>
 #include <memory>
 #include <sstream>
+#include <string>
 #include <utility>
 
 #include "core/fxcrt/maybe_owned.h"
@@ -65,6 +66,8 @@
                           RenderingLevel level,
                           int width,
                           int height) {
+  DCHECK(pStream);
+
   m_Level = level;
   m_pStream = pStream;
   m_ClipBox.left = 0;
@@ -101,6 +104,10 @@
 
   WriteString("\nrestore\n");
   m_bInited = false;
+
+  // Flush `m_Output`. It's never empty because of the WriteString() call above.
+  m_pStream->WriteBlock(m_Output.str().c_str(), m_Output.tellp());
+  m_Output.str(std::string());
 }
 
 void CFX_PSRenderer::SaveState() {
@@ -709,17 +716,17 @@
   std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf;
   uint32_t dest_size;
   if (m_pEncoderIface->pA85EncodeFunc(data, &dest_buf, &dest_size)) {
-    m_pStream->WriteBlock(dest_buf.get(), dest_size);
+    m_Output.write(reinterpret_cast<const char*>(dest_buf.get()), dest_size);
   } else {
-    m_pStream->WriteBlock(data.data(), data.size());
+    m_Output.write(reinterpret_cast<const char*>(data.data()), data.size());
   }
 }
 
 void CFX_PSRenderer::WriteStream(std::ostringstream& stream) {
   if (stream.tellp() > 0)
-    m_pStream->WriteBlock(stream.str().c_str(), stream.tellp());
+    m_Output.write(stream.str().c_str(), stream.tellp());
 }
 
 void CFX_PSRenderer::WriteString(ByteStringView str) {
-  m_pStream->WriteString(str);
+  m_Output << str;
 }
diff --git a/core/fxge/win32/cfx_psrenderer.h b/core/fxge/win32/cfx_psrenderer.h
index 7fc1a8f..c59b5ae 100644
--- a/core/fxge/win32/cfx_psrenderer.h
+++ b/core/fxge/win32/cfx_psrenderer.h
@@ -156,6 +156,7 @@
   UnownedPtr<const EncoderIface> const m_pEncoderIface;
   RetainPtr<IFX_RetainableWriteStream> m_pStream;
   std::vector<std::unique_ptr<Glyph>> m_PSFontList;
+  std::ostringstream m_Output;
   std::vector<FX_RECT> m_ClipBoxStack;
 };