Return failure/unsupported in RenderDeviceDriverIface::StartDIBits()

Currently, StartDIBits() returns false to mean failure, but failure can
either be "something went wrong" or "operation not supported". Change
the bool return value to a Result enum to tell these two cases apart.
Then change CPDF_ImageRenderer::StartDIBBase() to return when something
goes wrong, and only use the fallback code in the not supported case.

Change-Id: I209bbd8e5d974ebd5ad485f2a706c59486730df0
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/122595
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/cpdf_imagerenderer.cpp b/core/fpdfapi/render/cpdf_imagerenderer.cpp
index bf9891c..56c71a2 100644
--- a/core/fpdfapi/render/cpdf_imagerenderer.cpp
+++ b/core/fpdfapi/render/cpdf_imagerenderer.cpp
@@ -423,7 +423,7 @@
       m_pRenderStatus->GetRenderDevice()->StartDIBitsWithBlend(
           m_pDIBBase, m_Alpha, m_FillArgb, m_ImageMatrix, m_ResampleOptions,
           m_BlendType);
-  if (result.success) {
+  if (result.result == RenderDeviceDriverIface::Result::kSuccess) {
     m_DeviceHandle = std::move(result.agg_image_renderer);
     if (m_DeviceHandle) {
       m_Mode = Mode::kBlend;
@@ -432,6 +432,12 @@
     return false;
   }
 
+  if (result.result == RenderDeviceDriverIface::Result::kFailure) {
+    m_Result = false;
+    return false;
+  }
+
+  CHECK_EQ(result.result, RenderDeviceDriverIface::Result::kNotSupported);
   if ((fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) ||
       (fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) {
 #if BUILDFLAG(IS_WIN)
diff --git a/core/fxge/agg/cfx_agg_devicedriver.cpp b/core/fxge/agg/cfx_agg_devicedriver.cpp
index a847ddb..06b1fd1 100644
--- a/core/fxge/agg/cfx_agg_devicedriver.cpp
+++ b/core/fxge/agg/cfx_agg_devicedriver.cpp
@@ -1433,12 +1433,12 @@
     const FXDIB_ResampleOptions& options,
     BlendMode blend_type) {
   if (m_pBitmap->GetBuffer().empty()) {
-    return {true, nullptr};
+    return {Result::kSuccess, nullptr};
   }
 
-  return {true, std::make_unique<CFX_AggImageRenderer>(
-                    m_pBitmap, m_pClipRgn.get(), std::move(bitmap), alpha, argb,
-                    matrix, options, m_bRgbByteOrder)};
+  return {Result::kSuccess, std::make_unique<CFX_AggImageRenderer>(
+                                m_pBitmap, m_pClipRgn.get(), std::move(bitmap),
+                                alpha, argb, matrix, options, m_bRgbByteOrder)};
 }
 
 bool CFX_AggDeviceDriver::ContinueDIBits(CFX_AggImageRenderer* pHandle,
diff --git a/core/fxge/renderdevicedriver_iface.cpp b/core/fxge/renderdevicedriver_iface.cpp
index b637735..f5a59db 100644
--- a/core/fxge/renderdevicedriver_iface.cpp
+++ b/core/fxge/renderdevicedriver_iface.cpp
@@ -92,8 +92,8 @@
 #endif  // defined(PDF_USE_SKIA)
 
 RenderDeviceDriverIface::StartResult::StartResult(
-    bool success,
+    Result result,
     std::unique_ptr<CFX_AggImageRenderer> agg_image_renderer)
-    : success(success), agg_image_renderer(std::move(agg_image_renderer)) {}
+    : result(result), agg_image_renderer(std::move(agg_image_renderer)) {}
 
 RenderDeviceDriverIface::StartResult::~StartResult() = default;
diff --git a/core/fxge/renderdevicedriver_iface.h b/core/fxge/renderdevicedriver_iface.h
index d19f6b8..ee4f4bf 100644
--- a/core/fxge/renderdevicedriver_iface.h
+++ b/core/fxge/renderdevicedriver_iface.h
@@ -40,12 +40,14 @@
 
 class RenderDeviceDriverIface {
  public:
+  enum class Result { kFailure, kSuccess, kNotSupported };
+
   struct StartResult {
-    StartResult(bool success,
+    StartResult(Result result,
                 std::unique_ptr<CFX_AggImageRenderer> agg_image_renderer);
     ~StartResult();
 
-    const bool success;
+    const Result result;
     std::unique_ptr<CFX_AggImageRenderer> agg_image_renderer;
   };
 
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index d9a2379..a1bb41b 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -1450,9 +1450,9 @@
     const FXDIB_ResampleOptions& options,
     BlendMode blend_type) {
   FX_RECT rect(0, 0, bitmap->GetWidth(), bitmap->GetHeight());
-  return {StartDIBitsSkia(std::move(bitmap), rect, alpha, color, matrix,
-                          options, blend_type),
-          nullptr};
+  bool success = StartDIBitsSkia(std::move(bitmap), rect, alpha, color, matrix,
+                                 options, blend_type);
+  return {success ? Result::kSuccess : Result::kFailure, nullptr};
 }
 
 void CFX_DIBitmap::UnPreMultiply() {
diff --git a/core/fxge/win32/cgdi_display_driver.cpp b/core/fxge/win32/cgdi_display_driver.cpp
index f5aefcb..ad4a090 100644
--- a/core/fxge/win32/cgdi_display_driver.cpp
+++ b/core/fxge/win32/cgdi_display_driver.cpp
@@ -222,5 +222,5 @@
     const CFX_Matrix& matrix,
     const FXDIB_ResampleOptions& options,
     BlendMode blend_type) {
-  return {false, nullptr};
+  return {Result::kNotSupported, nullptr};
 }
diff --git a/core/fxge/win32/cgdi_printer_driver.cpp b/core/fxge/win32/cgdi_printer_driver.cpp
index 8918a56..7281bc5 100644
--- a/core/fxge/win32/cgdi_printer_driver.cpp
+++ b/core/fxge/win32/cgdi_printer_driver.cpp
@@ -132,7 +132,7 @@
     BlendMode blend_type) {
   if (alpha != 1.0f || bitmap->IsAlphaFormat() ||
       (bitmap->IsMaskFormat() && (bitmap->GetBPP() != 1))) {
-    return {false, nullptr};
+    return {Result::kNotSupported, nullptr};
   }
   CFX_FloatRect unit_rect = matrix.GetUnitRect();
   FX_RECT full_rect = unit_rect.GetOuterRect();
@@ -140,29 +140,30 @@
       matrix.d != 0) {
     bool bFlipX = matrix.a < 0;
     bool bFlipY = matrix.d > 0;
-    return {StretchDIBits(std::move(bitmap), color,
-                          bFlipX ? full_rect.right : full_rect.left,
-                          bFlipY ? full_rect.bottom : full_rect.top,
-                          bFlipX ? -full_rect.Width() : full_rect.Width(),
-                          bFlipY ? -full_rect.Height() : full_rect.Height(),
-                          nullptr, FXDIB_ResampleOptions(), blend_type),
-            nullptr};
+    bool success = StretchDIBits(
+        std::move(bitmap), color, bFlipX ? full_rect.right : full_rect.left,
+        bFlipY ? full_rect.bottom : full_rect.top,
+        bFlipX ? -full_rect.Width() : full_rect.Width(),
+        bFlipY ? -full_rect.Height() : full_rect.Height(), nullptr,
+        FXDIB_ResampleOptions(), blend_type);
+    return {success ? Result::kSuccess : Result::kFailure, nullptr};
   }
   if (fabs(matrix.a) >= 0.5f || fabs(matrix.d) >= 0.5f) {
-    return {false, nullptr};
+    return {Result::kNotSupported, nullptr};
   }
 
   const bool flip_x = matrix.c > 0;
   const bool flip_y = matrix.b < 0;
   bitmap = bitmap->SwapXY(flip_x, flip_y);
   if (!bitmap) {
-    return {false, nullptr};
+    return {Result::kFailure, nullptr};
   }
 
-  return {StretchDIBits(std::move(bitmap), color, full_rect.left, full_rect.top,
-                        full_rect.Width(), full_rect.Height(), nullptr,
-                        FXDIB_ResampleOptions(), blend_type),
-          nullptr};
+  bool success =
+      StretchDIBits(std::move(bitmap), color, full_rect.left, full_rect.top,
+                    full_rect.Width(), full_rect.Height(), nullptr,
+                    FXDIB_ResampleOptions(), blend_type);
+  return {success ? Result::kSuccess : Result::kFailure, nullptr};
 }
 
 bool CGdiPrinterDriver::DrawDeviceText(
diff --git a/core/fxge/win32/cps_printer_driver.cpp b/core/fxge/win32/cps_printer_driver.cpp
index f7c121a..fd6b3cc 100644
--- a/core/fxge/win32/cps_printer_driver.cpp
+++ b/core/fxge/win32/cps_printer_driver.cpp
@@ -191,11 +191,12 @@
     const FXDIB_ResampleOptions& options,
     BlendMode blend_type) {
   if (blend_type != BlendMode::kNormal || alpha != 1.0f) {
-    return {false, nullptr};
+    return {Result::kNotSupported, nullptr};
   }
 
-  return {m_PSRenderer.DrawDIBits(std::move(bitmap), color, matrix, options),
-          nullptr};
+  bool success =
+      m_PSRenderer.DrawDIBits(std::move(bitmap), color, matrix, options);
+  return {success ? Result::kSuccess : Result::kFailure, nullptr};
 }
 
 bool CPSPrinterDriver::DrawDeviceText(
diff --git a/core/fxge/win32/ctext_only_printer_driver.cpp b/core/fxge/win32/ctext_only_printer_driver.cpp
index 8f20bd7..1b5b361 100644
--- a/core/fxge/win32/ctext_only_printer_driver.cpp
+++ b/core/fxge/win32/ctext_only_printer_driver.cpp
@@ -117,7 +117,7 @@
     const CFX_Matrix& matrix,
     const FXDIB_ResampleOptions& options,
     BlendMode blend_type) {
-  return {false, nullptr};
+  return {Result::kNotSupported, nullptr};
 }
 
 bool CTextOnlyPrinterDriver::DrawDeviceText(
diff --git a/xfa/fxfa/cxfa_imagerenderer.cpp b/xfa/fxfa/cxfa_imagerenderer.cpp
index 575f1a9..b78764c 100644
--- a/xfa/fxfa/cxfa_imagerenderer.cpp
+++ b/xfa/fxfa/cxfa_imagerenderer.cpp
@@ -33,10 +33,11 @@
   options.bInterpolateBilinear = true;
   RenderDeviceDriverIface::StartResult result = m_pDevice->StartDIBits(
       m_pBitmap, /*alpha=*/1.0f, /*argb=*/0, m_ImageMatrix, options);
-  if (!result.success) {
+  if (result.result == RenderDeviceDriverIface::Result::kFailure) {
     return false;
   }
 
+  CHECK_EQ(result.result, RenderDeviceDriverIface::Result::kSuccess);
   m_DeviceHandle = std::move(result.agg_image_renderer);
   if (!m_DeviceHandle) {
     return false;