xref: /aosp_15_r20/external/pdfium/fxjs/xfa/cjx_layoutpseudomodel.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2017 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker 
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker 
7*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cjx_layoutpseudomodel.h"
8*3ac0a46fSAndroid Build Coastguard Worker 
9*3ac0a46fSAndroid Build Coastguard Worker #include <set>
10*3ac0a46fSAndroid Build Coastguard Worker #include <utility>
11*3ac0a46fSAndroid Build Coastguard Worker 
12*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_coordinates.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/fxv8.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/js_resources.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_class.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_engine.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/containers/contains.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "v8/include/cppgc/allocation.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "v8/include/v8-object.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffnotify.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/layout/cxfa_contentlayoutitem.h"
22*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/layout/cxfa_layoutitem.h"
23*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/layout/cxfa_layoutprocessor.h"
24*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/layout/cxfa_traversestrategy_layoutitem.h"
25*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/layout/cxfa_viewlayoutitem.h"
26*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cscript_layoutpseudomodel.h"
27*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_arraynodelist.h"
28*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_document.h"
29*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_form.h"
30*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_measurement.h"
31*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_node.h"
32*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
33*3ac0a46fSAndroid Build Coastguard Worker 
34*3ac0a46fSAndroid Build Coastguard Worker const CJX_MethodSpec CJX_LayoutPseudoModel::MethodSpecs[] = {
35*3ac0a46fSAndroid Build Coastguard Worker     {"absPage", absPage_static},
36*3ac0a46fSAndroid Build Coastguard Worker     {"absPageCount", absPageCount_static},
37*3ac0a46fSAndroid Build Coastguard Worker     {"absPageCountInBatch", absPageCountInBatch_static},
38*3ac0a46fSAndroid Build Coastguard Worker     {"absPageInBatch", absPageInBatch_static},
39*3ac0a46fSAndroid Build Coastguard Worker     {"absPageSpan", absPageSpan_static},
40*3ac0a46fSAndroid Build Coastguard Worker     {"h", h_static},
41*3ac0a46fSAndroid Build Coastguard Worker     {"page", page_static},
42*3ac0a46fSAndroid Build Coastguard Worker     {"pageContent", pageContent_static},
43*3ac0a46fSAndroid Build Coastguard Worker     {"pageCount", pageCount_static},
44*3ac0a46fSAndroid Build Coastguard Worker     {"pageSpan", pageSpan_static},
45*3ac0a46fSAndroid Build Coastguard Worker     {"relayout", relayout_static},
46*3ac0a46fSAndroid Build Coastguard Worker     {"relayoutPageArea", relayoutPageArea_static},
47*3ac0a46fSAndroid Build Coastguard Worker     {"sheet", sheet_static},
48*3ac0a46fSAndroid Build Coastguard Worker     {"sheetCount", sheetCount_static},
49*3ac0a46fSAndroid Build Coastguard Worker     {"sheetCountInBatch", sheetCountInBatch_static},
50*3ac0a46fSAndroid Build Coastguard Worker     {"sheetInBatch", sheetInBatch_static},
51*3ac0a46fSAndroid Build Coastguard Worker     {"w", w_static},
52*3ac0a46fSAndroid Build Coastguard Worker     {"x", x_static},
53*3ac0a46fSAndroid Build Coastguard Worker     {"y", y_static}};
54*3ac0a46fSAndroid Build Coastguard Worker 
CJX_LayoutPseudoModel(CScript_LayoutPseudoModel * model)55*3ac0a46fSAndroid Build Coastguard Worker CJX_LayoutPseudoModel::CJX_LayoutPseudoModel(CScript_LayoutPseudoModel* model)
56*3ac0a46fSAndroid Build Coastguard Worker     : CJX_Object(model) {
57*3ac0a46fSAndroid Build Coastguard Worker   DefineMethods(MethodSpecs);
58*3ac0a46fSAndroid Build Coastguard Worker }
59*3ac0a46fSAndroid Build Coastguard Worker 
60*3ac0a46fSAndroid Build Coastguard Worker CJX_LayoutPseudoModel::~CJX_LayoutPseudoModel() = default;
61*3ac0a46fSAndroid Build Coastguard Worker 
DynamicTypeIs(TypeTag eType) const62*3ac0a46fSAndroid Build Coastguard Worker bool CJX_LayoutPseudoModel::DynamicTypeIs(TypeTag eType) const {
63*3ac0a46fSAndroid Build Coastguard Worker   return eType == static_type__ || ParentType__::DynamicTypeIs(eType);
64*3ac0a46fSAndroid Build Coastguard Worker }
65*3ac0a46fSAndroid Build Coastguard Worker 
ready(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)66*3ac0a46fSAndroid Build Coastguard Worker void CJX_LayoutPseudoModel::ready(v8::Isolate* pIsolate,
67*3ac0a46fSAndroid Build Coastguard Worker                                   v8::Local<v8::Value>* pValue,
68*3ac0a46fSAndroid Build Coastguard Worker                                   bool bSetting,
69*3ac0a46fSAndroid Build Coastguard Worker                                   XFA_Attribute eAttribute) {
70*3ac0a46fSAndroid Build Coastguard Worker   CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
71*3ac0a46fSAndroid Build Coastguard Worker   if (!pNotify)
72*3ac0a46fSAndroid Build Coastguard Worker     return;
73*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
74*3ac0a46fSAndroid Build Coastguard Worker     ThrowException(pIsolate,
75*3ac0a46fSAndroid Build Coastguard Worker                    WideString::FromASCII("Unable to set ready value."));
76*3ac0a46fSAndroid Build Coastguard Worker     return;
77*3ac0a46fSAndroid Build Coastguard Worker   }
78*3ac0a46fSAndroid Build Coastguard Worker 
79*3ac0a46fSAndroid Build Coastguard Worker   CXFA_FFDocView::LayoutStatus iStatus = pNotify->GetLayoutStatus();
80*3ac0a46fSAndroid Build Coastguard Worker   const bool bReady = iStatus != CXFA_FFDocView::LayoutStatus::kNone &&
81*3ac0a46fSAndroid Build Coastguard Worker                       iStatus != CXFA_FFDocView::LayoutStatus::kStart;
82*3ac0a46fSAndroid Build Coastguard Worker   *pValue = fxv8::NewBooleanHelper(pIsolate, bReady);
83*3ac0a46fSAndroid Build Coastguard Worker }
84*3ac0a46fSAndroid Build Coastguard Worker 
DoHWXYInternal(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params,HWXY layoutModel)85*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::DoHWXYInternal(
86*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
87*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params,
88*3ac0a46fSAndroid Build Coastguard Worker     HWXY layoutModel) {
89*3ac0a46fSAndroid Build Coastguard Worker   if (params.empty() || params.size() > 3)
90*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
91*3ac0a46fSAndroid Build Coastguard Worker 
92*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pNode = ToNode(runtime->ToXFAObject(params[0]));
93*3ac0a46fSAndroid Build Coastguard Worker   if (!pNode)
94*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success();
95*3ac0a46fSAndroid Build Coastguard Worker 
96*3ac0a46fSAndroid Build Coastguard Worker   WideString unit = WideString::FromASCII("pt");
97*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() >= 2) {
98*3ac0a46fSAndroid Build Coastguard Worker     WideString tmp_unit = runtime->ToWideString(params[1]);
99*3ac0a46fSAndroid Build Coastguard Worker     if (!tmp_unit.IsEmpty())
100*3ac0a46fSAndroid Build Coastguard Worker       unit = std::move(tmp_unit);
101*3ac0a46fSAndroid Build Coastguard Worker   }
102*3ac0a46fSAndroid Build Coastguard Worker   int32_t iIndex = params.size() >= 3 ? runtime->ToInt32(params[2]) : 0;
103*3ac0a46fSAndroid Build Coastguard Worker   auto* pDocLayout = CXFA_LayoutProcessor::FromDocument(GetDocument());
104*3ac0a46fSAndroid Build Coastguard Worker   CXFA_ContentLayoutItem* pLayoutItem =
105*3ac0a46fSAndroid Build Coastguard Worker       ToContentLayoutItem(pDocLayout->GetLayoutItem(pNode));
106*3ac0a46fSAndroid Build Coastguard Worker   if (!pLayoutItem)
107*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success();
108*3ac0a46fSAndroid Build Coastguard Worker 
109*3ac0a46fSAndroid Build Coastguard Worker   while (iIndex > 0 && pLayoutItem) {
110*3ac0a46fSAndroid Build Coastguard Worker     pLayoutItem = pLayoutItem->GetNext();
111*3ac0a46fSAndroid Build Coastguard Worker     --iIndex;
112*3ac0a46fSAndroid Build Coastguard Worker   }
113*3ac0a46fSAndroid Build Coastguard Worker 
114*3ac0a46fSAndroid Build Coastguard Worker   if (!pLayoutItem)
115*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success(runtime->NewNumber(0.0));
116*3ac0a46fSAndroid Build Coastguard Worker 
117*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Measurement measure;
118*3ac0a46fSAndroid Build Coastguard Worker   CFX_RectF rtRect = pLayoutItem->GetRelativeRect();
119*3ac0a46fSAndroid Build Coastguard Worker   switch (layoutModel) {
120*3ac0a46fSAndroid Build Coastguard Worker     case HWXY::kH:
121*3ac0a46fSAndroid Build Coastguard Worker       measure.Set(rtRect.height, XFA_Unit::Pt);
122*3ac0a46fSAndroid Build Coastguard Worker       break;
123*3ac0a46fSAndroid Build Coastguard Worker     case HWXY::kW:
124*3ac0a46fSAndroid Build Coastguard Worker       measure.Set(rtRect.width, XFA_Unit::Pt);
125*3ac0a46fSAndroid Build Coastguard Worker       break;
126*3ac0a46fSAndroid Build Coastguard Worker     case HWXY::kX:
127*3ac0a46fSAndroid Build Coastguard Worker       measure.Set(rtRect.left, XFA_Unit::Pt);
128*3ac0a46fSAndroid Build Coastguard Worker       break;
129*3ac0a46fSAndroid Build Coastguard Worker     case HWXY::kY:
130*3ac0a46fSAndroid Build Coastguard Worker       measure.Set(rtRect.top, XFA_Unit::Pt);
131*3ac0a46fSAndroid Build Coastguard Worker       break;
132*3ac0a46fSAndroid Build Coastguard Worker   }
133*3ac0a46fSAndroid Build Coastguard Worker 
134*3ac0a46fSAndroid Build Coastguard Worker   XFA_Unit eUnit = CXFA_Measurement::GetUnitFromString(unit.AsStringView());
135*3ac0a46fSAndroid Build Coastguard Worker   if (eUnit == XFA_Unit::Unknown)
136*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kValueError);
137*3ac0a46fSAndroid Build Coastguard Worker 
138*3ac0a46fSAndroid Build Coastguard Worker   float fValue = measure.ToUnit(eUnit);
139*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success(
140*3ac0a46fSAndroid Build Coastguard Worker       runtime->NewNumber(FXSYS_roundf(fValue * 1000) / 1000.0f));
141*3ac0a46fSAndroid Build Coastguard Worker }
142*3ac0a46fSAndroid Build Coastguard Worker 
h(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)143*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::h(
144*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
145*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
146*3ac0a46fSAndroid Build Coastguard Worker   return DoHWXYInternal(runtime, params, HWXY::kH);
147*3ac0a46fSAndroid Build Coastguard Worker }
148*3ac0a46fSAndroid Build Coastguard Worker 
w(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)149*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::w(
150*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
151*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
152*3ac0a46fSAndroid Build Coastguard Worker   return DoHWXYInternal(runtime, params, HWXY::kW);
153*3ac0a46fSAndroid Build Coastguard Worker }
154*3ac0a46fSAndroid Build Coastguard Worker 
x(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)155*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::x(
156*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
157*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
158*3ac0a46fSAndroid Build Coastguard Worker   return DoHWXYInternal(runtime, params, HWXY::kX);
159*3ac0a46fSAndroid Build Coastguard Worker }
160*3ac0a46fSAndroid Build Coastguard Worker 
y(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)161*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::y(
162*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
163*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
164*3ac0a46fSAndroid Build Coastguard Worker   return DoHWXYInternal(runtime, params, HWXY::kY);
165*3ac0a46fSAndroid Build Coastguard Worker }
166*3ac0a46fSAndroid Build Coastguard Worker 
AllPageCount(CFXJSE_Engine * runtime)167*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::AllPageCount(CFXJSE_Engine* runtime) {
168*3ac0a46fSAndroid Build Coastguard Worker   auto* pDocLayout = CXFA_LayoutProcessor::FromDocument(GetDocument());
169*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success(runtime->NewNumber(pDocLayout->CountPages()));
170*3ac0a46fSAndroid Build Coastguard Worker }
171*3ac0a46fSAndroid Build Coastguard Worker 
NumberedPageCount(CFXJSE_Engine * runtime)172*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::NumberedPageCount(CFXJSE_Engine* runtime) {
173*3ac0a46fSAndroid Build Coastguard Worker   auto* pDocLayout = CXFA_LayoutProcessor::FromDocument(GetDocument());
174*3ac0a46fSAndroid Build Coastguard Worker   int32_t iPageCount = 0;
175*3ac0a46fSAndroid Build Coastguard Worker   int32_t iPageNum = pDocLayout->CountPages();
176*3ac0a46fSAndroid Build Coastguard Worker   for (int32_t i = 0; i < iPageNum; i++) {
177*3ac0a46fSAndroid Build Coastguard Worker     CXFA_ViewLayoutItem* pLayoutPage = pDocLayout->GetPage(i);
178*3ac0a46fSAndroid Build Coastguard Worker     if (!pLayoutPage)
179*3ac0a46fSAndroid Build Coastguard Worker       continue;
180*3ac0a46fSAndroid Build Coastguard Worker 
181*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Node* pMasterPage = pLayoutPage->GetMasterPage();
182*3ac0a46fSAndroid Build Coastguard Worker     if (pMasterPage->JSObject()->GetInteger(XFA_Attribute::Numbered))
183*3ac0a46fSAndroid Build Coastguard Worker       iPageCount++;
184*3ac0a46fSAndroid Build Coastguard Worker   }
185*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success(runtime->NewNumber(iPageCount));
186*3ac0a46fSAndroid Build Coastguard Worker }
187*3ac0a46fSAndroid Build Coastguard Worker 
pageCount(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)188*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::pageCount(
189*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
190*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
191*3ac0a46fSAndroid Build Coastguard Worker   return NumberedPageCount(runtime);
192*3ac0a46fSAndroid Build Coastguard Worker }
193*3ac0a46fSAndroid Build Coastguard Worker 
pageSpan(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)194*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::pageSpan(
195*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
196*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
197*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() != 1)
198*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
199*3ac0a46fSAndroid Build Coastguard Worker 
200*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pNode = ToNode(runtime->ToXFAObject(params[0]));
201*3ac0a46fSAndroid Build Coastguard Worker   if (!pNode)
202*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success();
203*3ac0a46fSAndroid Build Coastguard Worker 
204*3ac0a46fSAndroid Build Coastguard Worker   auto* pDocLayout = CXFA_LayoutProcessor::FromDocument(GetDocument());
205*3ac0a46fSAndroid Build Coastguard Worker   CXFA_ContentLayoutItem* pLayoutItem =
206*3ac0a46fSAndroid Build Coastguard Worker       ToContentLayoutItem(pDocLayout->GetLayoutItem(pNode));
207*3ac0a46fSAndroid Build Coastguard Worker   if (!pLayoutItem)
208*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success(runtime->NewNumber(-1));
209*3ac0a46fSAndroid Build Coastguard Worker 
210*3ac0a46fSAndroid Build Coastguard Worker   int32_t iLast = pLayoutItem->GetLast()->GetPage()->GetPageIndex();
211*3ac0a46fSAndroid Build Coastguard Worker   int32_t iFirst = pLayoutItem->GetFirst()->GetPage()->GetPageIndex();
212*3ac0a46fSAndroid Build Coastguard Worker   int32_t iPageSpan = iLast - iFirst + 1;
213*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success(runtime->NewNumber(iPageSpan));
214*3ac0a46fSAndroid Build Coastguard Worker }
215*3ac0a46fSAndroid Build Coastguard Worker 
page(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)216*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::page(
217*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
218*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
219*3ac0a46fSAndroid Build Coastguard Worker   return PageInternals(runtime, params, false);
220*3ac0a46fSAndroid Build Coastguard Worker }
221*3ac0a46fSAndroid Build Coastguard Worker 
GetObjArray(CXFA_LayoutProcessor * pDocLayout,int32_t iPageNo,const WideString & wsType,bool bOnPageArea)222*3ac0a46fSAndroid Build Coastguard Worker std::vector<CXFA_Node*> CJX_LayoutPseudoModel::GetObjArray(
223*3ac0a46fSAndroid Build Coastguard Worker     CXFA_LayoutProcessor* pDocLayout,
224*3ac0a46fSAndroid Build Coastguard Worker     int32_t iPageNo,
225*3ac0a46fSAndroid Build Coastguard Worker     const WideString& wsType,
226*3ac0a46fSAndroid Build Coastguard Worker     bool bOnPageArea) {
227*3ac0a46fSAndroid Build Coastguard Worker   CXFA_ViewLayoutItem* pLayoutPage = pDocLayout->GetPage(iPageNo);
228*3ac0a46fSAndroid Build Coastguard Worker   if (!pLayoutPage)
229*3ac0a46fSAndroid Build Coastguard Worker     return std::vector<CXFA_Node*>();
230*3ac0a46fSAndroid Build Coastguard Worker 
231*3ac0a46fSAndroid Build Coastguard Worker   std::vector<CXFA_Node*> retArray;
232*3ac0a46fSAndroid Build Coastguard Worker   if (wsType.EqualsASCII("pageArea")) {
233*3ac0a46fSAndroid Build Coastguard Worker     if (pLayoutPage->GetFormNode())
234*3ac0a46fSAndroid Build Coastguard Worker       retArray.push_back(pLayoutPage->GetFormNode());
235*3ac0a46fSAndroid Build Coastguard Worker     return retArray;
236*3ac0a46fSAndroid Build Coastguard Worker   }
237*3ac0a46fSAndroid Build Coastguard Worker   if (wsType.EqualsASCII("contentArea")) {
238*3ac0a46fSAndroid Build Coastguard Worker     for (CXFA_LayoutItem* pItem = pLayoutPage->GetFirstChild(); pItem;
239*3ac0a46fSAndroid Build Coastguard Worker          pItem = pItem->GetNextSibling()) {
240*3ac0a46fSAndroid Build Coastguard Worker       if (pItem->GetFormNode()->GetElementType() == XFA_Element::ContentArea)
241*3ac0a46fSAndroid Build Coastguard Worker         retArray.push_back(pItem->GetFormNode());
242*3ac0a46fSAndroid Build Coastguard Worker     }
243*3ac0a46fSAndroid Build Coastguard Worker     return retArray;
244*3ac0a46fSAndroid Build Coastguard Worker   }
245*3ac0a46fSAndroid Build Coastguard Worker   std::set<CXFA_Node*> formItems;
246*3ac0a46fSAndroid Build Coastguard Worker   if (wsType.IsEmpty()) {
247*3ac0a46fSAndroid Build Coastguard Worker     if (pLayoutPage->GetFormNode())
248*3ac0a46fSAndroid Build Coastguard Worker       retArray.push_back(pLayoutPage->GetFormNode());
249*3ac0a46fSAndroid Build Coastguard Worker 
250*3ac0a46fSAndroid Build Coastguard Worker     for (CXFA_LayoutItem* pItem = pLayoutPage->GetFirstChild(); pItem;
251*3ac0a46fSAndroid Build Coastguard Worker          pItem = pItem->GetNextSibling()) {
252*3ac0a46fSAndroid Build Coastguard Worker       if (pItem->GetFormNode()->GetElementType() == XFA_Element::ContentArea) {
253*3ac0a46fSAndroid Build Coastguard Worker         retArray.push_back(pItem->GetFormNode());
254*3ac0a46fSAndroid Build Coastguard Worker         if (!bOnPageArea) {
255*3ac0a46fSAndroid Build Coastguard Worker           CXFA_LayoutItemIterator iterator(pItem->GetFirstChild());
256*3ac0a46fSAndroid Build Coastguard Worker           for (CXFA_LayoutItem* pChild = iterator.GetCurrent(); pChild;
257*3ac0a46fSAndroid Build Coastguard Worker                pChild = iterator.MoveToNext()) {
258*3ac0a46fSAndroid Build Coastguard Worker             CXFA_ContentLayoutItem* pItemChild = pChild->AsContentLayoutItem();
259*3ac0a46fSAndroid Build Coastguard Worker             if (!pItemChild)
260*3ac0a46fSAndroid Build Coastguard Worker               continue;
261*3ac0a46fSAndroid Build Coastguard Worker 
262*3ac0a46fSAndroid Build Coastguard Worker             XFA_Element eType = pItemChild->GetFormNode()->GetElementType();
263*3ac0a46fSAndroid Build Coastguard Worker             if (eType != XFA_Element::Field && eType != XFA_Element::Draw &&
264*3ac0a46fSAndroid Build Coastguard Worker                 eType != XFA_Element::Subform && eType != XFA_Element::Area) {
265*3ac0a46fSAndroid Build Coastguard Worker               continue;
266*3ac0a46fSAndroid Build Coastguard Worker             }
267*3ac0a46fSAndroid Build Coastguard Worker             if (pdfium::Contains(formItems, pItemChild->GetFormNode()))
268*3ac0a46fSAndroid Build Coastguard Worker               continue;
269*3ac0a46fSAndroid Build Coastguard Worker 
270*3ac0a46fSAndroid Build Coastguard Worker             formItems.insert(pItemChild->GetFormNode());
271*3ac0a46fSAndroid Build Coastguard Worker             retArray.push_back(pItemChild->GetFormNode());
272*3ac0a46fSAndroid Build Coastguard Worker           }
273*3ac0a46fSAndroid Build Coastguard Worker         }
274*3ac0a46fSAndroid Build Coastguard Worker       } else {
275*3ac0a46fSAndroid Build Coastguard Worker         if (bOnPageArea) {
276*3ac0a46fSAndroid Build Coastguard Worker           CXFA_LayoutItemIterator iterator(pItem);
277*3ac0a46fSAndroid Build Coastguard Worker           for (CXFA_LayoutItem* pChild = iterator.GetCurrent(); pChild;
278*3ac0a46fSAndroid Build Coastguard Worker                pChild = iterator.MoveToNext()) {
279*3ac0a46fSAndroid Build Coastguard Worker             CXFA_ContentLayoutItem* pItemChild = pChild->AsContentLayoutItem();
280*3ac0a46fSAndroid Build Coastguard Worker             if (!pItemChild)
281*3ac0a46fSAndroid Build Coastguard Worker               continue;
282*3ac0a46fSAndroid Build Coastguard Worker 
283*3ac0a46fSAndroid Build Coastguard Worker             XFA_Element eType = pItemChild->GetFormNode()->GetElementType();
284*3ac0a46fSAndroid Build Coastguard Worker             if (eType != XFA_Element::Field && eType != XFA_Element::Draw &&
285*3ac0a46fSAndroid Build Coastguard Worker                 eType != XFA_Element::Subform && eType != XFA_Element::Area) {
286*3ac0a46fSAndroid Build Coastguard Worker               continue;
287*3ac0a46fSAndroid Build Coastguard Worker             }
288*3ac0a46fSAndroid Build Coastguard Worker             if (pdfium::Contains(formItems, pItemChild->GetFormNode()))
289*3ac0a46fSAndroid Build Coastguard Worker               continue;
290*3ac0a46fSAndroid Build Coastguard Worker 
291*3ac0a46fSAndroid Build Coastguard Worker             formItems.insert(pItemChild->GetFormNode());
292*3ac0a46fSAndroid Build Coastguard Worker             retArray.push_back(pItemChild->GetFormNode());
293*3ac0a46fSAndroid Build Coastguard Worker           }
294*3ac0a46fSAndroid Build Coastguard Worker         }
295*3ac0a46fSAndroid Build Coastguard Worker       }
296*3ac0a46fSAndroid Build Coastguard Worker     }
297*3ac0a46fSAndroid Build Coastguard Worker     return retArray;
298*3ac0a46fSAndroid Build Coastguard Worker   }
299*3ac0a46fSAndroid Build Coastguard Worker 
300*3ac0a46fSAndroid Build Coastguard Worker   XFA_Element eType = XFA_Element::Unknown;
301*3ac0a46fSAndroid Build Coastguard Worker   if (wsType.EqualsASCII("field"))
302*3ac0a46fSAndroid Build Coastguard Worker     eType = XFA_Element::Field;
303*3ac0a46fSAndroid Build Coastguard Worker   else if (wsType.EqualsASCII("draw"))
304*3ac0a46fSAndroid Build Coastguard Worker     eType = XFA_Element::Draw;
305*3ac0a46fSAndroid Build Coastguard Worker   else if (wsType.EqualsASCII("subform"))
306*3ac0a46fSAndroid Build Coastguard Worker     eType = XFA_Element::Subform;
307*3ac0a46fSAndroid Build Coastguard Worker   else if (wsType.EqualsASCII("area"))
308*3ac0a46fSAndroid Build Coastguard Worker     eType = XFA_Element::Area;
309*3ac0a46fSAndroid Build Coastguard Worker 
310*3ac0a46fSAndroid Build Coastguard Worker   if (eType != XFA_Element::Unknown) {
311*3ac0a46fSAndroid Build Coastguard Worker     for (CXFA_LayoutItem* pItem = pLayoutPage->GetFirstChild(); pItem;
312*3ac0a46fSAndroid Build Coastguard Worker          pItem = pItem->GetNextSibling()) {
313*3ac0a46fSAndroid Build Coastguard Worker       if (pItem->GetFormNode()->GetElementType() == XFA_Element::ContentArea) {
314*3ac0a46fSAndroid Build Coastguard Worker         if (!bOnPageArea) {
315*3ac0a46fSAndroid Build Coastguard Worker           CXFA_LayoutItemIterator iterator(pItem->GetFirstChild());
316*3ac0a46fSAndroid Build Coastguard Worker           for (CXFA_LayoutItem* pChild = iterator.GetCurrent(); pChild;
317*3ac0a46fSAndroid Build Coastguard Worker                pChild = iterator.MoveToNext()) {
318*3ac0a46fSAndroid Build Coastguard Worker             CXFA_ContentLayoutItem* pItemChild = pChild->AsContentLayoutItem();
319*3ac0a46fSAndroid Build Coastguard Worker             if (!pItemChild)
320*3ac0a46fSAndroid Build Coastguard Worker               continue;
321*3ac0a46fSAndroid Build Coastguard Worker             if (pItemChild->GetFormNode()->GetElementType() != eType)
322*3ac0a46fSAndroid Build Coastguard Worker               continue;
323*3ac0a46fSAndroid Build Coastguard Worker             if (pdfium::Contains(formItems, pItemChild->GetFormNode()))
324*3ac0a46fSAndroid Build Coastguard Worker               continue;
325*3ac0a46fSAndroid Build Coastguard Worker 
326*3ac0a46fSAndroid Build Coastguard Worker             formItems.insert(pItemChild->GetFormNode());
327*3ac0a46fSAndroid Build Coastguard Worker             retArray.push_back(pItemChild->GetFormNode());
328*3ac0a46fSAndroid Build Coastguard Worker           }
329*3ac0a46fSAndroid Build Coastguard Worker         }
330*3ac0a46fSAndroid Build Coastguard Worker       } else {
331*3ac0a46fSAndroid Build Coastguard Worker         if (bOnPageArea) {
332*3ac0a46fSAndroid Build Coastguard Worker           CXFA_LayoutItemIterator iterator(pItem);
333*3ac0a46fSAndroid Build Coastguard Worker           for (CXFA_LayoutItem* pChild = iterator.GetCurrent(); pChild;
334*3ac0a46fSAndroid Build Coastguard Worker                pChild = iterator.MoveToNext()) {
335*3ac0a46fSAndroid Build Coastguard Worker             CXFA_ContentLayoutItem* pItemChild = pChild->AsContentLayoutItem();
336*3ac0a46fSAndroid Build Coastguard Worker             if (!pItemChild)
337*3ac0a46fSAndroid Build Coastguard Worker               continue;
338*3ac0a46fSAndroid Build Coastguard Worker             if (pItemChild->GetFormNode()->GetElementType() != eType)
339*3ac0a46fSAndroid Build Coastguard Worker               continue;
340*3ac0a46fSAndroid Build Coastguard Worker             if (pdfium::Contains(formItems, pItemChild->GetFormNode()))
341*3ac0a46fSAndroid Build Coastguard Worker               continue;
342*3ac0a46fSAndroid Build Coastguard Worker 
343*3ac0a46fSAndroid Build Coastguard Worker             formItems.insert(pItemChild->GetFormNode());
344*3ac0a46fSAndroid Build Coastguard Worker             retArray.push_back(pItemChild->GetFormNode());
345*3ac0a46fSAndroid Build Coastguard Worker           }
346*3ac0a46fSAndroid Build Coastguard Worker         }
347*3ac0a46fSAndroid Build Coastguard Worker       }
348*3ac0a46fSAndroid Build Coastguard Worker     }
349*3ac0a46fSAndroid Build Coastguard Worker   }
350*3ac0a46fSAndroid Build Coastguard Worker   return retArray;
351*3ac0a46fSAndroid Build Coastguard Worker }
352*3ac0a46fSAndroid Build Coastguard Worker 
pageContent(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)353*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::pageContent(
354*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
355*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
356*3ac0a46fSAndroid Build Coastguard Worker   if (params.empty() || params.size() > 3)
357*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
358*3ac0a46fSAndroid Build Coastguard Worker 
359*3ac0a46fSAndroid Build Coastguard Worker   int32_t iIndex = 0;
360*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() >= 1)
361*3ac0a46fSAndroid Build Coastguard Worker     iIndex = runtime->ToInt32(params[0]);
362*3ac0a46fSAndroid Build Coastguard Worker 
363*3ac0a46fSAndroid Build Coastguard Worker   WideString wsType;
364*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() >= 2)
365*3ac0a46fSAndroid Build Coastguard Worker     wsType = runtime->ToWideString(params[1]);
366*3ac0a46fSAndroid Build Coastguard Worker 
367*3ac0a46fSAndroid Build Coastguard Worker   bool bOnPageArea = false;
368*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() >= 3)
369*3ac0a46fSAndroid Build Coastguard Worker     bOnPageArea = runtime->ToBoolean(params[2]);
370*3ac0a46fSAndroid Build Coastguard Worker 
371*3ac0a46fSAndroid Build Coastguard Worker   CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
372*3ac0a46fSAndroid Build Coastguard Worker   if (!pNotify)
373*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success();
374*3ac0a46fSAndroid Build Coastguard Worker 
375*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Document* pDoc = GetDocument();
376*3ac0a46fSAndroid Build Coastguard Worker   auto* pDocLayout = CXFA_LayoutProcessor::FromDocument(pDoc);
377*3ac0a46fSAndroid Build Coastguard Worker   auto* pArrayNodeList = cppgc::MakeGarbageCollected<CXFA_ArrayNodeList>(
378*3ac0a46fSAndroid Build Coastguard Worker       pDoc->GetHeap()->GetAllocationHandle(), pDoc);
379*3ac0a46fSAndroid Build Coastguard Worker   pDoc->GetNodeOwner()->PersistList(pArrayNodeList);
380*3ac0a46fSAndroid Build Coastguard Worker   pArrayNodeList->SetArrayNodeList(
381*3ac0a46fSAndroid Build Coastguard Worker       GetObjArray(pDocLayout, iIndex, wsType, bOnPageArea));
382*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success(runtime->NewNormalXFAObject(pArrayNodeList));
383*3ac0a46fSAndroid Build Coastguard Worker }
384*3ac0a46fSAndroid Build Coastguard Worker 
absPageCount(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)385*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::absPageCount(
386*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
387*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
388*3ac0a46fSAndroid Build Coastguard Worker   return AllPageCount(runtime);
389*3ac0a46fSAndroid Build Coastguard Worker }
390*3ac0a46fSAndroid Build Coastguard Worker 
absPageCountInBatch(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)391*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::absPageCountInBatch(
392*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
393*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
394*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success(runtime->NewNumber(0));
395*3ac0a46fSAndroid Build Coastguard Worker }
396*3ac0a46fSAndroid Build Coastguard Worker 
sheetCountInBatch(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)397*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::sheetCountInBatch(
398*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
399*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
400*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success(runtime->NewNumber(0));
401*3ac0a46fSAndroid Build Coastguard Worker }
402*3ac0a46fSAndroid Build Coastguard Worker 
relayout(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)403*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::relayout(
404*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
405*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
406*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pRootNode = GetDocument()->GetRoot();
407*3ac0a46fSAndroid Build Coastguard Worker   auto* pLayoutProcessor = GetDocument()->GetLayoutProcessor();
408*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Form* pFormRoot =
409*3ac0a46fSAndroid Build Coastguard Worker       pRootNode->GetFirstChildByClass<CXFA_Form>(XFA_Element::Form);
410*3ac0a46fSAndroid Build Coastguard Worker   if (pFormRoot) {
411*3ac0a46fSAndroid Build Coastguard Worker     if (pFormRoot->GetFirstChild())
412*3ac0a46fSAndroid Build Coastguard Worker       pLayoutProcessor->SetHasChangedContainer();
413*3ac0a46fSAndroid Build Coastguard Worker   }
414*3ac0a46fSAndroid Build Coastguard Worker   pLayoutProcessor->SetForceRelayout();
415*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success();
416*3ac0a46fSAndroid Build Coastguard Worker }
417*3ac0a46fSAndroid Build Coastguard Worker 
absPageSpan(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)418*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::absPageSpan(
419*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
420*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
421*3ac0a46fSAndroid Build Coastguard Worker   return pageSpan(runtime, params);
422*3ac0a46fSAndroid Build Coastguard Worker }
423*3ac0a46fSAndroid Build Coastguard Worker 
absPageInBatch(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)424*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::absPageInBatch(
425*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
426*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
427*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() != 1)
428*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
429*3ac0a46fSAndroid Build Coastguard Worker 
430*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success(runtime->NewNumber(0));
431*3ac0a46fSAndroid Build Coastguard Worker }
432*3ac0a46fSAndroid Build Coastguard Worker 
sheetInBatch(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)433*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::sheetInBatch(
434*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
435*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
436*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() != 1)
437*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
438*3ac0a46fSAndroid Build Coastguard Worker 
439*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success(runtime->NewNumber(0));
440*3ac0a46fSAndroid Build Coastguard Worker }
441*3ac0a46fSAndroid Build Coastguard Worker 
sheet(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)442*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::sheet(
443*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
444*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
445*3ac0a46fSAndroid Build Coastguard Worker   return PageInternals(runtime, params, true);
446*3ac0a46fSAndroid Build Coastguard Worker }
447*3ac0a46fSAndroid Build Coastguard Worker 
relayoutPageArea(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)448*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::relayoutPageArea(
449*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
450*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
451*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success();
452*3ac0a46fSAndroid Build Coastguard Worker }
453*3ac0a46fSAndroid Build Coastguard Worker 
sheetCount(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)454*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::sheetCount(
455*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
456*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
457*3ac0a46fSAndroid Build Coastguard Worker   return AllPageCount(runtime);
458*3ac0a46fSAndroid Build Coastguard Worker }
459*3ac0a46fSAndroid Build Coastguard Worker 
absPage(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)460*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::absPage(
461*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
462*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
463*3ac0a46fSAndroid Build Coastguard Worker   return PageInternals(runtime, params, true);
464*3ac0a46fSAndroid Build Coastguard Worker }
465*3ac0a46fSAndroid Build Coastguard Worker 
PageInternals(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params,bool bAbsPage)466*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_LayoutPseudoModel::PageInternals(
467*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
468*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params,
469*3ac0a46fSAndroid Build Coastguard Worker     bool bAbsPage) {
470*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() != 1)
471*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
472*3ac0a46fSAndroid Build Coastguard Worker 
473*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pNode = ToNode(runtime->ToXFAObject(params[0]));
474*3ac0a46fSAndroid Build Coastguard Worker   if (!pNode)
475*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success(runtime->NewNumber(0));
476*3ac0a46fSAndroid Build Coastguard Worker 
477*3ac0a46fSAndroid Build Coastguard Worker   auto* pDocLayout = CXFA_LayoutProcessor::FromDocument(GetDocument());
478*3ac0a46fSAndroid Build Coastguard Worker   CXFA_ContentLayoutItem* pLayoutItem =
479*3ac0a46fSAndroid Build Coastguard Worker       ToContentLayoutItem(pDocLayout->GetLayoutItem(pNode));
480*3ac0a46fSAndroid Build Coastguard Worker   if (!pLayoutItem)
481*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success(runtime->NewNumber(-1));
482*3ac0a46fSAndroid Build Coastguard Worker 
483*3ac0a46fSAndroid Build Coastguard Worker   int32_t iPage = pLayoutItem->GetFirst()->GetPage()->GetPageIndex();
484*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success(runtime->NewNumber(bAbsPage ? iPage : iPage + 1));
485*3ac0a46fSAndroid Build Coastguard Worker }
486