Make CPDF_ScaledRenderBuffer Windows-only

Refactor its only user in CPDF_RenderStatus to draw directly to its
render device on non-Windows platforms. For Windows, optionally draw
with CPDF_ScaledRenderBuffer when needed. Move the code that determines
if CPDF_ScaledRenderBuffer is needed to CPDF_RenderStatus. Then
CPDF_ScaledRenderBuffer can become slightly simpler.

Change-Id: I026cd6d0c898d462d3129c493ad0161ae0507555
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/123213
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Tom Sepez <tsepez@google.com>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/render/BUILD.gn b/core/fpdfapi/render/BUILD.gn
index bb76ef8..a3964f2 100644
--- a/core/fpdfapi/render/BUILD.gn
+++ b/core/fpdfapi/render/BUILD.gn
@@ -29,8 +29,6 @@
     "cpdf_renderstatus.h",
     "cpdf_rendertiling.cpp",
     "cpdf_rendertiling.h",
-    "cpdf_scaledrenderbuffer.cpp",
-    "cpdf_scaledrenderbuffer.h",
     "cpdf_textrenderer.cpp",
     "cpdf_textrenderer.h",
     "cpdf_type3cache.cpp",
@@ -54,6 +52,8 @@
   visibility = [ "../../../*" ]
   if (is_win) {
     sources += [
+      "cpdf_scaledrenderbuffer.cpp",
+      "cpdf_scaledrenderbuffer.h",
       "cpdf_windowsrenderdevice.cpp",
       "cpdf_windowsrenderdevice.h",
     ]
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index ee09437..e50d012 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -48,7 +48,6 @@
 #include "core/fpdfapi/render/cpdf_renderoptions.h"
 #include "core/fpdfapi/render/cpdf_rendershading.h"
 #include "core/fpdfapi/render/cpdf_rendertiling.h"
-#include "core/fpdfapi/render/cpdf_scaledrenderbuffer.h"
 #include "core/fpdfapi/render/cpdf_textrenderer.h"
 #include "core/fpdfapi/render/cpdf_type3cache.h"
 #include "core/fxcrt/autorestorer.h"
@@ -74,6 +73,10 @@
 #include "core/fxge/text_char_pos.h"
 #include "core/fxge/text_glyph_pos.h"
 
+#if BUILDFLAG(IS_WIN)
+#include "core/fpdfapi/render/cpdf_scaledrenderbuffer.h"
+#endif
+
 namespace {
 
 constexpr int kRenderMaxRecursionDepth = 64;
@@ -334,26 +337,48 @@
   if (rect.IsEmpty())
     return;
 
-  int res = (pObj->IsImage() && IsPrint()) ? 0 : 300;
+  const bool needs_buffer =
+      !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS);
+  if (!needs_buffer) {
+    DrawObjWithBackgroundToDevice(pObj, mtObj2Device, m_pDevice, CFX_Matrix());
+    return;
+  }
+
+#if BUILDFLAG(IS_WIN)
   CPDF_ScaledRenderBuffer buffer(m_pDevice, rect);
+  int res = (pObj->IsImage() && IsPrint()) ? 0 : 300;
   if (!buffer.Initialize(m_pContext, pObj, m_Options, res)) {
     return;
   }
+
+  DrawObjWithBackgroundToDevice(pObj, mtObj2Device, buffer.GetDevice(),
+                                buffer.GetMatrix());
+  buffer.OutputToDevice();
+#else
+  NOTREACHED_NORETURN();
+#endif
+}
+
+void CPDF_RenderStatus::DrawObjWithBackgroundToDevice(
+    CPDF_PageObject* obj,
+    const CFX_Matrix& object_to_device,
+    CFX_RenderDevice* device,
+    const CFX_Matrix& device_matrix) {
   RetainPtr<const CPDF_Dictionary> pFormResource;
-  CFX_Matrix matrix = mtObj2Device * buffer.GetMatrix();
-  const CPDF_FormObject* pFormObj = pObj->AsForm();
-  if (pFormObj)
+  const CPDF_FormObject* pFormObj = obj->AsForm();
+  if (pFormObj) {
     pFormResource = pFormObj->form()->GetDict()->GetDictFor("Resources");
-  CPDF_RenderStatus status(m_pContext, buffer.GetDevice());
+  }
+
+  CPDF_RenderStatus status(m_pContext, device);
   status.SetOptions(m_Options);
-  status.SetDeviceMatrix(buffer.GetMatrix());
+  status.SetDeviceMatrix(device_matrix);
   status.SetTransparency(m_Transparency);
   status.SetDropObjects(m_bDropObjects);
   status.SetFormResource(std::move(pFormResource));
   status.SetInGroup(m_bInGroup);
   status.Initialize(nullptr, nullptr);
-  status.RenderSingleObject(pObj, matrix);
-  buffer.OutputToDevice();
+  status.RenderSingleObject(obj, object_to_device * device_matrix);
 }
 
 bool CPDF_RenderStatus::ProcessForm(const CPDF_FormObject* pFormObj,
diff --git a/core/fpdfapi/render/cpdf_renderstatus.h b/core/fpdfapi/render/cpdf_renderstatus.h
index 9df2711..5f89694 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.h
+++ b/core/fpdfapi/render/cpdf_renderstatus.h
@@ -136,6 +136,10 @@
                            const CFX_Matrix& mtObj2Device);
   void DrawObjWithBackground(CPDF_PageObject* pObj,
                              const CFX_Matrix& mtObj2Device);
+  void DrawObjWithBackgroundToDevice(CPDF_PageObject* obj,
+                                     const CFX_Matrix& object_to_device,
+                                     CFX_RenderDevice* device,
+                                     const CFX_Matrix& device_matrix);
   bool DrawObjWithBlend(CPDF_PageObject* pObj, const CFX_Matrix& mtObj2Device);
   bool ProcessPath(CPDF_PathObject* path_obj, const CFX_Matrix& mtObj2Device);
   void ProcessPathPattern(CPDF_PathObject* path_obj,
diff --git a/core/fpdfapi/render/cpdf_scaledrenderbuffer.cpp b/core/fpdfapi/render/cpdf_scaledrenderbuffer.cpp
index b8c10fb..ce54ff3 100644
--- a/core/fpdfapi/render/cpdf_scaledrenderbuffer.cpp
+++ b/core/fpdfapi/render/cpdf_scaledrenderbuffer.cpp
@@ -6,6 +6,7 @@
 
 #include "core/fpdfapi/render/cpdf_scaledrenderbuffer.h"
 
+#include "build/build_config.h"
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fpdfapi/render/cpdf_devicebuffer.h"
 #include "core/fpdfapi/render/cpdf_rendercontext.h"
@@ -20,7 +21,9 @@
 
 CPDF_ScaledRenderBuffer::CPDF_ScaledRenderBuffer(CFX_RenderDevice* device,
                                                  const FX_RECT& rect)
-    : device_(device), rect_(rect) {}
+    : device_(device),
+      bitmap_device_(std::make_unique<CFX_DefaultRenderDevice>()),
+      rect_(rect) {}
 
 CPDF_ScaledRenderBuffer::~CPDF_ScaledRenderBuffer() = default;
 
@@ -28,13 +31,8 @@
                                          const CPDF_PageObject* pObj,
                                          const CPDF_RenderOptions& options,
                                          int max_dpi) {
-  if (device_->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) {
-    return true;
-  }
-
   matrix_ = CPDF_DeviceBuffer::CalculateMatrix(device_, rect_, max_dpi,
                                                /*scale=*/true);
-  bitmap_device_ = std::make_unique<CFX_DefaultRenderDevice>();
   bool bIsAlpha =
       !!(device_->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_ALPHA_OUTPUT);
   FXDIB_Format dibFormat = bIsAlpha ? FXDIB_Format::kArgb : FXDIB_Format::kRgb;
@@ -61,17 +59,14 @@
   return true;
 }
 
-CFX_RenderDevice* CPDF_ScaledRenderBuffer::GetDevice() const {
-  return bitmap_device_ ? static_cast<CFX_RenderDevice*>(bitmap_device_.get())
-                        : device_.get();
+CFX_DefaultRenderDevice* CPDF_ScaledRenderBuffer::GetDevice() {
+  return bitmap_device_.get();
 }
 
 void CPDF_ScaledRenderBuffer::OutputToDevice() {
-  if (bitmap_device_) {
 #if defined(PDF_USE_SKIA)
-    bitmap_device_->SyncInternalBitmaps();
+  bitmap_device_->SyncInternalBitmaps();
 #endif
-    device_->StretchDIBits(bitmap_device_->GetBitmap(), rect_.left, rect_.top,
-                           rect_.Width(), rect_.Height());
-  }
+  device_->StretchDIBits(bitmap_device_->GetBitmap(), rect_.left, rect_.top,
+                         rect_.Width(), rect_.Height());
 }
diff --git a/core/fpdfapi/render/cpdf_scaledrenderbuffer.h b/core/fpdfapi/render/cpdf_scaledrenderbuffer.h
index 16eb4f4..6a9c8c4 100644
--- a/core/fpdfapi/render/cpdf_scaledrenderbuffer.h
+++ b/core/fpdfapi/render/cpdf_scaledrenderbuffer.h
@@ -28,13 +28,13 @@
                   const CPDF_RenderOptions& options,
                   int max_dpi);
 
-  CFX_RenderDevice* GetDevice() const;
+  CFX_DefaultRenderDevice* GetDevice();
   const CFX_Matrix& GetMatrix() const { return matrix_; }
   void OutputToDevice();
 
  private:
   UnownedPtr<CFX_RenderDevice> const device_;
-  std::unique_ptr<CFX_DefaultRenderDevice> bitmap_device_;
+  std::unique_ptr<CFX_DefaultRenderDevice> const bitmap_device_;
   const FX_RECT rect_;
   CFX_Matrix matrix_;
 };