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 +++++------ 4 files changed, 100 insertions(+), 378 deletions(-) (limited to 'core') 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"); } -- cgit v1.2.3