• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/parser/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/parser/cxfa_contentlayoutitem.h"
13 #include "xfa/fxfa/parser/cxfa_document.h"
14 #include "xfa/fxfa/parser/cxfa_itemlayoutprocessor.h"
15 #include "xfa/fxfa/parser/cxfa_layoutpagemgr.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 
CXFA_LayoutProcessor(CXFA_Document * pDocument)23 CXFA_LayoutProcessor::CXFA_LayoutProcessor(CXFA_Document* pDocument)
24     : m_pDocument(pDocument), m_nProgressCounter(0), m_bNeedLayout(true) {}
25 
~CXFA_LayoutProcessor()26 CXFA_LayoutProcessor::~CXFA_LayoutProcessor() {}
27 
GetDocument() const28 CXFA_Document* CXFA_LayoutProcessor::GetDocument() const {
29   return m_pDocument.Get();
30 }
31 
StartLayout(bool bForceRestart)32 int32_t CXFA_LayoutProcessor::StartLayout(bool bForceRestart) {
33   if (!bForceRestart && !IsNeedLayout())
34     return 100;
35 
36   m_pRootItemLayoutProcessor.reset();
37   m_nProgressCounter = 0;
38   CXFA_Node* pFormPacketNode =
39       ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Form));
40   if (!pFormPacketNode)
41     return -1;
42 
43   CXFA_Subform* pFormRoot =
44       pFormPacketNode->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform);
45   if (!pFormRoot)
46     return -1;
47 
48   if (!m_pLayoutPageMgr)
49     m_pLayoutPageMgr = pdfium::MakeUnique<CXFA_LayoutPageMgr>(this);
50   if (!m_pLayoutPageMgr->InitLayoutPage(pFormRoot))
51     return -1;
52 
53   if (!m_pLayoutPageMgr->PrepareFirstPage(pFormRoot))
54     return -1;
55 
56   m_pRootItemLayoutProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>(
57       pFormRoot, m_pLayoutPageMgr.get());
58   m_nProgressCounter = 1;
59   return 0;
60 }
61 
DoLayout()62 int32_t CXFA_LayoutProcessor::DoLayout() {
63   if (m_nProgressCounter < 1)
64     return -1;
65 
66   XFA_ItemLayoutProcessorResult eStatus;
67   CXFA_Node* pFormNode = m_pRootItemLayoutProcessor->GetFormNode();
68   float fPosX =
69       pFormNode->JSObject()->GetMeasure(XFA_Attribute::X).ToUnit(XFA_Unit::Pt);
70   float fPosY =
71       pFormNode->JSObject()->GetMeasure(XFA_Attribute::Y).ToUnit(XFA_Unit::Pt);
72   do {
73     float fAvailHeight = m_pLayoutPageMgr->GetAvailHeight();
74     eStatus = m_pRootItemLayoutProcessor->DoLayout(true, fAvailHeight,
75                                                    fAvailHeight, nullptr);
76     if (eStatus != XFA_ItemLayoutProcessorResult::Done)
77       m_nProgressCounter++;
78 
79     CXFA_ContentLayoutItem* pLayoutItem =
80         m_pRootItemLayoutProcessor->ExtractLayoutItem();
81     if (pLayoutItem)
82       pLayoutItem->m_sPos = CFX_PointF(fPosX, fPosY);
83 
84     m_pLayoutPageMgr->SubmitContentItem(pLayoutItem, eStatus);
85   } while (eStatus != XFA_ItemLayoutProcessorResult::Done);
86 
87   if (eStatus == XFA_ItemLayoutProcessorResult::Done) {
88     m_pLayoutPageMgr->FinishPaginatedPageSets();
89     m_pLayoutPageMgr->SyncLayoutData();
90     m_bNeedLayout = false;
91     m_rgChangedContainers.clear();
92   }
93   return 100 * (eStatus == XFA_ItemLayoutProcessorResult::Done
94                     ? m_nProgressCounter
95                     : m_nProgressCounter - 1) /
96          m_nProgressCounter;
97 }
98 
IncrementLayout()99 bool CXFA_LayoutProcessor::IncrementLayout() {
100   if (m_bNeedLayout) {
101     StartLayout(true);
102     return DoLayout() == 100;
103   }
104   for (CXFA_Node* pNode : m_rgChangedContainers) {
105     CXFA_Node* pParentNode = pNode->GetContainerParent();
106     if (!pParentNode)
107       return false;
108     if (!CXFA_ItemLayoutProcessor::IncrementRelayoutNode(this, pNode,
109                                                          pParentNode)) {
110       return false;
111     }
112   }
113   m_rgChangedContainers.clear();
114   return true;
115 }
116 
CountPages() const117 int32_t CXFA_LayoutProcessor::CountPages() const {
118   return m_pLayoutPageMgr ? m_pLayoutPageMgr->GetPageCount() : 0;
119 }
120 
GetPage(int32_t index) const121 CXFA_ContainerLayoutItem* CXFA_LayoutProcessor::GetPage(int32_t index) const {
122   return m_pLayoutPageMgr ? m_pLayoutPageMgr->GetPage(index) : nullptr;
123 }
124 
GetLayoutItem(CXFA_Node * pFormItem)125 CXFA_LayoutItem* CXFA_LayoutProcessor::GetLayoutItem(CXFA_Node* pFormItem) {
126   return pFormItem->JSObject()->GetLayoutItem();
127 }
128 
AddChangedContainer(CXFA_Node * pContainer)129 void CXFA_LayoutProcessor::AddChangedContainer(CXFA_Node* pContainer) {
130   if (!pdfium::ContainsValue(m_rgChangedContainers, pContainer))
131     m_rgChangedContainers.push_back(pContainer);
132 }
133 
GetRootLayoutItem() const134 CXFA_ContainerLayoutItem* CXFA_LayoutProcessor::GetRootLayoutItem() const {
135   return m_pLayoutPageMgr ? m_pLayoutPageMgr->GetRootLayoutItem() : nullptr;
136 }
137 
IsNeedLayout()138 bool CXFA_LayoutProcessor::IsNeedLayout() {
139   return m_bNeedLayout || !m_rgChangedContainers.empty();
140 }
141