blob: a447034cda3ae1aafd9894b5eb0dc99fb23aea0c [file] [log] [blame]
jaepark611adb82016-08-17 11:34:36 -07001// Copyright 2016 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
dsinclair114e46a2016-09-29 17:18:21 -07007#include "fpdfsdk/cba_annotiterator.h"
jaepark611adb82016-08-17 11:34:36 -07008
dsinclair41872fa2016-10-04 11:29:35 -07009#include "core/fpdfapi/page/cpdf_page.h"
dsinclair114e46a2016-09-29 17:18:21 -070010#include "fpdfsdk/cpdfsdk_annot.h"
11#include "fpdfsdk/cpdfsdk_pageview.h"
jaepark611adb82016-08-17 11:34:36 -070012
dsinclair8afe15a2016-10-05 12:00:34 -070013namespace {
14
15CFX_FloatRect GetAnnotRect(const CPDFSDK_Annot* pAnnot) {
16 return pAnnot->GetPDFAnnot()->GetRect();
17}
18
19bool CompareByLeftAscending(const CPDFSDK_Annot* p1, const CPDFSDK_Annot* p2) {
jaepark611adb82016-08-17 11:34:36 -070020 return GetAnnotRect(p1).left < GetAnnotRect(p2).left;
21}
22
dsinclair8afe15a2016-10-05 12:00:34 -070023bool CompareByTopDescending(const CPDFSDK_Annot* p1, const CPDFSDK_Annot* p2) {
jaepark611adb82016-08-17 11:34:36 -070024 return GetAnnotRect(p1).top > GetAnnotRect(p2).top;
25}
26
dsinclair8afe15a2016-10-05 12:00:34 -070027} // namespace
28
jaepark611adb82016-08-17 11:34:36 -070029CBA_AnnotIterator::CBA_AnnotIterator(CPDFSDK_PageView* pPageView,
jaepark956553e2016-08-31 06:49:27 -070030 CPDF_Annot::Subtype nAnnotSubtype)
jaepark611adb82016-08-17 11:34:36 -070031 : m_eTabOrder(STRUCTURE),
32 m_pPageView(pPageView),
jaepark956553e2016-08-31 06:49:27 -070033 m_nAnnotSubtype(nAnnotSubtype) {
jaepark611adb82016-08-17 11:34:36 -070034 CPDF_Page* pPDFPage = m_pPageView->GetPDFPage();
dsinclair38fd8442016-09-15 10:15:32 -070035 CFX_ByteString sTabs = pPDFPage->m_pFormDict->GetStringFor("Tabs");
jaepark611adb82016-08-17 11:34:36 -070036 if (sTabs == "R")
37 m_eTabOrder = ROW;
38 else if (sTabs == "C")
39 m_eTabOrder = COLUMN;
40
41 GenerateResults();
42}
43
44CBA_AnnotIterator::~CBA_AnnotIterator() {}
45
46CPDFSDK_Annot* CBA_AnnotIterator::GetFirstAnnot() {
47 return m_Annots.empty() ? nullptr : m_Annots.front();
48}
49
50CPDFSDK_Annot* CBA_AnnotIterator::GetLastAnnot() {
51 return m_Annots.empty() ? nullptr : m_Annots.back();
52}
53
54CPDFSDK_Annot* CBA_AnnotIterator::GetNextAnnot(CPDFSDK_Annot* pAnnot) {
55 auto iter = std::find(m_Annots.begin(), m_Annots.end(), pAnnot);
56 if (iter == m_Annots.end())
57 return nullptr;
58 ++iter;
59 if (iter == m_Annots.end())
60 iter = m_Annots.begin();
61 return *iter;
62}
63
64CPDFSDK_Annot* CBA_AnnotIterator::GetPrevAnnot(CPDFSDK_Annot* pAnnot) {
65 auto iter = std::find(m_Annots.begin(), m_Annots.end(), pAnnot);
66 if (iter == m_Annots.end())
67 return nullptr;
68 if (iter == m_Annots.begin())
69 iter = m_Annots.end();
70 return *(--iter);
71}
72
dsinclair8afe15a2016-10-05 12:00:34 -070073void CBA_AnnotIterator::CollectAnnots(std::vector<CPDFSDK_Annot*>* pArray) {
74 for (auto pAnnot : m_pPageView->GetAnnotList()) {
75 if (pAnnot->GetAnnotSubtype() == m_nAnnotSubtype &&
76 !pAnnot->IsSignatureWidget()) {
77 pArray->push_back(pAnnot);
78 }
79 }
80}
81
82CFX_FloatRect CBA_AnnotIterator::AddToAnnotsList(
83 std::vector<CPDFSDK_Annot*>* sa,
84 size_t idx) {
85 CPDFSDK_Annot* pLeftTopAnnot = sa->at(idx);
86 CFX_FloatRect rcLeftTop = GetAnnotRect(pLeftTopAnnot);
87 m_Annots.push_back(pLeftTopAnnot);
88 sa->erase(sa->begin() + idx);
89 return rcLeftTop;
90}
91
92void CBA_AnnotIterator::AddSelectedToAnnots(std::vector<CPDFSDK_Annot*>* sa,
93 std::vector<size_t>* aSelect) {
94 for (size_t i = 0; i < aSelect->size(); ++i)
95 m_Annots.push_back(sa->at(aSelect->at(i)));
96
97 for (int i = aSelect->size() - 1; i >= 0; --i)
98 sa->erase(sa->begin() + aSelect->at(i));
99}
100
jaepark611adb82016-08-17 11:34:36 -0700101void CBA_AnnotIterator::GenerateResults() {
102 switch (m_eTabOrder) {
dsinclair8afe15a2016-10-05 12:00:34 -0700103 case STRUCTURE:
104 CollectAnnots(&m_Annots);
jaepark611adb82016-08-17 11:34:36 -0700105 break;
dsinclair8afe15a2016-10-05 12:00:34 -0700106
jaepark611adb82016-08-17 11:34:36 -0700107 case ROW: {
108 std::vector<CPDFSDK_Annot*> sa;
dsinclair8afe15a2016-10-05 12:00:34 -0700109 CollectAnnots(&sa);
jaepark611adb82016-08-17 11:34:36 -0700110 std::sort(sa.begin(), sa.end(), CompareByLeftAscending);
dsinclair8afe15a2016-10-05 12:00:34 -0700111
jaepark611adb82016-08-17 11:34:36 -0700112 while (!sa.empty()) {
113 int nLeftTopIndex = -1;
114 FX_FLOAT fTop = 0.0f;
115 for (int i = sa.size() - 1; i >= 0; i--) {
116 CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]);
117 if (rcAnnot.top > fTop) {
118 nLeftTopIndex = i;
119 fTop = rcAnnot.top;
120 }
121 }
dsinclair8afe15a2016-10-05 12:00:34 -0700122 if (nLeftTopIndex < 0)
123 continue;
jaepark611adb82016-08-17 11:34:36 -0700124
dsinclair8afe15a2016-10-05 12:00:34 -0700125 CFX_FloatRect rcLeftTop = AddToAnnotsList(&sa, nLeftTopIndex);
jaepark611adb82016-08-17 11:34:36 -0700126
dsinclair8afe15a2016-10-05 12:00:34 -0700127 std::vector<size_t> aSelect;
128 for (size_t i = 0; i < sa.size(); ++i) {
129 CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]);
130 FX_FLOAT fCenterY = (rcAnnot.top + rcAnnot.bottom) / 2.0f;
131 if (fCenterY > rcLeftTop.bottom && fCenterY < rcLeftTop.top)
132 aSelect.push_back(i);
jaepark611adb82016-08-17 11:34:36 -0700133 }
dsinclair8afe15a2016-10-05 12:00:34 -0700134 AddSelectedToAnnots(&sa, &aSelect);
jaepark611adb82016-08-17 11:34:36 -0700135 }
136 break;
137 }
dsinclair8afe15a2016-10-05 12:00:34 -0700138
jaepark611adb82016-08-17 11:34:36 -0700139 case COLUMN: {
140 std::vector<CPDFSDK_Annot*> sa;
dsinclair8afe15a2016-10-05 12:00:34 -0700141 CollectAnnots(&sa);
jaepark611adb82016-08-17 11:34:36 -0700142 std::sort(sa.begin(), sa.end(), CompareByTopDescending);
dsinclair8afe15a2016-10-05 12:00:34 -0700143
jaepark611adb82016-08-17 11:34:36 -0700144 while (!sa.empty()) {
145 int nLeftTopIndex = -1;
146 FX_FLOAT fLeft = -1.0f;
147 for (int i = sa.size() - 1; i >= 0; --i) {
148 CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]);
149 if (fLeft < 0) {
150 nLeftTopIndex = 0;
151 fLeft = rcAnnot.left;
152 } else if (rcAnnot.left < fLeft) {
153 nLeftTopIndex = i;
154 fLeft = rcAnnot.left;
155 }
156 }
dsinclair8afe15a2016-10-05 12:00:34 -0700157 if (nLeftTopIndex < 0)
158 continue;
jaepark611adb82016-08-17 11:34:36 -0700159
dsinclair8afe15a2016-10-05 12:00:34 -0700160 CFX_FloatRect rcLeftTop = AddToAnnotsList(&sa, nLeftTopIndex);
jaepark611adb82016-08-17 11:34:36 -0700161
dsinclair8afe15a2016-10-05 12:00:34 -0700162 std::vector<size_t> aSelect;
163 for (size_t i = 0; i < sa.size(); ++i) {
164 CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]);
165 FX_FLOAT fCenterX = (rcAnnot.left + rcAnnot.right) / 2.0f;
166 if (fCenterX > rcLeftTop.left && fCenterX < rcLeftTop.right)
167 aSelect.push_back(i);
jaepark611adb82016-08-17 11:34:36 -0700168 }
dsinclair8afe15a2016-10-05 12:00:34 -0700169 AddSelectedToAnnots(&sa, &aSelect);
jaepark611adb82016-08-17 11:34:36 -0700170 }
171 break;
172 }
173 }
174}