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