• 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/cpvt_wordinfo.h"
13 
CSection(CPDF_VariableText * pVT)14 CSection::CSection(CPDF_VariableText* pVT) : m_pVT(pVT) {}
15 
~CSection()16 CSection::~CSection() {
17   ResetAll();
18 }
19 
ResetAll()20 void CSection::ResetAll() {
21   ResetWordArray();
22   ResetLineArray();
23 }
24 
ResetLineArray()25 void CSection::ResetLineArray() {
26   m_LineArray.RemoveAll();
27 }
28 
ResetWordArray()29 void CSection::ResetWordArray() {
30   for (int32_t i = 0, sz = m_WordArray.GetSize(); i < sz; i++) {
31     delete m_WordArray.GetAt(i);
32   }
33   m_WordArray.RemoveAll();
34 }
35 
ResetLinePlace()36 void CSection::ResetLinePlace() {
37   for (int32_t i = 0, sz = m_LineArray.GetSize(); i < sz; i++) {
38     if (CLine* pLine = m_LineArray.GetAt(i)) {
39       pLine->LinePlace = CPVT_WordPlace(SecPlace.nSecIndex, i, -1);
40     }
41   }
42 }
43 
AddWord(const CPVT_WordPlace & place,const CPVT_WordInfo & wordinfo)44 CPVT_WordPlace CSection::AddWord(const CPVT_WordPlace& place,
45                                  const CPVT_WordInfo& wordinfo) {
46   CPVT_WordInfo* pWord = new CPVT_WordInfo(wordinfo);
47   int32_t nWordIndex =
48       std::max(std::min(place.nWordIndex, m_WordArray.GetSize()), 0);
49   if (nWordIndex == m_WordArray.GetSize()) {
50     m_WordArray.Add(pWord);
51   } else {
52     m_WordArray.InsertAt(nWordIndex, pWord);
53   }
54   return place;
55 }
56 
AddLine(const CPVT_LineInfo & lineinfo)57 CPVT_WordPlace CSection::AddLine(const CPVT_LineInfo& lineinfo) {
58   return CPVT_WordPlace(SecPlace.nSecIndex, m_LineArray.Add(lineinfo), -1);
59 }
60 
Rearrange()61 CPVT_FloatRect CSection::Rearrange() {
62   if (m_pVT->m_nCharArray > 0) {
63     return CTypeset(this).CharArray();
64   }
65   return CTypeset(this).Typeset();
66 }
67 
GetSectionSize(FX_FLOAT fFontSize)68 CFX_SizeF CSection::GetSectionSize(FX_FLOAT fFontSize) {
69   return CTypeset(this).GetEditSize(fFontSize);
70 }
71 
GetBeginWordPlace() const72 CPVT_WordPlace CSection::GetBeginWordPlace() const {
73   if (CLine* pLine = m_LineArray.GetAt(0)) {
74     return pLine->GetBeginWordPlace();
75   }
76   return SecPlace;
77 }
78 
GetEndWordPlace() const79 CPVT_WordPlace CSection::GetEndWordPlace() const {
80   if (CLine* pLine = m_LineArray.GetAt(m_LineArray.GetSize() - 1)) {
81     return pLine->GetEndWordPlace();
82   }
83   return SecPlace;
84 }
85 
GetPrevWordPlace(const CPVT_WordPlace & place) const86 CPVT_WordPlace CSection::GetPrevWordPlace(const CPVT_WordPlace& place) const {
87   if (place.nLineIndex < 0) {
88     return GetBeginWordPlace();
89   }
90   if (place.nLineIndex >= m_LineArray.GetSize()) {
91     return GetEndWordPlace();
92   }
93   if (CLine* pLine = m_LineArray.GetAt(place.nLineIndex)) {
94     if (place.nWordIndex == pLine->m_LineInfo.nBeginWordIndex) {
95       return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);
96     }
97     if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) {
98       if (CLine* pPrevLine = m_LineArray.GetAt(place.nLineIndex - 1)) {
99         return pPrevLine->GetEndWordPlace();
100       }
101     } else {
102       return pLine->GetPrevWordPlace(place);
103     }
104   }
105   return place;
106 }
107 
GetNextWordPlace(const CPVT_WordPlace & place) const108 CPVT_WordPlace CSection::GetNextWordPlace(const CPVT_WordPlace& place) const {
109   if (place.nLineIndex < 0) {
110     return GetBeginWordPlace();
111   }
112   if (place.nLineIndex >= m_LineArray.GetSize()) {
113     return GetEndWordPlace();
114   }
115   if (CLine* pLine = m_LineArray.GetAt(place.nLineIndex)) {
116     if (place.nWordIndex >= pLine->m_LineInfo.nEndWordIndex) {
117       if (CLine* pNextLine = m_LineArray.GetAt(place.nLineIndex + 1)) {
118         return pNextLine->GetBeginWordPlace();
119       }
120     } else {
121       return pLine->GetNextWordPlace(place);
122     }
123   }
124   return place;
125 }
126 
UpdateWordPlace(CPVT_WordPlace & place) const127 void CSection::UpdateWordPlace(CPVT_WordPlace& place) const {
128   int32_t nLeft = 0;
129   int32_t nRight = m_LineArray.GetSize() - 1;
130   int32_t nMid = (nLeft + nRight) / 2;
131   while (nLeft <= nRight) {
132     if (CLine* pLine = m_LineArray.GetAt(nMid)) {
133       if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) {
134         nRight = nMid - 1;
135         nMid = (nLeft + nRight) / 2;
136       } else if (place.nWordIndex > pLine->m_LineInfo.nEndWordIndex) {
137         nLeft = nMid + 1;
138         nMid = (nLeft + nRight) / 2;
139       } else {
140         place.nLineIndex = nMid;
141         return;
142       }
143     } else {
144       break;
145     }
146   }
147 }
148 
SearchWordPlace(const CFX_PointF & point) const149 CPVT_WordPlace CSection::SearchWordPlace(const CFX_PointF& point) const {
150   ASSERT(m_pVT);
151   CPVT_WordPlace place = GetBeginWordPlace();
152   bool bUp = true;
153   bool bDown = true;
154   int32_t nLeft = 0;
155   int32_t nRight = m_LineArray.GetSize() - 1;
156   int32_t nMid = m_LineArray.GetSize() / 2;
157   FX_FLOAT fTop = 0;
158   FX_FLOAT fBottom = 0;
159   while (nLeft <= nRight) {
160     if (CLine* pLine = m_LineArray.GetAt(nMid)) {
161       fTop = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineAscent -
162              m_pVT->GetLineLeading(m_SecInfo);
163       fBottom = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineDescent;
164       if (IsFloatBigger(point.y, fTop)) {
165         bUp = false;
166       }
167       if (IsFloatSmaller(point.y, fBottom)) {
168         bDown = false;
169       }
170       if (IsFloatSmaller(point.y, fTop)) {
171         nRight = nMid - 1;
172         nMid = (nLeft + nRight) / 2;
173         continue;
174       } else if (IsFloatBigger(point.y, fBottom)) {
175         nLeft = nMid + 1;
176         nMid = (nLeft + nRight) / 2;
177         continue;
178       } else {
179         place = SearchWordPlace(
180             point.x,
181             CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()),
182                            pLine->GetEndWordPlace()));
183         place.nLineIndex = nMid;
184         return place;
185       }
186     }
187   }
188   if (bUp) {
189     place = GetBeginWordPlace();
190   }
191   if (bDown) {
192     place = GetEndWordPlace();
193   }
194   return place;
195 }
196 
SearchWordPlace(FX_FLOAT fx,const CPVT_WordPlace & lineplace) const197 CPVT_WordPlace CSection::SearchWordPlace(
198     FX_FLOAT fx,
199     const CPVT_WordPlace& lineplace) const {
200   if (CLine* pLine = m_LineArray.GetAt(lineplace.nLineIndex)) {
201     return SearchWordPlace(
202         fx - m_SecInfo.rcSection.left,
203         CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()),
204                        pLine->GetEndWordPlace()));
205   }
206   return GetBeginWordPlace();
207 }
208 
SearchWordPlace(FX_FLOAT fx,const CPVT_WordRange & range) const209 CPVT_WordPlace CSection::SearchWordPlace(FX_FLOAT fx,
210                                          const CPVT_WordRange& range) const {
211   CPVT_WordPlace wordplace = range.BeginPos;
212   wordplace.nWordIndex = -1;
213   if (!m_pVT) {
214     return wordplace;
215   }
216   int32_t nLeft = range.BeginPos.nWordIndex;
217   int32_t nRight = range.EndPos.nWordIndex + 1;
218   int32_t nMid = (nLeft + nRight) / 2;
219   while (nLeft < nRight) {
220     if (nMid == nLeft) {
221       break;
222     }
223     if (nMid == nRight) {
224       nMid--;
225       break;
226     }
227     if (CPVT_WordInfo* pWord = m_WordArray.GetAt(nMid)) {
228       if (fx >
229           pWord->fWordX + m_pVT->GetWordWidth(*pWord) * VARIABLETEXT_HALF) {
230         nLeft = nMid;
231         nMid = (nLeft + nRight) / 2;
232         continue;
233       } else {
234         nRight = nMid;
235         nMid = (nLeft + nRight) / 2;
236         continue;
237       }
238     } else {
239       break;
240     }
241   }
242   if (CPVT_WordInfo* pWord = m_WordArray.GetAt(nMid)) {
243     if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * VARIABLETEXT_HALF) {
244       wordplace.nWordIndex = nMid;
245     }
246   }
247   return wordplace;
248 }
249 
ClearLeftWords(int32_t nWordIndex)250 void CSection::ClearLeftWords(int32_t nWordIndex) {
251   for (int32_t i = nWordIndex; i >= 0; i--) {
252     delete m_WordArray.GetAt(i);
253     m_WordArray.RemoveAt(i);
254   }
255 }
256 
ClearRightWords(int32_t nWordIndex)257 void CSection::ClearRightWords(int32_t nWordIndex) {
258   for (int32_t i = m_WordArray.GetSize() - 1; i > nWordIndex; i--) {
259     delete m_WordArray.GetAt(i);
260     m_WordArray.RemoveAt(i);
261   }
262 }
263 
ClearMidWords(int32_t nBeginIndex,int32_t nEndIndex)264 void CSection::ClearMidWords(int32_t nBeginIndex, int32_t nEndIndex) {
265   for (int32_t i = nEndIndex; i > nBeginIndex; i--) {
266     delete m_WordArray.GetAt(i);
267     m_WordArray.RemoveAt(i);
268   }
269 }
270 
ClearWords(const CPVT_WordRange & PlaceRange)271 void CSection::ClearWords(const CPVT_WordRange& PlaceRange) {
272   CPVT_WordPlace SecBeginPos = GetBeginWordPlace();
273   CPVT_WordPlace SecEndPos = GetEndWordPlace();
274   if (PlaceRange.BeginPos.WordCmp(SecBeginPos) >= 0) {
275     if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) {
276       ClearMidWords(PlaceRange.BeginPos.nWordIndex,
277                     PlaceRange.EndPos.nWordIndex);
278     } else {
279       ClearRightWords(PlaceRange.BeginPos.nWordIndex);
280     }
281   } else if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) {
282     ClearLeftWords(PlaceRange.EndPos.nWordIndex);
283   } else {
284     ResetWordArray();
285   }
286 }
287 
ClearWord(const CPVT_WordPlace & place)288 void CSection::ClearWord(const CPVT_WordPlace& place) {
289   delete m_WordArray.GetAt(place.nWordIndex);
290   m_WordArray.RemoveAt(place.nWordIndex);
291 }
292