1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "public/fpdf_progressive.h"
8 
9 #include "core/fpdfapi/cpdf_pagerendercontext.h"
10 #include "core/fpdfapi/page/cpdf_page.h"
11 #include "core/fpdfapi/render/cpdf_progressiverenderer.h"
12 #include "core/fxcrt/fx_memory.h"
13 #include "core/fxge/cfx_fxgedevice.h"
14 #include "core/fxge/cfx_renderdevice.h"
15 #include "fpdfsdk/fsdk_define.h"
16 #include "fpdfsdk/fsdk_pauseadapter.h"
17 #include "public/fpdfview.h"
18 #include "third_party/base/ptr_util.h"
19 
20 // These checks are here because core/ and public/ cannot depend on each other.
21 static_assert(CPDF_ProgressiveRenderer::Ready == FPDF_RENDER_READER,
22               "CPDF_ProgressiveRenderer::Ready value mismatch");
23 static_assert(CPDF_ProgressiveRenderer::ToBeContinued ==
24                   FPDF_RENDER_TOBECOUNTINUED,
25               "CPDF_ProgressiveRenderer::ToBeContinued value mismatch");
26 static_assert(CPDF_ProgressiveRenderer::Done == FPDF_RENDER_DONE,
27               "CPDF_ProgressiveRenderer::Done value mismatch");
28 static_assert(CPDF_ProgressiveRenderer::Failed == FPDF_RENDER_FAILED,
29               "CPDF_ProgressiveRenderer::Failed value mismatch");
30 
FPDF_RenderPageBitmap_Start(FPDF_BITMAP bitmap,FPDF_PAGE page,int start_x,int start_y,int size_x,int size_y,int rotate,int flags,IFSDK_PAUSE * pause)31 DLLEXPORT int STDCALL FPDF_RenderPageBitmap_Start(FPDF_BITMAP bitmap,
32                                                   FPDF_PAGE page,
33                                                   int start_x,
34                                                   int start_y,
35                                                   int size_x,
36                                                   int size_y,
37                                                   int rotate,
38                                                   int flags,
39                                                   IFSDK_PAUSE* pause) {
40   if (!bitmap || !pause || pause->version != 1)
41     return FPDF_RENDER_FAILED;
42 
43   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
44   if (!pPage)
45     return FPDF_RENDER_FAILED;
46 
47   CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
48   pPage->SetRenderContext(pdfium::WrapUnique(pContext));
49   CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
50   pContext->m_pDevice.reset(pDevice);
51   CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap);
52   pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
53 
54   IFSDK_PAUSE_Adapter IPauseAdapter(pause);
55   FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
56                          rotate, flags, false, &IPauseAdapter);
57 
58   if (pContext->m_pRenderer) {
59     return CPDF_ProgressiveRenderer::ToFPDFStatus(
60         pContext->m_pRenderer->GetStatus());
61   }
62   return FPDF_RENDER_FAILED;
63 }
64 
FPDF_RenderPage_Continue(FPDF_PAGE page,IFSDK_PAUSE * pause)65 DLLEXPORT int STDCALL FPDF_RenderPage_Continue(FPDF_PAGE page,
66                                                IFSDK_PAUSE* pause) {
67   if (!pause || pause->version != 1)
68     return FPDF_RENDER_FAILED;
69 
70   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
71   if (!pPage)
72     return FPDF_RENDER_FAILED;
73 
74   CPDF_PageRenderContext* pContext = pPage->GetRenderContext();
75   if (pContext && pContext->m_pRenderer) {
76     IFSDK_PAUSE_Adapter IPauseAdapter(pause);
77     pContext->m_pRenderer->Continue(&IPauseAdapter);
78     return CPDF_ProgressiveRenderer::ToFPDFStatus(
79         pContext->m_pRenderer->GetStatus());
80   }
81   return FPDF_RENDER_FAILED;
82 }
83 
FPDF_RenderPage_Close(FPDF_PAGE page)84 DLLEXPORT void STDCALL FPDF_RenderPage_Close(FPDF_PAGE page) {
85   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
86   if (!pPage)
87     return;
88 
89   CPDF_PageRenderContext* pContext = pPage->GetRenderContext();
90   if (!pContext)
91     return;
92 
93   pContext->m_pDevice->RestoreState(false);
94   pPage->SetRenderContext(nullptr);
95 }
96