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