Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fxfa / src / parser / xfa_document_layout_imp.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../../foxitlib.h"\r
8 #include "../common/xfa_utils.h"\r
9 #include "../common/xfa_object.h"\r
10 #include "../common/xfa_document.h"\r
11 #include "../common/xfa_parser.h"\r
12 #include "../common/xfa_script.h"\r
13 #include "../common/xfa_docdata.h"\r
14 #include "../common/xfa_doclayout.h"\r
15 #include "../common/xfa_debug.h"\r
16 #include "../common/xfa_localemgr.h"\r
17 #include "../common/xfa_fm2jsapi.h"\r
18 #include "xfa_debug_parser.h"\r
19 #include "xfa_basic_imp.h"\r
20 #include "xfa_document_imp.h"\r
21 #include "xfa_document_layout_imp.h"\r
22 #include "xfa_document_datamerger_imp.h"\r
23 #include "xfa_layout_itemlayout.h"\r
24 #include "xfa_layout_pagemgr_new.h"\r
25 #include "xfa_layout_appadapter.h"\r
26 CXFA_LayoutProcessor* CXFA_Document::GetLayoutProcessor()\r
27 {\r
28     if(!m_pLayoutProcessor) {\r
29         m_pLayoutProcessor = FX_NEW CXFA_LayoutProcessor(this);\r
30         ASSERT(m_pLayoutProcessor);\r
31     }\r
32     return m_pLayoutProcessor;\r
33 }\r
34 IXFA_DocLayout* CXFA_Document::GetDocLayout()\r
35 {\r
36     return GetLayoutProcessor();\r
37 }\r
38 CXFA_LayoutProcessor::CXFA_LayoutProcessor(CXFA_Document* pDocument)\r
39     : m_pDocument(pDocument)\r
40     , m_pRootItemLayoutProcessor(NULL)\r
41     , m_pLayoutPageMgr(NULL)\r
42     , m_nProgressCounter(0)\r
43     , m_bNeeLayout(TRUE)\r
44 {\r
45 }\r
46 CXFA_LayoutProcessor::~CXFA_LayoutProcessor()\r
47 {\r
48     ClearLayoutData();\r
49 }\r
50 CXFA_Document* CXFA_LayoutProcessor::GetDocument() const\r
51 {\r
52     return m_pDocument;\r
53 }\r
54 FX_INT32 CXFA_LayoutProcessor::StartLayout(FX_BOOL bForceRestart)\r
55 {\r
56     if (!bForceRestart && !IsNeedLayout()) {\r
57         return 100;\r
58     }\r
59     if(m_pRootItemLayoutProcessor) {\r
60         delete m_pRootItemLayoutProcessor;\r
61         m_pRootItemLayoutProcessor = NULL;\r
62     }\r
63     m_nProgressCounter = 0;\r
64     CXFA_Node* pFormPacketNode = (CXFA_Node*)m_pDocument->GetXFANode(XFA_HASHCODE_Form);\r
65     if (!pFormPacketNode) {\r
66         return -1;\r
67     }\r
68     CXFA_Node* pFormRoot = pFormPacketNode->GetFirstChildByClass(XFA_ELEMENT_Subform);\r
69     if(!pFormRoot) {\r
70         return -1;\r
71     }\r
72     if (!m_pLayoutPageMgr) {\r
73         m_pLayoutPageMgr = FX_NEW CXFA_LayoutPageMgr(this);\r
74     }\r
75     if (!m_pLayoutPageMgr->InitLayoutPage(pFormRoot)) {\r
76         return -1;\r
77     }\r
78     if (!m_pLayoutPageMgr->PrepareFirstPage(pFormRoot)) {\r
79         return -1;\r
80     }\r
81     m_pRootItemLayoutProcessor = FX_NEW CXFA_ItemLayoutProcessor(pFormRoot, m_pLayoutPageMgr);\r
82 #ifndef _XFA_LAYOUTITEM_ProcessCACHE_\r
83     m_pRootItemLayoutProcessor->m_pPageMgrCreateItem = m_pLayoutPageMgr;\r
84 #endif\r
85     m_nProgressCounter = 1;\r
86     return 0;\r
87 }\r
88 FX_INT32 CXFA_LayoutProcessor::DoLayout(IFX_Pause* pPause )\r
89 {\r
90     if (m_nProgressCounter < 1) {\r
91         return -1;\r
92     }\r
93     XFA_ItemLayoutProcessorResult eStatus;\r
94     CXFA_Node* pFormNode =  m_pRootItemLayoutProcessor->GetFormNode();\r
95     FX_FLOAT fPosX = pFormNode->GetMeasure(XFA_ATTRIBUTE_X).ToUnit(XFA_UNIT_Pt);\r
96     FX_FLOAT fPosY = pFormNode->GetMeasure(XFA_ATTRIBUTE_Y).ToUnit(XFA_UNIT_Pt);\r
97     do {\r
98         FX_FLOAT fAvailHeight = m_pLayoutPageMgr->GetAvailHeight();\r
99         eStatus = m_pRootItemLayoutProcessor->DoLayout(TRUE, fAvailHeight, fAvailHeight);\r
100         if(eStatus != XFA_ItemLayoutProcessorResult_Done) {\r
101             m_nProgressCounter++;\r
102         }\r
103         CXFA_ContentLayoutItemImpl* pLayoutItem = m_pRootItemLayoutProcessor->ExtractLayoutItem();\r
104         if(pLayoutItem) {\r
105             pLayoutItem->m_sPos.Set(fPosX, fPosY);\r
106         }\r
107         m_pLayoutPageMgr->SubmitContentItem(pLayoutItem, eStatus);\r
108     } while (eStatus != XFA_ItemLayoutProcessorResult_Done && (!pPause || !pPause->NeedToPauseNow()));\r
109     if (eStatus == XFA_ItemLayoutProcessorResult_Done) {\r
110         m_pLayoutPageMgr->FinishPaginatedPageSets();\r
111         m_pLayoutPageMgr->SyncLayoutData();\r
112         m_bNeeLayout = FALSE;\r
113         m_rgChangedContainers.RemoveAll();\r
114     }\r
115     return 100 * (eStatus == XFA_ItemLayoutProcessorResult_Done ? m_nProgressCounter : m_nProgressCounter - 1) / m_nProgressCounter;\r
116 }\r
117 FX_BOOL CXFA_LayoutProcessor::IncrementLayout()\r
118 {\r
119     if (m_bNeeLayout) {\r
120         StartLayout(TRUE);\r
121         return DoLayout(NULL) == 100;\r
122     }\r
123     for (FX_INT32 i = 0, c = m_rgChangedContainers.GetSize(); i < c; i++) {\r
124         CXFA_Node *pNode = m_rgChangedContainers[i];\r
125         CXFA_Node *pParentNode = pNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode);\r
126         if(!pParentNode) {\r
127             return FALSE;\r
128         }\r
129         if(!CXFA_ItemLayoutProcessor::IncrementRelayoutNode(this, pNode, pParentNode)) {\r
130             return FALSE;\r
131         }\r
132     }\r
133     m_rgChangedContainers.RemoveAll();\r
134     return TRUE;\r
135 }\r
136 FX_INT32 CXFA_LayoutProcessor::CountPages() const\r
137 {\r
138     return m_pLayoutPageMgr ? m_pLayoutPageMgr->GetPageCount() : 0;\r
139 }\r
140 IXFA_LayoutPage* CXFA_LayoutProcessor::GetPage(FX_INT32 index) const\r
141 {\r
142     return m_pLayoutPageMgr ? m_pLayoutPageMgr->GetPage(index) : NULL;\r
143 }\r
144 CXFA_LayoutItem* CXFA_LayoutProcessor::GetLayoutItem(CXFA_Node *pFormItem)\r
145 {\r
146     return (CXFA_LayoutItem*)pFormItem->GetUserData(XFA_LAYOUTITEMKEY);\r
147 }\r
148 void CXFA_LayoutProcessor::AddChangedContainer(CXFA_Node* pContainer)\r
149 {\r
150     if (m_rgChangedContainers.Find(pContainer) < 0) {\r
151         m_rgChangedContainers.Add(pContainer);\r
152     }\r
153 }\r
154 CXFA_ContainerLayoutItemImpl* CXFA_LayoutProcessor::GetRootLayoutItem() const\r
155 {\r
156     return m_pLayoutPageMgr ? m_pLayoutPageMgr->GetRootLayoutItem() : NULL;\r
157 }\r
158 void CXFA_LayoutProcessor::ClearLayoutData()\r
159 {\r
160     if(m_pLayoutPageMgr) {\r
161         delete m_pLayoutPageMgr;\r
162         m_pLayoutPageMgr = NULL;\r
163     }\r
164     if(m_pRootItemLayoutProcessor) {\r
165         delete m_pRootItemLayoutProcessor;\r
166         m_pRootItemLayoutProcessor = NULL;\r
167     }\r
168     m_nProgressCounter = 0;\r
169 }\r
170 FX_BOOL CXFA_LayoutProcessor::IsNeedLayout()\r
171 {\r
172     return m_bNeeLayout || m_rgChangedContainers.GetSize() > 0;\r
173 }\r
174 CXFA_LayoutItemImpl::CXFA_LayoutItemImpl(CXFA_Node *pNode, FX_BOOL bIsContentLayoutItem)\r
175     : m_pFormNode(pNode)\r
176     , m_bIsContentLayoutItem(bIsContentLayoutItem)\r
177     , m_pParent(NULL)\r
178     , m_pNextSibling(NULL)\r
179     , m_pFirstChild(NULL)\r
180 {\r
181 }\r
182 CXFA_LayoutItemImpl::~CXFA_LayoutItemImpl()\r
183 {\r
184 }\r
185 CXFA_ContainerLayoutItemImpl::CXFA_ContainerLayoutItemImpl(CXFA_Node *pNode)\r
186     : CXFA_LayoutItemImpl(pNode, FALSE), m_pOldSubform(NULL)\r
187 {\r
188 }\r
189 CXFA_ContentLayoutItemImpl::CXFA_ContentLayoutItemImpl(CXFA_Node *pNode)\r
190     : CXFA_LayoutItemImpl(pNode, TRUE)\r
191     , m_pPrev(NULL)\r
192     , m_pNext(NULL)\r
193     , m_dwStatus(0)\r
194 {\r
195 }\r
196 CXFA_ContentLayoutItemImpl::~CXFA_ContentLayoutItemImpl()\r
197 {\r
198     if (m_pFormNode->GetUserData(XFA_LAYOUTITEMKEY) == this) {\r
199         m_pFormNode->SetUserData(XFA_LAYOUTITEMKEY, NULL);\r
200     }\r
201 }\r