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