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 "xfa/src/foxitlib.h" 8 #include "xfa/src/fxfa/src/common/xfa_utils.h" 9 #include "xfa/src/fxfa/src/common/xfa_object.h" 10 #include "xfa/src/fxfa/src/common/xfa_document.h" 11 #include "xfa/src/fxfa/src/common/xfa_parser.h" 12 #include "xfa/src/fxfa/src/common/xfa_script.h" 13 #include "xfa/src/fxfa/src/common/xfa_docdata.h" 14 #include "xfa/src/fxfa/src/common/xfa_doclayout.h" 15 #include "xfa/src/fxfa/src/common/xfa_localemgr.h" 16 #include "xfa/src/fxfa/src/common/xfa_fm2jsapi.h" 17 #include "xfa_basic_imp.h" 18 #include "xfa_document_layout_imp.h" 19 #include "xfa_document_datamerger_imp.h" 20 #include "xfa_layout_itemlayout.h" 21 #include "xfa_layout_pagemgr_new.h" 22 #include "xfa_layout_appadapter.h" 23 CXFA_LayoutProcessor* CXFA_Document::GetLayoutProcessor() { 24 if (!m_pLayoutProcessor) { 25 m_pLayoutProcessor = new CXFA_LayoutProcessor(this); 26 ASSERT(m_pLayoutProcessor); 27 } 28 return m_pLayoutProcessor; 29 } 30 IXFA_DocLayout* CXFA_Document::GetDocLayout() { 31 return GetLayoutProcessor(); 32 } 33 CXFA_LayoutProcessor::CXFA_LayoutProcessor(CXFA_Document* pDocument) 34 : m_pDocument(pDocument), 35 m_pRootItemLayoutProcessor(NULL), 36 m_pLayoutPageMgr(NULL), 37 m_nProgressCounter(0), 38 m_bNeeLayout(TRUE) {} 39 CXFA_LayoutProcessor::~CXFA_LayoutProcessor() { 40 ClearLayoutData(); 41 } 42 CXFA_Document* CXFA_LayoutProcessor::GetDocument() const { 43 return m_pDocument; 44 } 45 int32_t CXFA_LayoutProcessor::StartLayout(FX_BOOL bForceRestart) { 46 if (!bForceRestart && !IsNeedLayout()) { 47 return 100; 48 } 49 if (m_pRootItemLayoutProcessor) { 50 delete m_pRootItemLayoutProcessor; 51 m_pRootItemLayoutProcessor = NULL; 52 } 53 m_nProgressCounter = 0; 54 CXFA_Node* pFormPacketNode = 55 (CXFA_Node*)m_pDocument->GetXFANode(XFA_HASHCODE_Form); 56 if (!pFormPacketNode) { 57 return -1; 58 } 59 CXFA_Node* pFormRoot = 60 pFormPacketNode->GetFirstChildByClass(XFA_ELEMENT_Subform); 61 if (!pFormRoot) { 62 return -1; 63 } 64 if (!m_pLayoutPageMgr) { 65 m_pLayoutPageMgr = new CXFA_LayoutPageMgr(this); 66 } 67 if (!m_pLayoutPageMgr->InitLayoutPage(pFormRoot)) { 68 return -1; 69 } 70 if (!m_pLayoutPageMgr->PrepareFirstPage(pFormRoot)) { 71 return -1; 72 } 73 m_pRootItemLayoutProcessor = 74 new CXFA_ItemLayoutProcessor(pFormRoot, m_pLayoutPageMgr); 75 #ifndef _XFA_LAYOUTITEM_ProcessCACHE_ 76 m_pRootItemLayoutProcessor->m_pPageMgrCreateItem = m_pLayoutPageMgr; 77 #endif 78 m_nProgressCounter = 1; 79 return 0; 80 } 81 int32_t CXFA_LayoutProcessor::DoLayout(IFX_Pause* pPause) { 82 if (m_nProgressCounter < 1) { 83 return -1; 84 } 85 XFA_ItemLayoutProcessorResult eStatus; 86 CXFA_Node* pFormNode = m_pRootItemLayoutProcessor->GetFormNode(); 87 FX_FLOAT fPosX = pFormNode->GetMeasure(XFA_ATTRIBUTE_X).ToUnit(XFA_UNIT_Pt); 88 FX_FLOAT fPosY = pFormNode->GetMeasure(XFA_ATTRIBUTE_Y).ToUnit(XFA_UNIT_Pt); 89 do { 90 FX_FLOAT fAvailHeight = m_pLayoutPageMgr->GetAvailHeight(); 91 eStatus = 92 m_pRootItemLayoutProcessor->DoLayout(TRUE, fAvailHeight, fAvailHeight); 93 if (eStatus != XFA_ItemLayoutProcessorResult_Done) { 94 m_nProgressCounter++; 95 } 96 CXFA_ContentLayoutItem* pLayoutItem = 97 m_pRootItemLayoutProcessor->ExtractLayoutItem(); 98 if (pLayoutItem) { 99 pLayoutItem->m_sPos.Set(fPosX, fPosY); 100 } 101 m_pLayoutPageMgr->SubmitContentItem(pLayoutItem, eStatus); 102 } while (eStatus != XFA_ItemLayoutProcessorResult_Done && 103 (!pPause || !pPause->NeedToPauseNow())); 104 if (eStatus == XFA_ItemLayoutProcessorResult_Done) { 105 m_pLayoutPageMgr->FinishPaginatedPageSets(); 106 m_pLayoutPageMgr->SyncLayoutData(); 107 m_bNeeLayout = FALSE; 108 m_rgChangedContainers.RemoveAll(); 109 } 110 return 100 * (eStatus == XFA_ItemLayoutProcessorResult_Done 111 ? m_nProgressCounter 112 : m_nProgressCounter - 1) / 113 m_nProgressCounter; 114 } 115 FX_BOOL CXFA_LayoutProcessor::IncrementLayout() { 116 if (m_bNeeLayout) { 117 StartLayout(TRUE); 118 return DoLayout(NULL) == 100; 119 } 120 for (int32_t i = 0, c = m_rgChangedContainers.GetSize(); i < c; i++) { 121 CXFA_Node* pNode = m_rgChangedContainers[i]; 122 CXFA_Node* pParentNode = 123 pNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode); 124 if (!pParentNode) { 125 return FALSE; 126 } 127 if (!CXFA_ItemLayoutProcessor::IncrementRelayoutNode(this, pNode, 128 pParentNode)) { 129 return FALSE; 130 } 131 } 132 m_rgChangedContainers.RemoveAll(); 133 return TRUE; 134 } 135 int32_t CXFA_LayoutProcessor::CountPages() const { 136 return m_pLayoutPageMgr ? m_pLayoutPageMgr->GetPageCount() : 0; 137 } 138 IXFA_LayoutPage* CXFA_LayoutProcessor::GetPage(int32_t index) const { 139 return m_pLayoutPageMgr ? m_pLayoutPageMgr->GetPage(index) : NULL; 140 } 141 CXFA_LayoutItem* CXFA_LayoutProcessor::GetLayoutItem(CXFA_Node* pFormItem) { 142 return static_cast<CXFA_LayoutItem*>( 143 pFormItem->GetUserData(XFA_LAYOUTITEMKEY)); 144 } 145 void CXFA_LayoutProcessor::AddChangedContainer(CXFA_Node* pContainer) { 146 if (m_rgChangedContainers.Find(pContainer) < 0) { 147 m_rgChangedContainers.Add(pContainer); 148 } 149 } 150 CXFA_ContainerLayoutItem* CXFA_LayoutProcessor::GetRootLayoutItem() const { 151 return m_pLayoutPageMgr ? m_pLayoutPageMgr->GetRootLayoutItem() : NULL; 152 } 153 void CXFA_LayoutProcessor::ClearLayoutData() { 154 if (m_pLayoutPageMgr) { 155 delete m_pLayoutPageMgr; 156 m_pLayoutPageMgr = NULL; 157 } 158 if (m_pRootItemLayoutProcessor) { 159 delete m_pRootItemLayoutProcessor; 160 m_pRootItemLayoutProcessor = NULL; 161 } 162 m_nProgressCounter = 0; 163 } 164 FX_BOOL CXFA_LayoutProcessor::IsNeedLayout() { 165 return m_bNeeLayout || m_rgChangedContainers.GetSize() > 0; 166 } 167 CXFA_LayoutItem::CXFA_LayoutItem(CXFA_Node* pNode, FX_BOOL bIsContentLayoutItem) 168 : m_pFormNode(pNode), 169 m_pParent(NULL), 170 m_pNextSibling(NULL), 171 m_pFirstChild(NULL), 172 m_bIsContentLayoutItem(bIsContentLayoutItem) { 173 } 174 CXFA_LayoutItem::~CXFA_LayoutItem() { 175 } 176 CXFA_ContainerLayoutItem::CXFA_ContainerLayoutItem(CXFA_Node* pNode) 177 : CXFA_LayoutItem(pNode, FALSE), m_pOldSubform(NULL) { 178 } 179 IXFA_DocLayout* CXFA_ContainerLayoutItem::GetLayout() const { 180 return m_pFormNode->GetDocument()->GetLayoutProcessor(); 181 } 182 int32_t CXFA_ContainerLayoutItem::GetPageIndex() const { 183 return m_pFormNode->GetDocument() 184 ->GetLayoutProcessor() 185 ->GetLayoutPageMgr() 186 ->GetPageIndex(this); 187 } 188 void CXFA_ContainerLayoutItem::GetPageSize(CFX_SizeF& size) { 189 size.Set(0, 0); 190 CXFA_Node* pMedium = m_pFormNode->GetFirstChildByClass(XFA_ELEMENT_Medium); 191 if (pMedium) { 192 size.x = pMedium->GetMeasure(XFA_ATTRIBUTE_Short).ToUnit(XFA_UNIT_Pt); 193 size.y = pMedium->GetMeasure(XFA_ATTRIBUTE_Long).ToUnit(XFA_UNIT_Pt); 194 if (pMedium->GetEnum(XFA_ATTRIBUTE_Orientation) == 195 XFA_ATTRIBUTEENUM_Landscape) { 196 size.Set(size.y, size.x); 197 } 198 } 199 } 200 CXFA_Node* CXFA_ContainerLayoutItem::GetMasterPage() const { 201 return m_pFormNode; 202 } 203 CXFA_ContentLayoutItem::CXFA_ContentLayoutItem(CXFA_Node* pNode) 204 : CXFA_LayoutItem(pNode, TRUE), 205 m_pPrev(NULL), 206 m_pNext(NULL), 207 m_dwStatus(0) { 208 } 209 CXFA_ContentLayoutItem::~CXFA_ContentLayoutItem() { 210 if (m_pFormNode->GetUserData(XFA_LAYOUTITEMKEY) == this) { 211 m_pFormNode->SetUserData(XFA_LAYOUTITEMKEY, NULL); 212 } 213 } 214