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 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 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 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