From 24fbf134d43a7ec4226de3db601f0a617bbe428b Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Fri, 14 Aug 2015 19:02:30 -0700 Subject: Add new public APIs to find the z-order for links and widgets. - Implement FPDFLink_GetLinkZOrderAtPoint(). - Implement FPDFPage_FormFieldZOrderAtPoint(). - Mark FPDPage_HasFormFieldAtPoint() as deprecated. - Modify CPDF_LinkList and CPDF_InterForm to support new APIs. - Clean up dead code in CPDF_LinkList and CPDF_InterForm. BUG=chromium:515837 R=jun_fang@foxitsoftware.com, tsepez@chromium.org Review URL: https://codereview.chromium.org/1278053004 . --- core/include/fpdfdoc/fpdf_doc.h | 58 ++----- core/src/fpdfdoc/doc_form.cpp | 319 ++++------------------------------- core/src/fpdfdoc/doc_formcontrol.cpp | 2 +- core/src/fpdfdoc/doc_link.cpp | 99 +++++------ fpdfsdk/src/fpdfdoc.cpp | 63 ++++--- fpdfsdk/src/fpdfformfill.cpp | 39 ++++- fpdfsdk/src/fpdfview_c_api_test.c | 5 +- public/fpdf_doc.h | 39 +++-- public/fpdf_formfill.h | 45 ++++- 9 files changed, 243 insertions(+), 426 deletions(-) diff --git a/core/include/fpdfdoc/fpdf_doc.h b/core/include/fpdfdoc/fpdf_doc.h index e0c6d337ca..2d37a48153 100644 --- a/core/include/fpdfdoc/fpdf_doc.h +++ b/core/include/fpdfdoc/fpdf_doc.h @@ -8,6 +8,7 @@ #define CORE_INCLUDE_FPDFDOC_FPDF_DOC_H_ #include +#include #include "../../../third_party/base/nonstd_unique_ptr.h" #include "../fpdfapi/fpdf_parser.h" @@ -32,7 +33,6 @@ class CPDF_FormNotify; class CPDF_IconFit; class CPDF_InterForm; class CPDF_Link; -class CPDF_LinkList; class CPDF_LWinParam; class CPDF_Metadata; class CPDF_NumberTree; @@ -357,29 +357,25 @@ class CPDF_FileSpec { protected: CPDF_Object* m_pObj; }; + class CPDF_LinkList { public: - CPDF_LinkList(CPDF_Document* pDoc) { m_pDocument = pDoc; } - + CPDF_LinkList(); ~CPDF_LinkList(); - CPDF_Link GetLinkAtPoint(CPDF_Page* pPage, FX_FLOAT pdf_x, FX_FLOAT pdf_y); - - int CountLinks(CPDF_Page* pPage); - - CPDF_Link GetLink(CPDF_Page* pPage, int index); - - CPDF_Document* GetDocument() const { return m_pDocument; } - - protected: - CPDF_Document* m_pDocument; + CPDF_Link GetLinkAtPoint(CPDF_Page* pPage, + FX_FLOAT pdf_x, + FX_FLOAT pdf_y, + int* z_order); - CFX_MapPtrToPtr m_PageMap; + private: + const std::vector* GetPageLinks(CPDF_Page* pPage); - CFX_PtrArray* GetPageLinks(CPDF_Page* pPage); + void LoadPageLinks(CPDF_Page* pPage, std::vector* pList); - void LoadPageLinks(CPDF_Page* pPage, CFX_PtrArray* pList); + std::map> m_PageMap; }; + class CPDF_Link { public: CPDF_Link() : m_pDict(nullptr) {} @@ -642,29 +638,13 @@ class CPDF_InterForm : public CFX_PrivateData { CPDF_FormField* GetFieldByDict(CPDF_Dictionary* pFieldDict) const; - FX_DWORD CountControls(CFX_WideString csFieldName = L""); - - CPDF_FormControl* GetControl(FX_DWORD index, - CFX_WideString csFieldName = L""); - - FX_BOOL IsValidFormControl(const void* pControl); - - int CountPageControls(CPDF_Page* pPage) const; - - CPDF_FormControl* GetPageControl(CPDF_Page* pPage, int index) const; - CPDF_FormControl* GetControlAtPoint(CPDF_Page* pPage, FX_FLOAT pdf_x, - FX_FLOAT pdf_y) const; + FX_FLOAT pdf_y, + int* z_order) const; CPDF_FormControl* GetControlByDict(CPDF_Dictionary* pWidgetDict) const; - FX_DWORD CountInternalFields(const CFX_WideString& csFieldName = L"") const; - - CPDF_Dictionary* GetInternalField( - FX_DWORD index, - const CFX_WideString& csFieldName = L"") const; - CPDF_Document* GetDocument() const { return m_pDocument; } CPDF_Dictionary* GetFormDict() const { return m_pFormDict; } @@ -738,14 +718,10 @@ class CPDF_InterForm : public CFX_PrivateData { FX_BOOL ResetForm(FX_BOOL bNotify = FALSE); - void ReloadForm(); - CPDF_FormNotify* GetFormNotify() const { return m_pFormNotify; } void SetFormNotify(const CPDF_FormNotify* pNotify); - int GetPageWithWidget(int iCurPage, FX_BOOL bNext); - FX_BOOL IsUpdated() { return m_bUpdated; } void ClearUpdatedFlag() { m_bUpdated = FALSE; } @@ -788,7 +764,7 @@ class CPDF_InterForm : public CFX_PrivateData { CPDF_Dictionary* m_pFormDict; - CFX_MapPtrToPtr m_ControlMap; + std::map m_ControlMap; CFieldTree* m_pFieldTree; @@ -832,8 +808,6 @@ class CPDF_FormField { FX_DWORD GetFlags() { return m_Flags; } - CPDF_InterForm* GetInterForm() const { return m_pForm; } - CPDF_Dictionary* GetFieldDict() const { return m_pDict; } void SetFieldDict(CPDF_Dictionary* pDict) { m_pDict = pDict; } @@ -1000,7 +974,7 @@ class CPDF_FormControl { CPDF_Dictionary* GetWidget() const { return m_pWidgetDict; } - CFX_FloatRect GetRect(); + CFX_FloatRect GetRect() const; void DrawControl(CFX_RenderDevice* pDevice, CFX_AffineMatrix* pMatrix, diff --git a/core/src/fpdfdoc/doc_form.cpp b/core/src/fpdfdoc/doc_form.cpp index a59f35eeac..970b4b9f40 100644 --- a/core/src/fpdfdoc/doc_form.cpp +++ b/core/src/fpdfdoc/doc_form.cpp @@ -253,23 +253,19 @@ CPDF_InterForm::CPDF_InterForm(CPDF_Document* pDocument, FX_BOOL bGenerateAP) LoadField(pFields->GetDict(i)); } } + CPDF_InterForm::~CPDF_InterForm() { - FX_POSITION pos = m_ControlMap.GetStartPosition(); - while (pos) { - void* key; - void* value; - m_ControlMap.GetNextAssoc(pos, key, value); - delete (CPDF_FormControl*)value; - } - if (m_pFieldTree != NULL) { + for (auto it : m_ControlMap) + delete it.second; + if (m_pFieldTree) { int nCount = m_pFieldTree->m_Root.CountFields(); - for (int i = 0; i < nCount; i++) { - CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i); - delete pField; + for (int i = 0; i < nCount; ++i) { + delete m_pFieldTree->m_Root.GetField(i); } delete m_pFieldTree; } } + FX_BOOL CPDF_InterForm::m_bUpdateAP = TRUE; FX_BOOL CPDF_InterForm::UpdatingAPEnabled() { return m_bUpdateAP; @@ -788,215 +784,43 @@ CPDF_FormField* CPDF_InterForm::GetFieldByDict( CFX_WideString csWName = GetFullName(pFieldDict); return m_pFieldTree->GetField(csWName); } -FX_DWORD CPDF_InterForm::CountControls(CFX_WideString csFieldName) { - if (csFieldName.IsEmpty()) { - return (FX_DWORD)m_ControlMap.GetCount(); - } - CPDF_FormField* pField = m_pFieldTree->GetField(csFieldName); - if (pField == NULL) { - return 0; - } - return pField->m_ControlList.GetSize(); -} -CPDF_FormControl* CPDF_InterForm::GetControl(FX_DWORD index, - CFX_WideString csFieldName) { - CPDF_FormField* pField = m_pFieldTree->GetField(csFieldName); - if (pField == NULL) { - return NULL; - } - if (index < (FX_DWORD)pField->m_ControlList.GetSize()) { - return (CPDF_FormControl*)pField->m_ControlList.GetAt(index); - } - return NULL; -} -FX_BOOL CPDF_InterForm::IsValidFormControl(const void* pControl) { - if (pControl == NULL) { - return FALSE; - } - FX_POSITION pos = m_ControlMap.GetStartPosition(); - while (pos) { - CPDF_Dictionary* pWidgetDict = NULL; - void* pFormControl = NULL; - m_ControlMap.GetNextAssoc(pos, (void*&)pWidgetDict, pFormControl); - if (pControl == pFormControl) { - return TRUE; - } - } - return FALSE; -} -int CPDF_InterForm::CountPageControls(CPDF_Page* pPage) const { - CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots"); - if (pAnnotList == NULL) { - return 0; - } - int count = 0; - for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i++) { - CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i); - if (pAnnot == NULL) { - continue; - } - CPDF_FormControl* pControl; - if (!m_ControlMap.Lookup(pAnnot, (void*&)pControl)) { - continue; - } - count++; - } - return count; -} -CPDF_FormControl* CPDF_InterForm::GetPageControl(CPDF_Page* pPage, - int index) const { - CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots"); - if (pAnnotList == NULL) { - return NULL; - } - int count = 0; - for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i++) { - CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i); - if (pAnnot == NULL) { - continue; - } - CPDF_FormControl* pControl; - if (!m_ControlMap.Lookup(pAnnot, (void*&)pControl)) { - continue; - } - if (index == count) { - return pControl; - } - count++; - } - return NULL; -} + CPDF_FormControl* CPDF_InterForm::GetControlAtPoint(CPDF_Page* pPage, FX_FLOAT pdf_x, - FX_FLOAT pdf_y) const { + FX_FLOAT pdf_y, + int* z_order) const { CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots"); - if (pAnnotList == NULL) { - return NULL; - } - for (FX_DWORD i = pAnnotList->GetCount(); i > 0; i--) { - CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i - 1); - if (pAnnot == NULL) { + if (!pAnnotList) + return nullptr; + + for (FX_DWORD i = pAnnotList->GetCount(); i > 0; --i) { + FX_DWORD annot_index = i - 1; + CPDF_Dictionary* pAnnot = pAnnotList->GetDict(annot_index); + if (!pAnnot) continue; - } - CPDF_FormControl* pControl; - if (!m_ControlMap.Lookup(pAnnot, (void*&)pControl)) { + + const auto it = m_ControlMap.find(pAnnot); + if (it == m_ControlMap.end()) continue; - } + + CPDF_FormControl* pControl = it->second; CFX_FloatRect rect = pControl->GetRect(); - if (rect.Contains(pdf_x, pdf_y)) { - return pControl; - } + if (!rect.Contains(pdf_x, pdf_y)) + continue; + + if (z_order) + *z_order = annot_index; + return pControl; } - return NULL; + return nullptr; } + CPDF_FormControl* CPDF_InterForm::GetControlByDict( CPDF_Dictionary* pWidgetDict) const { - CPDF_FormControl* pControl = NULL; - m_ControlMap.Lookup(pWidgetDict, (void*&)pControl); - return pControl; -} -FX_DWORD CPDF_InterForm::CountInternalFields( - const CFX_WideString& csFieldName) const { - if (!m_pFormDict) { - return 0; - } - CPDF_Array* pArray = m_pFormDict->GetArray("Fields"); - if (!pArray) { - return 0; - } - if (csFieldName.IsEmpty()) { - return pArray->GetCount(); - } - int iLength = csFieldName.GetLength(); - int iPos = 0; - CPDF_Dictionary* pDict = NULL; - while (pArray != NULL) { - CFX_WideString csSub; - if (iPos < iLength && csFieldName[iPos] == L'.') { - iPos++; - } - while (iPos < iLength && csFieldName[iPos] != L'.') { - csSub += csFieldName[iPos++]; - } - int iCount = pArray->GetCount(); - FX_BOOL bFind = FALSE; - for (int i = 0; i < iCount; i++) { - pDict = pArray->GetDict(i); - if (pDict == NULL) { - continue; - } - CFX_WideString csT = pDict->GetUnicodeText("T"); - if (csT == csSub) { - bFind = TRUE; - break; - } - } - if (!bFind) { - return 0; - } - if (iPos >= iLength) { - break; - } - pArray = pDict->GetArray("Kids"); - } - if (!pDict) { - return 0; - } - pArray = pDict->GetArray("Kids"); - return pArray ? pArray->GetCount() : 1; + const auto it = m_ControlMap.find(pWidgetDict); + return it != m_ControlMap.end() ? it->second : nullptr; } -CPDF_Dictionary* CPDF_InterForm::GetInternalField( - FX_DWORD index, - const CFX_WideString& csFieldName) const { - if (!m_pFormDict) { - return nullptr; - } - CPDF_Array* pArray = m_pFormDict->GetArray("Fields"); - if (!pArray) { - return nullptr; - } - if (csFieldName.IsEmpty()) { - return pArray->GetDict(index); - } - int iLength = csFieldName.GetLength(); - int iPos = 0; - CPDF_Dictionary* pDict = NULL; - while (pArray != NULL) { - CFX_WideString csSub; - if (iPos < iLength && csFieldName[iPos] == L'.') { - iPos++; - } - while (iPos < iLength && csFieldName[iPos] != L'.') { - csSub += csFieldName[iPos++]; - } - int iCount = pArray->GetCount(); - FX_BOOL bFind = FALSE; - for (int i = 0; i < iCount; i++) { - pDict = pArray->GetDict(i); - if (pDict == NULL) { - continue; - } - CFX_WideString csT = pDict->GetUnicodeText("T"); - if (csT == csSub) { - bFind = TRUE; - break; - } - } - if (!bFind) { - return NULL; - } - if (iPos >= iLength) { - break; - } - pArray = pDict->GetArray("Kids"); - } - if (!pDict) { - return nullptr; - } - pArray = pDict->GetArray("Kids"); - return pArray ? pArray->GetDict(index) : pDict; -} FX_BOOL CPDF_InterForm::NeedConstructAP() { if (m_pFormDict == NULL) { return FALSE; @@ -1172,33 +996,6 @@ FX_BOOL CPDF_InterForm::ResetForm(FX_BOOL bNotify) { } return TRUE; } -void CPDF_InterForm::ReloadForm() { - FX_POSITION pos = m_ControlMap.GetStartPosition(); - while (pos) { - CPDF_Dictionary* pWidgetDict; - CPDF_FormControl* pControl; - m_ControlMap.GetNextAssoc(pos, (void*&)pWidgetDict, (void*&)pControl); - delete pControl; - } - m_ControlMap.RemoveAll(); - int nCount = m_pFieldTree->m_Root.CountFields(); - for (int k = 0; k < nCount; k++) { - CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(k); - delete pField; - } - m_pFieldTree->RemoveAll(); - if (m_pFormDict == NULL) { - return; - } - CPDF_Array* pFields = m_pFormDict->GetArray("Fields"); - if (pFields == NULL) { - return; - } - int iCount = pFields->GetCount(); - for (int i = 0; i < iCount; i++) { - LoadField(pFields->GetDict(i)); - } -} void CPDF_InterForm::LoadField(CPDF_Dictionary* pFieldDict, int nLevel) { if (nLevel > nMaxRecursion) { return; @@ -1320,13 +1117,13 @@ CPDF_FormField* CPDF_InterForm::AddTerminalField( CPDF_FormControl* CPDF_InterForm::AddControl( const CPDF_FormField* pField, const CPDF_Dictionary* pWidgetDict) { - void* rValue = NULL; - if (m_ControlMap.Lookup((CPDF_Dictionary*)pWidgetDict, rValue)) { - return (CPDF_FormControl*)rValue; - } + const auto it = m_ControlMap.find(pWidgetDict); + if (it != m_ControlMap.end()) + return it->second; + CPDF_FormControl* pControl = new CPDF_FormControl( (CPDF_FormField*)pField, (CPDF_Dictionary*)pWidgetDict); - m_ControlMap.SetAt((CPDF_Dictionary*)pWidgetDict, pControl); + m_ControlMap[pWidgetDict] = pControl; ((CPDF_FormField*)pField)->m_ControlList.Add(pControl); return pControl; } @@ -1581,45 +1378,3 @@ FX_BOOL CPDF_InterForm::ImportFromFDF(const CFDF_Document* pFDF, void CPDF_InterForm::SetFormNotify(const CPDF_FormNotify* pNotify) { m_pFormNotify = (CPDF_FormNotify*)pNotify; } -int CPDF_InterForm::GetPageWithWidget(int iCurPage, FX_BOOL bNext) { - if (iCurPage < 0) { - return -1; - } - int iPageCount = m_pDocument->GetPageCount(); - if (iCurPage >= iPageCount) { - return -1; - } - int iNewPage = iCurPage; - do { - iNewPage += bNext ? 1 : -1; - if (iNewPage >= iPageCount) { - iNewPage = 0; - } - if (iNewPage < 0) { - iNewPage = iPageCount - 1; - } - if (iNewPage == iCurPage) { - break; - } - CPDF_Dictionary* pPageDict = m_pDocument->GetPage(iNewPage); - if (pPageDict == NULL) { - continue; - } - CPDF_Array* pAnnots = pPageDict->GetArray("Annots"); - if (pAnnots == NULL) { - continue; - } - FX_DWORD dwCount = pAnnots->GetCount(); - for (FX_DWORD i = 0; i < dwCount; i++) { - CPDF_Object* pAnnotDict = pAnnots->GetElementValue(i); - if (pAnnotDict == NULL) { - continue; - } - CPDF_FormControl* pControl = NULL; - if (m_ControlMap.Lookup(pAnnotDict, (void*&)pControl)) { - return iNewPage; - } - } - } while (TRUE); - return -1; -} diff --git a/core/src/fpdfdoc/doc_formcontrol.cpp b/core/src/fpdfdoc/doc_formcontrol.cpp index db7cf37fdb..410f9a1f21 100644 --- a/core/src/fpdfdoc/doc_formcontrol.cpp +++ b/core/src/fpdfdoc/doc_formcontrol.cpp @@ -11,7 +11,7 @@ CPDF_FormControl::CPDF_FormControl(CPDF_FormField* pField, m_pWidgetDict = pWidgetDict; m_pForm = m_pField->m_pForm; } -CFX_FloatRect CPDF_FormControl::GetRect() { +CFX_FloatRect CPDF_FormControl::GetRect() const { return m_pWidgetDict->GetRect("Rect"); } CFX_ByteString CPDF_FormControl::GetOnStateName() { diff --git a/core/src/fpdfdoc/doc_link.cpp b/core/src/fpdfdoc/doc_link.cpp index 15bd14c31e..fbf18f99e5 100644 --- a/core/src/fpdfdoc/doc_link.cpp +++ b/core/src/fpdfdoc/doc_link.cpp @@ -6,75 +6,68 @@ #include "../../include/fpdfdoc/fpdf_doc.h" +CPDF_LinkList::CPDF_LinkList() { +} + CPDF_LinkList::~CPDF_LinkList() { - FX_POSITION pos = m_PageMap.GetStartPosition(); - while (pos) { - void* key; - void* value; - m_PageMap.GetNextAssoc(pos, key, value); - delete (CFX_PtrArray*)value; - } } -CFX_PtrArray* CPDF_LinkList::GetPageLinks(CPDF_Page* pPage) { + +const std::vector* CPDF_LinkList::GetPageLinks( + CPDF_Page* pPage) { FX_DWORD objnum = pPage->m_pFormDict->GetObjNum(); - if (objnum == 0) { - return NULL; - } - CFX_PtrArray* pPageLinkList = NULL; - if (!m_PageMap.Lookup((void*)(uintptr_t)objnum, (void*&)pPageLinkList)) { - pPageLinkList = new CFX_PtrArray; - m_PageMap.SetAt((void*)(uintptr_t)objnum, pPageLinkList); - LoadPageLinks(pPage, pPageLinkList); - } - return pPageLinkList; -} -int CPDF_LinkList::CountLinks(CPDF_Page* pPage) { - CFX_PtrArray* pPageLinkList = GetPageLinks(pPage); - if (pPageLinkList == NULL) { - return 0; - } - return pPageLinkList->GetSize(); -} -CPDF_Link CPDF_LinkList::GetLink(CPDF_Page* pPage, int index) { - CFX_PtrArray* pPageLinkList = GetPageLinks(pPage); - if (!pPageLinkList) { - return CPDF_Link(); - } - return CPDF_Link((CPDF_Dictionary*)pPageLinkList->GetAt(index)); + if (objnum == 0) + return nullptr; + + auto it = m_PageMap.find(objnum); + if (it != m_PageMap.end()) + return &it->second; + + // std::map::operator[] forces the creation of a map entry. + std::vector& page_link_list = m_PageMap[objnum]; + LoadPageLinks(pPage, &page_link_list); + return &page_link_list; } + CPDF_Link CPDF_LinkList::GetLinkAtPoint(CPDF_Page* pPage, FX_FLOAT pdf_x, - FX_FLOAT pdf_y) { - CFX_PtrArray* pPageLinkList = GetPageLinks(pPage); - if (!pPageLinkList) { + FX_FLOAT pdf_y, + int* z_order) { + const std::vector* pPageLinkList = GetPageLinks(pPage); + if (!pPageLinkList) return CPDF_Link(); - } - int size = pPageLinkList->GetSize(); - for (int i = size - 1; i >= 0; --i) { - CPDF_Link link((CPDF_Dictionary*)pPageLinkList->GetAt(i)); + + for (size_t i = pPageLinkList->size(); i > 0; --i) { + size_t annot_index = i - 1; + CPDF_Dictionary* pAnnot = (*pPageLinkList)[annot_index]; + if (!pAnnot) + continue; + + CPDF_Link link(pAnnot); CPDF_Rect rect = link.GetRect(); - if (rect.Contains(pdf_x, pdf_y)) { - return link; - } + if (!rect.Contains(pdf_x, pdf_y)) + continue; + + if (z_order) + *z_order = annot_index; + return link; } return CPDF_Link(); } -void CPDF_LinkList::LoadPageLinks(CPDF_Page* pPage, CFX_PtrArray* pList) { + +void CPDF_LinkList::LoadPageLinks(CPDF_Page* pPage, + std::vector* pList) { CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots"); - if (pAnnotList == NULL) { + if (!pAnnotList) return; - } - for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i++) { + + for (FX_DWORD i = 0; i < pAnnotList->GetCount(); ++i) { CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i); - if (pAnnot == NULL) { - continue; - } - if (pAnnot->GetString("Subtype") != "Link") { - continue; - } - pList->Add(pAnnot); + bool add_link = (pAnnot && pAnnot->GetString("Subtype") == "Link"); + // Add non-links as nullptrs to preserve z-order. + pList->push_back(add_link ? pAnnot : nullptr); } } + CPDF_Rect CPDF_Link::GetRect() { return m_pDict->GetRect("Rect"); } diff --git a/fpdfsdk/src/fpdfdoc.cpp b/fpdfsdk/src/fpdfdoc.cpp index bcd401b4c4..5d2469c160 100644 --- a/fpdfsdk/src/fpdfdoc.cpp +++ b/fpdfsdk/src/fpdfdoc.cpp @@ -7,11 +7,13 @@ #include "../include/fsdk_define.h" #include "../../public/fpdf_doc.h" -static int THISMODULE = 0; +namespace { -static CPDF_Bookmark FindBookmark(const CPDF_BookmarkTree& tree, - CPDF_Bookmark bookmark, - const CFX_WideString& title) { +int THISMODULE = 0; + +CPDF_Bookmark FindBookmark(const CPDF_BookmarkTree& tree, + CPDF_Bookmark bookmark, + const CFX_WideString& title) { if (bookmark && bookmark.GetTitle().CompareNoCase(title.c_str()) == 0) { // First check this item return bookmark; @@ -28,6 +30,26 @@ static CPDF_Bookmark FindBookmark(const CPDF_BookmarkTree& tree, return CPDF_Bookmark(); } +void ReleaseLinkList(void* data) { + delete (CPDF_LinkList*)data; +} + +CPDF_LinkList* GetLinkList(CPDF_Page* page) { + if (!page) + return nullptr; + + // Link list is stored with the document + CPDF_Document* pDoc = page->m_pDocument; + CPDF_LinkList* pLinkList = (CPDF_LinkList*)pDoc->GetPrivateData(&THISMODULE); + if (!pLinkList) { + pLinkList = new CPDF_LinkList; + pDoc->SetPrivateData(&THISMODULE, pLinkList, ReleaseLinkList); + } + return pLinkList; +} + +} // namespace + DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_GetFirstChild(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict) { if (!document) @@ -161,24 +183,27 @@ DLLEXPORT unsigned long STDCALL FPDFDest_GetPageIndex(FPDF_DOCUMENT document, return dest.GetPageIndex(pDoc); } -static void ReleaseLinkList(void* data) { - delete (CPDF_LinkList*)data; +DLLEXPORT FPDF_LINK STDCALL +FPDFLink_GetLinkAtPoint(FPDF_PAGE page, double x, double y) { + CPDF_Page* pPage = (CPDF_Page*)page; + CPDF_LinkList* pLinkList = GetLinkList(pPage); + if (!pLinkList) + return nullptr; + + return pLinkList->GetLinkAtPoint(pPage, (FX_FLOAT)x, (FX_FLOAT)y, nullptr) + .GetDict(); } -DLLEXPORT FPDF_LINK STDCALL FPDFLink_GetLinkAtPoint(FPDF_PAGE page, - double x, - double y) { - if (!page) - return NULL; +DLLEXPORT int STDCALL +FPDFLink_GetLinkZOrderAtPoint(FPDF_PAGE page, double x, double y) { CPDF_Page* pPage = (CPDF_Page*)page; - // Link list is stored with the document - CPDF_Document* pDoc = pPage->m_pDocument; - CPDF_LinkList* pLinkList = (CPDF_LinkList*)pDoc->GetPrivateData(&THISMODULE); - if (!pLinkList) { - pLinkList = new CPDF_LinkList(pDoc); - pDoc->SetPrivateData(&THISMODULE, pLinkList, ReleaseLinkList); - } - return pLinkList->GetLinkAtPoint(pPage, (FX_FLOAT)x, (FX_FLOAT)y).GetDict(); + CPDF_LinkList* pLinkList = GetLinkList(pPage); + if (!pLinkList) + return -1; + + int z_order = -1; + pLinkList->GetLinkAtPoint(pPage, (FX_FLOAT)x, (FX_FLOAT)y, &z_order); + return z_order; } DLLEXPORT FPDF_DEST STDCALL FPDFLink_GetDest(FPDF_DOCUMENT document, diff --git a/fpdfsdk/src/fpdfformfill.cpp b/fpdfsdk/src/fpdfformfill.cpp index 170ae15799..272e781cc2 100644 --- a/fpdfsdk/src/fpdfformfill.cpp +++ b/fpdfsdk/src/fpdfformfill.cpp @@ -34,18 +34,17 @@ CPDFSDK_PageView* FormHandleToPageView(FPDF_FORMHANDLE hHandle, } // namespace -DLLEXPORT int STDCALL FPDPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - double page_x, - double page_y) { +DLLEXPORT int STDCALL FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + double page_x, + double page_y) { if (!page || !hHandle) return -1; - CPDF_Page* pPage = (CPDF_Page*)page; - nonstd::unique_ptr pInterForm( - new CPDF_InterForm(pPage->m_pDocument, FALSE)); - CPDF_FormControl* pFormCtrl = - pInterForm->GetControlAtPoint(pPage, (FX_FLOAT)page_x, (FX_FLOAT)page_y); + CPDF_Page* pPage = (CPDF_Page*)page; + CPDF_InterForm interform(pPage->m_pDocument, FALSE); + CPDF_FormControl* pFormCtrl = interform.GetControlAtPoint( + pPage, (FX_FLOAT)page_x, (FX_FLOAT)page_y, nullptr); if (!pFormCtrl) return -1; @@ -56,6 +55,28 @@ DLLEXPORT int STDCALL FPDPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, return pFormField->GetFieldType(); } +DLLEXPORT int STDCALL FPDPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + double page_x, + double page_y) { + return FPDFPage_HasFormFieldAtPoint(hHandle, page, page_x, page_y); +} + +DLLEXPORT int STDCALL FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + double page_x, + double page_y) { + if (!page || !hHandle) + return -1; + + CPDF_Page* pPage = (CPDF_Page*)page; + CPDF_InterForm interform(pPage->m_pDocument, FALSE); + int z_order = -1; + (void)interform.GetControlAtPoint(pPage, (FX_FLOAT)page_x, (FX_FLOAT)page_y, + &z_order); + return z_order; +} + DLLEXPORT FPDF_FORMHANDLE STDCALL FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document, FPDF_FORMFILLINFO* formInfo) { diff --git a/fpdfsdk/src/fpdfview_c_api_test.c b/fpdfsdk/src/fpdfview_c_api_test.c index a17f7b6c1e..9bd2747f83 100644 --- a/fpdfsdk/src/fpdfview_c_api_test.c +++ b/fpdfsdk/src/fpdfview_c_api_test.c @@ -54,6 +54,7 @@ int CheckPDFiumCApi() { CHK(FPDFAction_GetURIPath); CHK(FPDFDest_GetPageIndex); CHK(FPDFLink_GetLinkAtPoint); + CHK(FPDFLink_GetLinkZOrderAtPoint); CHK(FPDFLink_GetDest); CHK(FPDFLink_GetAction); CHK(FPDFLink_Enumerate); @@ -106,7 +107,9 @@ int CheckPDFiumCApi() { CHK(FORM_OnKeyUp); CHK(FORM_OnChar); CHK(FORM_ForceToKillFocus); - CHK(FPDPage_HasFormFieldAtPoint); + CHK(FPDFPage_HasFormFieldAtPoint); + CHK(FPDPage_HasFormFieldAtPoint); // DEPRECATED. Remove in the future. + CHK(FPDFPage_FormFieldZOrderAtPoint); CHK(FPDF_SetFormFieldHighlightColor); CHK(FPDF_SetFormFieldHighlightAlpha); CHK(FPDF_RemoveFormFieldHighlight); diff --git a/public/fpdf_doc.h b/public/fpdf_doc.h index ed05aed4d9..e537d2b6c1 100644 --- a/public/fpdf_doc.h +++ b/public/fpdf_doc.h @@ -177,24 +177,43 @@ DLLEXPORT unsigned long STDCALL FPDFDest_GetPageIndex(FPDF_DOCUMENT document, FPDF_DEST dest); // Function: FPDFLink_GetLinkAtPoint -// Find a link at specified point on a document page. +// Find a link at specified point on a document page. // Parameters: -// page - Handle to the document page. -// x - The x coordinate of the point, specified in page -// coordinate system. -// y - The y coordinate of the point, specified in page -// coordinate system. +// page - Handle to the document page. +// x - The x coordinate of the point, specified in page +// coordinate system. +// y - The y coordinate of the point, specified in page +// coordinate system. // Return value: -// Handle to the link. NULL if no link found at that point. +// Handle to the link. NULL if no link found at that point. // Comments: -// The point coordinates are specified in page coordinate system. You -// can convert coordinates -// from screen system to page system using FPDF_DeviceToPage functions. +// The point coordinates are specified in page coordinate system. You can +// convert coordinates from screen system to page system using +// FPDF_DeviceToPage(). // DLLEXPORT FPDF_LINK STDCALL FPDFLink_GetLinkAtPoint(FPDF_PAGE page, double x, double y); +// Function: FPDFLink_GetLinkZOrderAtPoint +// Find the z-order of a link at specified point on a document page. +// Parameters: +// page - Handle to the document page. +// x - The x coordinate of the point, specified in page +// coordinate system. +// y - The y coordinate of the point, specified in page +// coordinate system. +// Return value: +// Z-order of the link, or -1 if no link found at that point. +// Higher numbers are closer to the front. +// Comments: +// The point coordinates are specified in page coordinate system. You can +// convert coordinates from screen system to page system using +// FPDF_DeviceToPage(). +// +DLLEXPORT int STDCALL +FPDFLink_GetLinkZOrderAtPoint(FPDF_PAGE page, double x, double y); + // Function: FPDFLink_GetDest // Get destination info of a link. // Parameters: diff --git a/public/fpdf_formfill.h b/public/fpdf_formfill.h index 625a2b63e9..128c7ec818 100644 --- a/public/fpdf_formfill.h +++ b/public/fpdf_formfill.h @@ -962,23 +962,50 @@ DLLEXPORT FPDF_BOOL STDCALL FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle); #define FPDF_FORMFIELD_TEXTFIELD 6 // text field type. /** - * Function: FPDPage_HasFormFieldAtPoint - * Check the form filed position by point. + * Function: FPDFPage_HasFormFieldAtPoint + * Get the form field type by point. * Parameters: - * hHandle - Handle to the form fill module. Returned by - *FPDFDOC_InitFormFillEnvironment. - * page - Handle to the page. Returned by FPDF_LoadPage - *function. - * page_x - X position in PDF "user space". - * page_y - Y position in PDF "user space". + * hHandle - Handle to the form fill module. Returned by + * FPDFDOC_InitFormFillEnvironment(). + * page - Handle to the page. Returned by FPDF_LoadPage(). + * page_x - X position in PDF "user space". + * page_y - Y position in PDF "user space". * Return Value: - * Return the type of the formfiled; -1 indicates no fields. + * Return the type of the form field; -1 indicates no field. + * See field types above. + **/ +DLLEXPORT int STDCALL FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + double page_x, + double page_y); + +/** + * Function: FPDPage_HasFormFieldAtPoint + * DEPRECATED. Please use FPDFPage_HasFormFieldAtPoint. **/ DLLEXPORT int STDCALL FPDPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, FPDF_PAGE page, double page_x, double page_y); +/** + * Function: FPDFPage_FormFieldZOrderAtPoint + * Get the form field z-order by point. + * Parameters: + * hHandle - Handle to the form fill module. Returned by + * FPDFDOC_InitFormFillEnvironment(). + * page - Handle to the page. Returned by FPDF_LoadPage(). + * page_x - X position in PDF "user space". + * page_y - Y position in PDF "user space". + * Return Value: + * Return the z-order of the form field; -1 indicates no field. + * Higher numbers are closer to the front. + **/ +DLLEXPORT int STDCALL FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + double page_x, + double page_y); + /** * Function: FPDF_SetFormFieldHighlightColor * Set the highlight color of specified or all the form fields in the -- cgit v1.2.3