• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 
7 #include "core/fpdfdoc/csection.h"
8 
9 #include <algorithm>
10 
11 #include "core/fpdfdoc/cline.h"
12 #include "core/fpdfdoc/cpdf_variabletext.h"
13 #include "core/fpdfdoc/cpvt_wordinfo.h"
14 #include "third_party/base/ptr_util.h"
15 #include "third_party/base/stl_util.h"
16 
CSection(CPDF_VariableText * pVT)17 CSection::CSection(CPDF_VariableText* pVT) : m_pVT(pVT) {
18   ASSERT(m_pVT);
19 }
20 
21 CSection::~CSection() = default;
22 
ResetLinePlace()23 void CSection::ResetLinePlace() {
24   int32_t i = 0;
25   for (auto& pLine : m_LineArray) {
26     pLine->LinePlace = CPVT_WordPlace(SecPlace.nSecIndex, i, -1);
27     ++i;
28   }
29 }
30 
AddWord(const CPVT_WordPlace & place,const CPVT_WordInfo & wordinfo)31 CPVT_WordPlace CSection::AddWord(const CPVT_WordPlace& place,
32                                  const CPVT_WordInfo& wordinfo) {
33   int32_t nWordIndex = pdfium::clamp(
34       place.nWordIndex, 0, pdfium::CollectionSize<int32_t>(m_WordArray));
35   m_WordArray.insert(m_WordArray.begin() + nWordIndex,
36                      pdfium::MakeUnique<CPVT_WordInfo>(wordinfo));
37   return place;
38 }
39 
AddLine(const CPVT_LineInfo & lineinfo)40 CPVT_WordPlace CSection::AddLine(const CPVT_LineInfo& lineinfo) {
41   m_LineArray.push_back(pdfium::MakeUnique<CLine>(lineinfo));
42   return CPVT_WordPlace(SecPlace.nSecIndex, m_LineArray.size() - 1, -1);
43 }
44 
Rearrange()45 CPVT_FloatRect CSection::Rearrange() {
46   if (m_pVT->GetCharArray() > 0)
47     return CTypeset(this).CharArray();
48   return CTypeset(this).Typeset();
49 }
50 
GetSectionSize(float fFontSize)51 CFX_SizeF CSection::GetSectionSize(float fFontSize) {
52   return CTypeset(this).GetEditSize(fFontSize);
53 }
54 
GetBeginWordPlace() const55 CPVT_WordPlace CSection::GetBeginWordPlace() const {
56   if (m_LineArray.empty())
57     return SecPlace;
58   return m_LineArray.front()->GetBeginWordPlace();
59 }
60 
GetEndWordPlace() const61 CPVT_WordPlace CSection::GetEndWordPlace() const {
62   if (m_LineArray.empty())
63     return SecPlace;
64   return m_LineArray.back()->GetEndWordPlace();
65 }
66 
GetPrevWordPlace(const CPVT_WordPlace & place) const67 CPVT_WordPlace CSection::GetPrevWordPlace(const CPVT_WordPlace& place) const {
68   if (place.nLineIndex < 0)
69     return GetBeginWordPlace();
70 
71   if (place.nLineIndex >= pdfium::CollectionSize<int32_t>(m_LineArray))
72     return GetEndWordPlace();
73 
74   CLine* pLine = m_LineArray[place.nLineIndex].get();
75   if (place.nWordIndex == pLine->m_LineInfo.nBeginWordIndex)
76     return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);
77 
78   if (place.nWordIndex >= pLine->m_LineInfo.nBeginWordIndex)
79     return pLine->GetPrevWordPlace(place);
80 
81   if (!pdfium::IndexInBounds(m_LineArray, place.nLineIndex - 1))
82     return place;
83 
84   return m_LineArray[place.nLineIndex - 1]->GetEndWordPlace();
85 }
86 
GetNextWordPlace(const CPVT_WordPlace & place) const87 CPVT_WordPlace CSection::GetNextWordPlace(const CPVT_WordPlace& place) const {
88   if (place.nLineIndex < 0)
89     return GetBeginWordPlace();
90 
91   if (place.nLineIndex >= pdfium::CollectionSize<int32_t>(m_LineArray))
92     return GetEndWordPlace();
93 
94   CLine* pLine = m_LineArray[place.nLineIndex].get();
95   if (place.nWordIndex < pLine->m_LineInfo.nEndWordIndex)
96     return pLine->GetNextWordPlace(place);
97 
98   if (!pdfium::IndexInBounds(m_LineArray, place.nLineIndex + 1))
99     return place;
100 
101   return m_LineArray[place.nLineIndex + 1]->GetBeginWordPlace();
102 }
103 
UpdateWordPlace(CPVT_WordPlace & place) const104 void CSection::UpdateWordPlace(CPVT_WordPlace& place) const {
105   int32_t nLeft = 0;
106   int32_t nRight = pdfium::CollectionSize<int32_t>(m_LineArray) - 1;
107   int32_t nMid = (nLeft + nRight) / 2;
108   while (nLeft <= nRight) {
109     CLine* pLine = m_LineArray[nMid].get();
110     if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) {
111       nRight = nMid - 1;
112       nMid = (nLeft + nRight) / 2;
113     } else if (place.nWordIndex > pLine->m_LineInfo.nEndWordIndex) {
114       nLeft = nMid + 1;
115       nMid = (nLeft + nRight) / 2;
116     } else {
117       place.nLineIndex = nMid;
118       return;
119     }
120   }
121 }
122 
SearchWordPlace(const CFX_PointF & point) const123 CPVT_WordPlace CSection::SearchWordPlace(const CFX_PointF& point) const {
124   CPVT_WordPlace place = GetBeginWordPlace();
125   bool bUp = true;
126   bool bDown = true;
127   int32_t nLeft = 0;
128   int32_t nRight = pdfium::CollectionSize<int32_t>(m_LineArray) - 1;
129   int32_t nMid = pdfium::CollectionSize<int32_t>(m_LineArray) / 2;
130   while (nLeft <= nRight) {
131     CLine* pLine = m_LineArray[nMid].get();
132     float fTop = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineAscent -
133                  m_pVT->GetLineLeading();
134     float fBottom = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineDescent;
135     if (IsFloatBigger(point.y, fTop))
136       bUp = false;
137     if (IsFloatSmaller(point.y, fBottom))
138       bDown = false;
139     if (IsFloatSmaller(point.y, fTop)) {
140       nRight = nMid - 1;
141       nMid = (nLeft + nRight) / 2;
142       continue;
143     }
144     if (IsFloatBigger(point.y, fBottom)) {
145       nLeft = nMid + 1;
146       nMid = (nLeft + nRight) / 2;
147       continue;
148     }
149     place = SearchWordPlace(
150         point.x,
151         CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()),
152                        pLine->GetEndWordPlace()));
153     place.nLineIndex = nMid;
154     return place;
155   }
156   if (bUp)
157     place = GetBeginWordPlace();
158   if (bDown)
159     place = GetEndWordPlace();
160   return place;
161 }
162 
SearchWordPlace(float fx,const CPVT_WordPlace & lineplace) const163 CPVT_WordPlace CSection::SearchWordPlace(
164     float fx,
165     const CPVT_WordPlace& lineplace) const {
166   if (!pdfium::IndexInBounds(m_LineArray, lineplace.nLineIndex))
167     return GetBeginWordPlace();
168 
169   CLine* pLine = m_LineArray[lineplace.nLineIndex].get();
170   return SearchWordPlace(
171       fx - m_Rect.left,
172       CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()),
173                      pLine->GetEndWordPlace()));
174 }
175 
SearchWordPlace(float fx,const CPVT_WordRange & range) const176 CPVT_WordPlace CSection::SearchWordPlace(float fx,
177                                          const CPVT_WordRange& range) const {
178   CPVT_WordPlace wordplace = range.BeginPos;
179   wordplace.nWordIndex = -1;
180 
181   int32_t nLeft = range.BeginPos.nWordIndex;
182   int32_t nRight = range.EndPos.nWordIndex + 1;
183   int32_t nMid = (nLeft + nRight) / 2;
184   while (nLeft < nRight) {
185     if (nMid == nLeft)
186       break;
187     if (nMid == nRight) {
188       nMid--;
189       break;
190     }
191     if (!pdfium::IndexInBounds(m_WordArray, nMid))
192       break;
193     CPVT_WordInfo* pWord = m_WordArray[nMid].get();
194     if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * VARIABLETEXT_HALF) {
195       nLeft = nMid;
196       nMid = (nLeft + nRight) / 2;
197       continue;
198     }
199     nRight = nMid;
200     nMid = (nLeft + nRight) / 2;
201   }
202   if (pdfium::IndexInBounds(m_WordArray, nMid)) {
203     CPVT_WordInfo* pWord = m_WordArray[nMid].get();
204     if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * VARIABLETEXT_HALF)
205       wordplace.nWordIndex = nMid;
206   }
207   return wordplace;
208 }
209 
ClearLeftWords(int32_t nWordIndex)210 void CSection::ClearLeftWords(int32_t nWordIndex) {
211   for (int32_t i = nWordIndex; i >= 0; i--) {
212     if (pdfium::IndexInBounds(m_WordArray, i))
213       m_WordArray.erase(m_WordArray.begin() + i);
214   }
215 }
216 
ClearRightWords(int32_t nWordIndex)217 void CSection::ClearRightWords(int32_t nWordIndex) {
218   int32_t sz = pdfium::CollectionSize<int32_t>(m_WordArray);
219   for (int32_t i = sz - 1; i > nWordIndex; i--) {
220     if (pdfium::IndexInBounds(m_WordArray, i))
221       m_WordArray.erase(m_WordArray.begin() + i);
222   }
223 }
224 
ClearMidWords(int32_t nBeginIndex,int32_t nEndIndex)225 void CSection::ClearMidWords(int32_t nBeginIndex, int32_t nEndIndex) {
226   for (int32_t i = nEndIndex; i > nBeginIndex; i--) {
227     if (pdfium::IndexInBounds(m_WordArray, i))
228       m_WordArray.erase(m_WordArray.begin() + i);
229   }
230 }
231 
ClearWords(const CPVT_WordRange & PlaceRange)232 void CSection::ClearWords(const CPVT_WordRange& PlaceRange) {
233   CPVT_WordPlace SecBeginPos = GetBeginWordPlace();
234   CPVT_WordPlace SecEndPos = GetEndWordPlace();
235   if (PlaceRange.BeginPos >= SecBeginPos) {
236     if (PlaceRange.EndPos <= SecEndPos) {
237       ClearMidWords(PlaceRange.BeginPos.nWordIndex,
238                     PlaceRange.EndPos.nWordIndex);
239     } else {
240       ClearRightWords(PlaceRange.BeginPos.nWordIndex);
241     }
242   } else if (PlaceRange.EndPos <= SecEndPos) {
243     ClearLeftWords(PlaceRange.EndPos.nWordIndex);
244   } else {
245     m_WordArray.clear();
246   }
247 }
248 
ClearWord(const CPVT_WordPlace & place)249 void CSection::ClearWord(const CPVT_WordPlace& place) {
250   if (pdfium::IndexInBounds(m_WordArray, place.nWordIndex))
251     m_WordArray.erase(m_WordArray.begin() + place.nWordIndex);
252 }
253