// Copyright 2016 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "fpdfsdk/cpdfsdk_pageview.h"

#include <memory>
#include <utility>
#include <vector>

#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/render/cpdf_renderoptions.h"
#include "core/fpdfdoc/cpdf_annotlist.h"
#include "core/fpdfdoc/cpdf_interactiveform.h"
#include "core/fxcrt/autorestorer.h"
#include "core/fxcrt/stl_util.h"
#include "fpdfsdk/cpdfsdk_annot.h"
#include "fpdfsdk/cpdfsdk_annotiteration.h"
#include "fpdfsdk/cpdfsdk_annotiterator.h"
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
#include "fpdfsdk/cpdfsdk_interactiveform.h"
#include "third_party/base/check.h"
#include "third_party/base/containers/contains.h"

#ifdef PDF_ENABLE_XFA
#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
#include "fpdfsdk/fpdfxfa/cpdfxfa_widget.h"
#include "xfa/fxfa/cxfa_ffpageview.h"
#endif  // PDF_ENABLE_XFA

CPDFSDK_PageView::CPDFSDK_PageView(CPDFSDK_FormFillEnvironment* pFormFillEnv,
                                   IPDF_Page* page)
    : m_page(page), m_pFormFillEnv(pFormFillEnv) {
  DCHECK(m_page);
  CPDF_Page* pPDFPage = ToPDFPage(page);
  if (pPDFPage) {
    CPDFSDK_InteractiveForm* pForm = pFormFillEnv->GetInteractiveForm();
    CPDF_InteractiveForm* pPDFForm = pForm->GetInteractiveForm();
    pPDFForm->FixPageFields(pPDFPage);
    if (!page->AsXFAPage())
      pPDFPage->SetView(this);
  }
}

CPDFSDK_PageView::~CPDFSDK_PageView() {
  if (!m_page->AsXFAPage()) {
    // Deleting from `m_SDKAnnotArray` below can cause the page pointed to by
    // `m_page` to be freed, which will cause issues if we try to cleanup the
    // pageview pointer in `m_page`. So, reset the pageview pointer before doing
    // anything else.
    m_page->AsPDFPage()->SetView(nullptr);
  }

  // Manually reset elements to ensure they are deleted in order.
  for (std::unique_ptr<CPDFSDK_Annot>& pAnnot : m_SDKAnnotArray)
    pAnnot.reset();

  m_SDKAnnotArray.clear();
  m_pAnnotList.reset();
}

void CPDFSDK_PageView::ClearPage(CPDF_Page* pPage) {
  if (!IsBeingDestroyed())
    GetFormFillEnv()->RemovePageView(pPage);
}

void CPDFSDK_PageView::PageView_OnDraw(CFX_RenderDevice* pDevice,
                                       const CFX_Matrix& mtUser2Device,
                                       CPDF_RenderOptions* pOptions,
                                       const FX_RECT& pClip) {
  m_curMatrix = mtUser2Device;

#ifdef PDF_ENABLE_XFA
  IPDF_Page* pPage = GetXFAPage();
  CPDF_Document::Extension* pContext =
      pPage ? pPage->GetDocument()->GetExtension() : nullptr;
  if (pContext && pContext->ContainsExtensionFullForm()) {
    static_cast<CPDFXFA_Page*>(pPage)->DrawFocusAnnot(pDevice, GetFocusAnnot(),
                                                      mtUser2Device, pClip);
    return;
  }
#endif  // PDF_ENABLE_XFA

  // for pdf/static xfa.
  auto annot_iteration = CPDFSDK_AnnotIteration::CreateForDrawing(this);
  for (const auto& pSDKAnnot : annot_iteration) {
    pSDKAnnot->OnDraw(pDevice, mtUser2Device, pOptions->GetDrawAnnots());
  }
}

std::unique_ptr<CPDFSDK_Annot> CPDFSDK_PageView::NewAnnot(CPDF_Annot* annot) {
  const CPDF_Annot::Subtype sub_type = annot->GetSubtype();
  if (sub_type == CPDF_Annot::Subtype::WIDGET) {
    CPDFSDK_InteractiveForm* form = m_pFormFillEnv->GetInteractiveForm();
    CPDF_InteractiveForm* pdf_form = form->GetInteractiveForm();
    CPDF_FormControl* form_control =
        pdf_form->GetControlByDict(annot->GetAnnotDict());
    if (!form_control)
      return nullptr;

    auto ret = std::make_unique<CPDFSDK_Widget>(annot, this, form);
    form->AddMap(form_control, ret.get());
    if (pdf_form->NeedConstructAP())
      ret->ResetAppearance(absl::nullopt, CPDFSDK_Widget::kValueUnchanged);
    return ret;
  }

#ifdef PDF_ENABLE_XFA
  if (sub_type == CPDF_Annot::Subtype::XFAWIDGET)
    return nullptr;
#endif  // PDF_ENABLE_XFA

  return std::make_unique<CPDFSDK_BAAnnot>(annot, this);
}

CPDFSDK_Annot* CPDFSDK_PageView::GetFXAnnotAtPoint(const CFX_PointF& point) {
  CPDFSDK_AnnotIteration annot_iteration(this);
  for (const auto& pSDKAnnot : annot_iteration) {
    CFX_FloatRect rc = pSDKAnnot->GetViewBBox();
    if (pSDKAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::POPUP)
      continue;
    if (rc.Contains(point))
      return pSDKAnnot.Get();
  }
  return nullptr;
}

CPDFSDK_Annot* CPDFSDK_PageView::GetFXWidgetAtPoint(const CFX_PointF& point) {
  CPDFSDK_AnnotIteration annot_iteration(this);
  for (const auto& pSDKAnnot : annot_iteration) {
    const CPDF_Annot::Subtype sub_type = pSDKAnnot->GetAnnotSubtype();
    bool do_hit_test = sub_type == CPDF_Annot::Subtype::WIDGET;
#ifdef PDF_ENABLE_XFA
    do_hit_test = do_hit_test || sub_type == CPDF_Annot::Subtype::XFAWIDGET;
#endif  // PDF_ENABLE_XFA
    if (do_hit_test && pSDKAnnot->DoHitTest(point))
      return pSDKAnnot.Get();
  }
  return nullptr;
}

#ifdef PDF_ENABLE_XFA
CPDFSDK_Annot* CPDFSDK_PageView::AddAnnotForFFWidget(CXFA_FFWidget* pWidget) {
  CPDFSDK_Annot* pSDKAnnot = GetAnnotForFFWidget(pWidget);
  if (pSDKAnnot)
    return pSDKAnnot;

  m_SDKAnnotArray.push_back(std::make_unique<CPDFXFA_Widget>(pWidget, this));
  return m_SDKAnnotArray.back().get();
}

void CPDFSDK_PageView::DeleteAnnotForFFWidget(CXFA_FFWidget* pWidget) {
  CPDFSDK_Annot* pAnnot = GetAnnotForFFWidget(pWidget);
  if (!pAnnot)
    return;

  IPDF_Page* pPage = pAnnot->GetXFAPage();
  if (!pPage)
    return;

  CPDF_Document::Extension* pContext = pPage->GetDocument()->GetExtension();
  if (pContext && !pContext->ContainsExtensionForm())
    return;

  ObservedPtr<CPDFSDK_Annot> pObserved(pAnnot);
  if (GetFocusAnnot() == pAnnot)
    m_pFormFillEnv->KillFocusAnnot({});  // May invoke JS, invalidating pAnnot.

  if (pObserved) {
    auto it = std::find(m_SDKAnnotArray.begin(), m_SDKAnnotArray.end(),
                        fxcrt::MakeFakeUniquePtr(pAnnot));
    if (it != m_SDKAnnotArray.end())
      m_SDKAnnotArray.erase(it);
  }

  if (m_pCaptureWidget.Get() == pAnnot)
    m_pCaptureWidget.Reset();
}

CPDFXFA_Page* CPDFSDK_PageView::XFAPageIfNotBackedByPDFPage() {
  auto* pPage = static_cast<CPDFXFA_Page*>(GetXFAPage());
  return pPage && !pPage->AsPDFPage() ? pPage : nullptr;
}
#endif  // PDF_ENABLE_XFA

CPDF_Document* CPDFSDK_PageView::GetPDFDocument() {
  return m_page->GetDocument();
}

CPDF_Page* CPDFSDK_PageView::GetPDFPage() const {
  return ToPDFPage(m_page);
}

CPDFSDK_InteractiveForm* CPDFSDK_PageView::GetInteractiveForm() const {
  return m_pFormFillEnv->GetInteractiveForm();
}

std::vector<CPDFSDK_Annot*> CPDFSDK_PageView::GetAnnotList() const {
  std::vector<CPDFSDK_Annot*> list;
  list.reserve(m_SDKAnnotArray.size());
  for (const std::unique_ptr<CPDFSDK_Annot>& elem : m_SDKAnnotArray)
    list.push_back(elem.get());
  return list;
}

CPDFSDK_Annot* CPDFSDK_PageView::GetAnnotByDict(const CPDF_Dictionary* pDict) {
  for (std::unique_ptr<CPDFSDK_Annot>& pAnnot : m_SDKAnnotArray) {
    CPDF_Annot* pPDFAnnot = pAnnot->GetPDFAnnot();
    if (pPDFAnnot && pPDFAnnot->GetAnnotDict() == pDict)
      return pAnnot.get();
  }
  return nullptr;
}

#ifdef PDF_ENABLE_XFA
CPDFSDK_Annot* CPDFSDK_PageView::GetAnnotForFFWidget(CXFA_FFWidget* pWidget) {
  if (!pWidget)
    return nullptr;

  for (std::unique_ptr<CPDFSDK_Annot>& pAnnot : m_SDKAnnotArray) {
    CPDFXFA_Widget* pCurrentWidget = pAnnot->AsXFAWidget();
    if (pCurrentWidget && pCurrentWidget->GetXFAFFWidget() == pWidget)
      return pAnnot.get();
  }
  return nullptr;
}

IPDF_Page* CPDFSDK_PageView::GetXFAPage() {
  return ToXFAPage(m_page);
}
#endif  // PDF_ENABLE_XFA

WideString CPDFSDK_PageView::GetFocusedFormText() {
  CPDFSDK_Annot* annot = GetFocusAnnot();
  return annot ? annot->GetText() : WideString();
}

CPDFSDK_Annot* CPDFSDK_PageView::GetNextAnnot(CPDFSDK_Annot* pAnnot) {
#ifdef PDF_ENABLE_XFA
  CPDFXFA_Page* pXFAPage = XFAPageIfNotBackedByPDFPage();
  if (pXFAPage)
    return pXFAPage->GetNextXFAAnnot(pAnnot);
#endif  // PDF_ENABLE_XFA
  CPDFSDK_AnnotIterator ai(this, GetFormFillEnv()->GetFocusableAnnotSubtypes());
  return ai.GetNextAnnot(pAnnot);
}

CPDFSDK_Annot* CPDFSDK_PageView::GetPrevAnnot(CPDFSDK_Annot* pAnnot) {
#ifdef PDF_ENABLE_XFA
  CPDFXFA_Page* pXFAPage = XFAPageIfNotBackedByPDFPage();
  if (pXFAPage)
    return pXFAPage->GetPrevXFAAnnot(pAnnot);
#endif  // PDF_ENABLE_XFA
  CPDFSDK_AnnotIterator ai(this, GetFormFillEnv()->GetFocusableAnnotSubtypes());
  return ai.GetPrevAnnot(pAnnot);
}

CPDFSDK_Annot* CPDFSDK_PageView::GetFirstFocusableAnnot() {
#ifdef PDF_ENABLE_XFA
  CPDFXFA_Page* pXFAPage = XFAPageIfNotBackedByPDFPage();
  if (pXFAPage)
    return pXFAPage->GetFirstXFAAnnot(this);
#endif  // PDF_ENABLE_XFA
  CPDFSDK_AnnotIterator ai(this, GetFormFillEnv()->GetFocusableAnnotSubtypes());
  return ai.GetFirstAnnot();
}

CPDFSDK_Annot* CPDFSDK_PageView::GetLastFocusableAnnot() {
#ifdef PDF_ENABLE_XFA
  CPDFXFA_Page* pXFAPage = XFAPageIfNotBackedByPDFPage();
  if (pXFAPage)
    return pXFAPage->GetLastXFAAnnot(this);
#endif  // PDF_ENABLE_XFA
  CPDFSDK_AnnotIterator ai(this, GetFormFillEnv()->GetFocusableAnnotSubtypes());
  return ai.GetLastAnnot();
}

WideString CPDFSDK_PageView::GetSelectedText() {
  CPDFSDK_Annot* annot = GetFocusAnnot();
  if (!annot)
    return WideString();
  return annot->GetSelectedText();
}

void CPDFSDK_PageView::ReplaceSelection(const WideString& text) {
  CPDFSDK_Annot* annot = GetFocusAnnot();
  if (annot)
    annot->ReplaceSelection(text);
}

bool CPDFSDK_PageView::SelectAllText() {
  CPDFSDK_Annot* annot = GetFocusAnnot();
  return annot && annot->SelectAllText();
}

bool CPDFSDK_PageView::CanUndo() {
  CPDFSDK_Annot* annot = GetFocusAnnot();
  return annot && annot->CanUndo();
}

bool CPDFSDK_PageView::CanRedo() {
  CPDFSDK_Annot* annot = GetFocusAnnot();
  return annot && annot->CanRedo();
}

bool CPDFSDK_PageView::Undo() {
  CPDFSDK_Annot* annot = GetFocusAnnot();
  return annot && annot->Undo();
}

bool CPDFSDK_PageView::Redo() {
  CPDFSDK_Annot* annot = GetFocusAnnot();
  return annot && annot->Redo();
}

bool CPDFSDK_PageView::OnFocus(Mask<FWL_EVENTFLAG> nFlags,
                               const CFX_PointF& point) {
  ObservedPtr<CPDFSDK_Annot> pAnnot(GetFXWidgetAtPoint(point));
  if (!pAnnot) {
    m_pFormFillEnv->KillFocusAnnot(nFlags);
    return false;
  }

  m_pFormFillEnv->SetFocusAnnot(pAnnot);
  return true;
}

bool CPDFSDK_PageView::OnLButtonDown(Mask<FWL_EVENTFLAG> nFlags,
                                     const CFX_PointF& point) {
  ObservedPtr<CPDFSDK_Annot> pAnnot(GetFXWidgetAtPoint(point));
  if (!pAnnot) {
    m_pFormFillEnv->KillFocusAnnot(nFlags);
    return false;
  }

  if (!CPDFSDK_Annot::OnLButtonDown(pAnnot, nFlags, point))
    return false;

  if (!pAnnot)
    return false;

  m_pFormFillEnv->SetFocusAnnot(pAnnot);
  return true;
}

bool CPDFSDK_PageView::OnLButtonUp(Mask<FWL_EVENTFLAG> nFlags,
                                   const CFX_PointF& point) {
  ObservedPtr<CPDFSDK_Annot> pFXAnnot(GetFXWidgetAtPoint(point));
  ObservedPtr<CPDFSDK_Annot> pFocusAnnot(GetFocusAnnot());
  if (pFocusAnnot && pFocusAnnot != pFXAnnot) {
    // Last focus Annot gets a chance to handle the event.
    if (CPDFSDK_Annot::OnLButtonUp(pFocusAnnot, nFlags, point))
      return true;
  }
  return pFXAnnot && CPDFSDK_Annot::OnLButtonUp(pFXAnnot, nFlags, point);
}

bool CPDFSDK_PageView::OnLButtonDblClk(Mask<FWL_EVENTFLAG> nFlags,
                                       const CFX_PointF& point) {
  ObservedPtr<CPDFSDK_Annot> pAnnot(GetFXWidgetAtPoint(point));
  if (!pAnnot) {
    m_pFormFillEnv->KillFocusAnnot(nFlags);
    return false;
  }

  if (!CPDFSDK_Annot::OnLButtonDblClk(pAnnot, nFlags, point))
    return false;

  if (!pAnnot)
    return false;

  m_pFormFillEnv->SetFocusAnnot(pAnnot);
  return true;
}

bool CPDFSDK_PageView::OnRButtonDown(Mask<FWL_EVENTFLAG> nFlags,
                                     const CFX_PointF& point) {
  ObservedPtr<CPDFSDK_Annot> pAnnot(GetFXWidgetAtPoint(point));
  if (!pAnnot)
    return false;

  bool ok = CPDFSDK_Annot::OnRButtonDown(pAnnot, nFlags, point);
  if (!pAnnot)
    return false;

  if (ok)
    m_pFormFillEnv->SetFocusAnnot(pAnnot);

  return true;
}

bool CPDFSDK_PageView::OnRButtonUp(Mask<FWL_EVENTFLAG> nFlags,
                                   const CFX_PointF& point) {
  ObservedPtr<CPDFSDK_Annot> pAnnot(GetFXWidgetAtPoint(point));
  if (!pAnnot)
    return false;

  bool ok = CPDFSDK_Annot::OnRButtonUp(pAnnot, nFlags, point);
  if (!pAnnot)
    return false;

  if (ok)
    m_pFormFillEnv->SetFocusAnnot(pAnnot);

  return true;
}

bool CPDFSDK_PageView::OnMouseMove(Mask<FWL_EVENTFLAG> nFlags,
                                   const CFX_PointF& point) {
  ObservedPtr<CPDFSDK_Annot> pFXAnnot(GetFXAnnotAtPoint(point));
  ObservedPtr<CPDFSDK_PageView> pThis(this);

  if (m_bOnWidget && m_pCaptureWidget != pFXAnnot)
    ExitWidget(true, nFlags);

  // ExitWidget() may have invalidated objects.
  if (!pThis || !pFXAnnot)
    return false;

  if (!m_bOnWidget) {
    EnterWidget(pFXAnnot, nFlags);

    // EnterWidget() may have invalidated objects.
    if (!pThis)
      return false;

    if (!pFXAnnot) {
      ExitWidget(false, nFlags);
      return true;
    }
  }
  CPDFSDK_Annot::OnMouseMove(pFXAnnot, nFlags, point);
  return true;
}

void CPDFSDK_PageView::EnterWidget(ObservedPtr<CPDFSDK_Annot>& pAnnot,
                                   Mask<FWL_EVENTFLAG> nFlags) {
  m_bOnWidget = true;
  m_pCaptureWidget.Reset(pAnnot.Get());
  CPDFSDK_Annot::OnMouseEnter(m_pCaptureWidget, nFlags);
}

void CPDFSDK_PageView::ExitWidget(bool callExitCallback,
                                  Mask<FWL_EVENTFLAG> nFlags) {
  m_bOnWidget = false;
  if (!m_pCaptureWidget)
    return;

  if (callExitCallback) {
    ObservedPtr<CPDFSDK_PageView> pThis(this);
    CPDFSDK_Annot::OnMouseExit(m_pCaptureWidget, nFlags);

    // OnMouseExit() may have invalidated |this|.
    if (!pThis)
      return;
  }

  m_pCaptureWidget.Reset();
}

bool CPDFSDK_PageView::OnMouseWheel(Mask<FWL_EVENTFLAG> nFlags,
                                    const CFX_PointF& point,
                                    const CFX_Vector& delta) {
  ObservedPtr<CPDFSDK_Annot> pAnnot(GetFXWidgetAtPoint(point));
  if (!pAnnot)
    return false;

  return CPDFSDK_Annot::OnMouseWheel(pAnnot, nFlags, point, delta);
}

bool CPDFSDK_PageView::SetIndexSelected(int index, bool selected) {
  CPDFSDK_Annot* annot = GetFocusAnnot();
  return annot && annot->SetIndexSelected(index, selected);
}

bool CPDFSDK_PageView::IsIndexSelected(int index) {
  CPDFSDK_Annot* annot = GetFocusAnnot();
  return annot && annot->IsIndexSelected(index);
}

bool CPDFSDK_PageView::OnChar(uint32_t nChar, Mask<FWL_EVENTFLAG> nFlags) {
  ObservedPtr<CPDFSDK_Annot> pAnnot(GetFocusAnnot());
  return pAnnot && CPDFSDK_Annot::OnChar(pAnnot, nChar, nFlags);
}

bool CPDFSDK_PageView::OnKeyDown(FWL_VKEYCODE nKeyCode,
                                 Mask<FWL_EVENTFLAG> nFlags) {
  ObservedPtr<CPDFSDK_Annot> pAnnot(GetFocusAnnot());
  if (!pAnnot) {
    // If pressed key is not tab then no action is needed.
    if (nKeyCode != FWL_VKEY_Tab)
      return false;

    // If ctrl key or alt key is pressed, then no action is needed.
    if (CPWL_Wnd::IsCTRLKeyDown(nFlags) || CPWL_Wnd::IsALTKeyDown(nFlags))
      return false;

    ObservedPtr<CPDFSDK_Annot> end_annot(CPWL_Wnd::IsSHIFTKeyDown(nFlags)
                                             ? GetLastFocusableAnnot()
                                             : GetFirstFocusableAnnot());
    return end_annot && m_pFormFillEnv->SetFocusAnnot(end_annot);
  }

  if (CPWL_Wnd::IsCTRLKeyDown(nFlags) || CPWL_Wnd::IsALTKeyDown(nFlags))
    return CPDFSDK_Annot::OnKeyDown(pAnnot, nKeyCode, nFlags);

  CPDFSDK_Annot* pFocusAnnot = GetFocusAnnot();
  if (pFocusAnnot && (nKeyCode == FWL_VKEY_Tab)) {
    ObservedPtr<CPDFSDK_Annot> pNext(CPWL_Wnd::IsSHIFTKeyDown(nFlags)
                                         ? GetPrevAnnot(pFocusAnnot)
                                         : GetNextAnnot(pFocusAnnot));
    if (!pNext)
      return false;
    if (pNext.Get() != pFocusAnnot) {
      GetFormFillEnv()->SetFocusAnnot(pNext);
      return true;
    }
  }

  // Check |pAnnot| again because JS may have destroyed it in GetNextAnnot().
  if (!pAnnot)
    return false;

  return CPDFSDK_Annot::OnKeyDown(pAnnot, nKeyCode, nFlags);
}

void CPDFSDK_PageView::LoadFXAnnots() {
  AutoRestorer<bool> lock(&m_bLocked);
  m_bLocked = true;

#ifdef PDF_ENABLE_XFA
  RetainPtr<CPDFXFA_Page> protector(ToXFAPage(m_page));
  CPDF_Document::Extension* pContext = m_pFormFillEnv->GetDocExtension();
  if (pContext && pContext->ContainsExtensionFullForm()) {
    CXFA_FFPageView* pageView = protector->GetXFAPageView();
    CXFA_FFWidget::IteratorIface* pWidgetHandler =
        pageView->CreateGCedFormWidgetIterator(Mask<XFA_WidgetStatus>{
            XFA_WidgetStatus::kVisible, XFA_WidgetStatus::kViewable});

    while (CXFA_FFWidget* pXFAAnnot = pWidgetHandler->MoveToNext()) {
      m_SDKAnnotArray.push_back(
          std::make_unique<CPDFXFA_Widget>(pXFAAnnot, this));
      m_SDKAnnotArray.back()->OnLoad();
    }
    return;
  }
#endif  // PDF_ENABLE_XFA

  CPDF_Page* pPage = GetPDFPage();
  DCHECK(pPage);
  bool bUpdateAP = CPDF_InteractiveForm::IsUpdateAPEnabled();
  // Disable the default AP construction.
  CPDF_InteractiveForm::SetUpdateAP(false);
  m_pAnnotList = std::make_unique<CPDF_AnnotList>(pPage);
  CPDF_InteractiveForm::SetUpdateAP(bUpdateAP);

  const size_t nCount = m_pAnnotList->Count();
  for (size_t i = 0; i < nCount; ++i) {
    CPDF_Annot* pPDFAnnot = m_pAnnotList->GetAt(i);
    CheckForUnsupportedAnnot(pPDFAnnot);
    std::unique_ptr<CPDFSDK_Annot> pAnnot = NewAnnot(pPDFAnnot);
    if (!pAnnot)
      continue;
    m_SDKAnnotArray.push_back(std::move(pAnnot));
    m_SDKAnnotArray.back()->OnLoad();
  }
}

void CPDFSDK_PageView::UpdateRects(const std::vector<CFX_FloatRect>& rects) {
  for (const auto& rc : rects)
    m_pFormFillEnv->Invalidate(m_page, rc.GetOuterRect());
}

void CPDFSDK_PageView::UpdateView(CPDFSDK_Annot* pAnnot) {
  CFX_FloatRect rcWindow = pAnnot->GetRect();
  m_pFormFillEnv->Invalidate(m_page, rcWindow.GetOuterRect());
}

int CPDFSDK_PageView::GetPageIndex() const {
#ifdef PDF_ENABLE_XFA
  CPDF_Document::Extension* pContext = m_page->GetDocument()->GetExtension();
  if (pContext && pContext->ContainsExtensionFullForm()) {
    CXFA_FFPageView* pPageView = m_page->AsXFAPage()->GetXFAPageView();
    return pPageView ? pPageView->GetLayoutItem()->GetPageIndex() : -1;
  }
#endif  // PDF_ENABLE_XFA
  return GetPageIndexForStaticPDF();
}

bool CPDFSDK_PageView::IsValidAnnot(const CPDF_Annot* p) const {
  return p && m_pAnnotList->Contains(p);
}

bool CPDFSDK_PageView::IsValidSDKAnnot(const CPDFSDK_Annot* p) const {
  return p && pdfium::Contains(m_SDKAnnotArray, fxcrt::MakeFakeUniquePtr(p));
}

CPDFSDK_Annot* CPDFSDK_PageView::GetFocusAnnot() {
  CPDFSDK_Annot* pFocusAnnot = m_pFormFillEnv->GetFocusAnnot();
  return IsValidSDKAnnot(pFocusAnnot) ? pFocusAnnot : nullptr;
}

int CPDFSDK_PageView::GetPageIndexForStaticPDF() const {
  CPDF_Document* pDoc = m_pFormFillEnv->GetPDFDocument();
  return pDoc->GetPageIndex(GetPDFPage()->GetDict()->GetObjNum());
}
