blob: 47444ff7e314321162eb02f414a84a86d6e9953b [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
Dan Sinclaircbf76e62018-03-28 21:00:35 +00007#include "fpdfsdk/cpdfsdk_annotiterator.h"
jaepark611adb82016-08-17 11:34:36 -07008
Dan Sinclair85c8e7f2016-11-21 13:50:32 -05009#include <algorithm>
10
dsinclair41872fa2016-10-04 11:29:35 -070011#include "core/fpdfapi/page/cpdf_page.h"
Lei Zhang81535612018-10-09 21:15:17 +000012#include "core/fpdfapi/parser/cpdf_dictionary.h"
dsinclair114e46a2016-09-29 17:18:21 -070013#include "fpdfsdk/cpdfsdk_annot.h"
14#include "fpdfsdk/cpdfsdk_pageview.h"
Lei Zhanga39ead92020-04-22 01:52:36 +000015#include "third_party/base/stl_util.h"
jaepark611adb82016-08-17 11:34:36 -070016
dsinclair8afe15a2016-10-05 12:00:34 -070017namespace {
18
19CFX_FloatRect GetAnnotRect(const CPDFSDK_Annot* pAnnot) {
20 return pAnnot->GetPDFAnnot()->GetRect();
21}
22
23bool CompareByLeftAscending(const CPDFSDK_Annot* p1, const CPDFSDK_Annot* p2) {
jaepark611adb82016-08-17 11:34:36 -070024 return GetAnnotRect(p1).left < GetAnnotRect(p2).left;
25}
26
dsinclair8afe15a2016-10-05 12:00:34 -070027bool CompareByTopDescending(const CPDFSDK_Annot* p1, const CPDFSDK_Annot* p2) {
jaepark611adb82016-08-17 11:34:36 -070028 return GetAnnotRect(p1).top > GetAnnotRect(p2).top;
29}
30
dsinclair8afe15a2016-10-05 12:00:34 -070031} // namespace
32
Dan Sinclaircbf76e62018-03-28 21:00:35 +000033CPDFSDK_AnnotIterator::CPDFSDK_AnnotIterator(CPDFSDK_PageView* pPageView,
34 CPDF_Annot::Subtype nAnnotSubtype)
Neha Gupta1eb6ddd2020-03-19 08:37:15 +000035 : CPDFSDK_AnnotIterator(
36 pPageView,
37 std::vector<CPDF_Annot::Subtype>(1, nAnnotSubtype)) {}
38
39CPDFSDK_AnnotIterator::CPDFSDK_AnnotIterator(
40 CPDFSDK_PageView* pPageView,
41 const std::vector<CPDF_Annot::Subtype>& subtypes_to_iterate)
Lei Zhang7fb895f2018-10-09 19:02:24 +000042 : m_pPageView(pPageView),
Neha Gupta1eb6ddd2020-03-19 08:37:15 +000043 m_subtypes(subtypes_to_iterate),
Lei Zhang7fb895f2018-10-09 19:02:24 +000044 m_eTabOrder(GetTabOrder(pPageView)) {
jaepark611adb82016-08-17 11:34:36 -070045 GenerateResults();
46}
47
Lei Zhang81535612018-10-09 21:15:17 +000048CPDFSDK_AnnotIterator::~CPDFSDK_AnnotIterator() = default;
jaepark611adb82016-08-17 11:34:36 -070049
Dan Sinclaircbf76e62018-03-28 21:00:35 +000050CPDFSDK_Annot* CPDFSDK_AnnotIterator::GetFirstAnnot() {
jaepark611adb82016-08-17 11:34:36 -070051 return m_Annots.empty() ? nullptr : m_Annots.front();
52}
53
Dan Sinclaircbf76e62018-03-28 21:00:35 +000054CPDFSDK_Annot* CPDFSDK_AnnotIterator::GetLastAnnot() {
jaepark611adb82016-08-17 11:34:36 -070055 return m_Annots.empty() ? nullptr : m_Annots.back();
56}
57
Dan Sinclaircbf76e62018-03-28 21:00:35 +000058CPDFSDK_Annot* CPDFSDK_AnnotIterator::GetNextAnnot(CPDFSDK_Annot* pAnnot) {
jaepark611adb82016-08-17 11:34:36 -070059 auto iter = std::find(m_Annots.begin(), m_Annots.end(), pAnnot);
60 if (iter == m_Annots.end())
61 return nullptr;
62 ++iter;
63 if (iter == m_Annots.end())
Ankit Kumarafc869e2020-04-07 21:21:51 +000064 return nullptr;
jaepark611adb82016-08-17 11:34:36 -070065 return *iter;
66}
67
Dan Sinclaircbf76e62018-03-28 21:00:35 +000068CPDFSDK_Annot* CPDFSDK_AnnotIterator::GetPrevAnnot(CPDFSDK_Annot* pAnnot) {
jaepark611adb82016-08-17 11:34:36 -070069 auto iter = std::find(m_Annots.begin(), m_Annots.end(), pAnnot);
Ankit Kumarafc869e2020-04-07 21:21:51 +000070 if (iter == m_Annots.begin() || iter == m_Annots.end())
jaepark611adb82016-08-17 11:34:36 -070071 return nullptr;
jaepark611adb82016-08-17 11:34:36 -070072 return *(--iter);
73}
74
Tom Sepez00c19bf2021-04-05 17:38:15 +000075void CPDFSDK_AnnotIterator::CollectAnnots(
76 std::vector<UnownedPtr<CPDFSDK_Annot>>* pArray) {
Lei Zhang375c2762017-03-10 14:37:14 -080077 for (auto* pAnnot : m_pPageView->GetAnnotList()) {
Lei Zhangf245ae62020-05-15 21:49:46 +000078 if (pdfium::Contains(m_subtypes, pAnnot->GetAnnotSubtype()) &&
dsinclair8afe15a2016-10-05 12:00:34 -070079 !pAnnot->IsSignatureWidget()) {
Tom Sepez00c19bf2021-04-05 17:38:15 +000080 pArray->emplace_back(pAnnot);
dsinclair8afe15a2016-10-05 12:00:34 -070081 }
82 }
83}
84
Dan Sinclaircbf76e62018-03-28 21:00:35 +000085CFX_FloatRect CPDFSDK_AnnotIterator::AddToAnnotsList(
Tom Sepez00c19bf2021-04-05 17:38:15 +000086 std::vector<UnownedPtr<CPDFSDK_Annot>>* sa,
dsinclair8afe15a2016-10-05 12:00:34 -070087 size_t idx) {
88 CPDFSDK_Annot* pLeftTopAnnot = sa->at(idx);
89 CFX_FloatRect rcLeftTop = GetAnnotRect(pLeftTopAnnot);
Tom Sepez00c19bf2021-04-05 17:38:15 +000090 m_Annots.emplace_back(pLeftTopAnnot);
dsinclair8afe15a2016-10-05 12:00:34 -070091 sa->erase(sa->begin() + idx);
92 return rcLeftTop;
93}
94
Tom Sepez00c19bf2021-04-05 17:38:15 +000095void CPDFSDK_AnnotIterator::AddSelectedToAnnots(
96 std::vector<UnownedPtr<CPDFSDK_Annot>>* sa,
97 std::vector<size_t>* aSelect) {
dsinclair8afe15a2016-10-05 12:00:34 -070098 for (size_t i = 0; i < aSelect->size(); ++i)
Tom Sepez00c19bf2021-04-05 17:38:15 +000099 m_Annots.emplace_back(sa->at(aSelect->at(i)));
dsinclair8afe15a2016-10-05 12:00:34 -0700100
101 for (int i = aSelect->size() - 1; i >= 0; --i)
102 sa->erase(sa->begin() + aSelect->at(i));
103}
104
Lei Zhangb05abe42021-06-07 19:20:55 +0000105// static
106CPDFSDK_AnnotIterator::TabOrder CPDFSDK_AnnotIterator::GetTabOrder(
107 CPDFSDK_PageView* pPageView) {
108 CPDF_Page* pPDFPage = pPageView->GetPDFPage();
109 ByteString sTabs = pPDFPage->GetDict()->GetStringFor("Tabs");
110 if (sTabs == "R")
111 return kRow;
112 if (sTabs == "C")
113 return kColumn;
114 return kStructure;
115}
116
Dan Sinclaircbf76e62018-03-28 21:00:35 +0000117void CPDFSDK_AnnotIterator::GenerateResults() {
jaepark611adb82016-08-17 11:34:36 -0700118 switch (m_eTabOrder) {
Lei Zhangb05abe42021-06-07 19:20:55 +0000119 case kStructure:
dsinclair8afe15a2016-10-05 12:00:34 -0700120 CollectAnnots(&m_Annots);
jaepark611adb82016-08-17 11:34:36 -0700121 break;
dsinclair8afe15a2016-10-05 12:00:34 -0700122
Lei Zhangb05abe42021-06-07 19:20:55 +0000123 case kRow: {
Tom Sepez00c19bf2021-04-05 17:38:15 +0000124 std::vector<UnownedPtr<CPDFSDK_Annot>> sa;
dsinclair8afe15a2016-10-05 12:00:34 -0700125 CollectAnnots(&sa);
jaepark611adb82016-08-17 11:34:36 -0700126 std::sort(sa.begin(), sa.end(), CompareByLeftAscending);
dsinclair8afe15a2016-10-05 12:00:34 -0700127
jaepark611adb82016-08-17 11:34:36 -0700128 while (!sa.empty()) {
129 int nLeftTopIndex = -1;
Dan Sinclair05df0752017-03-14 14:43:42 -0400130 float fTop = 0.0f;
jaepark611adb82016-08-17 11:34:36 -0700131 for (int i = sa.size() - 1; i >= 0; i--) {
132 CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]);
133 if (rcAnnot.top > fTop) {
134 nLeftTopIndex = i;
135 fTop = rcAnnot.top;
136 }
137 }
dsinclair8afe15a2016-10-05 12:00:34 -0700138 if (nLeftTopIndex < 0)
139 continue;
jaepark611adb82016-08-17 11:34:36 -0700140
dsinclair8afe15a2016-10-05 12:00:34 -0700141 CFX_FloatRect rcLeftTop = AddToAnnotsList(&sa, nLeftTopIndex);
jaepark611adb82016-08-17 11:34:36 -0700142
dsinclair8afe15a2016-10-05 12:00:34 -0700143 std::vector<size_t> aSelect;
144 for (size_t i = 0; i < sa.size(); ++i) {
145 CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]);
Dan Sinclair05df0752017-03-14 14:43:42 -0400146 float fCenterY = (rcAnnot.top + rcAnnot.bottom) / 2.0f;
dsinclair8afe15a2016-10-05 12:00:34 -0700147 if (fCenterY > rcLeftTop.bottom && fCenterY < rcLeftTop.top)
148 aSelect.push_back(i);
jaepark611adb82016-08-17 11:34:36 -0700149 }
dsinclair8afe15a2016-10-05 12:00:34 -0700150 AddSelectedToAnnots(&sa, &aSelect);
jaepark611adb82016-08-17 11:34:36 -0700151 }
152 break;
153 }
dsinclair8afe15a2016-10-05 12:00:34 -0700154
Lei Zhangb05abe42021-06-07 19:20:55 +0000155 case kColumn: {
Tom Sepez00c19bf2021-04-05 17:38:15 +0000156 std::vector<UnownedPtr<CPDFSDK_Annot>> sa;
dsinclair8afe15a2016-10-05 12:00:34 -0700157 CollectAnnots(&sa);
jaepark611adb82016-08-17 11:34:36 -0700158 std::sort(sa.begin(), sa.end(), CompareByTopDescending);
dsinclair8afe15a2016-10-05 12:00:34 -0700159
jaepark611adb82016-08-17 11:34:36 -0700160 while (!sa.empty()) {
161 int nLeftTopIndex = -1;
Dan Sinclair05df0752017-03-14 14:43:42 -0400162 float fLeft = -1.0f;
jaepark611adb82016-08-17 11:34:36 -0700163 for (int i = sa.size() - 1; i >= 0; --i) {
164 CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]);
165 if (fLeft < 0) {
166 nLeftTopIndex = 0;
167 fLeft = rcAnnot.left;
168 } else if (rcAnnot.left < fLeft) {
169 nLeftTopIndex = i;
170 fLeft = rcAnnot.left;
171 }
172 }
dsinclair8afe15a2016-10-05 12:00:34 -0700173 if (nLeftTopIndex < 0)
174 continue;
jaepark611adb82016-08-17 11:34:36 -0700175
dsinclair8afe15a2016-10-05 12:00:34 -0700176 CFX_FloatRect rcLeftTop = AddToAnnotsList(&sa, nLeftTopIndex);
jaepark611adb82016-08-17 11:34:36 -0700177
dsinclair8afe15a2016-10-05 12:00:34 -0700178 std::vector<size_t> aSelect;
179 for (size_t i = 0; i < sa.size(); ++i) {
180 CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]);
Dan Sinclair05df0752017-03-14 14:43:42 -0400181 float fCenterX = (rcAnnot.left + rcAnnot.right) / 2.0f;
dsinclair8afe15a2016-10-05 12:00:34 -0700182 if (fCenterX > rcLeftTop.left && fCenterX < rcLeftTop.right)
183 aSelect.push_back(i);
jaepark611adb82016-08-17 11:34:36 -0700184 }
dsinclair8afe15a2016-10-05 12:00:34 -0700185 AddSelectedToAnnots(&sa, &aSelect);
jaepark611adb82016-08-17 11:34:36 -0700186 }
187 break;
188 }
189 }
190}