Always return recorder from FPDF_RenderPageSkp()

Always returns a valid SkPictureRecorder from FPDF_RenderPageSkp(), in
order to better match the behavior of the other FPDF_RenderPage() APIs.

The other APIs accept a caller-provided destination, such as an
FPDF_Bitmap, while FPDF_RenderPageSkp() returns a non-null recorder
instead. This causes differences in behavior when FPDF_RenderPageSkp()
returns null for "errors" that the other APIs do not distinguish.

In particular, for XFA pages, CPDFPageFromFPDFPage() returns null, which
FPDF_RenderPageSkp() previously considered an error, while the other
APIs just skip rendering and defer all the real work to FPDF_FFLDraw().
(The equivalent API for FPDF_RenderPageSkp() is FPDF_FFLRecord().)

This change also reorders the CPDF_PageRenderContext assignments to make
the lifetime management a little more obvious.

Bug: pdfium:1929
Change-Id: Iee81b4f3a422b1616a543699ec901dc941849d41
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/103373
Commit-Queue: K. Moon <kmoon@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index a93cf95..00293a8 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -731,19 +731,27 @@
 FPDF_EXPORT FPDF_RECORDER FPDF_CALLCONV FPDF_RenderPageSkp(FPDF_PAGE page,
                                                            int size_x,
                                                            int size_y) {
-  CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
-  if (!pPage)
-    return nullptr;
-
-  auto pOwnedContext = std::make_unique<CPDF_PageRenderContext>();
-  CPDF_PageRenderContext* pContext = pOwnedContext.get();
-  CPDF_Page::RenderContextClearer clearer(pPage);
-  pPage->SetRenderContext(std::move(pOwnedContext));
-
   auto skDevice = std::make_unique<CFX_DefaultRenderDevice>();
   std::unique_ptr<SkPictureRecorder> recorder =
       skDevice->CreateRecorder(SkRect::MakeWH(size_x, size_y));
-  pContext->m_pDevice = std::move(skDevice);
+
+  CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+  if (!pPage) {
+    // The equivalent bitmap APIs don't signal failure in this case, but defer
+    // the real work to a later call to `FPDF_FFLDraw()`. This is the case for
+    // XFA pages, for example.
+    //
+    // The caller still needs the `SkPictureRecorder` in order to call
+    // `FPDF_FFLRecord()` later.
+    return recorder.release();
+  }
+
+  auto pOwnedContext = std::make_unique<CPDF_PageRenderContext>();
+  pOwnedContext->m_pDevice = std::move(skDevice);
+
+  CPDF_Page::RenderContextClearer clearer(pPage);
+  CPDF_PageRenderContext* pContext = pOwnedContext.get();
+  pPage->SetRenderContext(std::move(pOwnedContext));
 
   CPDFSDK_RenderPageWithContext(pContext, pPage, 0, 0, size_x, size_y, 0, 0,
                                 /*color_scheme=*/nullptr,