summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLei Zhang <thestig@chromium.org>2015-08-14 19:24:08 -0700
committerLei Zhang <thestig@chromium.org>2015-08-14 19:24:08 -0700
commitbdf72c353af5b8a34ef5efdeddfff36d2089a158 (patch)
tree34258c3019152b41bbfd8f3332683dbc25c0c9da
parent88f0bafb4163d297b51055124d4d35b769905216 (diff)
downloadpdfium-bdf72c353af5b8a34ef5efdeddfff36d2089a158.tar.xz
Merge to XFA: 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 . (cherry picked from commit 24fbf134d43a7ec4226de3db601f0a617bbe428b) Review URL: https://codereview.chromium.org/1295893005 .
-rw-r--r--core/include/fpdfdoc/fpdf_doc.h58
-rw-r--r--core/src/fpdfdoc/doc_form.cpp322
-rw-r--r--core/src/fpdfdoc/doc_formcontrol.cpp2
-rw-r--r--core/src/fpdfdoc/doc_link.cpp99
-rw-r--r--fpdfsdk/src/fpdfdoc.cpp73
-rw-r--r--fpdfsdk/src/fpdfformfill.cpp50
-rw-r--r--fpdfsdk/src/fpdfview_c_api_test.c5
-rw-r--r--public/fpdf_doc.h49
-rw-r--r--public/fpdf_formfill.h45
9 files changed, 262 insertions, 441 deletions
diff --git a/core/include/fpdfdoc/fpdf_doc.h b/core/include/fpdfdoc/fpdf_doc.h
index 6e444149e4..0d8dd3caec 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 <map>
+#include <vector>
#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;
@@ -358,29 +358,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<CPDF_Dictionary*>* GetPageLinks(CPDF_Page* pPage);
- CFX_PtrArray* GetPageLinks(CPDF_Page* pPage);
+ void LoadPageLinks(CPDF_Page* pPage, std::vector<CPDF_Dictionary*>* pList);
- void LoadPageLinks(CPDF_Page* pPage, CFX_PtrArray* pList);
+ std::map<FX_DWORD, std::vector<CPDF_Dictionary*>> m_PageMap;
};
+
class CPDF_Link {
public:
CPDF_Link() : m_pDict(nullptr) {}
@@ -644,29 +640,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; }
@@ -740,14 +720,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; }
@@ -790,7 +766,7 @@ class CPDF_InterForm : public CFX_PrivateData {
CPDF_Dictionary* m_pFormDict;
- CFX_MapPtrToPtr m_ControlMap;
+ std::map<const CPDF_Dictionary*, CPDF_FormControl*> m_ControlMap;
CFieldTree* m_pFieldTree;
@@ -834,8 +810,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; }
@@ -1008,7 +982,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 d25fd27d13..e57ac9aa50 100644
--- a/core/src/fpdfdoc/doc_form.cpp
+++ b/core/src/fpdfdoc/doc_form.cpp
@@ -256,23 +256,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;
@@ -791,215 +787,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;
@@ -1175,33 +999,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;
@@ -1323,16 +1120,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);
- if (pControl == NULL) {
- return NULL;
- }
- m_ControlMap.SetAt((CPDF_Dictionary*)pWidgetDict, pControl);
+ m_ControlMap[pWidgetDict] = pControl;
((CPDF_FormField*)pField)->m_ControlList.Add(pControl);
return pControl;
}
@@ -1587,45 +1381,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_Dictionary*>* 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<CPDF_Dictionary*>& 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<CPDF_Dictionary*>* 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<CPDF_Dictionary*>* 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 0006094f1a..47225dd2b1 100644
--- a/fpdfsdk/src/fpdfdoc.cpp
+++ b/fpdfsdk/src/fpdfdoc.cpp
@@ -9,11 +9,13 @@
#include "../include/fpdfxfa/fpdfxfa_doc.h"
#include "../include/fpdfxfa/fpdfxfa_page.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;
@@ -30,6 +32,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 || !pDict)
@@ -163,26 +185,35 @@ 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) {
+ CPDFXFA_Page* pXFAPage = (CPDFXFA_Page*)page;
+ CPDF_Page* pPage = pXFAPage->GetPDFPage();
+ if (!pPage)
+ return nullptr;
+
+ 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;
- CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
+DLLEXPORT int STDCALL
+FPDFLink_GetLinkZOrderAtPoint(FPDF_PAGE page, double x, double y) {
+ CPDFXFA_Page* pXFAPage = (CPDFXFA_Page*)page;
+ CPDF_Page* pPage = pXFAPage->GetPDFPage();
if (!pPage)
- return NULL;
- // 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();
+ return -1;
+
+ 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 abb8026a7f..51d90b7eab 100644
--- a/fpdfsdk/src/fpdfformfill.cpp
+++ b/fpdfsdk/src/fpdfformfill.cpp
@@ -37,32 +37,26 @@ 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 = ((CPDFXFA_Page*)page)->GetPDFPage();
if (pPage) {
- CPDF_InterForm* pInterForm = NULL;
- pInterForm = new CPDF_InterForm(pPage->m_pDocument, FALSE);
- if (!pInterForm)
+ 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;
- CPDF_FormControl* pFormCtrl = pInterForm->GetControlAtPoint(
- pPage, (FX_FLOAT)page_x, (FX_FLOAT)page_y);
- if (!pFormCtrl) {
- delete pInterForm;
- return -1;
- }
+
CPDF_FormField* pFormField = pFormCtrl->GetField();
- if (!pFormField) {
- delete pInterForm;
+ if (!pFormField)
return -1;
- }
int nType = pFormField->GetFieldType();
- delete pInterForm;
return nType;
}
@@ -109,6 +103,28 @@ DLLEXPORT int STDCALL FPDPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
return -1;
}
+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 f96aec40e3..01789b4432 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);
@@ -108,7 +109,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 9e3f0af6d1..ca16d26627 100644
--- a/public/fpdf_doc.h
+++ b/public/fpdf_doc.h
@@ -177,27 +177,52 @@ 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().
+//
// Notes:
-// The method can not support this feature for the document consists of
-// dynamic XFA fields.
+// The method can not support this feature for the document consists of
+// dynamic XFA fields.
//
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().
+//
+// Notes:
+// The method can not support this feature for the document consists of
+// dynamic XFA fields.
+//
+//
+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 73fe491435..7be678cd47 100644
--- a/public/fpdf_formfill.h
+++ b/public/fpdf_formfill.h
@@ -1311,17 +1311,26 @@ DLLEXPORT FPDF_BOOL STDCALL FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle);
#define FPDF_FORMFIELD_XFA 7 // 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,
@@ -1329,6 +1338,24 @@ DLLEXPORT int STDCALL FPDPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
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
*document.