1 // Copyright 2016 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 "core/fpdfapi/render/cpdf_progressiverenderer.h" 8 9 #include "core/fpdfapi/page/cpdf_pageobject.h" 10 #include "core/fpdfapi/page/cpdf_pageobjectholder.h" 11 #include "core/fpdfapi/render/cpdf_pagerendercache.h" 12 #include "core/fpdfapi/render/cpdf_renderoptions.h" 13 #include "core/fpdfapi/render/cpdf_renderstatus.h" 14 #include "core/fxge/cfx_renderdevice.h" 15 #include "third_party/base/ptr_util.h" 16 17 CPDF_ProgressiveRenderer::CPDF_ProgressiveRenderer( 18 CPDF_RenderContext* pContext, 19 CFX_RenderDevice* pDevice, 20 const CPDF_RenderOptions* pOptions) 21 : m_Status(Ready), 22 m_pContext(pContext), 23 m_pDevice(pDevice), 24 m_pOptions(pOptions), 25 m_LayerIndex(0), 26 m_pCurrentLayer(nullptr) {} 27 28 CPDF_ProgressiveRenderer::~CPDF_ProgressiveRenderer() { 29 if (m_pRenderStatus) 30 m_pDevice->RestoreState(false); 31 } 32 33 void CPDF_ProgressiveRenderer::Start(IFX_Pause* pPause) { 34 if (!m_pContext || !m_pDevice || m_Status != Ready) { 35 m_Status = Failed; 36 return; 37 } 38 m_Status = ToBeContinued; 39 Continue(pPause); 40 } 41 42 void CPDF_ProgressiveRenderer::Continue(IFX_Pause* pPause) { 43 while (m_Status == ToBeContinued) { 44 if (!m_pCurrentLayer) { 45 if (m_LayerIndex >= m_pContext->CountLayers()) { 46 m_Status = Done; 47 return; 48 } 49 m_pCurrentLayer = m_pContext->GetLayer(m_LayerIndex); 50 m_LastObjectRendered = 51 m_pCurrentLayer->m_pObjectHolder->GetPageObjectList()->end(); 52 m_pRenderStatus = pdfium::MakeUnique<CPDF_RenderStatus>(); 53 m_pRenderStatus->Initialize( 54 m_pContext, m_pDevice, nullptr, nullptr, nullptr, nullptr, m_pOptions, 55 m_pCurrentLayer->m_pObjectHolder->m_Transparency, false, nullptr); 56 m_pDevice->SaveState(); 57 m_ClipRect = CFX_FloatRect(m_pDevice->GetClipBox()); 58 CFX_Matrix device2object; 59 device2object.SetReverse(m_pCurrentLayer->m_Matrix); 60 device2object.TransformRect(m_ClipRect); 61 } 62 CPDF_PageObjectList::iterator iter; 63 CPDF_PageObjectList::iterator iterEnd = 64 m_pCurrentLayer->m_pObjectHolder->GetPageObjectList()->end(); 65 if (m_LastObjectRendered != iterEnd) { 66 iter = m_LastObjectRendered; 67 ++iter; 68 } else { 69 iter = m_pCurrentLayer->m_pObjectHolder->GetPageObjectList()->begin(); 70 } 71 int nObjsToGo = kStepLimit; 72 while (iter != iterEnd) { 73 CPDF_PageObject* pCurObj = iter->get(); 74 if (pCurObj && pCurObj->m_Left <= m_ClipRect.right && 75 pCurObj->m_Right >= m_ClipRect.left && 76 pCurObj->m_Bottom <= m_ClipRect.top && 77 pCurObj->m_Top >= m_ClipRect.bottom) { 78 if (m_pRenderStatus->ContinueSingleObject( 79 pCurObj, &m_pCurrentLayer->m_Matrix, pPause)) { 80 return; 81 } 82 if (pCurObj->IsImage() && 83 m_pRenderStatus->m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) { 84 m_pContext->GetPageCache()->CacheOptimization( 85 m_pRenderStatus->m_Options.m_dwLimitCacheSize); 86 } 87 if (pCurObj->IsForm() || pCurObj->IsShading()) 88 nObjsToGo = 0; 89 else 90 --nObjsToGo; 91 } 92 m_LastObjectRendered = iter; 93 if (nObjsToGo == 0) { 94 if (pPause && pPause->NeedToPauseNow()) 95 return; 96 nObjsToGo = kStepLimit; 97 } 98 ++iter; 99 } 100 if (m_pCurrentLayer->m_pObjectHolder->IsParsed()) { 101 m_pRenderStatus.reset(); 102 m_pDevice->RestoreState(false); 103 m_pCurrentLayer = nullptr; 104 m_LayerIndex++; 105 if (pPause && pPause->NeedToPauseNow()) { 106 return; 107 } 108 } else { 109 m_pCurrentLayer->m_pObjectHolder->ContinueParse(pPause); 110 if (!m_pCurrentLayer->m_pObjectHolder->IsParsed()) 111 return; 112 } 113 } 114 } 115