• 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 "fpdfsdk/cpdfsdk_pageview.h"
8 
9 #include <memory>
10 #include <vector>
11 
12 #include "core/fpdfapi/parser/cpdf_document.h"
13 #include "core/fpdfapi/render/cpdf_renderoptions.h"
14 #include "core/fpdfdoc/cpdf_annotlist.h"
15 #include "core/fpdfdoc/cpdf_interform.h"
16 #include "fpdfsdk/cpdfsdk_annot.h"
17 #include "fpdfsdk/cpdfsdk_annothandlermgr.h"
18 #include "fpdfsdk/cpdfsdk_annotiteration.h"
19 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
20 #include "fpdfsdk/cpdfsdk_interform.h"
21 #include "third_party/base/ptr_util.h"
22 
23 #ifdef PDF_ENABLE_XFA
24 #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
25 #include "xfa/fxfa/xfa_ffdocview.h"
26 #include "xfa/fxfa/xfa_ffpageview.h"
27 #include "xfa/fxfa/xfa_ffwidgethandler.h"
28 #include "xfa/fxfa/xfa_rendercontext.h"
29 #include "xfa/fxgraphics/cfx_graphics.h"
30 #endif  // PDF_ENABLE_XFA
31 
CPDFSDK_PageView(CPDFSDK_FormFillEnvironment * pFormFillEnv,UnderlyingPageType * page)32 CPDFSDK_PageView::CPDFSDK_PageView(CPDFSDK_FormFillEnvironment* pFormFillEnv,
33                                    UnderlyingPageType* page)
34     : m_page(page),
35       m_pFormFillEnv(pFormFillEnv),
36 #ifndef PDF_ENABLE_XFA
37       m_bOwnsPage(false),
38 #endif  // PDF_ENABLE_XFA
39       m_bEnterWidget(false),
40       m_bExitWidget(false),
41       m_bOnWidget(false),
42       m_bValid(false),
43       m_bLocked(false),
44       m_bBeingDestroyed(false) {
45   CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm();
46   if (pInterForm) {
47     CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm();
48 #ifdef PDF_ENABLE_XFA
49     if (page->GetPDFPage())
50       pPDFInterForm->FixPageFields(page->GetPDFPage());
51 #else   // PDF_ENABLE_XFA
52     pPDFInterForm->FixPageFields(page);
53 #endif  // PDF_ENABLE_XFA
54   }
55 #ifndef PDF_ENABLE_XFA
56   m_page->SetView(this);
57 #endif  // PDF_ENABLE_XFA
58 }
59 
~CPDFSDK_PageView()60 CPDFSDK_PageView::~CPDFSDK_PageView() {
61 #ifndef PDF_ENABLE_XFA
62   // The call to |ReleaseAnnot| can cause the page pointed to by |m_page| to
63   // be freed, which will cause issues if we try to cleanup the pageview pointer
64   // in |m_page|. So, reset the pageview pointer before doing anything else.
65   m_page->SetView(nullptr);
66 #endif  // PDF_ENABLE_XFA
67 
68   CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
69       m_pFormFillEnv->GetAnnotHandlerMgr();
70   for (CPDFSDK_Annot* pAnnot : m_SDKAnnotArray)
71     pAnnotHandlerMgr->ReleaseAnnot(pAnnot);
72 
73   m_SDKAnnotArray.clear();
74   m_pAnnotList.reset();
75 
76 #ifndef PDF_ENABLE_XFA
77   if (m_bOwnsPage)
78     delete m_page;
79 #endif  // PDF_ENABLE_XFA
80 }
81 
PageView_OnDraw(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device,CPDF_RenderOptions * pOptions,const FX_RECT & pClip)82 void CPDFSDK_PageView::PageView_OnDraw(CFX_RenderDevice* pDevice,
83                                        CFX_Matrix* pUser2Device,
84 #ifdef PDF_ENABLE_XFA
85                                        CPDF_RenderOptions* pOptions,
86                                        const FX_RECT& pClip) {
87 #else
88                                        CPDF_RenderOptions* pOptions) {
89 #endif  // PDF_ENABLE_XFA
90   m_curMatrix = *pUser2Device;
91 
92 #ifdef PDF_ENABLE_XFA
93   CPDFXFA_Page* pPage = GetPDFXFAPage();
94   if (!pPage)
95     return;
96 
97   if (pPage->GetContext()->GetDocType() == DOCTYPE_DYNAMIC_XFA) {
98     CFX_Graphics gs(pDevice);
99     CFX_RectF rectClip(static_cast<FX_FLOAT>(pClip.left),
100                        static_cast<FX_FLOAT>(pClip.top),
101                        static_cast<FX_FLOAT>(pClip.Width()),
102                        static_cast<FX_FLOAT>(pClip.Height()));
103     gs.SetClipRect(rectClip);
104     std::unique_ptr<CXFA_RenderContext> pRenderContext(new CXFA_RenderContext);
105     CXFA_RenderOptions renderOptions;
106     renderOptions.m_bHighlight = true;
107     CXFA_FFPageView* xfaView = pPage->GetXFAPageView();
108     pRenderContext->StartRender(xfaView, &gs, *pUser2Device, renderOptions);
109     pRenderContext->DoRender();
110     pRenderContext->StopRender();
111     CXFA_FFDocView* docView = xfaView->GetDocView();
112     if (!docView)
113       return;
114     CPDFSDK_Annot* annot = GetFocusAnnot();
115     if (!annot)
116       return;
117     // Render the focus widget
118     docView->GetWidgetHandler()->RenderWidget(annot->GetXFAWidget(), &gs,
119                                               pUser2Device, false);
120     return;
121   }
122 #endif  // PDF_ENABLE_XFA
123 
124   // for pdf/static xfa.
125   CPDFSDK_AnnotIteration annotIteration(this, true);
126   for (const auto& pSDKAnnot : annotIteration) {
127     m_pFormFillEnv->GetAnnotHandlerMgr()->Annot_OnDraw(
128         this, pSDKAnnot.Get(), pDevice, pUser2Device, pOptions->m_bDrawAnnots);
129   }
130 }
131 
132 CPDFSDK_Annot* CPDFSDK_PageView::GetFXAnnotAtPoint(const CFX_PointF& point) {
133   CPDFSDK_AnnotHandlerMgr* pAnnotMgr = m_pFormFillEnv->GetAnnotHandlerMgr();
134   CPDFSDK_AnnotIteration annotIteration(this, false);
135   for (const auto& pSDKAnnot : annotIteration) {
136     CFX_FloatRect rc = pAnnotMgr->Annot_OnGetViewBBox(this, pSDKAnnot.Get());
137     if (pSDKAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::POPUP)
138       continue;
139     if (rc.Contains(point))
140       return pSDKAnnot.Get();
141   }
142   return nullptr;
143 }
144 
145 CPDFSDK_Annot* CPDFSDK_PageView::GetFXWidgetAtPoint(const CFX_PointF& point) {
146   CPDFSDK_AnnotHandlerMgr* pAnnotMgr = m_pFormFillEnv->GetAnnotHandlerMgr();
147   CPDFSDK_AnnotIteration annotIteration(this, false);
148   for (const auto& pSDKAnnot : annotIteration) {
149     bool bHitTest = pSDKAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::WIDGET;
150 #ifdef PDF_ENABLE_XFA
151     bHitTest = bHitTest ||
152                pSDKAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::XFAWIDGET;
153 #endif  // PDF_ENABLE_XFA
154     if (bHitTest) {
155       pAnnotMgr->Annot_OnGetViewBBox(this, pSDKAnnot.Get());
156       if (pAnnotMgr->Annot_OnHitTest(this, pSDKAnnot.Get(), point))
157         return pSDKAnnot.Get();
158     }
159   }
160   return nullptr;
161 }
162 
163 #ifdef PDF_ENABLE_XFA
164 CPDFSDK_Annot* CPDFSDK_PageView::AddAnnot(CXFA_FFWidget* pPDFAnnot) {
165   if (!pPDFAnnot)
166     return nullptr;
167 
168   CPDFSDK_Annot* pSDKAnnot = GetAnnotByXFAWidget(pPDFAnnot);
169   if (pSDKAnnot)
170     return pSDKAnnot;
171 
172   CPDFSDK_AnnotHandlerMgr* pAnnotHandler = m_pFormFillEnv->GetAnnotHandlerMgr();
173   pSDKAnnot = pAnnotHandler->NewAnnot(pPDFAnnot, this);
174   if (!pSDKAnnot)
175     return nullptr;
176 
177   m_SDKAnnotArray.push_back(pSDKAnnot);
178   return pSDKAnnot;
179 }
180 
181 bool CPDFSDK_PageView::DeleteAnnot(CPDFSDK_Annot* pAnnot) {
182   if (!pAnnot)
183     return false;
184   CPDFXFA_Page* pPage = pAnnot->GetPDFXFAPage();
185   if (!pPage || (pPage->GetContext()->GetDocType() != DOCTYPE_STATIC_XFA &&
186                  pPage->GetContext()->GetDocType() != DOCTYPE_DYNAMIC_XFA))
187     return false;
188 
189   if (GetFocusAnnot() == pAnnot)
190     m_pFormFillEnv->KillFocusAnnot(0);
191   CPDFSDK_AnnotHandlerMgr* pAnnotHandler = m_pFormFillEnv->GetAnnotHandlerMgr();
192   if (pAnnotHandler)
193     pAnnotHandler->ReleaseAnnot(pAnnot);
194 
195   auto it = std::find(m_SDKAnnotArray.begin(), m_SDKAnnotArray.end(), pAnnot);
196   if (it != m_SDKAnnotArray.end())
197     m_SDKAnnotArray.erase(it);
198   if (m_pCaptureWidget.Get() == pAnnot)
199     m_pCaptureWidget.Reset();
200 
201   return true;
202 }
203 #endif  // PDF_ENABLE_XFA
204 
205 CPDF_Document* CPDFSDK_PageView::GetPDFDocument() {
206   if (m_page) {
207 #ifdef PDF_ENABLE_XFA
208     return m_page->GetContext()->GetPDFDoc();
209 #else   // PDF_ENABLE_XFA
210     return m_page->m_pDocument;
211 #endif  // PDF_ENABLE_XFA
212   }
213   return nullptr;
214 }
215 
216 CPDF_Page* CPDFSDK_PageView::GetPDFPage() const {
217 #ifdef PDF_ENABLE_XFA
218   return m_page ? m_page->GetPDFPage() : nullptr;
219 #else   // PDF_ENABLE_XFA
220   return m_page;
221 #endif  // PDF_ENABLE_XFA
222 }
223 
224 CPDFSDK_Annot* CPDFSDK_PageView::GetAnnotByDict(CPDF_Dictionary* pDict) {
225   for (CPDFSDK_Annot* pAnnot : m_SDKAnnotArray) {
226     if (pAnnot->GetPDFAnnot()->GetAnnotDict() == pDict)
227       return pAnnot;
228   }
229   return nullptr;
230 }
231 
232 #ifdef PDF_ENABLE_XFA
233 CPDFSDK_Annot* CPDFSDK_PageView::GetAnnotByXFAWidget(CXFA_FFWidget* hWidget) {
234   if (!hWidget)
235     return nullptr;
236 
237   for (CPDFSDK_Annot* pAnnot : m_SDKAnnotArray) {
238     if (pAnnot->GetXFAWidget() == hWidget)
239       return pAnnot;
240   }
241   return nullptr;
242 }
243 #endif  // PDF_ENABLE_XFA
244 
245 bool CPDFSDK_PageView::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
246   CPDFSDK_Annot::ObservedPtr pAnnot(GetFXWidgetAtPoint(point));
247   if (!pAnnot) {
248     m_pFormFillEnv->KillFocusAnnot(nFlag);
249     return false;
250   }
251 
252   CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
253       m_pFormFillEnv->GetAnnotHandlerMgr();
254   if (!pAnnotHandlerMgr->Annot_OnLButtonDown(this, &pAnnot, nFlag, point))
255     return false;
256 
257   if (!pAnnot)
258     return false;
259 
260   m_pFormFillEnv->SetFocusAnnot(&pAnnot);
261   return true;
262 }
263 
264 #ifdef PDF_ENABLE_XFA
265 bool CPDFSDK_PageView::OnRButtonDown(const CFX_PointF& point, uint32_t nFlag) {
266   CPDFSDK_Annot::ObservedPtr pAnnot(GetFXWidgetAtPoint(point));
267   if (!pAnnot)
268     return false;
269 
270   CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
271       m_pFormFillEnv->GetAnnotHandlerMgr();
272   bool ok = pAnnotHandlerMgr->Annot_OnRButtonDown(this, &pAnnot, nFlag, point);
273   if (!pAnnot)
274     return false;
275 
276   if (ok)
277     m_pFormFillEnv->SetFocusAnnot(&pAnnot);
278 
279   return true;
280 }
281 
282 bool CPDFSDK_PageView::OnRButtonUp(const CFX_PointF& point, uint32_t nFlag) {
283   CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
284       m_pFormFillEnv->GetAnnotHandlerMgr();
285   CPDFSDK_Annot::ObservedPtr pFXAnnot(GetFXWidgetAtPoint(point));
286   if (!pFXAnnot)
287     return false;
288 
289   if (pAnnotHandlerMgr->Annot_OnRButtonUp(this, &pFXAnnot, nFlag, point))
290     m_pFormFillEnv->SetFocusAnnot(&pFXAnnot);
291 
292   return true;
293 }
294 #endif  // PDF_ENABLE_XFA
295 
296 bool CPDFSDK_PageView::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
297   CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
298       m_pFormFillEnv->GetAnnotHandlerMgr();
299   CPDFSDK_Annot::ObservedPtr pFXAnnot(GetFXWidgetAtPoint(point));
300   CPDFSDK_Annot::ObservedPtr pFocusAnnot(GetFocusAnnot());
301   if (pFocusAnnot && pFocusAnnot != pFXAnnot) {
302     // Last focus Annot gets a chance to handle the event.
303     if (pAnnotHandlerMgr->Annot_OnLButtonUp(this, &pFocusAnnot, nFlag, point))
304       return true;
305   }
306   return pFXAnnot &&
307          pAnnotHandlerMgr->Annot_OnLButtonUp(this, &pFXAnnot, nFlag, point);
308 }
309 
310 bool CPDFSDK_PageView::OnMouseMove(const CFX_PointF& point, int nFlag) {
311   CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
312       m_pFormFillEnv->GetAnnotHandlerMgr();
313   CPDFSDK_Annot::ObservedPtr pFXAnnot(GetFXAnnotAtPoint(point));
314   if (pFXAnnot) {
315     if (m_pCaptureWidget && m_pCaptureWidget != pFXAnnot) {
316       m_bExitWidget = true;
317       m_bEnterWidget = false;
318       pAnnotHandlerMgr->Annot_OnMouseExit(this, &m_pCaptureWidget, nFlag);
319     }
320     m_pCaptureWidget.Reset(pFXAnnot.Get());
321     m_bOnWidget = true;
322     if (!m_bEnterWidget) {
323       m_bEnterWidget = true;
324       m_bExitWidget = false;
325       pAnnotHandlerMgr->Annot_OnMouseEnter(this, &pFXAnnot, nFlag);
326     }
327     pAnnotHandlerMgr->Annot_OnMouseMove(this, &pFXAnnot, nFlag, point);
328     return true;
329   }
330   if (m_bOnWidget) {
331     m_bOnWidget = false;
332     m_bExitWidget = true;
333     m_bEnterWidget = false;
334     if (m_pCaptureWidget) {
335       pAnnotHandlerMgr->Annot_OnMouseExit(this, &m_pCaptureWidget, nFlag);
336       m_pCaptureWidget.Reset();
337     }
338   }
339   return false;
340 }
341 
342 bool CPDFSDK_PageView::OnMouseWheel(double deltaX,
343                                     double deltaY,
344                                     const CFX_PointF& point,
345                                     int nFlag) {
346   CPDFSDK_Annot::ObservedPtr pAnnot(GetFXWidgetAtPoint(point));
347   if (!pAnnot)
348     return false;
349 
350   CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
351       m_pFormFillEnv->GetAnnotHandlerMgr();
352   return pAnnotHandlerMgr->Annot_OnMouseWheel(this, &pAnnot, nFlag, (int)deltaY,
353                                               point);
354 }
355 
356 bool CPDFSDK_PageView::OnChar(int nChar, uint32_t nFlag) {
357   if (CPDFSDK_Annot* pAnnot = GetFocusAnnot()) {
358     CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
359         m_pFormFillEnv->GetAnnotHandlerMgr();
360     return pAnnotHandlerMgr->Annot_OnChar(pAnnot, nChar, nFlag);
361   }
362 
363   return false;
364 }
365 
366 bool CPDFSDK_PageView::OnKeyDown(int nKeyCode, int nFlag) {
367   if (CPDFSDK_Annot* pAnnot = GetFocusAnnot()) {
368     CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
369         m_pFormFillEnv->GetAnnotHandlerMgr();
370     return pAnnotHandlerMgr->Annot_OnKeyDown(pAnnot, nKeyCode, nFlag);
371   }
372   return false;
373 }
374 
375 bool CPDFSDK_PageView::OnKeyUp(int nKeyCode, int nFlag) {
376   return false;
377 }
378 
379 void CPDFSDK_PageView::LoadFXAnnots() {
380   CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
381       m_pFormFillEnv->GetAnnotHandlerMgr();
382 
383   SetLock(true);
384 
385 #ifdef PDF_ENABLE_XFA
386   CFX_RetainPtr<CPDFXFA_Page> protector(m_page);
387   if (m_pFormFillEnv->GetXFAContext()->GetDocType() == DOCTYPE_DYNAMIC_XFA) {
388     CXFA_FFPageView* pageView = m_page->GetXFAPageView();
389     std::unique_ptr<IXFA_WidgetIterator> pWidgetHander(
390         pageView->CreateWidgetIterator(
391             XFA_TRAVERSEWAY_Form,
392             XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable));
393     if (!pWidgetHander) {
394       SetLock(false);
395       return;
396     }
397 
398     while (CXFA_FFWidget* pXFAAnnot = pWidgetHander->MoveToNext()) {
399       CPDFSDK_Annot* pAnnot = pAnnotHandlerMgr->NewAnnot(pXFAAnnot, this);
400       if (!pAnnot)
401         continue;
402       m_SDKAnnotArray.push_back(pAnnot);
403       pAnnotHandlerMgr->Annot_OnLoad(pAnnot);
404     }
405 
406     SetLock(false);
407     return;
408   }
409 #endif  // PDF_ENABLE_XFA
410 
411   CPDF_Page* pPage = GetPDFPage();
412   ASSERT(pPage);
413   bool bUpdateAP = CPDF_InterForm::IsUpdateAPEnabled();
414   // Disable the default AP construction.
415   CPDF_InterForm::SetUpdateAP(false);
416   m_pAnnotList = pdfium::MakeUnique<CPDF_AnnotList>(pPage);
417   CPDF_InterForm::SetUpdateAP(bUpdateAP);
418 
419   const size_t nCount = m_pAnnotList->Count();
420   for (size_t i = 0; i < nCount; ++i) {
421     CPDF_Annot* pPDFAnnot = m_pAnnotList->GetAt(i);
422     CheckUnSupportAnnot(GetPDFDocument(), pPDFAnnot);
423     CPDFSDK_Annot* pAnnot = pAnnotHandlerMgr->NewAnnot(pPDFAnnot, this);
424     if (!pAnnot)
425       continue;
426     m_SDKAnnotArray.push_back(pAnnot);
427     pAnnotHandlerMgr->Annot_OnLoad(pAnnot);
428   }
429 
430   SetLock(false);
431 }
432 
433 void CPDFSDK_PageView::UpdateRects(const std::vector<CFX_FloatRect>& rects) {
434   for (const auto& rc : rects)
435     m_pFormFillEnv->Invalidate(m_page, rc.ToFxRect());
436 }
437 
438 void CPDFSDK_PageView::UpdateView(CPDFSDK_Annot* pAnnot) {
439   CFX_FloatRect rcWindow = pAnnot->GetRect();
440   m_pFormFillEnv->Invalidate(m_page, rcWindow.ToFxRect());
441 }
442 
443 int CPDFSDK_PageView::GetPageIndex() const {
444   if (!m_page)
445     return -1;
446 
447 #ifdef PDF_ENABLE_XFA
448   int nDocType = m_page->GetContext()->GetDocType();
449   switch (nDocType) {
450     case DOCTYPE_DYNAMIC_XFA: {
451       CXFA_FFPageView* pPageView = m_page->GetXFAPageView();
452       return pPageView ? pPageView->GetPageIndex() : -1;
453     }
454     case DOCTYPE_STATIC_XFA:
455     case DOCTYPE_PDF:
456       return GetPageIndexForStaticPDF();
457     default:
458       return -1;
459   }
460 #else   // PDF_ENABLE_XFA
461   return GetPageIndexForStaticPDF();
462 #endif  // PDF_ENABLE_XFA
463 }
464 
465 bool CPDFSDK_PageView::IsValidAnnot(const CPDF_Annot* p) const {
466   if (!p)
467     return false;
468 
469   const auto& annots = m_pAnnotList->All();
470   auto it = std::find_if(annots.begin(), annots.end(),
471                          [p](const std::unique_ptr<CPDF_Annot>& annot) {
472                            return annot.get() == p;
473                          });
474   return it != annots.end();
475 }
476 
477 bool CPDFSDK_PageView::IsValidSDKAnnot(const CPDFSDK_Annot* p) const {
478   if (!p)
479     return false;
480   return pdfium::ContainsValue(m_SDKAnnotArray, p);
481 }
482 
483 CPDFSDK_Annot* CPDFSDK_PageView::GetFocusAnnot() {
484   CPDFSDK_Annot* pFocusAnnot = m_pFormFillEnv->GetFocusAnnot();
485   return IsValidSDKAnnot(pFocusAnnot) ? pFocusAnnot : nullptr;
486 }
487 
488 int CPDFSDK_PageView::GetPageIndexForStaticPDF() const {
489   CPDF_Dictionary* pDict = GetPDFPage()->m_pFormDict;
490   CPDF_Document* pDoc = m_pFormFillEnv->GetPDFDocument();
491   return (pDoc && pDict) ? pDoc->GetPageIndex(pDict->GetObjNum()) : -1;
492 }
493