blob: 3400d24537cb99ed62950a40eeb4356c5e46c9e2 [file]
// Copyright 2026 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "fpdfsdk/display_list_renderer.h"
#include <utility>
#include "core/fpdfapi/page/cpdf_occontext.h"
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/render/cpdf_pagerendercontext.h"
#include "core/fpdfapi/render/cpdf_renderoptions.h"
#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxge/cfx_renderdevice.h"
#include "core/fxge/display_list_device_driver.h"
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
#include "fpdfsdk/cpdfsdk_pageview.h"
#include "fpdfsdk/cpdfsdk_renderpage.h"
#include "public/fpdfview.h"
// static
std::string DisplayListRenderer::RenderPage(FPDF_PAGE page,
FPDF_FORMHANDLE form,
int flags) {
int width = static_cast<int>(FPDF_GetPageWidthF(page));
int height = static_cast<int>(FPDF_GetPageHeightF(page));
DisplayListRenderer renderer(page, width, height, flags);
if (!renderer.Start()) {
return std::string();
}
renderer.Finish(form);
return renderer.GetDisplayList();
}
DisplayListRenderer::DisplayListRenderer(FPDF_PAGE page,
int width,
int height,
int flags)
: page_(page), width_(width), height_(height), flags_(flags) {
auto driver = std::make_unique<DisplayListDeviceDriver>(width, height);
driver_ = driver.get();
device_ = CFX_RenderDevice::CreateWithDriver(std::move(driver));
}
DisplayListRenderer::~DisplayListRenderer() = default;
bool DisplayListRenderer::Start() {
if (!device_) {
return false;
}
CPDF_Page* cpdf_page = CPDFPageFromFPDFPage(page_);
if (!cpdf_page) {
return false;
}
context_ = std::make_unique<CPDF_PageRenderContext>();
context_->device_ = std::move(device_);
CPDFSDK_RenderPageWithContext(context_.get(), cpdf_page, /*start_x=*/0,
/*start_y=*/0, /*size_x=*/width_,
/*size_y=*/height_, /*rotate=*/0,
/*flags=*/flags_, nullptr,
/*need_to_restore=*/true, nullptr);
return true;
}
void DisplayListRenderer::Finish(FPDF_FORMHANDLE form) {
if (form && context_ && context_->device_) {
CPDFSDK_FormFillEnvironment* form_fill_env =
CPDFSDKFormFillEnvironmentFromFPDFFormHandle(form);
IPDF_Page* ipdf_page = IPDFPageFromFPDFPage(page_);
if (form_fill_env && ipdf_page) {
CPDFSDK_PageView* page_view =
form_fill_env->GetOrCreatePageView(ipdf_page);
if (page_view) {
CPDF_Page* cpdf_page = CPDFPageFromFPDFPage(page_);
const FX_RECT rect(0, 0, width_, height_);
CFX_Matrix matrix = cpdf_page->GetDisplayMatrixForRect(rect, 0);
CPDF_RenderOptions options;
options.GetOptions().bClearType = !!(flags_ & FPDF_LCD_TEXT);
if (flags_ & FPDF_GRAYSCALE) {
options.SetColorMode(CPDF_RenderOptions::kGray);
}
options.SetDrawAnnots(flags_ & FPDF_ANNOT);
options.SetOCContext(pdfium::MakeRetain<CPDF_OCContext>(
cpdf_page->GetDocument(), CPDF_OCContext::kView));
page_view->PageView_OnDraw(context_->device_.get(), matrix, &options,
rect);
}
}
}
}
std::string DisplayListRenderer::GetDisplayList() const {
return std::string(driver_->display_list().c_str());
}