1 // Copyright 2014 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/formfiller/cffl_formfiller.h" 8 9 #include <utility> 10 11 #include "core/fpdfapi/page/cpdf_page.h" 12 #include "core/fxge/cfx_renderdevice.h" 13 #include "fpdfsdk/cpdfsdk_formfillenvironment.h" 14 #include "fpdfsdk/cpdfsdk_pageview.h" 15 #include "fpdfsdk/cpdfsdk_widget.h" 16 #include "fpdfsdk/formfiller/cba_fontmap.h" 17 #include "fpdfsdk/fsdk_common.h" 18 19 namespace { 20 21 CPDFSDK_Widget* CPDFSDKAnnotToWidget(CPDFSDK_Annot* annot) { 22 return static_cast<CPDFSDK_Widget*>(annot); 23 } 24 25 } // namespace 26 27 CFFL_FormFiller::CFFL_FormFiller(CPDFSDK_FormFillEnvironment* pFormFillEnv, 28 CPDFSDK_Widget* pWidget) 29 : m_pFormFillEnv(pFormFillEnv), m_pWidget(pWidget), m_bValid(false) { 30 ASSERT(m_pFormFillEnv); 31 } 32 33 CFFL_FormFiller::~CFFL_FormFiller() { 34 DestroyWindows(); 35 } 36 37 void CFFL_FormFiller::DestroyWindows() { 38 for (const auto& it : m_Maps) { 39 CPWL_Wnd* pWnd = it.second; 40 auto* pData = static_cast<CFFL_PrivateData*>(pWnd->GetAttachedData()); 41 pWnd->InvalidateProvider(this); 42 pWnd->Destroy(); 43 delete pWnd; 44 delete pData; 45 } 46 m_Maps.clear(); 47 } 48 49 FX_RECT CFFL_FormFiller::GetViewBBox(CPDFSDK_PageView* pPageView, 50 CPDFSDK_Annot* pAnnot) { 51 ASSERT(pPageView); 52 ASSERT(pAnnot); 53 54 CFX_FloatRect rcAnnot = m_pWidget->GetRect(); 55 if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) 56 rcAnnot = PWLtoFFL(pWnd->GetWindowRect()); 57 58 CFX_FloatRect rcWin = rcAnnot; 59 CFX_FloatRect rcFocus = GetFocusBox(pPageView); 60 if (!rcFocus.IsEmpty()) 61 rcWin.Union(rcFocus); 62 63 if (!rcWin.IsEmpty()) { 64 rcWin.Inflate(1, 1); 65 rcWin.Normalize(); 66 } 67 return rcWin.GetOuterRect(); 68 } 69 70 void CFFL_FormFiller::OnDraw(CPDFSDK_PageView* pPageView, 71 CPDFSDK_Annot* pAnnot, 72 CFX_RenderDevice* pDevice, 73 const CFX_Matrix& mtUser2Device) { 74 ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 75 76 if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) { 77 CFX_Matrix mt = GetCurMatrix(); 78 mt.Concat(mtUser2Device); 79 pWnd->DrawAppearance(pDevice, mt); 80 return; 81 } 82 83 CPDFSDK_Widget* pWidget = CPDFSDKAnnotToWidget(pAnnot); 84 if (!CFFL_InteractiveFormFiller::IsVisible(pWidget)) 85 return; 86 87 pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Normal, nullptr); 88 } 89 90 void CFFL_FormFiller::OnDrawDeactive(CPDFSDK_PageView* pPageView, 91 CPDFSDK_Annot* pAnnot, 92 CFX_RenderDevice* pDevice, 93 const CFX_Matrix& mtUser2Device) { 94 CPDFSDKAnnotToWidget(pAnnot)->DrawAppearance(pDevice, mtUser2Device, 95 CPDF_Annot::Normal, nullptr); 96 } 97 98 void CFFL_FormFiller::OnMouseEnter(CPDFSDK_PageView* pPageView, 99 CPDFSDK_Annot* pAnnot) {} 100 101 void CFFL_FormFiller::OnMouseExit(CPDFSDK_PageView* pPageView, 102 CPDFSDK_Annot* pAnnot) { 103 EndTimer(); 104 ASSERT(m_pWidget); 105 } 106 107 bool CFFL_FormFiller::OnLButtonDown(CPDFSDK_PageView* pPageView, 108 CPDFSDK_Annot* pAnnot, 109 uint32_t nFlags, 110 const CFX_PointF& point) { 111 CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true); 112 if (!pWnd) 113 return false; 114 115 m_bValid = true; 116 FX_RECT rect = GetViewBBox(pPageView, pAnnot); 117 InvalidateRect(rect); 118 if (!rect.Contains(static_cast<int>(point.x), static_cast<int>(point.y))) 119 return false; 120 return pWnd->OnLButtonDown(WndtoPWL(pPageView, point), nFlags); 121 } 122 123 bool CFFL_FormFiller::OnLButtonUp(CPDFSDK_PageView* pPageView, 124 CPDFSDK_Annot* pAnnot, 125 uint32_t nFlags, 126 const CFX_PointF& point) { 127 CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); 128 if (!pWnd) 129 return false; 130 131 InvalidateRect(GetViewBBox(pPageView, pAnnot)); 132 pWnd->OnLButtonUp(WndtoPWL(pPageView, point), nFlags); 133 return true; 134 } 135 136 bool CFFL_FormFiller::OnLButtonDblClk(CPDFSDK_PageView* pPageView, 137 CPDFSDK_Annot* pAnnot, 138 uint32_t nFlags, 139 const CFX_PointF& point) { 140 CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); 141 if (!pWnd) 142 return false; 143 144 pWnd->OnLButtonDblClk(WndtoPWL(pPageView, point), nFlags); 145 return true; 146 } 147 148 bool CFFL_FormFiller::OnMouseMove(CPDFSDK_PageView* pPageView, 149 CPDFSDK_Annot* pAnnot, 150 uint32_t nFlags, 151 const CFX_PointF& point) { 152 CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); 153 if (!pWnd) 154 return false; 155 156 pWnd->OnMouseMove(WndtoPWL(pPageView, point), nFlags); 157 return true; 158 } 159 160 bool CFFL_FormFiller::OnMouseWheel(CPDFSDK_PageView* pPageView, 161 CPDFSDK_Annot* pAnnot, 162 uint32_t nFlags, 163 short zDelta, 164 const CFX_PointF& point) { 165 if (!IsValid()) 166 return false; 167 168 CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true); 169 return pWnd && pWnd->OnMouseWheel(zDelta, WndtoPWL(pPageView, point), nFlags); 170 } 171 172 bool CFFL_FormFiller::OnRButtonDown(CPDFSDK_PageView* pPageView, 173 CPDFSDK_Annot* pAnnot, 174 uint32_t nFlags, 175 const CFX_PointF& point) { 176 CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true); 177 if (!pWnd) 178 return false; 179 180 pWnd->OnRButtonDown(WndtoPWL(pPageView, point), nFlags); 181 return true; 182 } 183 184 bool CFFL_FormFiller::OnRButtonUp(CPDFSDK_PageView* pPageView, 185 CPDFSDK_Annot* pAnnot, 186 uint32_t nFlags, 187 const CFX_PointF& point) { 188 CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); 189 if (!pWnd) 190 return false; 191 192 pWnd->OnRButtonUp(WndtoPWL(pPageView, point), nFlags); 193 return true; 194 } 195 196 bool CFFL_FormFiller::OnKeyDown(CPDFSDK_Annot* pAnnot, 197 uint32_t nKeyCode, 198 uint32_t nFlags) { 199 if (!IsValid()) 200 return false; 201 202 CPDFSDK_PageView* pPageView = GetCurPageView(true); 203 ASSERT(pPageView); 204 205 CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); 206 return pWnd && pWnd->OnKeyDown(nKeyCode, nFlags); 207 } 208 209 bool CFFL_FormFiller::OnChar(CPDFSDK_Annot* pAnnot, 210 uint32_t nChar, 211 uint32_t nFlags) { 212 if (!IsValid()) 213 return false; 214 215 CPDFSDK_PageView* pPageView = GetCurPageView(true); 216 ASSERT(pPageView); 217 218 CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); 219 return pWnd && pWnd->OnChar(nChar, nFlags); 220 } 221 222 WideString CFFL_FormFiller::GetSelectedText(CPDFSDK_Annot* pAnnot) { 223 if (!IsValid()) 224 return WideString(); 225 226 CPDFSDK_PageView* pPageView = GetCurPageView(true); 227 ASSERT(pPageView); 228 229 CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); 230 return pWnd ? pWnd->GetSelectedText() : WideString(); 231 } 232 233 void CFFL_FormFiller::ReplaceSelection(CPDFSDK_Annot* pAnnot, 234 const WideString& text) { 235 if (!IsValid()) 236 return; 237 238 CPDFSDK_PageView* pPageView = GetCurPageView(true); 239 ASSERT(pPageView); 240 241 CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); 242 if (!pWnd) 243 return; 244 245 pWnd->ReplaceSelection(text); 246 } 247 248 void CFFL_FormFiller::SetFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag) { 249 CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot; 250 UnderlyingPageType* pPage = pWidget->GetUnderlyingPage(); 251 CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(pPage, true); 252 if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true)) 253 pWnd->SetFocus(); 254 255 m_bValid = true; 256 InvalidateRect(GetViewBBox(pPageView, pAnnot)); 257 } 258 259 void CFFL_FormFiller::KillFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag) { 260 if (!IsValid()) 261 return; 262 263 CPDFSDK_PageView* pPageView = GetCurPageView(false); 264 if (!pPageView || !CommitData(pPageView, nFlag)) 265 return; 266 if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) 267 pWnd->KillFocus(); 268 269 bool bDestroyPDFWindow; 270 switch (m_pWidget->GetFieldType()) { 271 case FormFieldType::kPushButton: 272 case FormFieldType::kCheckBox: 273 case FormFieldType::kRadioButton: 274 bDestroyPDFWindow = true; 275 break; 276 default: 277 bDestroyPDFWindow = false; 278 break; 279 } 280 EscapeFiller(pPageView, bDestroyPDFWindow); 281 } 282 283 bool CFFL_FormFiller::IsValid() const { 284 return m_bValid; 285 } 286 287 CPWL_Wnd::CreateParams CFFL_FormFiller::GetCreateParam() { 288 CPWL_Wnd::CreateParams cp; 289 cp.pParentWnd = nullptr; 290 cp.pProvider.Reset(this); 291 cp.rcRectWnd = GetPDFWindowRect(); 292 293 uint32_t dwCreateFlags = PWS_BORDER | PWS_BACKGROUND | PWS_VISIBLE; 294 uint32_t dwFieldFlag = m_pWidget->GetFieldFlags(); 295 if (dwFieldFlag & FIELDFLAG_READONLY) 296 dwCreateFlags |= PWS_READONLY; 297 298 FX_COLORREF color; 299 if (m_pWidget->GetFillColor(color)) 300 cp.sBackgroundColor = CFX_Color(color); 301 if (m_pWidget->GetBorderColor(color)) 302 cp.sBorderColor = CFX_Color(color); 303 304 cp.sTextColor = CFX_Color(CFX_Color::kGray, 0); 305 306 if (m_pWidget->GetTextColor(color)) 307 cp.sTextColor = CFX_Color(color); 308 309 cp.fFontSize = m_pWidget->GetFontSize(); 310 cp.dwBorderWidth = m_pWidget->GetBorderWidth(); 311 312 cp.nBorderStyle = m_pWidget->GetBorderStyle(); 313 switch (cp.nBorderStyle) { 314 case BorderStyle::DASH: 315 cp.sDash = CPWL_Dash(3, 3, 0); 316 break; 317 case BorderStyle::BEVELED: 318 case BorderStyle::INSET: 319 cp.dwBorderWidth *= 2; 320 break; 321 default: 322 break; 323 } 324 325 if (cp.fFontSize <= 0) 326 dwCreateFlags |= PWS_AUTOFONTSIZE; 327 328 cp.dwFlags = dwCreateFlags; 329 cp.pSystemHandler = m_pFormFillEnv->GetSysHandler(); 330 return cp; 331 } 332 333 CPWL_Wnd* CFFL_FormFiller::GetPDFWindow(CPDFSDK_PageView* pPageView, 334 bool bNew) { 335 ASSERT(pPageView); 336 337 auto it = m_Maps.find(pPageView); 338 const bool found = it != m_Maps.end(); 339 CPWL_Wnd* pWnd = found ? it->second : nullptr; 340 if (!bNew) 341 return pWnd; 342 343 if (!found) { 344 CPWL_Wnd::CreateParams cp = GetCreateParam(); 345 cp.pAttachedWidget.Reset(m_pWidget.Get()); 346 347 auto* pPrivateData = new CFFL_PrivateData; 348 pPrivateData->pWidget = m_pWidget.Get(); 349 pPrivateData->pPageView = pPageView; 350 pPrivateData->nWidgetAppearanceAge = m_pWidget->GetAppearanceAge(); 351 pPrivateData->nWidgetValueAge = 0; 352 cp.pAttachedData = pPrivateData; 353 CPWL_Wnd* pNewWnd = NewPDFWindow(cp); 354 m_Maps[pPageView] = pNewWnd; 355 return pNewWnd; 356 } 357 358 auto* pPrivateData = static_cast<CFFL_PrivateData*>(pWnd->GetAttachedData()); 359 if (pPrivateData->nWidgetAppearanceAge == m_pWidget->GetAppearanceAge()) 360 return pWnd; 361 362 return ResetPDFWindow( 363 pPageView, pPrivateData->nWidgetValueAge == m_pWidget->GetValueAge()); 364 } 365 366 void CFFL_FormFiller::DestroyPDFWindow(CPDFSDK_PageView* pPageView) { 367 auto it = m_Maps.find(pPageView); 368 if (it == m_Maps.end()) 369 return; 370 371 CPWL_Wnd* pWnd = it->second; 372 auto* pData = static_cast<CFFL_PrivateData*>(pWnd->GetAttachedData()); 373 pWnd->Destroy(); 374 delete pWnd; 375 delete pData; 376 m_Maps.erase(it); 377 } 378 379 CFX_Matrix CFFL_FormFiller::GetWindowMatrix(CPWL_Wnd::PrivateData* pAttached) { 380 CFX_Matrix mt; 381 auto* pPrivateData = static_cast<CFFL_PrivateData*>(pAttached); 382 if (!pPrivateData || !pPrivateData->pPageView) 383 return mt; 384 385 CFX_Matrix mtPageView; 386 pPrivateData->pPageView->GetCurrentMatrix(mtPageView); 387 mt = GetCurMatrix(); 388 mt.Concat(mtPageView); 389 return mt; 390 } 391 392 CFX_Matrix CFFL_FormFiller::GetCurMatrix() { 393 CFX_Matrix mt; 394 CFX_FloatRect rcDA = m_pWidget->GetPDFAnnot()->GetRect(); 395 switch (m_pWidget->GetRotate()) { 396 case 90: 397 mt = CFX_Matrix(0, 1, -1, 0, rcDA.right - rcDA.left, 0); 398 break; 399 case 180: 400 mt = CFX_Matrix(-1, 0, 0, -1, rcDA.right - rcDA.left, 401 rcDA.top - rcDA.bottom); 402 break; 403 case 270: 404 mt = CFX_Matrix(0, -1, 1, 0, 0, rcDA.top - rcDA.bottom); 405 break; 406 case 0: 407 default: 408 break; 409 } 410 mt.e += rcDA.left; 411 mt.f += rcDA.bottom; 412 413 return mt; 414 } 415 416 CFX_FloatRect CFFL_FormFiller::GetPDFWindowRect() const { 417 CFX_FloatRect rectAnnot = m_pWidget->GetPDFAnnot()->GetRect(); 418 419 float fWidth = rectAnnot.right - rectAnnot.left; 420 float fHeight = rectAnnot.top - rectAnnot.bottom; 421 if ((m_pWidget->GetRotate() / 90) & 0x01) 422 std::swap(fWidth, fHeight); 423 return CFX_FloatRect(0, 0, fWidth, fHeight); 424 } 425 426 CPDFSDK_PageView* CFFL_FormFiller::GetCurPageView(bool renew) { 427 UnderlyingPageType* pPage = m_pWidget->GetUnderlyingPage(); 428 return m_pFormFillEnv->GetPageView(pPage, renew); 429 } 430 431 CFX_FloatRect CFFL_FormFiller::GetFocusBox(CPDFSDK_PageView* pPageView) { 432 CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); 433 if (!pWnd) 434 return CFX_FloatRect(); 435 436 CFX_FloatRect rcFocus = FFLtoWnd(pPageView, PWLtoFFL(pWnd->GetFocusRect())); 437 return pPageView->GetPDFPage()->GetPageBBox().Contains(rcFocus) 438 ? rcFocus 439 : CFX_FloatRect(); 440 } 441 442 CFX_FloatRect CFFL_FormFiller::FFLtoPWL(const CFX_FloatRect& rect) { 443 return GetCurMatrix().GetInverse().TransformRect(rect); 444 } 445 446 CFX_FloatRect CFFL_FormFiller::PWLtoFFL(const CFX_FloatRect& rect) { 447 return GetCurMatrix().TransformRect(rect); 448 } 449 450 CFX_PointF CFFL_FormFiller::FFLtoPWL(const CFX_PointF& point) { 451 return GetCurMatrix().GetInverse().Transform(point); 452 } 453 454 CFX_PointF CFFL_FormFiller::PWLtoFFL(const CFX_PointF& point) { 455 return GetCurMatrix().Transform(point); 456 } 457 458 CFX_PointF CFFL_FormFiller::WndtoPWL(CPDFSDK_PageView* pPageView, 459 const CFX_PointF& pt) { 460 return FFLtoPWL(pt); 461 } 462 463 CFX_FloatRect CFFL_FormFiller::FFLtoWnd(CPDFSDK_PageView* pPageView, 464 const CFX_FloatRect& rect) { 465 return rect; 466 } 467 468 bool CFFL_FormFiller::CommitData(CPDFSDK_PageView* pPageView, uint32_t nFlag) { 469 if (!IsDataChanged(pPageView)) 470 return true; 471 472 CFFL_InteractiveFormFiller* pFormFiller = 473 m_pFormFillEnv->GetInteractiveFormFiller(); 474 CPDFSDK_Annot::ObservedPtr pObserved(m_pWidget.Get()); 475 476 if (!pFormFiller->OnKeyStrokeCommit(&pObserved, pPageView, nFlag)) { 477 if (!pObserved) 478 return false; 479 ResetPDFWindow(pPageView, false); 480 return true; 481 } 482 if (!pObserved) 483 return false; 484 485 if (!pFormFiller->OnValidate(&pObserved, pPageView, nFlag)) { 486 if (!pObserved) 487 return false; 488 ResetPDFWindow(pPageView, false); 489 return true; 490 } 491 if (!pObserved) 492 return false; 493 494 SaveData(pPageView); // may invoking JS to delete this widget. 495 if (!pObserved) 496 return false; 497 498 pFormFiller->OnCalculate(&pObserved, pPageView, nFlag); 499 if (!pObserved) 500 return false; 501 502 pFormFiller->OnFormat(&pObserved, pPageView, nFlag); 503 if (!pObserved) 504 return false; 505 506 return true; 507 } 508 509 bool CFFL_FormFiller::IsDataChanged(CPDFSDK_PageView* pPageView) { 510 return false; 511 } 512 513 void CFFL_FormFiller::SaveData(CPDFSDK_PageView* pPageView) {} 514 515 #ifdef PDF_ENABLE_XFA 516 bool CFFL_FormFiller::IsFieldFull(CPDFSDK_PageView* pPageView) { 517 return false; 518 } 519 #endif // PDF_ENABLE_XFA 520 521 void CFFL_FormFiller::SetChangeMark() { 522 m_pFormFillEnv->OnChange(); 523 } 524 525 void CFFL_FormFiller::GetActionData(CPDFSDK_PageView* pPageView, 526 CPDF_AAction::AActionType type, 527 PDFSDK_FieldAction& fa) { 528 fa.sValue = m_pWidget->GetValue(); 529 } 530 531 void CFFL_FormFiller::SetActionData(CPDFSDK_PageView* pPageView, 532 CPDF_AAction::AActionType type, 533 const PDFSDK_FieldAction& fa) {} 534 535 bool CFFL_FormFiller::IsActionDataChanged(CPDF_AAction::AActionType type, 536 const PDFSDK_FieldAction& faOld, 537 const PDFSDK_FieldAction& faNew) { 538 return false; 539 } 540 541 void CFFL_FormFiller::SaveState(CPDFSDK_PageView* pPageView) {} 542 543 void CFFL_FormFiller::RestoreState(CPDFSDK_PageView* pPageView) {} 544 545 CPWL_Wnd* CFFL_FormFiller::ResetPDFWindow(CPDFSDK_PageView* pPageView, 546 bool bRestoreValue) { 547 return GetPDFWindow(pPageView, false); 548 } 549 550 void CFFL_FormFiller::TimerProc() {} 551 552 CFX_SystemHandler* CFFL_FormFiller::GetSystemHandler() const { 553 return m_pFormFillEnv->GetSysHandler(); 554 } 555 556 void CFFL_FormFiller::EscapeFiller(CPDFSDK_PageView* pPageView, 557 bool bDestroyPDFWindow) { 558 m_bValid = false; 559 560 InvalidateRect(GetViewBBox(pPageView, m_pWidget.Get())); 561 if (bDestroyPDFWindow) 562 DestroyPDFWindow(pPageView); 563 } 564 565 void CFFL_FormFiller::InvalidateRect(const FX_RECT& rect) { 566 m_pFormFillEnv->Invalidate(m_pWidget->GetUnderlyingPage(), rect); 567 } 568