1 // Copyright 2014 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 <algorithm>
8
9 #include "core/include/fpdfdoc/fpdf_doc.h"
10 #include "core/include/fpdfdoc/fpdf_vt.h"
11 #include "pdf_vt.h"
12
13 const uint8_t gFontSizeSteps[] = {4, 6, 8, 9, 10, 12, 14, 18, 20,
14 25, 30, 35, 40, 45, 50, 55, 60, 70,
15 80, 90, 100, 110, 120, 130, 144};
16 #define PVT_RETURN_LENGTH 1
17 #define PVT_DEFAULT_FONTSIZE 18.0f
18 #define PVTWORD_SCRIPT_NORMAL 0
19 #define PVTWORD_SCRIPT_SUPER 1
20 #define PVTWORD_SCRIPT_SUB 2
21 #define PVT_FONTSCALE 0.001f
22 #define PVT_PERCENT 0.01f
23 #define PVT_HALF 0.5f
CLine()24 CLine::CLine() {}
~CLine()25 CLine::~CLine() {}
GetBeginWordPlace() const26 CPVT_WordPlace CLine::GetBeginWordPlace() const {
27 return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex, -1);
28 }
GetEndWordPlace() const29 CPVT_WordPlace CLine::GetEndWordPlace() const {
30 return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex,
31 m_LineInfo.nEndWordIndex);
32 }
GetPrevWordPlace(const CPVT_WordPlace & place) const33 CPVT_WordPlace CLine::GetPrevWordPlace(const CPVT_WordPlace& place) const {
34 if (place.nWordIndex > m_LineInfo.nEndWordIndex) {
35 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex,
36 m_LineInfo.nEndWordIndex);
37 }
38 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex,
39 place.nWordIndex - 1);
40 }
GetNextWordPlace(const CPVT_WordPlace & place) const41 CPVT_WordPlace CLine::GetNextWordPlace(const CPVT_WordPlace& place) const {
42 if (place.nWordIndex < m_LineInfo.nBeginWordIndex) {
43 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex,
44 m_LineInfo.nBeginWordIndex);
45 }
46 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex,
47 place.nWordIndex + 1);
48 }
CSection(CPDF_VariableText * pVT)49 CSection::CSection(CPDF_VariableText* pVT) : m_pVT(pVT) {}
~CSection()50 CSection::~CSection() {
51 ResetAll();
52 }
ResetAll()53 void CSection::ResetAll() {
54 ResetWordArray();
55 ResetLineArray();
56 }
ResetLineArray()57 void CSection::ResetLineArray() {
58 m_LineArray.RemoveAll();
59 }
ResetWordArray()60 void CSection::ResetWordArray() {
61 for (int32_t i = 0, sz = m_WordArray.GetSize(); i < sz; i++) {
62 delete m_WordArray.GetAt(i);
63 }
64 m_WordArray.RemoveAll();
65 }
ResetLinePlace()66 void CSection::ResetLinePlace() {
67 for (int32_t i = 0, sz = m_LineArray.GetSize(); i < sz; i++) {
68 if (CLine* pLine = m_LineArray.GetAt(i)) {
69 pLine->LinePlace = CPVT_WordPlace(SecPlace.nSecIndex, i, -1);
70 }
71 }
72 }
AddWord(const CPVT_WordPlace & place,const CPVT_WordInfo & wordinfo)73 CPVT_WordPlace CSection::AddWord(const CPVT_WordPlace& place,
74 const CPVT_WordInfo& wordinfo) {
75 CPVT_WordInfo* pWord = new CPVT_WordInfo(wordinfo);
76 int32_t nWordIndex =
77 std::max(std::min(place.nWordIndex, m_WordArray.GetSize()), 0);
78 if (nWordIndex == m_WordArray.GetSize()) {
79 m_WordArray.Add(pWord);
80 } else {
81 m_WordArray.InsertAt(nWordIndex, pWord);
82 }
83 return place;
84 }
AddLine(const CPVT_LineInfo & lineinfo)85 CPVT_WordPlace CSection::AddLine(const CPVT_LineInfo& lineinfo) {
86 return CPVT_WordPlace(SecPlace.nSecIndex, m_LineArray.Add(lineinfo), -1);
87 }
Rearrange()88 CPVT_FloatRect CSection::Rearrange() {
89 if (m_pVT->m_nCharArray > 0) {
90 return CTypeset(this).CharArray();
91 }
92 return CTypeset(this).Typeset();
93 }
GetSectionSize(FX_FLOAT fFontSize)94 CPVT_Size CSection::GetSectionSize(FX_FLOAT fFontSize) {
95 return CTypeset(this).GetEditSize(fFontSize);
96 }
GetBeginWordPlace() const97 CPVT_WordPlace CSection::GetBeginWordPlace() const {
98 if (CLine* pLine = m_LineArray.GetAt(0)) {
99 return pLine->GetBeginWordPlace();
100 }
101 return SecPlace;
102 }
GetEndWordPlace() const103 CPVT_WordPlace CSection::GetEndWordPlace() const {
104 if (CLine* pLine = m_LineArray.GetAt(m_LineArray.GetSize() - 1)) {
105 return pLine->GetEndWordPlace();
106 }
107 return SecPlace;
108 }
GetPrevWordPlace(const CPVT_WordPlace & place) const109 CPVT_WordPlace CSection::GetPrevWordPlace(const CPVT_WordPlace& place) const {
110 if (place.nLineIndex < 0) {
111 return GetBeginWordPlace();
112 }
113 if (place.nLineIndex >= m_LineArray.GetSize()) {
114 return GetEndWordPlace();
115 }
116 if (CLine* pLine = m_LineArray.GetAt(place.nLineIndex)) {
117 if (place.nWordIndex == pLine->m_LineInfo.nBeginWordIndex) {
118 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);
119 }
120 if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) {
121 if (CLine* pPrevLine = m_LineArray.GetAt(place.nLineIndex - 1)) {
122 return pPrevLine->GetEndWordPlace();
123 }
124 } else {
125 return pLine->GetPrevWordPlace(place);
126 }
127 }
128 return place;
129 }
GetNextWordPlace(const CPVT_WordPlace & place) const130 CPVT_WordPlace CSection::GetNextWordPlace(const CPVT_WordPlace& place) const {
131 if (place.nLineIndex < 0) {
132 return GetBeginWordPlace();
133 }
134 if (place.nLineIndex >= m_LineArray.GetSize()) {
135 return GetEndWordPlace();
136 }
137 if (CLine* pLine = m_LineArray.GetAt(place.nLineIndex)) {
138 if (place.nWordIndex >= pLine->m_LineInfo.nEndWordIndex) {
139 if (CLine* pNextLine = m_LineArray.GetAt(place.nLineIndex + 1)) {
140 return pNextLine->GetBeginWordPlace();
141 }
142 } else {
143 return pLine->GetNextWordPlace(place);
144 }
145 }
146 return place;
147 }
UpdateWordPlace(CPVT_WordPlace & place) const148 void CSection::UpdateWordPlace(CPVT_WordPlace& place) const {
149 int32_t nLeft = 0;
150 int32_t nRight = m_LineArray.GetSize() - 1;
151 int32_t nMid = (nLeft + nRight) / 2;
152 while (nLeft <= nRight) {
153 if (CLine* pLine = m_LineArray.GetAt(nMid)) {
154 if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) {
155 nRight = nMid - 1;
156 nMid = (nLeft + nRight) / 2;
157 } else if (place.nWordIndex > pLine->m_LineInfo.nEndWordIndex) {
158 nLeft = nMid + 1;
159 nMid = (nLeft + nRight) / 2;
160 } else {
161 place.nLineIndex = nMid;
162 return;
163 }
164 } else {
165 break;
166 }
167 }
168 }
SearchWordPlace(const CPDF_Point & point) const169 CPVT_WordPlace CSection::SearchWordPlace(const CPDF_Point& point) const {
170 ASSERT(m_pVT);
171 CPVT_WordPlace place = GetBeginWordPlace();
172 FX_BOOL bUp = TRUE;
173 FX_BOOL bDown = TRUE;
174 int32_t nLeft = 0;
175 int32_t nRight = m_LineArray.GetSize() - 1;
176 int32_t nMid = m_LineArray.GetSize() / 2;
177 FX_FLOAT fTop = 0;
178 FX_FLOAT fBottom = 0;
179 while (nLeft <= nRight) {
180 if (CLine* pLine = m_LineArray.GetAt(nMid)) {
181 fTop = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineAscent -
182 m_pVT->GetLineLeading(m_SecInfo);
183 fBottom = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineDescent;
184 if (IsFloatBigger(point.y, fTop)) {
185 bUp = FALSE;
186 }
187 if (IsFloatSmaller(point.y, fBottom)) {
188 bDown = FALSE;
189 }
190 if (IsFloatSmaller(point.y, fTop)) {
191 nRight = nMid - 1;
192 nMid = (nLeft + nRight) / 2;
193 continue;
194 } else if (IsFloatBigger(point.y, fBottom)) {
195 nLeft = nMid + 1;
196 nMid = (nLeft + nRight) / 2;
197 continue;
198 } else {
199 place = SearchWordPlace(
200 point.x,
201 CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()),
202 pLine->GetEndWordPlace()));
203 place.nLineIndex = nMid;
204 return place;
205 }
206 }
207 }
208 if (bUp) {
209 place = GetBeginWordPlace();
210 }
211 if (bDown) {
212 place = GetEndWordPlace();
213 }
214 return place;
215 }
SearchWordPlace(FX_FLOAT fx,const CPVT_WordPlace & lineplace) const216 CPVT_WordPlace CSection::SearchWordPlace(
217 FX_FLOAT fx,
218 const CPVT_WordPlace& lineplace) const {
219 if (CLine* pLine = m_LineArray.GetAt(lineplace.nLineIndex)) {
220 return SearchWordPlace(
221 fx - m_SecInfo.rcSection.left,
222 CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()),
223 pLine->GetEndWordPlace()));
224 }
225 return GetBeginWordPlace();
226 }
SearchWordPlace(FX_FLOAT fx,const CPVT_WordRange & range) const227 CPVT_WordPlace CSection::SearchWordPlace(FX_FLOAT fx,
228 const CPVT_WordRange& range) const {
229 CPVT_WordPlace wordplace = range.BeginPos;
230 wordplace.nWordIndex = -1;
231 if (!m_pVT) {
232 return wordplace;
233 }
234 int32_t nLeft = range.BeginPos.nWordIndex;
235 int32_t nRight = range.EndPos.nWordIndex + 1;
236 int32_t nMid = (nLeft + nRight) / 2;
237 while (nLeft < nRight) {
238 if (nMid == nLeft) {
239 break;
240 }
241 if (nMid == nRight) {
242 nMid--;
243 break;
244 }
245 if (CPVT_WordInfo* pWord = m_WordArray.GetAt(nMid)) {
246 if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * PVT_HALF) {
247 nLeft = nMid;
248 nMid = (nLeft + nRight) / 2;
249 continue;
250 } else {
251 nRight = nMid;
252 nMid = (nLeft + nRight) / 2;
253 continue;
254 }
255 } else {
256 break;
257 }
258 }
259 if (CPVT_WordInfo* pWord = m_WordArray.GetAt(nMid)) {
260 if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * PVT_HALF) {
261 wordplace.nWordIndex = nMid;
262 }
263 }
264 return wordplace;
265 }
ClearLeftWords(int32_t nWordIndex)266 void CSection::ClearLeftWords(int32_t nWordIndex) {
267 for (int32_t i = nWordIndex; i >= 0; i--) {
268 delete m_WordArray.GetAt(i);
269 m_WordArray.RemoveAt(i);
270 }
271 }
ClearRightWords(int32_t nWordIndex)272 void CSection::ClearRightWords(int32_t nWordIndex) {
273 for (int32_t i = m_WordArray.GetSize() - 1; i > nWordIndex; i--) {
274 delete m_WordArray.GetAt(i);
275 m_WordArray.RemoveAt(i);
276 }
277 }
ClearMidWords(int32_t nBeginIndex,int32_t nEndIndex)278 void CSection::ClearMidWords(int32_t nBeginIndex, int32_t nEndIndex) {
279 for (int32_t i = nEndIndex; i > nBeginIndex; i--) {
280 delete m_WordArray.GetAt(i);
281 m_WordArray.RemoveAt(i);
282 }
283 }
ClearWords(const CPVT_WordRange & PlaceRange)284 void CSection::ClearWords(const CPVT_WordRange& PlaceRange) {
285 CPVT_WordPlace SecBeginPos = GetBeginWordPlace();
286 CPVT_WordPlace SecEndPos = GetEndWordPlace();
287 if (PlaceRange.BeginPos.WordCmp(SecBeginPos) >= 0) {
288 if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) {
289 ClearMidWords(PlaceRange.BeginPos.nWordIndex,
290 PlaceRange.EndPos.nWordIndex);
291 } else {
292 ClearRightWords(PlaceRange.BeginPos.nWordIndex);
293 }
294 } else if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) {
295 ClearLeftWords(PlaceRange.EndPos.nWordIndex);
296 } else {
297 ResetWordArray();
298 }
299 }
ClearWord(const CPVT_WordPlace & place)300 void CSection::ClearWord(const CPVT_WordPlace& place) {
301 delete m_WordArray.GetAt(place.nWordIndex);
302 m_WordArray.RemoveAt(place.nWordIndex);
303 }
CTypeset(CSection * pSection)304 CTypeset::CTypeset(CSection* pSection)
305 : m_rcRet(0.0f, 0.0f, 0.0f, 0.0f),
306 m_pVT(pSection->m_pVT),
307 m_pSection(pSection) {}
~CTypeset()308 CTypeset::~CTypeset() {}
CharArray()309 CPVT_FloatRect CTypeset::CharArray() {
310 ASSERT(m_pSection);
311 FX_FLOAT fLineAscent =
312 m_pVT->GetFontAscent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize());
313 FX_FLOAT fLineDescent =
314 m_pVT->GetFontDescent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize());
315 m_rcRet.Default();
316 FX_FLOAT x = 0.0f, y = 0.0f;
317 FX_FLOAT fNextWidth;
318 int32_t nStart = 0;
319 FX_FLOAT fNodeWidth = m_pVT->GetPlateWidth() /
320 (m_pVT->m_nCharArray <= 0 ? 1 : m_pVT->m_nCharArray);
321 if (CLine* pLine = m_pSection->m_LineArray.GetAt(0)) {
322 x = 0.0f;
323 y += m_pVT->GetLineLeading(m_pSection->m_SecInfo);
324 y += fLineAscent;
325 nStart = 0;
326 switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {
327 case 0:
328 pLine->m_LineInfo.fLineX = fNodeWidth * PVT_HALF;
329 break;
330 case 1:
331 nStart = (m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize()) / 2;
332 pLine->m_LineInfo.fLineX = fNodeWidth * nStart - fNodeWidth * PVT_HALF;
333 break;
334 case 2:
335 nStart = m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize();
336 pLine->m_LineInfo.fLineX = fNodeWidth * nStart - fNodeWidth * PVT_HALF;
337 break;
338 }
339 for (int32_t w = 0, sz = m_pSection->m_WordArray.GetSize(); w < sz; w++) {
340 if (w >= m_pVT->m_nCharArray) {
341 break;
342 }
343 fNextWidth = 0;
344 if (CPVT_WordInfo* pNextWord =
345 (CPVT_WordInfo*)m_pSection->m_WordArray.GetAt(w + 1)) {
346 pNextWord->fWordTail = 0;
347 fNextWidth = m_pVT->GetWordWidth(*pNextWord);
348 }
349 if (CPVT_WordInfo* pWord =
350 (CPVT_WordInfo*)m_pSection->m_WordArray.GetAt(w)) {
351 pWord->fWordTail = 0;
352 FX_FLOAT fWordWidth = m_pVT->GetWordWidth(*pWord);
353 FX_FLOAT fWordAscent = m_pVT->GetWordAscent(*pWord);
354 FX_FLOAT fWordDescent = m_pVT->GetWordDescent(*pWord);
355 x = (FX_FLOAT)(fNodeWidth * (w + nStart + 0.5) - fWordWidth * PVT_HALF);
356 pWord->fWordX = x;
357 pWord->fWordY = y;
358 if (w == 0) {
359 pLine->m_LineInfo.fLineX = x;
360 }
361 if (w != m_pSection->m_WordArray.GetSize() - 1) {
362 pWord->fWordTail =
363 (fNodeWidth - (fWordWidth + fNextWidth) * PVT_HALF > 0
364 ? fNodeWidth - (fWordWidth + fNextWidth) * PVT_HALF
365 : 0);
366 } else {
367 pWord->fWordTail = 0;
368 }
369 x += fWordWidth;
370 fLineAscent = std::max(fLineAscent, fWordAscent);
371 fLineDescent = std::min(fLineDescent, fWordDescent);
372 }
373 }
374 pLine->m_LineInfo.nBeginWordIndex = 0;
375 pLine->m_LineInfo.nEndWordIndex = m_pSection->m_WordArray.GetSize() - 1;
376 pLine->m_LineInfo.fLineY = y;
377 pLine->m_LineInfo.fLineWidth = x - pLine->m_LineInfo.fLineX;
378 pLine->m_LineInfo.fLineAscent = fLineAscent;
379 pLine->m_LineInfo.fLineDescent = fLineDescent;
380 y += (-fLineDescent);
381 }
382 return m_rcRet = CPVT_FloatRect(0, 0, x, y);
383 }
GetEditSize(FX_FLOAT fFontSize)384 CPVT_Size CTypeset::GetEditSize(FX_FLOAT fFontSize) {
385 ASSERT(m_pSection);
386 ASSERT(m_pVT);
387 SplitLines(FALSE, fFontSize);
388 return CPVT_Size(m_rcRet.Width(), m_rcRet.Height());
389 }
Typeset()390 CPVT_FloatRect CTypeset::Typeset() {
391 ASSERT(m_pVT);
392 m_pSection->m_LineArray.Empty();
393 SplitLines(TRUE, 0.0f);
394 m_pSection->m_LineArray.Clear();
395 OutputLines();
396 return m_rcRet;
397 }
398 static int special_chars[128] = {
399 0x0000, 0x000C, 0x0008, 0x000C, 0x0008, 0x0000, 0x0020, 0x0000, 0x0000,
400 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
401 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
402 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0000,
403 0x0010, 0x0000, 0x0000, 0x0028, 0x000C, 0x0008, 0x0000, 0x0000, 0x0028,
404 0x0028, 0x0028, 0x0028, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
405 0x0002, 0x0002, 0x0002, 0x0002, 0x0008, 0x0008, 0x0000, 0x0000, 0x0000,
406 0x0008, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
407 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
408 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
409 0x0001, 0x000C, 0x0000, 0x0008, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001,
410 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
411 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
412 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x000C, 0x0000, 0x0008,
413 0x0000, 0x0000,
414 };
IsLatin(FX_WORD word)415 static FX_BOOL IsLatin(FX_WORD word) {
416 if (word <= 0x007F) {
417 if (special_chars[word] & 0x0001) {
418 return TRUE;
419 }
420 }
421 if ((word >= 0x00C0 && word <= 0x00FF) ||
422 (word >= 0x0100 && word <= 0x024F) ||
423 (word >= 0x1E00 && word <= 0x1EFF) ||
424 (word >= 0x2C60 && word <= 0x2C7F) ||
425 (word >= 0xA720 && word <= 0xA7FF) ||
426 (word >= 0xFF21 && word <= 0xFF3A) ||
427 (word >= 0xFF41 && word <= 0xFF5A)) {
428 return TRUE;
429 }
430 return FALSE;
431 }
IsDigit(FX_DWORD word)432 static FX_BOOL IsDigit(FX_DWORD word) {
433 return word >= 0x0030 && word <= 0x0039;
434 }
IsCJK(FX_DWORD word)435 static FX_BOOL IsCJK(FX_DWORD word) {
436 if ((word >= 0x1100 && word <= 0x11FF) ||
437 (word >= 0x2E80 && word <= 0x2FFF) ||
438 (word >= 0x3040 && word <= 0x9FBF) ||
439 (word >= 0xAC00 && word <= 0xD7AF) ||
440 (word >= 0xF900 && word <= 0xFAFF) ||
441 (word >= 0xFE30 && word <= 0xFE4F) ||
442 (word >= 0x20000 && word <= 0x2A6DF) ||
443 (word >= 0x2F800 && word <= 0x2FA1F)) {
444 return TRUE;
445 }
446 if (word >= 0x3000 && word <= 0x303F) {
447 if (word == 0x3005 || word == 0x3006 || word == 0x3021 || word == 0x3022 ||
448 word == 0x3023 || word == 0x3024 || word == 0x3025 || word == 0x3026 ||
449 word == 0x3027 || word == 0x3028 || word == 0x3029 || word == 0x3031 ||
450 word == 0x3032 || word == 0x3033 || word == 0x3034 || word == 0x3035) {
451 return TRUE;
452 }
453 return FALSE;
454 }
455 if (word >= 0xFF66 && word <= 0xFF9D) {
456 return TRUE;
457 }
458 return FALSE;
459 }
IsPunctuation(FX_DWORD word)460 static FX_BOOL IsPunctuation(FX_DWORD word) {
461 if (word <= 0x007F) {
462 if ((special_chars[word] >> 3) & 1) {
463 return TRUE;
464 }
465 } else if (word >= 0x0080 && word <= 0x00FF) {
466 if (word == 0x0082 || word == 0x0084 || word == 0x0085 || word == 0x0091 ||
467 word == 0x0092 || word == 0x0093 || word <= 0x0094 || word == 0x0096 ||
468 word == 0x00B4 || word == 0x00B8) {
469 return TRUE;
470 }
471 } else if (word >= 0x2000 && word <= 0x206F) {
472 if (word == 0x2010 || word == 0x2011 || word == 0x2012 || word == 0x2013 ||
473 word == 0x2018 || word == 0x2019 || word == 0x201A || word == 0x201B ||
474 word == 0x201C || word == 0x201D || word == 0x201E || word == 0x201F ||
475 word == 0x2032 || word == 0x2033 || word == 0x2034 || word == 0x2035 ||
476 word == 0x2036 || word == 0x2037 || word == 0x203C || word == 0x203D ||
477 word == 0x203E || word == 0x2044) {
478 return TRUE;
479 }
480 } else if (word >= 0x3000 && word <= 0x303F) {
481 if (word == 0x3001 || word == 0x3002 || word == 0x3003 || word == 0x3005 ||
482 word == 0x3009 || word == 0x300A || word == 0x300B || word == 0x300C ||
483 word == 0x300D || word == 0x300F || word == 0x300E || word == 0x3010 ||
484 word == 0x3011 || word == 0x3014 || word == 0x3015 || word == 0x3016 ||
485 word == 0x3017 || word == 0x3018 || word == 0x3019 || word == 0x301A ||
486 word == 0x301B || word == 0x301D || word == 0x301E || word == 0x301F) {
487 return TRUE;
488 }
489 } else if (word >= 0xFE50 && word <= 0xFE6F) {
490 if ((word >= 0xFE50 && word <= 0xFE5E) || word == 0xFE63) {
491 return TRUE;
492 }
493 } else if (word >= 0xFF00 && word <= 0xFFEF) {
494 if (word == 0xFF01 || word == 0xFF02 || word == 0xFF07 || word == 0xFF08 ||
495 word == 0xFF09 || word == 0xFF0C || word == 0xFF0E || word == 0xFF0F ||
496 word == 0xFF1A || word == 0xFF1B || word == 0xFF1F || word == 0xFF3B ||
497 word == 0xFF3D || word == 0xFF40 || word == 0xFF5B || word == 0xFF5C ||
498 word == 0xFF5D || word == 0xFF61 || word == 0xFF62 || word == 0xFF63 ||
499 word == 0xFF64 || word == 0xFF65 || word == 0xFF9E || word == 0xFF9F) {
500 return TRUE;
501 }
502 }
503 return FALSE;
504 }
IsConnectiveSymbol(FX_DWORD word)505 static FX_BOOL IsConnectiveSymbol(FX_DWORD word) {
506 if (word <= 0x007F) {
507 if ((special_chars[word] >> 5) & 1) {
508 return TRUE;
509 }
510 }
511 return FALSE;
512 }
IsOpenStylePunctuation(FX_DWORD word)513 static FX_BOOL IsOpenStylePunctuation(FX_DWORD word) {
514 if (word <= 0x007F) {
515 if ((special_chars[word] >> 2) & 1) {
516 return TRUE;
517 }
518 } else if (word == 0x300A || word == 0x300C || word == 0x300E ||
519 word == 0x3010 || word == 0x3014 || word == 0x3016 ||
520 word == 0x3018 || word == 0x301A || word == 0xFF08 ||
521 word == 0xFF3B || word == 0xFF5B || word == 0xFF62) {
522 return TRUE;
523 }
524 return FALSE;
525 }
IsCurrencySymbol(FX_WORD word)526 static FX_BOOL IsCurrencySymbol(FX_WORD word) {
527 if (word == 0x0024 || word == 0x0080 || word == 0x00A2 || word == 0x00A3 ||
528 word == 0x00A4 || word == 0x00A5 || (word >= 0x20A0 && word <= 0x20CF) ||
529 word == 0xFE69 || word == 0xFF04 || word == 0xFFE0 || word == 0xFFE1 ||
530 word == 0xFFE5 || word == 0xFFE6) {
531 return TRUE;
532 }
533 return FALSE;
534 }
IsPrefixSymbol(FX_WORD word)535 static FX_BOOL IsPrefixSymbol(FX_WORD word) {
536 if (IsCurrencySymbol(word)) {
537 return TRUE;
538 }
539 if (word == 0x2116) {
540 return TRUE;
541 }
542 return FALSE;
543 }
IsSpace(FX_WORD word)544 static FX_BOOL IsSpace(FX_WORD word) {
545 return word == 0x0020 || word == 0x3000;
546 }
NeedDivision(FX_WORD prevWord,FX_WORD curWord)547 static FX_BOOL NeedDivision(FX_WORD prevWord, FX_WORD curWord) {
548 if ((IsLatin(prevWord) || IsDigit(prevWord)) &&
549 (IsLatin(curWord) || IsDigit(curWord))) {
550 return FALSE;
551 }
552 if (IsSpace(curWord) || IsPunctuation(curWord)) {
553 return FALSE;
554 }
555 if (IsConnectiveSymbol(prevWord) || IsConnectiveSymbol(curWord)) {
556 return FALSE;
557 }
558 if (IsSpace(prevWord) || IsPunctuation(prevWord)) {
559 return TRUE;
560 }
561 if (IsPrefixSymbol(prevWord)) {
562 return FALSE;
563 }
564 if (IsPrefixSymbol(curWord) || IsCJK(curWord)) {
565 return TRUE;
566 }
567 if (IsCJK(prevWord)) {
568 return TRUE;
569 }
570 return FALSE;
571 }
SplitLines(FX_BOOL bTypeset,FX_FLOAT fFontSize)572 void CTypeset::SplitLines(FX_BOOL bTypeset, FX_FLOAT fFontSize) {
573 ASSERT(m_pVT);
574 ASSERT(m_pSection);
575 int32_t nLineHead = 0;
576 int32_t nLineTail = 0;
577 FX_FLOAT fMaxX = 0.0f, fMaxY = 0.0f;
578 FX_FLOAT fLineWidth = 0.0f, fBackupLineWidth = 0.0f;
579 FX_FLOAT fLineAscent = 0.0f, fBackupLineAscent = 0.0f;
580 FX_FLOAT fLineDescent = 0.0f, fBackupLineDescent = 0.0f;
581 int32_t nWordStartPos = 0;
582 FX_BOOL bFullWord = FALSE;
583 int32_t nLineFullWordIndex = 0;
584 int32_t nCharIndex = 0;
585 CPVT_LineInfo line;
586 FX_FLOAT fWordWidth = 0;
587 FX_FLOAT fTypesetWidth = std::max(
588 m_pVT->GetPlateWidth() - m_pVT->GetLineIndent(m_pSection->m_SecInfo),
589 0.0f);
590 int32_t nTotalWords = m_pSection->m_WordArray.GetSize();
591 FX_BOOL bOpened = FALSE;
592 if (nTotalWords > 0) {
593 int32_t i = 0;
594 while (i < nTotalWords) {
595 CPVT_WordInfo* pWord = m_pSection->m_WordArray.GetAt(i);
596 CPVT_WordInfo* pOldWord = pWord;
597 if (i > 0) {
598 pOldWord = m_pSection->m_WordArray.GetAt(i - 1);
599 }
600 if (pWord) {
601 if (bTypeset) {
602 fLineAscent =
603 std::max(fLineAscent, m_pVT->GetWordAscent(*pWord, TRUE));
604 fLineDescent =
605 std::min(fLineDescent, m_pVT->GetWordDescent(*pWord, TRUE));
606 fWordWidth = m_pVT->GetWordWidth(*pWord);
607 } else {
608 fLineAscent =
609 std::max(fLineAscent, m_pVT->GetWordAscent(*pWord, fFontSize));
610 fLineDescent =
611 std::min(fLineDescent, m_pVT->GetWordDescent(*pWord, fFontSize));
612 fWordWidth = m_pVT->GetWordWidth(
613 pWord->nFontIndex, pWord->Word, m_pVT->m_wSubWord,
614 m_pVT->m_fCharSpace, m_pVT->m_nHorzScale, fFontSize,
615 pWord->fWordTail, 0);
616 }
617 if (!bOpened) {
618 if (IsOpenStylePunctuation(pWord->Word)) {
619 bOpened = TRUE;
620 bFullWord = TRUE;
621 } else if (pOldWord) {
622 if (NeedDivision(pOldWord->Word, pWord->Word)) {
623 bFullWord = TRUE;
624 }
625 }
626 } else {
627 if (!IsSpace(pWord->Word) && !IsOpenStylePunctuation(pWord->Word)) {
628 bOpened = FALSE;
629 }
630 }
631 if (bFullWord) {
632 bFullWord = FALSE;
633 if (nCharIndex > 0) {
634 nLineFullWordIndex++;
635 }
636 nWordStartPos = i;
637 fBackupLineWidth = fLineWidth;
638 fBackupLineAscent = fLineAscent;
639 fBackupLineDescent = fLineDescent;
640 }
641 nCharIndex++;
642 }
643 if (m_pVT->m_bLimitWidth && fTypesetWidth > 0 &&
644 fLineWidth + fWordWidth > fTypesetWidth) {
645 if (nLineFullWordIndex > 0) {
646 i = nWordStartPos;
647 fLineWidth = fBackupLineWidth;
648 fLineAscent = fBackupLineAscent;
649 fLineDescent = fBackupLineDescent;
650 }
651 if (nCharIndex == 1) {
652 fLineWidth = fWordWidth;
653 i++;
654 }
655 nLineTail = i - 1;
656 if (bTypeset) {
657 line.nBeginWordIndex = nLineHead;
658 line.nEndWordIndex = nLineTail;
659 line.nTotalWord = nLineTail - nLineHead + 1;
660 line.fLineWidth = fLineWidth;
661 line.fLineAscent = fLineAscent;
662 line.fLineDescent = fLineDescent;
663 m_pSection->AddLine(line);
664 }
665 fMaxY += (fLineAscent + m_pVT->GetLineLeading(m_pSection->m_SecInfo));
666 fMaxY += (-fLineDescent);
667 fMaxX = std::max(fLineWidth, fMaxX);
668 nLineHead = i;
669 fLineWidth = 0.0f;
670 fLineAscent = 0.0f;
671 fLineDescent = 0.0f;
672 nCharIndex = 0;
673 nLineFullWordIndex = 0;
674 bFullWord = FALSE;
675 } else {
676 fLineWidth += fWordWidth;
677 i++;
678 }
679 }
680 if (nLineHead <= nTotalWords - 1) {
681 nLineTail = nTotalWords - 1;
682 if (bTypeset) {
683 line.nBeginWordIndex = nLineHead;
684 line.nEndWordIndex = nLineTail;
685 line.nTotalWord = nLineTail - nLineHead + 1;
686 line.fLineWidth = fLineWidth;
687 line.fLineAscent = fLineAscent;
688 line.fLineDescent = fLineDescent;
689 m_pSection->AddLine(line);
690 }
691 fMaxY += (fLineAscent + m_pVT->GetLineLeading(m_pSection->m_SecInfo));
692 fMaxY += (-fLineDescent);
693 fMaxX = std::max(fLineWidth, fMaxX);
694 }
695 } else {
696 if (bTypeset) {
697 fLineAscent = m_pVT->GetLineAscent(m_pSection->m_SecInfo);
698 fLineDescent = m_pVT->GetLineDescent(m_pSection->m_SecInfo);
699 } else {
700 fLineAscent =
701 m_pVT->GetFontAscent(m_pVT->GetDefaultFontIndex(), fFontSize);
702 fLineDescent =
703 m_pVT->GetFontDescent(m_pVT->GetDefaultFontIndex(), fFontSize);
704 }
705 if (bTypeset) {
706 line.nBeginWordIndex = -1;
707 line.nEndWordIndex = -1;
708 line.nTotalWord = 0;
709 line.fLineWidth = 0;
710 line.fLineAscent = fLineAscent;
711 line.fLineDescent = fLineDescent;
712 m_pSection->AddLine(line);
713 }
714 fMaxY += (m_pVT->GetLineLeading(m_pSection->m_SecInfo) + fLineAscent +
715 (-fLineDescent));
716 }
717 m_rcRet = CPVT_FloatRect(0, 0, fMaxX, fMaxY);
718 }
OutputLines()719 void CTypeset::OutputLines() {
720 ASSERT(m_pVT);
721 ASSERT(m_pSection);
722 FX_FLOAT fMinX = 0.0f, fMinY = 0.0f, fMaxX = 0.0f, fMaxY = 0.0f;
723 FX_FLOAT fPosX = 0.0f, fPosY = 0.0f;
724 FX_FLOAT fLineIndent = m_pVT->GetLineIndent(m_pSection->m_SecInfo);
725 FX_FLOAT fTypesetWidth = std::max(m_pVT->GetPlateWidth() - fLineIndent, 0.0f);
726 switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {
727 default:
728 case 0:
729 fMinX = 0.0f;
730 break;
731 case 1:
732 fMinX = (fTypesetWidth - m_rcRet.Width()) * PVT_HALF;
733 break;
734 case 2:
735 fMinX = fTypesetWidth - m_rcRet.Width();
736 break;
737 }
738 fMaxX = fMinX + m_rcRet.Width();
739 fMinY = 0.0f;
740 fMaxY = m_rcRet.Height();
741 int32_t nTotalLines = m_pSection->m_LineArray.GetSize();
742 if (nTotalLines > 0) {
743 m_pSection->m_SecInfo.nTotalLine = nTotalLines;
744 for (int32_t l = 0; l < nTotalLines; l++) {
745 if (CLine* pLine = m_pSection->m_LineArray.GetAt(l)) {
746 switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {
747 default:
748 case 0:
749 fPosX = 0;
750 break;
751 case 1:
752 fPosX = (fTypesetWidth - pLine->m_LineInfo.fLineWidth) * PVT_HALF;
753 break;
754 case 2:
755 fPosX = fTypesetWidth - pLine->m_LineInfo.fLineWidth;
756 break;
757 }
758 fPosX += fLineIndent;
759 fPosY += m_pVT->GetLineLeading(m_pSection->m_SecInfo);
760 fPosY += pLine->m_LineInfo.fLineAscent;
761 pLine->m_LineInfo.fLineX = fPosX - fMinX;
762 pLine->m_LineInfo.fLineY = fPosY - fMinY;
763 for (int32_t w = pLine->m_LineInfo.nBeginWordIndex;
764 w <= pLine->m_LineInfo.nEndWordIndex; w++) {
765 if (CPVT_WordInfo* pWord = m_pSection->m_WordArray.GetAt(w)) {
766 pWord->fWordX = fPosX - fMinX;
767 if (pWord->pWordProps) {
768 switch (pWord->pWordProps->nScriptType) {
769 default:
770 case PVTWORD_SCRIPT_NORMAL:
771 pWord->fWordY = fPosY - fMinY;
772 break;
773 case PVTWORD_SCRIPT_SUPER:
774 pWord->fWordY = fPosY - m_pVT->GetWordAscent(*pWord) - fMinY;
775 break;
776 case PVTWORD_SCRIPT_SUB:
777 pWord->fWordY = fPosY - m_pVT->GetWordDescent(*pWord) - fMinY;
778 break;
779 }
780 } else {
781 pWord->fWordY = fPosY - fMinY;
782 }
783 fPosX += m_pVT->GetWordWidth(*pWord);
784 }
785 }
786 fPosY += (-pLine->m_LineInfo.fLineDescent);
787 }
788 }
789 }
790 m_rcRet = CPVT_FloatRect(fMinX, fMinY, fMaxX, fMaxY);
791 }
CPDF_VariableText()792 CPDF_VariableText::CPDF_VariableText()
793 : m_nLimitChar(0),
794 m_nCharArray(0),
795 m_bMultiLine(FALSE),
796 m_bLimitWidth(FALSE),
797 m_bAutoFontSize(FALSE),
798 m_nAlignment(0),
799 m_fLineLeading(0.0f),
800 m_fCharSpace(0.0f),
801 m_nHorzScale(100),
802 m_wSubWord(0),
803 m_fFontSize(0.0f),
804 m_bInitial(FALSE),
805 m_bRichText(FALSE),
806 m_pVTProvider(NULL),
807 m_pVTIterator(NULL) {}
~CPDF_VariableText()808 CPDF_VariableText::~CPDF_VariableText() {
809 delete m_pVTIterator;
810 m_pVTIterator = NULL;
811 ResetAll();
812 }
Initialize()813 void CPDF_VariableText::Initialize() {
814 if (!m_bInitial) {
815 CPVT_SectionInfo secinfo;
816 if (m_bRichText) {
817 secinfo.pSecProps = new CPVT_SecProps(0.0f, 0.0f, 0);
818 secinfo.pWordProps = new CPVT_WordProps(GetDefaultFontIndex(),
819 PVT_DEFAULT_FONTSIZE, 0, 0, 0);
820 }
821 CPVT_WordPlace place;
822 place.nSecIndex = 0;
823 AddSection(place, secinfo);
824 CPVT_LineInfo lineinfo;
825 lineinfo.fLineAscent = GetFontAscent(GetDefaultFontIndex(), GetFontSize());
826 lineinfo.fLineDescent =
827 GetFontDescent(GetDefaultFontIndex(), GetFontSize());
828 AddLine(place, lineinfo);
829 if (CSection* pSection = m_SectionArray.GetAt(0)) {
830 pSection->ResetLinePlace();
831 }
832 m_bInitial = TRUE;
833 }
834 }
ResetAll()835 void CPDF_VariableText::ResetAll() {
836 m_bInitial = FALSE;
837 ResetSectionArray();
838 }
InsertWord(const CPVT_WordPlace & place,FX_WORD word,int32_t charset,const CPVT_WordProps * pWordProps)839 CPVT_WordPlace CPDF_VariableText::InsertWord(const CPVT_WordPlace& place,
840 FX_WORD word,
841 int32_t charset,
842 const CPVT_WordProps* pWordProps) {
843 int32_t nTotlaWords = GetTotalWords();
844 if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar) {
845 return place;
846 }
847 if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray) {
848 return place;
849 }
850 CPVT_WordPlace newplace = place;
851 newplace.nWordIndex++;
852 if (m_bRichText) {
853 CPVT_WordProps* pNewProps =
854 pWordProps ? new CPVT_WordProps(*pWordProps) : new CPVT_WordProps();
855 pNewProps->nFontIndex =
856 GetWordFontIndex(word, charset, pWordProps->nFontIndex);
857 return AddWord(newplace, CPVT_WordInfo(word, charset, -1, pNewProps));
858 }
859 int32_t nFontIndex =
860 GetSubWord() > 0 ? GetDefaultFontIndex()
861 : GetWordFontIndex(word, charset, GetDefaultFontIndex());
862 return AddWord(newplace, CPVT_WordInfo(word, charset, nFontIndex, NULL));
863 }
InsertSection(const CPVT_WordPlace & place,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps)864 CPVT_WordPlace CPDF_VariableText::InsertSection(
865 const CPVT_WordPlace& place,
866 const CPVT_SecProps* pSecProps,
867 const CPVT_WordProps* pWordProps) {
868 int32_t nTotlaWords = GetTotalWords();
869 if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar) {
870 return place;
871 }
872 if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray) {
873 return place;
874 }
875 if (!m_bMultiLine) {
876 return place;
877 }
878 CPVT_WordPlace wordplace = place;
879 UpdateWordPlace(wordplace);
880 CPVT_WordPlace newplace = place;
881 if (CSection* pSection = m_SectionArray.GetAt(wordplace.nSecIndex)) {
882 CPVT_WordPlace NewPlace(wordplace.nSecIndex + 1, 0, -1);
883 CPVT_SectionInfo secinfo;
884 if (m_bRichText) {
885 if (pSecProps) {
886 secinfo.pSecProps = new CPVT_SecProps(*pSecProps);
887 }
888 if (pWordProps) {
889 secinfo.pWordProps = new CPVT_WordProps(*pWordProps);
890 }
891 }
892 AddSection(NewPlace, secinfo);
893 newplace = NewPlace;
894 if (CSection* pNewSection = m_SectionArray.GetAt(NewPlace.nSecIndex)) {
895 for (int32_t w = wordplace.nWordIndex + 1,
896 sz = pSection->m_WordArray.GetSize();
897 w < sz; w++) {
898 if (CPVT_WordInfo* pWord = pSection->m_WordArray.GetAt(w)) {
899 NewPlace.nWordIndex++;
900 pNewSection->AddWord(NewPlace, *pWord);
901 }
902 }
903 }
904 ClearSectionRightWords(wordplace);
905 }
906 return newplace;
907 }
InsertText(const CPVT_WordPlace & place,const FX_WCHAR * text,int32_t charset,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pProps)908 CPVT_WordPlace CPDF_VariableText::InsertText(const CPVT_WordPlace& place,
909 const FX_WCHAR* text,
910 int32_t charset,
911 const CPVT_SecProps* pSecProps,
912 const CPVT_WordProps* pProps) {
913 CFX_WideString swText = text;
914 CPVT_WordPlace wp = place;
915 for (int32_t i = 0, sz = swText.GetLength(); i < sz; i++) {
916 CPVT_WordPlace oldwp = wp;
917 FX_WORD word = swText.GetAt(i);
918 switch (word) {
919 case 0x0D:
920 if (m_bMultiLine) {
921 if (swText.GetAt(i + 1) == 0x0A) {
922 i += 1;
923 }
924 wp = InsertSection(wp, pSecProps, pProps);
925 }
926 break;
927 case 0x0A:
928 if (m_bMultiLine) {
929 if (swText.GetAt(i + 1) == 0x0D) {
930 i += 1;
931 }
932 wp = InsertSection(wp, pSecProps, pProps);
933 }
934 break;
935 case 0x09:
936 word = 0x20;
937 default:
938 wp = InsertWord(wp, word, charset, pProps);
939 break;
940 }
941 if (wp == oldwp) {
942 break;
943 }
944 }
945 return wp;
946 }
DeleteWords(const CPVT_WordRange & PlaceRange)947 CPVT_WordPlace CPDF_VariableText::DeleteWords(
948 const CPVT_WordRange& PlaceRange) {
949 FX_BOOL bLastSecPos = FALSE;
950 if (CSection* pSection = m_SectionArray.GetAt(PlaceRange.EndPos.nSecIndex)) {
951 bLastSecPos = (PlaceRange.EndPos == pSection->GetEndWordPlace());
952 }
953 ClearWords(PlaceRange);
954 if (PlaceRange.BeginPos.nSecIndex != PlaceRange.EndPos.nSecIndex) {
955 ClearEmptySections(PlaceRange);
956 if (!bLastSecPos) {
957 LinkLatterSection(PlaceRange.BeginPos);
958 }
959 }
960 return PlaceRange.BeginPos;
961 }
DeleteWord(const CPVT_WordPlace & place)962 CPVT_WordPlace CPDF_VariableText::DeleteWord(const CPVT_WordPlace& place) {
963 return ClearRightWord(AdjustLineHeader(place, TRUE));
964 }
BackSpaceWord(const CPVT_WordPlace & place)965 CPVT_WordPlace CPDF_VariableText::BackSpaceWord(const CPVT_WordPlace& place) {
966 return ClearLeftWord(AdjustLineHeader(place, TRUE));
967 }
SetText(const FX_WCHAR * text,int32_t charset,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps)968 void CPDF_VariableText::SetText(const FX_WCHAR* text,
969 int32_t charset,
970 const CPVT_SecProps* pSecProps,
971 const CPVT_WordProps* pWordProps) {
972 DeleteWords(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
973 CFX_WideString swText = text;
974 CPVT_WordPlace wp(0, 0, -1);
975 CPVT_SectionInfo secinfo;
976 if (m_bRichText) {
977 if (pSecProps) {
978 secinfo.pSecProps = new CPVT_SecProps(*pSecProps);
979 }
980 if (pWordProps) {
981 secinfo.pWordProps = new CPVT_WordProps(*pWordProps);
982 }
983 }
984 if (CSection* pSection = m_SectionArray.GetAt(0)) {
985 pSection->m_SecInfo = secinfo;
986 }
987 int32_t nCharCount = 0;
988 for (int32_t i = 0, sz = swText.GetLength(); i < sz; i++) {
989 if (m_nLimitChar > 0 && nCharCount >= m_nLimitChar) {
990 break;
991 }
992 if (m_nCharArray > 0 && nCharCount >= m_nCharArray) {
993 break;
994 }
995 FX_WORD word = swText.GetAt(i);
996 switch (word) {
997 case 0x0D:
998 if (m_bMultiLine) {
999 if (swText.GetAt(i + 1) == 0x0A) {
1000 i += 1;
1001 }
1002 wp.nSecIndex++;
1003 wp.nLineIndex = 0;
1004 wp.nWordIndex = -1;
1005 AddSection(wp, secinfo);
1006 }
1007 break;
1008 case 0x0A:
1009 if (m_bMultiLine) {
1010 if (swText.GetAt(i + 1) == 0x0D) {
1011 i += 1;
1012 }
1013 wp.nSecIndex++;
1014 wp.nLineIndex = 0;
1015 wp.nWordIndex = -1;
1016 AddSection(wp, secinfo);
1017 }
1018 break;
1019 case 0x09:
1020 word = 0x20;
1021 default:
1022 wp = InsertWord(wp, word, charset, pWordProps);
1023 break;
1024 }
1025 nCharCount++;
1026 }
1027 }
UpdateWordPlace(CPVT_WordPlace & place) const1028 void CPDF_VariableText::UpdateWordPlace(CPVT_WordPlace& place) const {
1029 if (place.nSecIndex < 0) {
1030 place = GetBeginWordPlace();
1031 }
1032 if (place.nSecIndex >= m_SectionArray.GetSize()) {
1033 place = GetEndWordPlace();
1034 }
1035 place = AdjustLineHeader(place, TRUE);
1036 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1037 pSection->UpdateWordPlace(place);
1038 }
1039 }
WordPlaceToWordIndex(const CPVT_WordPlace & place) const1040 int32_t CPDF_VariableText::WordPlaceToWordIndex(
1041 const CPVT_WordPlace& place) const {
1042 CPVT_WordPlace newplace = place;
1043 UpdateWordPlace(newplace);
1044 int32_t nIndex = 0;
1045 int32_t i = 0;
1046 int32_t sz = 0;
1047 for (i = 0, sz = m_SectionArray.GetSize(); i < sz && i < newplace.nSecIndex;
1048 i++) {
1049 if (CSection* pSection = m_SectionArray.GetAt(i)) {
1050 nIndex += pSection->m_WordArray.GetSize();
1051 if (i != m_SectionArray.GetSize() - 1) {
1052 nIndex += PVT_RETURN_LENGTH;
1053 }
1054 }
1055 }
1056 if (i >= 0 && i < m_SectionArray.GetSize()) {
1057 nIndex += newplace.nWordIndex + PVT_RETURN_LENGTH;
1058 }
1059 return nIndex;
1060 }
WordIndexToWordPlace(int32_t index) const1061 CPVT_WordPlace CPDF_VariableText::WordIndexToWordPlace(int32_t index) const {
1062 CPVT_WordPlace place = GetBeginWordPlace();
1063 int32_t nOldIndex = 0, nIndex = 0;
1064 FX_BOOL bFind = FALSE;
1065 for (int32_t i = 0, sz = m_SectionArray.GetSize(); i < sz; i++) {
1066 if (CSection* pSection = m_SectionArray.GetAt(i)) {
1067 nIndex += pSection->m_WordArray.GetSize();
1068 if (nIndex == index) {
1069 place = pSection->GetEndWordPlace();
1070 bFind = TRUE;
1071 break;
1072 } else if (nIndex > index) {
1073 place.nSecIndex = i;
1074 place.nWordIndex = index - nOldIndex - 1;
1075 pSection->UpdateWordPlace(place);
1076 bFind = TRUE;
1077 break;
1078 }
1079 if (i != m_SectionArray.GetSize() - 1) {
1080 nIndex += PVT_RETURN_LENGTH;
1081 }
1082 nOldIndex = nIndex;
1083 }
1084 }
1085 if (!bFind) {
1086 place = GetEndWordPlace();
1087 }
1088 return place;
1089 }
GetBeginWordPlace() const1090 CPVT_WordPlace CPDF_VariableText::GetBeginWordPlace() const {
1091 return m_bInitial ? CPVT_WordPlace(0, 0, -1) : CPVT_WordPlace();
1092 }
GetEndWordPlace() const1093 CPVT_WordPlace CPDF_VariableText::GetEndWordPlace() const {
1094 if (CSection* pSection = m_SectionArray.GetAt(m_SectionArray.GetSize() - 1)) {
1095 return pSection->GetEndWordPlace();
1096 }
1097 return CPVT_WordPlace();
1098 }
GetPrevWordPlace(const CPVT_WordPlace & place) const1099 CPVT_WordPlace CPDF_VariableText::GetPrevWordPlace(
1100 const CPVT_WordPlace& place) const {
1101 if (place.nSecIndex < 0) {
1102 return GetBeginWordPlace();
1103 }
1104 if (place.nSecIndex >= m_SectionArray.GetSize()) {
1105 return GetEndWordPlace();
1106 }
1107 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1108 if (place.WordCmp(pSection->GetBeginWordPlace()) <= 0) {
1109 if (CSection* pPrevSection = m_SectionArray.GetAt(place.nSecIndex - 1)) {
1110 return pPrevSection->GetEndWordPlace();
1111 }
1112 return GetBeginWordPlace();
1113 }
1114 return pSection->GetPrevWordPlace(place);
1115 }
1116 return place;
1117 }
GetNextWordPlace(const CPVT_WordPlace & place) const1118 CPVT_WordPlace CPDF_VariableText::GetNextWordPlace(
1119 const CPVT_WordPlace& place) const {
1120 if (place.nSecIndex < 0) {
1121 return GetBeginWordPlace();
1122 }
1123 if (place.nSecIndex >= m_SectionArray.GetSize()) {
1124 return GetEndWordPlace();
1125 }
1126 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1127 if (place.WordCmp(pSection->GetEndWordPlace()) >= 0) {
1128 if (CSection* pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) {
1129 return pNextSection->GetBeginWordPlace();
1130 }
1131 return GetEndWordPlace();
1132 }
1133 return pSection->GetNextWordPlace(place);
1134 }
1135 return place;
1136 }
SearchWordPlace(const CPDF_Point & point) const1137 CPVT_WordPlace CPDF_VariableText::SearchWordPlace(
1138 const CPDF_Point& point) const {
1139 CPDF_Point pt = OutToIn(point);
1140 CPVT_WordPlace place = GetBeginWordPlace();
1141 int32_t nLeft = 0;
1142 int32_t nRight = m_SectionArray.GetSize() - 1;
1143 int32_t nMid = m_SectionArray.GetSize() / 2;
1144 FX_BOOL bUp = TRUE;
1145 FX_BOOL bDown = TRUE;
1146 while (nLeft <= nRight) {
1147 if (CSection* pSection = m_SectionArray.GetAt(nMid)) {
1148 if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.top)) {
1149 bUp = FALSE;
1150 }
1151 if (IsFloatBigger(pSection->m_SecInfo.rcSection.bottom, pt.y)) {
1152 bDown = FALSE;
1153 }
1154 if (IsFloatSmaller(pt.y, pSection->m_SecInfo.rcSection.top)) {
1155 nRight = nMid - 1;
1156 nMid = (nLeft + nRight) / 2;
1157 continue;
1158 } else if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.bottom)) {
1159 nLeft = nMid + 1;
1160 nMid = (nLeft + nRight) / 2;
1161 continue;
1162 } else {
1163 place = pSection->SearchWordPlace(
1164 CPDF_Point(pt.x - pSection->m_SecInfo.rcSection.left,
1165 pt.y - pSection->m_SecInfo.rcSection.top));
1166 place.nSecIndex = nMid;
1167 return place;
1168 }
1169 } else {
1170 break;
1171 }
1172 }
1173 if (bUp) {
1174 place = GetBeginWordPlace();
1175 }
1176 if (bDown) {
1177 place = GetEndWordPlace();
1178 }
1179 return place;
1180 }
GetUpWordPlace(const CPVT_WordPlace & place,const CPDF_Point & point) const1181 CPVT_WordPlace CPDF_VariableText::GetUpWordPlace(
1182 const CPVT_WordPlace& place,
1183 const CPDF_Point& point) const {
1184 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1185 CPVT_WordPlace temp = place;
1186 CPDF_Point pt = OutToIn(point);
1187 if (temp.nLineIndex-- > 0) {
1188 return pSection->SearchWordPlace(
1189 pt.x - pSection->m_SecInfo.rcSection.left, temp);
1190 }
1191 if (temp.nSecIndex-- > 0) {
1192 if (CSection* pLastSection = m_SectionArray.GetAt(temp.nSecIndex)) {
1193 temp.nLineIndex = pLastSection->m_LineArray.GetSize() - 1;
1194 return pLastSection->SearchWordPlace(
1195 pt.x - pLastSection->m_SecInfo.rcSection.left, temp);
1196 }
1197 }
1198 }
1199 return place;
1200 }
GetDownWordPlace(const CPVT_WordPlace & place,const CPDF_Point & point) const1201 CPVT_WordPlace CPDF_VariableText::GetDownWordPlace(
1202 const CPVT_WordPlace& place,
1203 const CPDF_Point& point) const {
1204 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1205 CPVT_WordPlace temp = place;
1206 CPDF_Point pt = OutToIn(point);
1207 if (temp.nLineIndex++ < pSection->m_LineArray.GetSize() - 1) {
1208 return pSection->SearchWordPlace(
1209 pt.x - pSection->m_SecInfo.rcSection.left, temp);
1210 }
1211 if (temp.nSecIndex++ < m_SectionArray.GetSize() - 1) {
1212 if (CSection* pNextSection = m_SectionArray.GetAt(temp.nSecIndex)) {
1213 temp.nLineIndex = 0;
1214 return pNextSection->SearchWordPlace(
1215 pt.x - pSection->m_SecInfo.rcSection.left, temp);
1216 }
1217 }
1218 }
1219 return place;
1220 }
GetLineBeginPlace(const CPVT_WordPlace & place) const1221 CPVT_WordPlace CPDF_VariableText::GetLineBeginPlace(
1222 const CPVT_WordPlace& place) const {
1223 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);
1224 }
GetLineEndPlace(const CPVT_WordPlace & place) const1225 CPVT_WordPlace CPDF_VariableText::GetLineEndPlace(
1226 const CPVT_WordPlace& place) const {
1227 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1228 if (CLine* pLine = pSection->m_LineArray.GetAt(place.nLineIndex))
1229 return pLine->GetEndWordPlace();
1230 }
1231 return place;
1232 }
GetSectionBeginPlace(const CPVT_WordPlace & place) const1233 CPVT_WordPlace CPDF_VariableText::GetSectionBeginPlace(
1234 const CPVT_WordPlace& place) const {
1235 return CPVT_WordPlace(place.nSecIndex, 0, -1);
1236 }
GetSectionEndPlace(const CPVT_WordPlace & place) const1237 CPVT_WordPlace CPDF_VariableText::GetSectionEndPlace(
1238 const CPVT_WordPlace& place) const {
1239 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1240 return pSection->GetEndWordPlace();
1241 }
1242 return place;
1243 }
GetTotalWords() const1244 int32_t CPDF_VariableText::GetTotalWords() const {
1245 int32_t nTotal = 0;
1246 for (int32_t i = 0, sz = m_SectionArray.GetSize(); i < sz; i++)
1247 if (CSection* pSection = m_SectionArray.GetAt(i)) {
1248 nTotal += (pSection->m_WordArray.GetSize() + PVT_RETURN_LENGTH);
1249 }
1250 return nTotal - PVT_RETURN_LENGTH;
1251 }
ResetSectionArray()1252 void CPDF_VariableText::ResetSectionArray() {
1253 for (int32_t s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
1254 delete m_SectionArray.GetAt(s);
1255 }
1256 m_SectionArray.RemoveAll();
1257 }
AddSection(const CPVT_WordPlace & place,const CPVT_SectionInfo & secinfo)1258 CPVT_WordPlace CPDF_VariableText::AddSection(const CPVT_WordPlace& place,
1259 const CPVT_SectionInfo& secinfo) {
1260 if (IsValid() && !m_bMultiLine) {
1261 return place;
1262 }
1263 int32_t nSecIndex =
1264 std::max(std::min(place.nSecIndex, m_SectionArray.GetSize()), 0);
1265 CSection* pSection = new CSection(this);
1266 pSection->m_SecInfo = secinfo;
1267 pSection->SecPlace.nSecIndex = nSecIndex;
1268 if (nSecIndex == m_SectionArray.GetSize()) {
1269 m_SectionArray.Add(pSection);
1270 } else {
1271 m_SectionArray.InsertAt(nSecIndex, pSection);
1272 }
1273 return place;
1274 }
AddLine(const CPVT_WordPlace & place,const CPVT_LineInfo & lineinfo)1275 CPVT_WordPlace CPDF_VariableText::AddLine(const CPVT_WordPlace& place,
1276 const CPVT_LineInfo& lineinfo) {
1277 if (m_SectionArray.IsEmpty()) {
1278 return place;
1279 }
1280 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1281 return pSection->AddLine(lineinfo);
1282 }
1283 return place;
1284 }
AddWord(const CPVT_WordPlace & place,const CPVT_WordInfo & wordinfo)1285 CPVT_WordPlace CPDF_VariableText::AddWord(const CPVT_WordPlace& place,
1286 const CPVT_WordInfo& wordinfo) {
1287 if (m_SectionArray.GetSize() <= 0) {
1288 return place;
1289 }
1290 CPVT_WordPlace newplace = place;
1291 newplace.nSecIndex =
1292 std::max(std::min(newplace.nSecIndex, m_SectionArray.GetSize() - 1), 0);
1293 if (CSection* pSection = m_SectionArray.GetAt(newplace.nSecIndex)) {
1294 return pSection->AddWord(newplace, wordinfo);
1295 }
1296 return place;
1297 }
GetWordInfo(const CPVT_WordPlace & place,CPVT_WordInfo & wordinfo)1298 FX_BOOL CPDF_VariableText::GetWordInfo(const CPVT_WordPlace& place,
1299 CPVT_WordInfo& wordinfo) {
1300 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1301 if (CPVT_WordInfo* pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {
1302 wordinfo = *pWord;
1303 return TRUE;
1304 }
1305 }
1306 return FALSE;
1307 }
SetWordInfo(const CPVT_WordPlace & place,const CPVT_WordInfo & wordinfo)1308 FX_BOOL CPDF_VariableText::SetWordInfo(const CPVT_WordPlace& place,
1309 const CPVT_WordInfo& wordinfo) {
1310 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1311 if (CPVT_WordInfo* pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {
1312 *pWord = wordinfo;
1313 return TRUE;
1314 }
1315 }
1316 return FALSE;
1317 }
GetLineInfo(const CPVT_WordPlace & place,CPVT_LineInfo & lineinfo)1318 FX_BOOL CPDF_VariableText::GetLineInfo(const CPVT_WordPlace& place,
1319 CPVT_LineInfo& lineinfo) {
1320 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1321 if (CLine* pLine = pSection->m_LineArray.GetAt(place.nLineIndex)) {
1322 lineinfo = pLine->m_LineInfo;
1323 return TRUE;
1324 }
1325 }
1326 return FALSE;
1327 }
GetSectionInfo(const CPVT_WordPlace & place,CPVT_SectionInfo & secinfo)1328 FX_BOOL CPDF_VariableText::GetSectionInfo(const CPVT_WordPlace& place,
1329 CPVT_SectionInfo& secinfo) {
1330 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1331 secinfo = pSection->m_SecInfo;
1332 return TRUE;
1333 }
1334 return FALSE;
1335 }
GetContentRect() const1336 CPDF_Rect CPDF_VariableText::GetContentRect() const {
1337 return InToOut(CPVT_FloatRect(CPDF_EditContainer::GetContentRect()));
1338 }
GetWordFontSize(const CPVT_WordInfo & WordInfo,FX_BOOL bFactFontSize)1339 FX_FLOAT CPDF_VariableText::GetWordFontSize(const CPVT_WordInfo& WordInfo,
1340 FX_BOOL bFactFontSize) {
1341 return m_bRichText && WordInfo.pWordProps
1342 ? (WordInfo.pWordProps->nScriptType == PVTWORD_SCRIPT_NORMAL ||
1343 bFactFontSize
1344 ? WordInfo.pWordProps->fFontSize
1345 : WordInfo.pWordProps->fFontSize * PVT_HALF)
1346 : GetFontSize();
1347 }
GetWordFontIndex(const CPVT_WordInfo & WordInfo)1348 int32_t CPDF_VariableText::GetWordFontIndex(const CPVT_WordInfo& WordInfo) {
1349 return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nFontIndex
1350 : WordInfo.nFontIndex;
1351 }
GetWordWidth(int32_t nFontIndex,FX_WORD Word,FX_WORD SubWord,FX_FLOAT fCharSpace,int32_t nHorzScale,FX_FLOAT fFontSize,FX_FLOAT fWordTail,int32_t nWordStyle)1352 FX_FLOAT CPDF_VariableText::GetWordWidth(int32_t nFontIndex,
1353 FX_WORD Word,
1354 FX_WORD SubWord,
1355 FX_FLOAT fCharSpace,
1356 int32_t nHorzScale,
1357 FX_FLOAT fFontSize,
1358 FX_FLOAT fWordTail,
1359 int32_t nWordStyle) {
1360 return (GetCharWidth(nFontIndex, Word, SubWord, nWordStyle) * fFontSize *
1361 PVT_FONTSCALE +
1362 fCharSpace) *
1363 nHorzScale * PVT_PERCENT +
1364 fWordTail;
1365 }
GetWordWidth(const CPVT_WordInfo & WordInfo)1366 FX_FLOAT CPDF_VariableText::GetWordWidth(const CPVT_WordInfo& WordInfo) {
1367 return GetWordWidth(
1368 GetWordFontIndex(WordInfo), WordInfo.Word, GetSubWord(),
1369 GetCharSpace(WordInfo), GetHorzScale(WordInfo), GetWordFontSize(WordInfo),
1370 WordInfo.fWordTail,
1371 WordInfo.pWordProps ? WordInfo.pWordProps->nWordStyle : 0);
1372 }
GetLineAscent(const CPVT_SectionInfo & SecInfo)1373 FX_FLOAT CPDF_VariableText::GetLineAscent(const CPVT_SectionInfo& SecInfo) {
1374 return m_bRichText && SecInfo.pWordProps
1375 ? GetFontAscent(SecInfo.pWordProps->nFontIndex,
1376 SecInfo.pWordProps->fFontSize)
1377 : GetFontAscent(GetDefaultFontIndex(), GetFontSize());
1378 }
GetLineDescent(const CPVT_SectionInfo & SecInfo)1379 FX_FLOAT CPDF_VariableText::GetLineDescent(const CPVT_SectionInfo& SecInfo) {
1380 return m_bRichText && SecInfo.pWordProps
1381 ? GetFontDescent(SecInfo.pWordProps->nFontIndex,
1382 SecInfo.pWordProps->fFontSize)
1383 : GetFontDescent(GetDefaultFontIndex(), GetFontSize());
1384 }
GetFontAscent(int32_t nFontIndex,FX_FLOAT fFontSize)1385 FX_FLOAT CPDF_VariableText::GetFontAscent(int32_t nFontIndex,
1386 FX_FLOAT fFontSize) {
1387 return (FX_FLOAT)GetTypeAscent(nFontIndex) * fFontSize * PVT_FONTSCALE;
1388 }
GetFontDescent(int32_t nFontIndex,FX_FLOAT fFontSize)1389 FX_FLOAT CPDF_VariableText::GetFontDescent(int32_t nFontIndex,
1390 FX_FLOAT fFontSize) {
1391 return (FX_FLOAT)GetTypeDescent(nFontIndex) * fFontSize * PVT_FONTSCALE;
1392 }
GetWordAscent(const CPVT_WordInfo & WordInfo,FX_FLOAT fFontSize)1393 FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo& WordInfo,
1394 FX_FLOAT fFontSize) {
1395 return GetFontAscent(GetWordFontIndex(WordInfo), fFontSize);
1396 }
GetWordDescent(const CPVT_WordInfo & WordInfo,FX_FLOAT fFontSize)1397 FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo& WordInfo,
1398 FX_FLOAT fFontSize) {
1399 return GetFontDescent(GetWordFontIndex(WordInfo), fFontSize);
1400 }
GetWordAscent(const CPVT_WordInfo & WordInfo,FX_BOOL bFactFontSize)1401 FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo& WordInfo,
1402 FX_BOOL bFactFontSize) {
1403 return GetFontAscent(GetWordFontIndex(WordInfo),
1404 GetWordFontSize(WordInfo, bFactFontSize));
1405 }
GetWordDescent(const CPVT_WordInfo & WordInfo,FX_BOOL bFactFontSize)1406 FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo& WordInfo,
1407 FX_BOOL bFactFontSize) {
1408 return GetFontDescent(GetWordFontIndex(WordInfo),
1409 GetWordFontSize(WordInfo, bFactFontSize));
1410 }
GetLineLeading(const CPVT_SectionInfo & SecInfo)1411 FX_FLOAT CPDF_VariableText::GetLineLeading(const CPVT_SectionInfo& SecInfo) {
1412 return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineLeading
1413 : m_fLineLeading;
1414 }
GetLineIndent(const CPVT_SectionInfo & SecInfo)1415 FX_FLOAT CPDF_VariableText::GetLineIndent(const CPVT_SectionInfo& SecInfo) {
1416 return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineIndent
1417 : 0.0f;
1418 }
GetAlignment(const CPVT_SectionInfo & SecInfo)1419 int32_t CPDF_VariableText::GetAlignment(const CPVT_SectionInfo& SecInfo) {
1420 return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->nAlignment
1421 : m_nAlignment;
1422 }
GetCharSpace(const CPVT_WordInfo & WordInfo)1423 FX_FLOAT CPDF_VariableText::GetCharSpace(const CPVT_WordInfo& WordInfo) {
1424 return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->fCharSpace
1425 : m_fCharSpace;
1426 }
GetHorzScale(const CPVT_WordInfo & WordInfo)1427 int32_t CPDF_VariableText::GetHorzScale(const CPVT_WordInfo& WordInfo) {
1428 return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nHorzScale
1429 : m_nHorzScale;
1430 }
ClearSectionRightWords(const CPVT_WordPlace & place)1431 void CPDF_VariableText::ClearSectionRightWords(const CPVT_WordPlace& place) {
1432 CPVT_WordPlace wordplace = AdjustLineHeader(place, TRUE);
1433 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1434 for (int32_t w = pSection->m_WordArray.GetSize() - 1;
1435 w > wordplace.nWordIndex; w--) {
1436 delete pSection->m_WordArray.GetAt(w);
1437 pSection->m_WordArray.RemoveAt(w);
1438 }
1439 }
1440 }
AdjustLineHeader(const CPVT_WordPlace & place,FX_BOOL bPrevOrNext) const1441 CPVT_WordPlace CPDF_VariableText::AdjustLineHeader(const CPVT_WordPlace& place,
1442 FX_BOOL bPrevOrNext) const {
1443 if (place.nWordIndex < 0 && place.nLineIndex > 0) {
1444 return bPrevOrNext ? GetPrevWordPlace(place) : GetNextWordPlace(place);
1445 }
1446 return place;
1447 }
ClearEmptySection(const CPVT_WordPlace & place)1448 FX_BOOL CPDF_VariableText::ClearEmptySection(const CPVT_WordPlace& place) {
1449 if (place.nSecIndex == 0 && m_SectionArray.GetSize() == 1) {
1450 return FALSE;
1451 }
1452 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1453 if (pSection->m_WordArray.GetSize() == 0) {
1454 delete pSection;
1455 m_SectionArray.RemoveAt(place.nSecIndex);
1456 return TRUE;
1457 }
1458 }
1459 return FALSE;
1460 }
ClearEmptySections(const CPVT_WordRange & PlaceRange)1461 void CPDF_VariableText::ClearEmptySections(const CPVT_WordRange& PlaceRange) {
1462 CPVT_WordPlace wordplace;
1463 for (int32_t s = PlaceRange.EndPos.nSecIndex;
1464 s > PlaceRange.BeginPos.nSecIndex; s--) {
1465 wordplace.nSecIndex = s;
1466 ClearEmptySection(wordplace);
1467 }
1468 }
LinkLatterSection(const CPVT_WordPlace & place)1469 void CPDF_VariableText::LinkLatterSection(const CPVT_WordPlace& place) {
1470 CPVT_WordPlace oldplace = AdjustLineHeader(place, TRUE);
1471 if (CSection* pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) {
1472 if (CSection* pSection = m_SectionArray.GetAt(oldplace.nSecIndex)) {
1473 for (int32_t w = 0, sz = pNextSection->m_WordArray.GetSize(); w < sz;
1474 w++) {
1475 if (CPVT_WordInfo* pWord = pNextSection->m_WordArray.GetAt(w)) {
1476 oldplace.nWordIndex++;
1477 pSection->AddWord(oldplace, *pWord);
1478 }
1479 }
1480 }
1481 delete pNextSection;
1482 m_SectionArray.RemoveAt(place.nSecIndex + 1);
1483 }
1484 }
ClearWords(const CPVT_WordRange & PlaceRange)1485 void CPDF_VariableText::ClearWords(const CPVT_WordRange& PlaceRange) {
1486 CPVT_WordRange NewRange;
1487 NewRange.BeginPos = AdjustLineHeader(PlaceRange.BeginPos, TRUE);
1488 NewRange.EndPos = AdjustLineHeader(PlaceRange.EndPos, TRUE);
1489 for (int32_t s = NewRange.EndPos.nSecIndex; s >= NewRange.BeginPos.nSecIndex;
1490 s--) {
1491 if (CSection* pSection = m_SectionArray.GetAt(s)) {
1492 pSection->ClearWords(NewRange);
1493 }
1494 }
1495 }
ClearLeftWord(const CPVT_WordPlace & place)1496 CPVT_WordPlace CPDF_VariableText::ClearLeftWord(const CPVT_WordPlace& place) {
1497 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1498 CPVT_WordPlace leftplace = GetPrevWordPlace(place);
1499 if (leftplace != place) {
1500 if (leftplace.nSecIndex != place.nSecIndex) {
1501 if (pSection->m_WordArray.GetSize() == 0) {
1502 ClearEmptySection(place);
1503 } else {
1504 LinkLatterSection(leftplace);
1505 }
1506 } else {
1507 pSection->ClearWord(place);
1508 }
1509 }
1510 return leftplace;
1511 }
1512 return place;
1513 }
ClearRightWord(const CPVT_WordPlace & place)1514 CPVT_WordPlace CPDF_VariableText::ClearRightWord(const CPVT_WordPlace& place) {
1515 if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1516 CPVT_WordPlace rightplace =
1517 AdjustLineHeader(GetNextWordPlace(place), FALSE);
1518 if (rightplace != place) {
1519 if (rightplace.nSecIndex != place.nSecIndex) {
1520 LinkLatterSection(place);
1521 } else {
1522 pSection->ClearWord(rightplace);
1523 }
1524 }
1525 }
1526 return place;
1527 }
RearrangeAll()1528 void CPDF_VariableText::RearrangeAll() {
1529 Rearrange(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
1530 }
RearrangePart(const CPVT_WordRange & PlaceRange)1531 void CPDF_VariableText::RearrangePart(const CPVT_WordRange& PlaceRange) {
1532 Rearrange(PlaceRange);
1533 }
Rearrange(const CPVT_WordRange & PlaceRange)1534 CPVT_FloatRect CPDF_VariableText::Rearrange(const CPVT_WordRange& PlaceRange) {
1535 CPVT_FloatRect rcRet;
1536 if (IsValid()) {
1537 if (m_bAutoFontSize) {
1538 SetFontSize(GetAutoFontSize());
1539 rcRet = RearrangeSections(
1540 CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
1541 } else {
1542 rcRet = RearrangeSections(PlaceRange);
1543 }
1544 }
1545 SetContentRect(rcRet);
1546 return rcRet;
1547 }
GetAutoFontSize()1548 FX_FLOAT CPDF_VariableText::GetAutoFontSize() {
1549 int32_t nTotal = sizeof(gFontSizeSteps) / sizeof(uint8_t);
1550 if (IsMultiLine()) {
1551 nTotal /= 4;
1552 }
1553 if (nTotal <= 0) {
1554 return 0;
1555 }
1556 if (GetPlateWidth() <= 0) {
1557 return 0;
1558 }
1559 int32_t nLeft = 0;
1560 int32_t nRight = nTotal - 1;
1561 int32_t nMid = nTotal / 2;
1562 while (nLeft <= nRight) {
1563 if (IsBigger(gFontSizeSteps[nMid])) {
1564 nRight = nMid - 1;
1565 nMid = (nLeft + nRight) / 2;
1566 continue;
1567 } else {
1568 nLeft = nMid + 1;
1569 nMid = (nLeft + nRight) / 2;
1570 continue;
1571 }
1572 }
1573 return (FX_FLOAT)gFontSizeSteps[nMid];
1574 }
IsBigger(FX_FLOAT fFontSize)1575 FX_BOOL CPDF_VariableText::IsBigger(FX_FLOAT fFontSize) {
1576 FX_BOOL bBigger = FALSE;
1577 CPVT_Size szTotal;
1578 for (int32_t s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
1579 if (CSection* pSection = m_SectionArray.GetAt(s)) {
1580 CPVT_Size size = pSection->GetSectionSize(fFontSize);
1581 szTotal.x = std::max(size.x, szTotal.x);
1582 szTotal.y += size.y;
1583 if (IsFloatBigger(szTotal.x, GetPlateWidth()) ||
1584 IsFloatBigger(szTotal.y, GetPlateHeight())) {
1585 bBigger = TRUE;
1586 break;
1587 }
1588 }
1589 }
1590 return bBigger;
1591 }
RearrangeSections(const CPVT_WordRange & PlaceRange)1592 CPVT_FloatRect CPDF_VariableText::RearrangeSections(
1593 const CPVT_WordRange& PlaceRange) {
1594 CPVT_WordPlace place;
1595 FX_FLOAT fPosY = 0;
1596 FX_FLOAT fOldHeight;
1597 int32_t nSSecIndex = PlaceRange.BeginPos.nSecIndex;
1598 int32_t nESecIndex = PlaceRange.EndPos.nSecIndex;
1599 CPVT_FloatRect rcRet;
1600 for (int32_t s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
1601 place.nSecIndex = s;
1602 if (CSection* pSection = m_SectionArray.GetAt(s)) {
1603 pSection->SecPlace = place;
1604 CPVT_FloatRect rcSec = pSection->m_SecInfo.rcSection;
1605 if (s >= nSSecIndex) {
1606 if (s <= nESecIndex) {
1607 rcSec = pSection->Rearrange();
1608 rcSec.top += fPosY;
1609 rcSec.bottom += fPosY;
1610 } else {
1611 fOldHeight = pSection->m_SecInfo.rcSection.bottom -
1612 pSection->m_SecInfo.rcSection.top;
1613 rcSec.top = fPosY;
1614 rcSec.bottom = fPosY + fOldHeight;
1615 }
1616 pSection->m_SecInfo.rcSection = rcSec;
1617 pSection->ResetLinePlace();
1618 }
1619 if (s == 0) {
1620 rcRet = rcSec;
1621 } else {
1622 rcRet.left = std::min(rcSec.left, rcRet.left);
1623 rcRet.top = std::min(rcSec.top, rcRet.top);
1624 rcRet.right = std::max(rcSec.right, rcRet.right);
1625 rcRet.bottom = std::max(rcSec.bottom, rcRet.bottom);
1626 }
1627 fPosY += rcSec.Height();
1628 }
1629 }
1630 return rcRet;
1631 }
GetCharWidth(int32_t nFontIndex,FX_WORD Word,FX_WORD SubWord,int32_t nWordStyle)1632 int32_t CPDF_VariableText::GetCharWidth(int32_t nFontIndex,
1633 FX_WORD Word,
1634 FX_WORD SubWord,
1635 int32_t nWordStyle) {
1636 if (!m_pVTProvider) {
1637 return 0;
1638 }
1639 if (SubWord > 0) {
1640 return m_pVTProvider->GetCharWidth(nFontIndex, SubWord, nWordStyle);
1641 }
1642 return m_pVTProvider->GetCharWidth(nFontIndex, Word, nWordStyle);
1643 }
GetTypeAscent(int32_t nFontIndex)1644 int32_t CPDF_VariableText::GetTypeAscent(int32_t nFontIndex) {
1645 return m_pVTProvider ? m_pVTProvider->GetTypeAscent(nFontIndex) : 0;
1646 }
GetTypeDescent(int32_t nFontIndex)1647 int32_t CPDF_VariableText::GetTypeDescent(int32_t nFontIndex) {
1648 return m_pVTProvider ? m_pVTProvider->GetTypeDescent(nFontIndex) : 0;
1649 }
GetWordFontIndex(FX_WORD word,int32_t charset,int32_t nFontIndex)1650 int32_t CPDF_VariableText::GetWordFontIndex(FX_WORD word,
1651 int32_t charset,
1652 int32_t nFontIndex) {
1653 return m_pVTProvider
1654 ? m_pVTProvider->GetWordFontIndex(word, charset, nFontIndex)
1655 : -1;
1656 }
GetDefaultFontIndex()1657 int32_t CPDF_VariableText::GetDefaultFontIndex() {
1658 return m_pVTProvider ? m_pVTProvider->GetDefaultFontIndex() : -1;
1659 }
IsLatinWord(FX_WORD word)1660 FX_BOOL CPDF_VariableText::IsLatinWord(FX_WORD word) {
1661 return m_pVTProvider ? m_pVTProvider->IsLatinWord(word) : FALSE;
1662 }
GetIterator()1663 IPDF_VariableText_Iterator* CPDF_VariableText::GetIterator() {
1664 if (!m_pVTIterator) {
1665 m_pVTIterator = new CPDF_VariableText_Iterator(this);
1666 }
1667 return m_pVTIterator;
1668 }
SetProvider(IPDF_VariableText_Provider * pProvider)1669 IPDF_VariableText_Provider* CPDF_VariableText::SetProvider(
1670 IPDF_VariableText_Provider* pProvider) {
1671 IPDF_VariableText_Provider* pOld = m_pVTProvider;
1672 m_pVTProvider = pProvider;
1673 return pOld;
1674 }
CPDF_VariableText_Iterator(CPDF_VariableText * pVT)1675 CPDF_VariableText_Iterator::CPDF_VariableText_Iterator(CPDF_VariableText* pVT)
1676 : m_CurPos(-1, -1, -1), m_pVT(pVT) {}
~CPDF_VariableText_Iterator()1677 CPDF_VariableText_Iterator::~CPDF_VariableText_Iterator() {}
SetAt(int32_t nWordIndex)1678 void CPDF_VariableText_Iterator::SetAt(int32_t nWordIndex) {
1679 m_CurPos = m_pVT->WordIndexToWordPlace(nWordIndex);
1680 }
SetAt(const CPVT_WordPlace & place)1681 void CPDF_VariableText_Iterator::SetAt(const CPVT_WordPlace& place) {
1682 ASSERT(m_pVT);
1683 m_CurPos = place;
1684 }
NextWord()1685 FX_BOOL CPDF_VariableText_Iterator::NextWord() {
1686 if (m_CurPos == m_pVT->GetEndWordPlace()) {
1687 return FALSE;
1688 }
1689 m_CurPos = m_pVT->GetNextWordPlace(m_CurPos);
1690 return TRUE;
1691 }
PrevWord()1692 FX_BOOL CPDF_VariableText_Iterator::PrevWord() {
1693 if (m_CurPos == m_pVT->GetBeginWordPlace()) {
1694 return FALSE;
1695 }
1696 m_CurPos = m_pVT->GetPrevWordPlace(m_CurPos);
1697 return TRUE;
1698 }
NextLine()1699 FX_BOOL CPDF_VariableText_Iterator::NextLine() {
1700 if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1701 if (m_CurPos.nLineIndex < pSection->m_LineArray.GetSize() - 1) {
1702 m_CurPos =
1703 CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex + 1, -1);
1704 return TRUE;
1705 }
1706 if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
1707 m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
1708 return TRUE;
1709 }
1710 }
1711 return FALSE;
1712 }
PrevLine()1713 FX_BOOL CPDF_VariableText_Iterator::PrevLine() {
1714 if (m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1715 if (m_CurPos.nLineIndex > 0) {
1716 m_CurPos =
1717 CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex - 1, -1);
1718 return TRUE;
1719 }
1720 if (m_CurPos.nSecIndex > 0) {
1721 if (CSection* pLastSection =
1722 m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex - 1)) {
1723 m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1,
1724 pLastSection->m_LineArray.GetSize() - 1, -1);
1725 return TRUE;
1726 }
1727 }
1728 }
1729 return FALSE;
1730 }
NextSection()1731 FX_BOOL CPDF_VariableText_Iterator::NextSection() {
1732 if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
1733 m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
1734 return TRUE;
1735 }
1736 return FALSE;
1737 }
PrevSection()1738 FX_BOOL CPDF_VariableText_Iterator::PrevSection() {
1739 ASSERT(m_pVT);
1740 if (m_CurPos.nSecIndex > 0) {
1741 m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, 0, -1);
1742 return TRUE;
1743 }
1744 return FALSE;
1745 }
GetWord(CPVT_Word & word) const1746 FX_BOOL CPDF_VariableText_Iterator::GetWord(CPVT_Word& word) const {
1747 word.WordPlace = m_CurPos;
1748 if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1749 if (pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
1750 if (CPVT_WordInfo* pWord =
1751 pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
1752 word.Word = pWord->Word;
1753 word.nCharset = pWord->nCharset;
1754 word.fWidth = m_pVT->GetWordWidth(*pWord);
1755 word.ptWord = m_pVT->InToOut(
1756 CPDF_Point(pWord->fWordX + pSection->m_SecInfo.rcSection.left,
1757 pWord->fWordY + pSection->m_SecInfo.rcSection.top));
1758 word.fAscent = m_pVT->GetWordAscent(*pWord);
1759 word.fDescent = m_pVT->GetWordDescent(*pWord);
1760 if (pWord->pWordProps) {
1761 word.WordProps = *pWord->pWordProps;
1762 }
1763 word.nFontIndex = m_pVT->GetWordFontIndex(*pWord);
1764 word.fFontSize = m_pVT->GetWordFontSize(*pWord);
1765 return TRUE;
1766 }
1767 }
1768 }
1769 return FALSE;
1770 }
SetWord(const CPVT_Word & word)1771 FX_BOOL CPDF_VariableText_Iterator::SetWord(const CPVT_Word& word) {
1772 if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1773 if (CPVT_WordInfo* pWord =
1774 pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
1775 if (pWord->pWordProps) {
1776 *pWord->pWordProps = word.WordProps;
1777 }
1778 return TRUE;
1779 }
1780 }
1781 return FALSE;
1782 }
GetLine(CPVT_Line & line) const1783 FX_BOOL CPDF_VariableText_Iterator::GetLine(CPVT_Line& line) const {
1784 ASSERT(m_pVT);
1785 line.lineplace = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex, -1);
1786 if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1787 if (CLine* pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
1788 line.ptLine = m_pVT->InToOut(CPDF_Point(
1789 pLine->m_LineInfo.fLineX + pSection->m_SecInfo.rcSection.left,
1790 pLine->m_LineInfo.fLineY + pSection->m_SecInfo.rcSection.top));
1791 line.fLineWidth = pLine->m_LineInfo.fLineWidth;
1792 line.fLineAscent = pLine->m_LineInfo.fLineAscent;
1793 line.fLineDescent = pLine->m_LineInfo.fLineDescent;
1794 line.lineEnd = pLine->GetEndWordPlace();
1795 return TRUE;
1796 }
1797 }
1798 return FALSE;
1799 }
GetSection(CPVT_Section & section) const1800 FX_BOOL CPDF_VariableText_Iterator::GetSection(CPVT_Section& section) const {
1801 section.secplace = CPVT_WordPlace(m_CurPos.nSecIndex, 0, -1);
1802 if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1803 section.rcSection = m_pVT->InToOut(pSection->m_SecInfo.rcSection);
1804 if (pSection->m_SecInfo.pSecProps) {
1805 section.SecProps = *pSection->m_SecInfo.pSecProps;
1806 }
1807 if (pSection->m_SecInfo.pWordProps) {
1808 section.WordProps = *pSection->m_SecInfo.pWordProps;
1809 }
1810 return TRUE;
1811 }
1812 return FALSE;
1813 }
SetSection(const CPVT_Section & section)1814 FX_BOOL CPDF_VariableText_Iterator::SetSection(const CPVT_Section& section) {
1815 if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1816 if (pSection->m_SecInfo.pSecProps) {
1817 *pSection->m_SecInfo.pSecProps = section.SecProps;
1818 }
1819 if (pSection->m_SecInfo.pWordProps) {
1820 *pSection->m_SecInfo.pWordProps = section.WordProps;
1821 }
1822 return TRUE;
1823 }
1824 return FALSE;
1825 }
1826