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 "xfa/fxfa/layout/cxfa_layoutprocessor.h" 8 9 #include "fxjs/xfa/cjx_object.h" 10 #include "third_party/base/ptr_util.h" 11 #include "third_party/base/stl_util.h" 12 #include "xfa/fxfa/layout/cxfa_contentlayoutitem.h" 13 #include "xfa/fxfa/layout/cxfa_contentlayoutprocessor.h" 14 #include "xfa/fxfa/layout/cxfa_viewlayoutprocessor.h" 15 #include "xfa/fxfa/parser/cxfa_document.h" 16 #include "xfa/fxfa/parser/cxfa_localemgr.h" 17 #include "xfa/fxfa/parser/cxfa_measurement.h" 18 #include "xfa/fxfa/parser/cxfa_node.h" 19 #include "xfa/fxfa/parser/cxfa_subform.h" 20 #include "xfa/fxfa/parser/xfa_document_datamerger_imp.h" 21 #include "xfa/fxfa/parser/xfa_utils.h" 22 23 // static FromDocument(const CXFA_Document * pXFADoc)24CXFA_LayoutProcessor* CXFA_LayoutProcessor::FromDocument( 25 const CXFA_Document* pXFADoc) { 26 return static_cast<CXFA_LayoutProcessor*>(pXFADoc->GetLayoutProcessor()); 27 } 28 29 CXFA_LayoutProcessor::CXFA_LayoutProcessor() = default; 30 31 CXFA_LayoutProcessor::~CXFA_LayoutProcessor() = default; 32 SetForceRelayout(bool bForceRestart)33void CXFA_LayoutProcessor::SetForceRelayout(bool bForceRestart) { 34 m_bNeedLayout = bForceRestart; 35 } 36 StartLayout(bool bForceRestart)37int32_t CXFA_LayoutProcessor::StartLayout(bool bForceRestart) { 38 if (!bForceRestart && !NeedLayout()) 39 return 100; 40 41 m_pContentLayoutProcessor.reset(); 42 m_nProgressCounter = 0; 43 CXFA_Node* pFormPacketNode = 44 ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form)); 45 if (!pFormPacketNode) 46 return -1; 47 48 CXFA_Subform* pFormRoot = 49 pFormPacketNode->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform); 50 if (!pFormRoot) 51 return -1; 52 53 if (!m_pViewLayoutProcessor) 54 m_pViewLayoutProcessor = pdfium::MakeUnique<CXFA_ViewLayoutProcessor>(this); 55 if (!m_pViewLayoutProcessor->InitLayoutPage(pFormRoot)) 56 return -1; 57 58 if (!m_pViewLayoutProcessor->PrepareFirstPage(pFormRoot)) 59 return -1; 60 61 m_pContentLayoutProcessor = pdfium::MakeUnique<CXFA_ContentLayoutProcessor>( 62 pFormRoot, m_pViewLayoutProcessor.get()); 63 m_nProgressCounter = 1; 64 return 0; 65 } 66 DoLayout()67int32_t CXFA_LayoutProcessor::DoLayout() { 68 if (m_nProgressCounter < 1) 69 return -1; 70 71 CXFA_ContentLayoutProcessor::Result eStatus; 72 CXFA_Node* pFormNode = m_pContentLayoutProcessor->GetFormNode(); 73 float fPosX = 74 pFormNode->JSObject()->GetMeasureInUnit(XFA_Attribute::X, XFA_Unit::Pt); 75 float fPosY = 76 pFormNode->JSObject()->GetMeasureInUnit(XFA_Attribute::Y, XFA_Unit::Pt); 77 do { 78 float fAvailHeight = m_pViewLayoutProcessor->GetAvailHeight(); 79 eStatus = 80 m_pContentLayoutProcessor->DoLayout(true, fAvailHeight, fAvailHeight); 81 if (eStatus != CXFA_ContentLayoutProcessor::Result::kDone) 82 m_nProgressCounter++; 83 84 RetainPtr<CXFA_ContentLayoutItem> pLayoutItem = 85 m_pContentLayoutProcessor->ExtractLayoutItem(); 86 if (pLayoutItem) 87 pLayoutItem->m_sPos = CFX_PointF(fPosX, fPosY); 88 89 m_pViewLayoutProcessor->SubmitContentItem(pLayoutItem, eStatus); 90 } while (eStatus != CXFA_ContentLayoutProcessor::Result::kDone); 91 92 if (eStatus == CXFA_ContentLayoutProcessor::Result::kDone) { 93 m_pViewLayoutProcessor->FinishPaginatedPageSets(); 94 m_pViewLayoutProcessor->SyncLayoutData(); 95 m_bNeedLayout = false; 96 m_rgChangedContainers.clear(); 97 } 98 return 100 * 99 (eStatus == CXFA_ContentLayoutProcessor::Result::kDone 100 ? m_nProgressCounter 101 : m_nProgressCounter - 1) / 102 m_nProgressCounter; 103 } 104 IncrementLayout()105bool CXFA_LayoutProcessor::IncrementLayout() { 106 if (m_bNeedLayout) { 107 StartLayout(true); 108 return DoLayout() == 100; 109 } 110 return m_rgChangedContainers.empty(); 111 } 112 CountPages() const113int32_t CXFA_LayoutProcessor::CountPages() const { 114 return m_pViewLayoutProcessor ? m_pViewLayoutProcessor->GetPageCount() : 0; 115 } 116 GetPage(int32_t index) const117CXFA_ViewLayoutItem* CXFA_LayoutProcessor::GetPage(int32_t index) const { 118 return m_pViewLayoutProcessor ? m_pViewLayoutProcessor->GetPage(index) 119 : nullptr; 120 } 121 GetLayoutItem(CXFA_Node * pFormItem)122CXFA_LayoutItem* CXFA_LayoutProcessor::GetLayoutItem(CXFA_Node* pFormItem) { 123 return pFormItem->JSObject()->GetLayoutItem(); 124 } 125 AddChangedContainer(CXFA_Node * pContainer)126void CXFA_LayoutProcessor::AddChangedContainer(CXFA_Node* pContainer) { 127 if (!pdfium::ContainsValue(m_rgChangedContainers, pContainer)) 128 m_rgChangedContainers.push_back(pContainer); 129 } 130 NeedLayout() const131bool CXFA_LayoutProcessor::NeedLayout() const { 132 return m_bNeedLayout || !m_rgChangedContainers.empty(); 133 } 134