xref: /aosp_15_r20/external/pdfium/xfa/fxfa/cxfa_ffdoc.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2014 The PDFium Authors
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/cxfa_ffdoc.h"
8 
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12 
13 #include "core/fpdfapi/parser/cpdf_dictionary.h"
14 #include "core/fpdfapi/parser/cpdf_document.h"
15 #include "core/fpdfapi/parser/cpdf_stream.h"
16 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
17 #include "core/fpdfdoc/cpdf_nametree.h"
18 #include "core/fxcrt/cfx_read_only_span_stream.h"
19 #include "core/fxcrt/fx_extension.h"
20 #include "core/fxcrt/xml/cfx_xmldocument.h"
21 #include "core/fxcrt/xml/cfx_xmlelement.h"
22 #include "core/fxcrt/xml/cfx_xmlnode.h"
23 #include "core/fxcrt/xml/cfx_xmlparser.h"
24 #include "core/fxge/dib/cfx_dibitmap.h"
25 #include "fxjs/xfa/cjx_object.h"
26 #include "third_party/base/check.h"
27 #include "v8/include/cppgc/allocation.h"
28 #include "v8/include/cppgc/heap.h"
29 #include "xfa/fgas/font/cfgas_gefont.h"
30 #include "xfa/fgas/font/cfgas_pdffontmgr.h"
31 #include "xfa/fwl/cfwl_notedriver.h"
32 #include "xfa/fxfa/cxfa_ffapp.h"
33 #include "xfa/fxfa/cxfa_ffdocview.h"
34 #include "xfa/fxfa/cxfa_ffnotify.h"
35 #include "xfa/fxfa/cxfa_ffwidget.h"
36 #include "xfa/fxfa/cxfa_fontmgr.h"
37 #include "xfa/fxfa/layout/cxfa_layoutprocessor.h"
38 #include "xfa/fxfa/parser/cxfa_acrobat.h"
39 #include "xfa/fxfa/parser/cxfa_acrobat7.h"
40 #include "xfa/fxfa/parser/cxfa_dataexporter.h"
41 #include "xfa/fxfa/parser/cxfa_document.h"
42 #include "xfa/fxfa/parser/cxfa_document_builder.h"
43 #include "xfa/fxfa/parser/cxfa_dynamicrender.h"
44 #include "xfa/fxfa/parser/cxfa_node.h"
45 
46 FX_IMAGEDIB_AND_DPI::FX_IMAGEDIB_AND_DPI() = default;
47 FX_IMAGEDIB_AND_DPI::FX_IMAGEDIB_AND_DPI(const FX_IMAGEDIB_AND_DPI& that) =
48     default;
49 
FX_IMAGEDIB_AND_DPI(const RetainPtr<CFX_DIBBase> & pDib,int32_t xDpi,int32_t yDpi)50 FX_IMAGEDIB_AND_DPI::FX_IMAGEDIB_AND_DPI(const RetainPtr<CFX_DIBBase>& pDib,
51                                          int32_t xDpi,
52                                          int32_t yDpi)
53     : pDibSource(pDib), iImageXDpi(xDpi), iImageYDpi(yDpi) {}
54 
55 FX_IMAGEDIB_AND_DPI::~FX_IMAGEDIB_AND_DPI() = default;
56 
CXFA_FFDoc(CXFA_FFApp * pApp,CallbackIface * pDocEnvironment,CPDF_Document * pPDFDoc,cppgc::Heap * pHeap)57 CXFA_FFDoc::CXFA_FFDoc(CXFA_FFApp* pApp,
58                        CallbackIface* pDocEnvironment,
59                        CPDF_Document* pPDFDoc,
60                        cppgc::Heap* pHeap)
61     : m_pDocEnvironment(pDocEnvironment),
62       m_pPDFDoc(pPDFDoc),
63       m_pHeap(pHeap),
64       m_pApp(pApp),
65       m_pNotify(cppgc::MakeGarbageCollected<CXFA_FFNotify>(
66           pHeap->GetAllocationHandle(),
67           this)),
68       m_pDocument(cppgc::MakeGarbageCollected<CXFA_Document>(
69           pHeap->GetAllocationHandle(),
70           m_pNotify,
71           pHeap,
72           cppgc::MakeGarbageCollected<CXFA_LayoutProcessor>(
73               pHeap->GetAllocationHandle(),
74               pHeap))) {}
75 
76 CXFA_FFDoc::~CXFA_FFDoc() = default;
77 
PreFinalize()78 void CXFA_FFDoc::PreFinalize() {
79   if (m_DocView)
80     m_DocView->RunDocClose();
81 
82   if (m_pDocument)
83     m_pDocument->ClearLayoutData();
84 }
85 
Trace(cppgc::Visitor * visitor) const86 void CXFA_FFDoc::Trace(cppgc::Visitor* visitor) const {
87   visitor->Trace(m_pApp);
88   visitor->Trace(m_pNotify);
89   visitor->Trace(m_pDocument);
90   visitor->Trace(m_DocView);
91 }
92 
BuildDoc(CFX_XMLDocument * pXML)93 bool CXFA_FFDoc::BuildDoc(CFX_XMLDocument* pXML) {
94   DCHECK(pXML);
95 
96   CXFA_DocumentBuilder builder(m_pDocument);
97   if (!builder.BuildDocument(pXML, XFA_PacketType::Xdp))
98     return false;
99 
100   m_pDocument->SetRoot(builder.GetRootNode());
101   return true;
102 }
103 
CreateDocView()104 CXFA_FFDocView* CXFA_FFDoc::CreateDocView() {
105   if (!m_DocView) {
106     m_DocView = cppgc::MakeGarbageCollected<CXFA_FFDocView>(
107         m_pHeap->GetAllocationHandle(), this);
108   }
109   return m_DocView;
110 }
111 
SetChangeMark()112 void CXFA_FFDoc::SetChangeMark() {
113   m_pDocEnvironment->SetChangeMark(this);
114 }
115 
InvalidateRect(CXFA_FFPageView * pPageView,const CFX_RectF & rt)116 void CXFA_FFDoc::InvalidateRect(CXFA_FFPageView* pPageView,
117                                 const CFX_RectF& rt) {
118   m_pDocEnvironment->InvalidateRect(pPageView, rt);
119 }
120 
DisplayCaret(CXFA_FFWidget * hWidget,bool bVisible,const CFX_RectF * pRtAnchor)121 void CXFA_FFDoc::DisplayCaret(CXFA_FFWidget* hWidget,
122                               bool bVisible,
123                               const CFX_RectF* pRtAnchor) {
124   return m_pDocEnvironment->DisplayCaret(hWidget, bVisible, pRtAnchor);
125 }
126 
GetPopupPos(CXFA_FFWidget * hWidget,float fMinPopup,float fMaxPopup,const CFX_RectF & rtAnchor,CFX_RectF * pPopupRect) const127 bool CXFA_FFDoc::GetPopupPos(CXFA_FFWidget* hWidget,
128                              float fMinPopup,
129                              float fMaxPopup,
130                              const CFX_RectF& rtAnchor,
131                              CFX_RectF* pPopupRect) const {
132   return m_pDocEnvironment->GetPopupPos(hWidget, fMinPopup, fMaxPopup, rtAnchor,
133                                         pPopupRect);
134 }
135 
PopupMenu(CXFA_FFWidget * hWidget,const CFX_PointF & ptPopup)136 bool CXFA_FFDoc::PopupMenu(CXFA_FFWidget* hWidget, const CFX_PointF& ptPopup) {
137   return m_pDocEnvironment->PopupMenu(hWidget, ptPopup);
138 }
139 
OnPageViewEvent(CXFA_FFPageView * pPageView,PageViewEvent eEvent)140 void CXFA_FFDoc::OnPageViewEvent(CXFA_FFPageView* pPageView,
141                                  PageViewEvent eEvent) {
142   m_pDocEnvironment->OnPageViewEvent(pPageView, eEvent);
143 }
144 
WidgetPostAdd(CXFA_FFWidget * hWidget)145 void CXFA_FFDoc::WidgetPostAdd(CXFA_FFWidget* hWidget) {
146   m_pDocEnvironment->WidgetPostAdd(hWidget);
147 }
148 
WidgetPreRemove(CXFA_FFWidget * hWidget)149 void CXFA_FFDoc::WidgetPreRemove(CXFA_FFWidget* hWidget) {
150   m_pDocEnvironment->WidgetPreRemove(hWidget);
151 }
152 
CountPages() const153 int32_t CXFA_FFDoc::CountPages() const {
154   return m_pDocEnvironment->CountPages(this);
155 }
156 
GetCurrentPage() const157 int32_t CXFA_FFDoc::GetCurrentPage() const {
158   return m_pDocEnvironment->GetCurrentPage(this);
159 }
160 
SetCurrentPage(int32_t iCurPage)161 void CXFA_FFDoc::SetCurrentPage(int32_t iCurPage) {
162   m_pDocEnvironment->SetCurrentPage(this, iCurPage);
163 }
164 
IsCalculationsEnabled() const165 bool CXFA_FFDoc::IsCalculationsEnabled() const {
166   return m_pDocEnvironment->IsCalculationsEnabled(this);
167 }
168 
SetCalculationsEnabled(bool bEnabled)169 void CXFA_FFDoc::SetCalculationsEnabled(bool bEnabled) {
170   return m_pDocEnvironment->SetCalculationsEnabled(this, bEnabled);
171 }
172 
GetTitle() const173 WideString CXFA_FFDoc::GetTitle() const {
174   return m_pDocEnvironment->GetTitle(this);
175 }
176 
SetTitle(const WideString & wsTitle)177 void CXFA_FFDoc::SetTitle(const WideString& wsTitle) {
178   m_pDocEnvironment->SetTitle(this, wsTitle);
179 }
180 
ExportData(const WideString & wsFilePath,bool bXDP)181 void CXFA_FFDoc::ExportData(const WideString& wsFilePath, bool bXDP) {
182   m_pDocEnvironment->ExportData(this, wsFilePath, bXDP);
183 }
184 
GotoURL(const WideString & bsURL)185 void CXFA_FFDoc::GotoURL(const WideString& bsURL) {
186   m_pDocEnvironment->GotoURL(this, bsURL);
187 }
188 
IsValidationsEnabled() const189 bool CXFA_FFDoc::IsValidationsEnabled() const {
190   return m_pDocEnvironment->IsValidationsEnabled(this);
191 }
192 
SetValidationsEnabled(bool bEnabled)193 void CXFA_FFDoc::SetValidationsEnabled(bool bEnabled) {
194   m_pDocEnvironment->SetValidationsEnabled(this, bEnabled);
195 }
196 
SetFocusWidget(CXFA_FFWidget * hWidget)197 void CXFA_FFDoc::SetFocusWidget(CXFA_FFWidget* hWidget) {
198   m_pDocEnvironment->SetFocusWidget(this, hWidget);
199 }
200 
Print(int32_t nStartPage,int32_t nEndPage,Mask<XFA_PrintOpt> dwOptions)201 void CXFA_FFDoc::Print(int32_t nStartPage,
202                        int32_t nEndPage,
203                        Mask<XFA_PrintOpt> dwOptions) {
204   m_pDocEnvironment->Print(this, nStartPage, nEndPage, dwOptions);
205 }
206 
GetHighlightColor() const207 FX_ARGB CXFA_FFDoc::GetHighlightColor() const {
208   return m_pDocEnvironment->GetHighlightColor(this);
209 }
210 
GetIJSRuntime() const211 IJS_Runtime* CXFA_FFDoc::GetIJSRuntime() const {
212   return m_pDocEnvironment->GetIJSRuntime(this);
213 }
214 
GetXMLDocument() const215 CFX_XMLDocument* CXFA_FFDoc::GetXMLDocument() const {
216   return m_pDocEnvironment->GetXMLDoc();
217 }
218 
OpenLinkedFile(const WideString & wsLink)219 RetainPtr<IFX_SeekableReadStream> CXFA_FFDoc::OpenLinkedFile(
220     const WideString& wsLink) {
221   return m_pDocEnvironment->OpenLinkedFile(this, wsLink);
222 }
223 
GetDocView(CXFA_LayoutProcessor * pLayout)224 CXFA_FFDocView* CXFA_FFDoc::GetDocView(CXFA_LayoutProcessor* pLayout) {
225   return m_DocView && m_DocView->GetLayoutProcessor() == pLayout ? m_DocView
226                                                                  : nullptr;
227 }
228 
GetDocView()229 CXFA_FFDocView* CXFA_FFDoc::GetDocView() {
230   return m_DocView;
231 }
232 
OpenDoc(CFX_XMLDocument * pXML)233 bool CXFA_FFDoc::OpenDoc(CFX_XMLDocument* pXML) {
234   if (!BuildDoc(pXML))
235     return false;
236 
237   // At this point we've got an XFA document and we want to always return
238   // true to signify the load succeeded.
239   m_pPDFFontMgr = std::make_unique<CFGAS_PDFFontMgr>(GetPDFDoc());
240   m_FormType = FormType::kXFAForeground;
241   CXFA_Node* pConfig = ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Config));
242   if (!pConfig)
243     return true;
244 
245   CXFA_Acrobat* pAcrobat =
246       pConfig->GetFirstChildByClass<CXFA_Acrobat>(XFA_Element::Acrobat);
247   if (!pAcrobat)
248     return true;
249 
250   CXFA_Acrobat7* pAcrobat7 =
251       pAcrobat->GetFirstChildByClass<CXFA_Acrobat7>(XFA_Element::Acrobat7);
252   if (!pAcrobat7)
253     return true;
254 
255   CXFA_DynamicRender* pDynamicRender =
256       pAcrobat7->GetFirstChildByClass<CXFA_DynamicRender>(
257           XFA_Element::DynamicRender);
258   if (!pDynamicRender)
259     return true;
260 
261   WideString wsType = pDynamicRender->JSObject()->GetContent(false);
262   if (wsType.EqualsASCII("required"))
263     m_FormType = FormType::kXFAFull;
264 
265   return true;
266 }
267 
GetPDFFont(const WideString & family,uint32_t styles,bool strict)268 RetainPtr<CFGAS_GEFont> CXFA_FFDoc::GetPDFFont(const WideString& family,
269                                                uint32_t styles,
270                                                bool strict) {
271   if (!m_pPDFFontMgr)
272     return nullptr;
273 
274   return m_pPDFFontMgr->GetFont(family, styles, strict);
275 }
276 
GetPDFNamedImage(WideStringView wsName,int32_t & iImageXDpi,int32_t & iImageYDpi)277 RetainPtr<CFX_DIBitmap> CXFA_FFDoc::GetPDFNamedImage(WideStringView wsName,
278                                                      int32_t& iImageXDpi,
279                                                      int32_t& iImageYDpi) {
280   uint32_t dwHash = FX_HashCode_GetW(wsName);
281   auto it = m_HashToDibDpiMap.find(dwHash);
282   if (it != m_HashToDibDpiMap.end()) {
283     iImageXDpi = it->second.iImageXDpi;
284     iImageYDpi = it->second.iImageYDpi;
285     return it->second.pDibSource.As<CFX_DIBitmap>();
286   }
287 
288   auto name_tree = CPDF_NameTree::Create(m_pPDFDoc, "XFAImages");
289   size_t count = name_tree ? name_tree->GetCount() : 0;
290   if (count == 0)
291     return nullptr;
292 
293   RetainPtr<const CPDF_Object> pObject =
294       name_tree->LookupValue(WideString(wsName));
295   if (!pObject) {
296     for (size_t i = 0; i < count; ++i) {
297       WideString wsTemp;
298       RetainPtr<CPDF_Object> pTempObject =
299           name_tree->LookupValueAndName(i, &wsTemp);
300       if (wsTemp == wsName) {
301         pObject = std::move(pTempObject);
302         break;
303       }
304     }
305   }
306 
307   RetainPtr<const CPDF_Stream> pStream = ToStream(pObject);
308   if (!pStream)
309     return nullptr;
310 
311   auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(std::move(pStream));
312   pAcc->LoadAllDataFiltered();
313 
314   auto pImageFileRead =
315       pdfium::MakeRetain<CFX_ReadOnlySpanStream>(pAcc->GetSpan());
316   RetainPtr<CFX_DIBitmap> pDibSource = XFA_LoadImageFromBuffer(
317       std::move(pImageFileRead), FXCODEC_IMAGE_UNKNOWN, iImageXDpi, iImageYDpi);
318   m_HashToDibDpiMap[dwHash] = {pDibSource, iImageXDpi, iImageYDpi};
319   return pDibSource;
320 }
321 
SavePackage(CXFA_Node * pNode,const RetainPtr<IFX_SeekableStream> & pFile)322 bool CXFA_FFDoc::SavePackage(CXFA_Node* pNode,
323                              const RetainPtr<IFX_SeekableStream>& pFile) {
324   DCHECK(pNode || GetXFADoc()->GetRoot());
325 
326   CXFA_DataExporter exporter;
327   return exporter.Export(pFile, pNode ? pNode : GetXFADoc()->GetRoot());
328 }
329