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