Use override in more classes in core/
[pdfium.git] / core / src / fpdfdoc / doc_vt.cpp
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 "../../include/fpdfdoc/fpdf_doc.h"
8 #include "../../include/fpdfdoc/fpdf_vt.h"
9 #include "pdf_vt.h"
10 const uint8_t gFontSizeSteps[] = {4,  6,  8,   9,   10,  12,  14, 18, 20,
11                                   25, 30, 35,  40,  45,  50,  55, 60, 70,
12                                   80, 90, 100, 110, 120, 130, 144};
13 #define PVT_RETURN_LENGTH 1
14 #define PVT_DEFAULT_FONTSIZE 18.0f
15 #define PVTWORD_SCRIPT_NORMAL 0
16 #define PVTWORD_SCRIPT_SUPER 1
17 #define PVTWORD_SCRIPT_SUB 2
18 #define PVT_FONTSCALE 0.001f
19 #define PVT_PERCENT 0.01f
20 #define PVT_HALF 0.5f
21 CLine::CLine() {}
22 CLine::~CLine() {}
23 CPVT_WordPlace CLine::GetBeginWordPlace() const {
24   return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex, -1);
25 }
26 CPVT_WordPlace CLine::GetEndWordPlace() const {
27   return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex,
28                         m_LineInfo.nEndWordIndex);
29 }
30 CPVT_WordPlace CLine::GetPrevWordPlace(const CPVT_WordPlace& place) const {
31   if (place.nWordIndex > m_LineInfo.nEndWordIndex) {
32     return CPVT_WordPlace(place.nSecIndex, place.nLineIndex,
33                           m_LineInfo.nEndWordIndex);
34   }
35   return CPVT_WordPlace(place.nSecIndex, place.nLineIndex,
36                         place.nWordIndex - 1);
37 }
38 CPVT_WordPlace CLine::GetNextWordPlace(const CPVT_WordPlace& place) const {
39   if (place.nWordIndex < m_LineInfo.nBeginWordIndex) {
40     return CPVT_WordPlace(place.nSecIndex, place.nLineIndex,
41                           m_LineInfo.nBeginWordIndex);
42   }
43   return CPVT_WordPlace(place.nSecIndex, place.nLineIndex,
44                         place.nWordIndex + 1);
45 }
46 CSection::CSection(CPDF_VariableText* pVT) : m_pVT(pVT) {}
47 CSection::~CSection() {
48   ResetAll();
49 }
50 void CSection::ResetAll() {
51   ResetWordArray();
52   ResetLineArray();
53 }
54 void CSection::ResetLineArray() {
55   m_LineArray.RemoveAll();
56 }
57 void CSection::ResetWordArray() {
58   for (int32_t i = 0, sz = m_WordArray.GetSize(); i < sz; i++) {
59     delete m_WordArray.GetAt(i);
60   }
61   m_WordArray.RemoveAll();
62 }
63 void CSection::ResetLinePlace() {
64   for (int32_t i = 0, sz = m_LineArray.GetSize(); i < sz; i++) {
65     if (CLine* pLine = m_LineArray.GetAt(i)) {
66       pLine->LinePlace = CPVT_WordPlace(SecPlace.nSecIndex, i, -1);
67     }
68   }
69 }
70 CPVT_WordPlace CSection::AddWord(const CPVT_WordPlace& place,
71                                  const CPVT_WordInfo& wordinfo) {
72   CPVT_WordInfo* pWord = new CPVT_WordInfo(wordinfo);
73   int32_t nWordIndex =
74       FPDF_MAX(FPDF_MIN(place.nWordIndex, m_WordArray.GetSize()), 0);
75   if (nWordIndex == m_WordArray.GetSize()) {
76     m_WordArray.Add(pWord);
77   } else {
78     m_WordArray.InsertAt(nWordIndex, pWord);
79   }
80   return place;
81 }
82 CPVT_WordPlace CSection::AddLine(const CPVT_LineInfo& lineinfo) {
83   return CPVT_WordPlace(SecPlace.nSecIndex, m_LineArray.Add(lineinfo), -1);
84 }
85 CPVT_FloatRect CSection::Rearrange() {
86   ASSERT(m_pVT != NULL);
87   if (m_pVT->m_nCharArray > 0) {
88     return CTypeset(this).CharArray();
89   }
90   return CTypeset(this).Typeset();
91 }
92 CPVT_Size CSection::GetSectionSize(FX_FLOAT fFontSize) {
93   return CTypeset(this).GetEditSize(fFontSize);
94 }
95 CPVT_WordPlace CSection::GetBeginWordPlace() const {
96   if (CLine* pLine = m_LineArray.GetAt(0)) {
97     return pLine->GetBeginWordPlace();
98   }
99   return SecPlace;
100 }
101 CPVT_WordPlace CSection::GetEndWordPlace() const {
102   if (CLine* pLine = m_LineArray.GetAt(m_LineArray.GetSize() - 1)) {
103     return pLine->GetEndWordPlace();
104   }
105   return SecPlace;
106 }
107 CPVT_WordPlace CSection::GetPrevWordPlace(const CPVT_WordPlace& place) const {
108   if (place.nLineIndex < 0) {
109     return GetBeginWordPlace();
110   }
111   if (place.nLineIndex >= m_LineArray.GetSize()) {
112     return GetEndWordPlace();
113   }
114   if (CLine* pLine = m_LineArray.GetAt(place.nLineIndex)) {
115     if (place.nWordIndex == pLine->m_LineInfo.nBeginWordIndex) {
116       return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);
117     }
118     if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) {
119       if (CLine* pPrevLine = m_LineArray.GetAt(place.nLineIndex - 1)) {
120         return pPrevLine->GetEndWordPlace();
121       }
122     } else {
123       return pLine->GetPrevWordPlace(place);
124     }
125   }
126   return place;
127 }
128 CPVT_WordPlace CSection::GetNextWordPlace(const CPVT_WordPlace& place) const {
129   if (place.nLineIndex < 0) {
130     return GetBeginWordPlace();
131   }
132   if (place.nLineIndex >= m_LineArray.GetSize()) {
133     return GetEndWordPlace();
134   }
135   if (CLine* pLine = m_LineArray.GetAt(place.nLineIndex)) {
136     if (place.nWordIndex >= pLine->m_LineInfo.nEndWordIndex) {
137       if (CLine* pNextLine = m_LineArray.GetAt(place.nLineIndex + 1)) {
138         return pNextLine->GetBeginWordPlace();
139       }
140     } else {
141       return pLine->GetNextWordPlace(place);
142     }
143   }
144   return place;
145 }
146 void CSection::UpdateWordPlace(CPVT_WordPlace& place) const {
147   int32_t nLeft = 0;
148   int32_t nRight = m_LineArray.GetSize() - 1;
149   int32_t nMid = (nLeft + nRight) / 2;
150   while (nLeft <= nRight) {
151     if (CLine* pLine = m_LineArray.GetAt(nMid)) {
152       if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) {
153         nRight = nMid - 1;
154         nMid = (nLeft + nRight) / 2;
155       } else if (place.nWordIndex > pLine->m_LineInfo.nEndWordIndex) {
156         nLeft = nMid + 1;
157         nMid = (nLeft + nRight) / 2;
158       } else {
159         place.nLineIndex = nMid;
160         return;
161       }
162     } else {
163       break;
164     }
165   }
166 }
167 CPVT_WordPlace CSection::SearchWordPlace(const CPDF_Point& point) const {
168   ASSERT(m_pVT != NULL);
169   CPVT_WordPlace place = GetBeginWordPlace();
170   FX_BOOL bUp = TRUE;
171   FX_BOOL bDown = TRUE;
172   int32_t nLeft = 0;
173   int32_t nRight = m_LineArray.GetSize() - 1;
174   int32_t nMid = m_LineArray.GetSize() / 2;
175   FX_FLOAT fTop = 0;
176   FX_FLOAT fBottom = 0;
177   while (nLeft <= nRight) {
178     if (CLine* pLine = m_LineArray.GetAt(nMid)) {
179       fTop = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineAscent -
180              m_pVT->GetLineLeading(m_SecInfo);
181       fBottom = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineDescent;
182       if (IsFloatBigger(point.y, fTop)) {
183         bUp = FALSE;
184       }
185       if (IsFloatSmaller(point.y, fBottom)) {
186         bDown = FALSE;
187       }
188       if (IsFloatSmaller(point.y, fTop)) {
189         nRight = nMid - 1;
190         nMid = (nLeft + nRight) / 2;
191         continue;
192       } else if (IsFloatBigger(point.y, fBottom)) {
193         nLeft = nMid + 1;
194         nMid = (nLeft + nRight) / 2;
195         continue;
196       } else {
197         place = SearchWordPlace(
198             point.x,
199             CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()),
200                            pLine->GetEndWordPlace()));
201         place.nLineIndex = nMid;
202         return place;
203       }
204     }
205   }
206   if (bUp) {
207     place = GetBeginWordPlace();
208   }
209   if (bDown) {
210     place = GetEndWordPlace();
211   }
212   return place;
213 }
214 CPVT_WordPlace CSection::SearchWordPlace(
215     FX_FLOAT fx,
216     const CPVT_WordPlace& lineplace) const {
217   if (CLine* pLine = m_LineArray.GetAt(lineplace.nLineIndex)) {
218     return SearchWordPlace(
219         fx - m_SecInfo.rcSection.left,
220         CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()),
221                        pLine->GetEndWordPlace()));
222   }
223   return GetBeginWordPlace();
224 }
225 CPVT_WordPlace CSection::SearchWordPlace(FX_FLOAT fx,
226                                          const CPVT_WordRange& range) const {
227   CPVT_WordPlace wordplace = range.BeginPos;
228   wordplace.nWordIndex = -1;
229   if (!m_pVT) {
230     return wordplace;
231   }
232   int32_t nLeft = range.BeginPos.nWordIndex;
233   int32_t nRight = range.EndPos.nWordIndex + 1;
234   int32_t nMid = (nLeft + nRight) / 2;
235   while (nLeft < nRight) {
236     if (nMid == nLeft) {
237       break;
238     }
239     if (nMid == nRight) {
240       nMid--;
241       break;
242     }
243     if (CPVT_WordInfo* pWord = m_WordArray.GetAt(nMid)) {
244       if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * PVT_HALF) {
245         nLeft = nMid;
246         nMid = (nLeft + nRight) / 2;
247         continue;
248       } else {
249         nRight = nMid;
250         nMid = (nLeft + nRight) / 2;
251         continue;
252       }
253     } else {
254       break;
255     }
256   }
257   if (CPVT_WordInfo* pWord = m_WordArray.GetAt(nMid)) {
258     if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * PVT_HALF) {
259       wordplace.nWordIndex = nMid;
260     }
261   }
262   return wordplace;
263 }
264 void CSection::ClearLeftWords(int32_t nWordIndex) {
265   for (int32_t i = nWordIndex; i >= 0; i--) {
266     delete m_WordArray.GetAt(i);
267     m_WordArray.RemoveAt(i);
268   }
269 }
270 void CSection::ClearRightWords(int32_t nWordIndex) {
271   for (int32_t i = m_WordArray.GetSize() - 1; i > nWordIndex; i--) {
272     delete m_WordArray.GetAt(i);
273     m_WordArray.RemoveAt(i);
274   }
275 }
276 void CSection::ClearMidWords(int32_t nBeginIndex, int32_t nEndIndex) {
277   for (int32_t i = nEndIndex; i > nBeginIndex; i--) {
278     delete m_WordArray.GetAt(i);
279     m_WordArray.RemoveAt(i);
280   }
281 }
282 void CSection::ClearWords(const CPVT_WordRange& PlaceRange) {
283   CPVT_WordPlace SecBeginPos = GetBeginWordPlace();
284   CPVT_WordPlace SecEndPos = GetEndWordPlace();
285   if (PlaceRange.BeginPos.WordCmp(SecBeginPos) >= 0) {
286     if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) {
287       ClearMidWords(PlaceRange.BeginPos.nWordIndex,
288                     PlaceRange.EndPos.nWordIndex);
289     } else {
290       ClearRightWords(PlaceRange.BeginPos.nWordIndex);
291     }
292   } else if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) {
293     ClearLeftWords(PlaceRange.EndPos.nWordIndex);
294   } else {
295     ResetWordArray();
296   }
297 }
298 void CSection::ClearWord(const CPVT_WordPlace& place) {
299   delete m_WordArray.GetAt(place.nWordIndex);
300   m_WordArray.RemoveAt(place.nWordIndex);
301 }
302 CTypeset::CTypeset(CSection* pSection)
303     : m_rcRet(0.0f, 0.0f, 0.0f, 0.0f),
304       m_pVT(pSection->m_pVT),
305       m_pSection(pSection) {}
306 CTypeset::~CTypeset() {}
307 CPVT_FloatRect CTypeset::CharArray() {
308   ASSERT(m_pSection != NULL);
309   ASSERT(m_pVT != NULL);
310   FX_FLOAT fLineAscent =
311       m_pVT->GetFontAscent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize());
312   FX_FLOAT fLineDescent =
313       m_pVT->GetFontDescent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize());
314   m_rcRet.Default();
315   FX_FLOAT x = 0.0f, y = 0.0f;
316   FX_FLOAT fNextWidth;
317   int32_t nStart = 0;
318   FX_FLOAT fNodeWidth = m_pVT->GetPlateWidth() /
319                         (m_pVT->m_nCharArray <= 0 ? 1 : m_pVT->m_nCharArray);
320   if (CLine* pLine = m_pSection->m_LineArray.GetAt(0)) {
321     x = 0.0f;
322     y += m_pVT->GetLineLeading(m_pSection->m_SecInfo);
323     y += fLineAscent;
324     nStart = 0;
325     switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {
326       case 0:
327         pLine->m_LineInfo.fLineX = fNodeWidth * PVT_HALF;
328         break;
329       case 1:
330         nStart = (m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize()) / 2;
331         pLine->m_LineInfo.fLineX = fNodeWidth * nStart - fNodeWidth * PVT_HALF;
332         break;
333       case 2:
334         nStart = m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize();
335         pLine->m_LineInfo.fLineX = fNodeWidth * nStart - fNodeWidth * PVT_HALF;
336         break;
337     }
338     for (int32_t w = 0, sz = m_pSection->m_WordArray.GetSize(); w < sz; w++) {
339       if (w >= m_pVT->m_nCharArray) {
340         break;
341       }
342       fNextWidth = 0;
343       if (CPVT_WordInfo* pNextWord =
344               (CPVT_WordInfo*)m_pSection->m_WordArray.GetAt(w + 1)) {
345         pNextWord->fWordTail = 0;
346         fNextWidth = m_pVT->GetWordWidth(*pNextWord);
347       }
348       if (CPVT_WordInfo* pWord =
349               (CPVT_WordInfo*)m_pSection->m_WordArray.GetAt(w)) {
350         pWord->fWordTail = 0;
351         FX_FLOAT fWordWidth = m_pVT->GetWordWidth(*pWord);
352         FX_FLOAT fWordAscent = m_pVT->GetWordAscent(*pWord);
353         FX_FLOAT fWordDescent = m_pVT->GetWordDescent(*pWord);
354         x = (FX_FLOAT)(fNodeWidth * (w + nStart + 0.5) - fWordWidth * PVT_HALF);
355         pWord->fWordX = x;
356         pWord->fWordY = y;
357         if (w == 0) {
358           pLine->m_LineInfo.fLineX = x;
359         }
360         if (w != m_pSection->m_WordArray.GetSize() - 1)
361           pWord->fWordTail =
362               (fNodeWidth - (fWordWidth + fNextWidth) * PVT_HALF > 0
363                    ? fNodeWidth - (fWordWidth + fNextWidth) * PVT_HALF
364                    : 0);
365         else {
366           pWord->fWordTail = 0;
367         }
368         x += fWordWidth;
369         fLineAscent = FPDF_MAX(fLineAscent, fWordAscent);
370         fLineDescent = FPDF_MIN(fLineDescent, fWordDescent);
371       }
372     }
373     pLine->m_LineInfo.nBeginWordIndex = 0;
374     pLine->m_LineInfo.nEndWordIndex = m_pSection->m_WordArray.GetSize() - 1;
375     pLine->m_LineInfo.fLineY = y;
376     pLine->m_LineInfo.fLineWidth = x - pLine->m_LineInfo.fLineX;
377     pLine->m_LineInfo.fLineAscent = fLineAscent;
378     pLine->m_LineInfo.fLineDescent = fLineDescent;
379     y += (-fLineDescent);
380   }
381   return m_rcRet = CPVT_FloatRect(0, 0, x, y);
382 }
383 CPVT_Size CTypeset::GetEditSize(FX_FLOAT fFontSize) {
384   ASSERT(m_pSection != NULL);
385   ASSERT(m_pVT != NULL);
386   SplitLines(FALSE, fFontSize);
387   return CPVT_Size(m_rcRet.Width(), m_rcRet.Height());
388 }
389 CPVT_FloatRect CTypeset::Typeset() {
390   ASSERT(m_pSection != NULL);
391   ASSERT(m_pVT != NULL);
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 };
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 }
432 static FX_BOOL IsDigit(FX_DWORD word) {
433   return (word >= 0x0030 && word <= 0x0039) ? TRUE : FALSE;
434 }
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 }
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 }
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 }
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 }
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 }
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 }
544 static FX_BOOL IsSpace(FX_WORD word) {
545   return (word == 0x0020 || word == 0x3000) ? TRUE : FALSE;
546 }
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 }
572 void CTypeset::SplitLines(FX_BOOL bTypeset, FX_FLOAT fFontSize) {
573   ASSERT(m_pVT != NULL);
574   ASSERT(m_pSection != NULL);
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 = FPDF_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               FPDF_MAX(fLineAscent, m_pVT->GetWordAscent(*pWord, TRUE));
604           fLineDescent =
605               FPDF_MIN(fLineDescent, m_pVT->GetWordDescent(*pWord, TRUE));
606           fWordWidth = m_pVT->GetWordWidth(*pWord);
607         } else {
608           fLineAscent =
609               FPDF_MAX(fLineAscent, m_pVT->GetWordAscent(*pWord, fFontSize));
610           fLineDescent =
611               FPDF_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 != NULL) {
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 = FPDF_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 = FPDF_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 }
719 void CTypeset::OutputLines() {
720   ASSERT(m_pVT != NULL);
721   ASSERT(m_pSection != NULL);
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 = FPDF_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 }
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) {}
808 CPDF_VariableText::~CPDF_VariableText() {
809   delete m_pVTIterator;
810   m_pVTIterator = NULL;
811   ResetAll();
812 }
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 }
835 void CPDF_VariableText::ResetAll() {
836   m_bInitial = FALSE;
837   ResetSectionArray();
838 }
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 }
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 }
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 }
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 }
962 CPVT_WordPlace CPDF_VariableText::DeleteWord(const CPVT_WordPlace& place) {
963   return ClearRightWord(AdjustLineHeader(place, TRUE));
964 }
965 CPVT_WordPlace CPDF_VariableText::BackSpaceWord(const CPVT_WordPlace& place) {
966   return ClearLeftWord(AdjustLineHeader(place, TRUE));
967 }
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 }
1028 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 }
1040 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 }
1061 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 }
1090 CPVT_WordPlace CPDF_VariableText::GetBeginWordPlace() const {
1091   return m_bInitial ? CPVT_WordPlace(0, 0, -1) : CPVT_WordPlace();
1092 }
1093 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 }
1099 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 }
1118 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 }
1137 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 }
1181 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 }
1201 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 }
1221 CPVT_WordPlace CPDF_VariableText::GetLineBeginPlace(
1222     const CPVT_WordPlace& place) const {
1223   return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);
1224 }
1225 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 }
1233 CPVT_WordPlace CPDF_VariableText::GetSectionBeginPlace(
1234     const CPVT_WordPlace& place) const {
1235   return CPVT_WordPlace(place.nSecIndex, 0, -1);
1236 }
1237 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 }
1244 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 }
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 }
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       FPDF_MAX(FPDF_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 }
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 }
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       FPDF_MAX(FPDF_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 }
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 }
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 }
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 }
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 }
1336 CPDF_Rect CPDF_VariableText::GetContentRect() const {
1337   return InToOut(CPDF_EditContainer::GetContentRect());
1338 }
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 }
1348 int32_t CPDF_VariableText::GetWordFontIndex(const CPVT_WordInfo& WordInfo) {
1349   return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nFontIndex
1350                                             : WordInfo.nFontIndex;
1351 }
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 }
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 }
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 }
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 }
1385 FX_FLOAT CPDF_VariableText::GetFontAscent(int32_t nFontIndex,
1386                                           FX_FLOAT fFontSize) {
1387   return (FX_FLOAT)GetTypeAscent(nFontIndex) * fFontSize * PVT_FONTSCALE;
1388 }
1389 FX_FLOAT CPDF_VariableText::GetFontDescent(int32_t nFontIndex,
1390                                            FX_FLOAT fFontSize) {
1391   return (FX_FLOAT)GetTypeDescent(nFontIndex) * fFontSize * PVT_FONTSCALE;
1392 }
1393 FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo& WordInfo,
1394                                           FX_FLOAT fFontSize) {
1395   return GetFontAscent(GetWordFontIndex(WordInfo), fFontSize);
1396 }
1397 FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo& WordInfo,
1398                                            FX_FLOAT fFontSize) {
1399   return GetFontDescent(GetWordFontIndex(WordInfo), fFontSize);
1400 }
1401 FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo& WordInfo,
1402                                           FX_BOOL bFactFontSize) {
1403   return GetFontAscent(GetWordFontIndex(WordInfo),
1404                        GetWordFontSize(WordInfo, bFactFontSize));
1405 }
1406 FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo& WordInfo,
1407                                            FX_BOOL bFactFontSize) {
1408   return GetFontDescent(GetWordFontIndex(WordInfo),
1409                         GetWordFontSize(WordInfo, bFactFontSize));
1410 }
1411 FX_FLOAT CPDF_VariableText::GetLineLeading(const CPVT_SectionInfo& SecInfo) {
1412   return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineLeading
1413                                           : m_fLineLeading;
1414 }
1415 FX_FLOAT CPDF_VariableText::GetLineIndent(const CPVT_SectionInfo& SecInfo) {
1416   return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineIndent
1417                                           : 0.0f;
1418 }
1419 int32_t CPDF_VariableText::GetAlignment(const CPVT_SectionInfo& SecInfo) {
1420   return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->nAlignment
1421                                           : m_nAlignment;
1422 }
1423 FX_FLOAT CPDF_VariableText::GetCharSpace(const CPVT_WordInfo& WordInfo) {
1424   return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->fCharSpace
1425                                             : m_fCharSpace;
1426 }
1427 int32_t CPDF_VariableText::GetHorzScale(const CPVT_WordInfo& WordInfo) {
1428   return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nHorzScale
1429                                             : m_nHorzScale;
1430 }
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 }
1441 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 }
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 }
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 }
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 }
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 }
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 }
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 }
1528 void CPDF_VariableText::RearrangeAll() {
1529   Rearrange(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
1530 }
1531 void CPDF_VariableText::RearrangePart(const CPVT_WordRange& PlaceRange) {
1532   Rearrange(PlaceRange);
1533 }
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 }
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 }
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 = FPDF_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 }
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 = FPDF_MIN(rcSec.left, rcRet.left);
1623         rcRet.top = FPDF_MIN(rcSec.top, rcRet.top);
1624         rcRet.right = FPDF_MAX(rcSec.right, rcRet.right);
1625         rcRet.bottom = FPDF_MAX(rcSec.bottom, rcRet.bottom);
1626       }
1627       fPosY += rcSec.Height();
1628     }
1629   }
1630   return rcRet;
1631 }
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 }
1644 int32_t CPDF_VariableText::GetTypeAscent(int32_t nFontIndex) {
1645   return m_pVTProvider ? m_pVTProvider->GetTypeAscent(nFontIndex) : 0;
1646 }
1647 int32_t CPDF_VariableText::GetTypeDescent(int32_t nFontIndex) {
1648   return m_pVTProvider ? m_pVTProvider->GetTypeDescent(nFontIndex) : 0;
1649 }
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 }
1657 int32_t CPDF_VariableText::GetDefaultFontIndex() {
1658   return m_pVTProvider ? m_pVTProvider->GetDefaultFontIndex() : -1;
1659 }
1660 FX_BOOL CPDF_VariableText::IsLatinWord(FX_WORD word) {
1661   return m_pVTProvider ? m_pVTProvider->IsLatinWord(word) : FALSE;
1662 }
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 }
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 }
1675 CPDF_VariableText_Iterator::CPDF_VariableText_Iterator(CPDF_VariableText* pVT)
1676     : m_CurPos(-1, -1, -1), m_pVT(pVT) {}
1677 CPDF_VariableText_Iterator::~CPDF_VariableText_Iterator() {}
1678 void CPDF_VariableText_Iterator::SetAt(int32_t nWordIndex) {
1679   ASSERT(m_pVT != NULL);
1680   m_CurPos = m_pVT->WordIndexToWordPlace(nWordIndex);
1681 }
1682 void CPDF_VariableText_Iterator::SetAt(const CPVT_WordPlace& place) {
1683   ASSERT(m_pVT != NULL);
1684   m_CurPos = place;
1685 }
1686 FX_BOOL CPDF_VariableText_Iterator::NextWord() {
1687   if (m_CurPos == m_pVT->GetEndWordPlace()) {
1688     return FALSE;
1689   }
1690   m_CurPos = m_pVT->GetNextWordPlace(m_CurPos);
1691   return TRUE;
1692 }
1693 FX_BOOL CPDF_VariableText_Iterator::PrevWord() {
1694   if (m_CurPos == m_pVT->GetBeginWordPlace()) {
1695     return FALSE;
1696   }
1697   m_CurPos = m_pVT->GetPrevWordPlace(m_CurPos);
1698   return TRUE;
1699 }
1700 FX_BOOL CPDF_VariableText_Iterator::NextLine() {
1701   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1702     if (m_CurPos.nLineIndex < pSection->m_LineArray.GetSize() - 1) {
1703       m_CurPos =
1704           CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex + 1, -1);
1705       return TRUE;
1706     }
1707     if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
1708       m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
1709       return TRUE;
1710     }
1711   }
1712   return FALSE;
1713 }
1714 FX_BOOL CPDF_VariableText_Iterator::PrevLine() {
1715   if (m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1716     if (m_CurPos.nLineIndex > 0) {
1717       m_CurPos =
1718           CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex - 1, -1);
1719       return TRUE;
1720     }
1721     if (m_CurPos.nSecIndex > 0) {
1722       if (CSection* pLastSection =
1723               m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex - 1)) {
1724         m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1,
1725                                   pLastSection->m_LineArray.GetSize() - 1, -1);
1726         return TRUE;
1727       }
1728     }
1729   }
1730   return FALSE;
1731 }
1732 FX_BOOL CPDF_VariableText_Iterator::NextSection() {
1733   if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
1734     m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
1735     return TRUE;
1736   }
1737   return FALSE;
1738 }
1739 FX_BOOL CPDF_VariableText_Iterator::PrevSection() {
1740   ASSERT(m_pVT != NULL);
1741   if (m_CurPos.nSecIndex > 0) {
1742     m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, 0, -1);
1743     return TRUE;
1744   }
1745   return FALSE;
1746 }
1747 FX_BOOL CPDF_VariableText_Iterator::GetWord(CPVT_Word& word) const {
1748   ASSERT(m_pVT != NULL);
1749   word.WordPlace = m_CurPos;
1750   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1751     if (pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
1752       if (CPVT_WordInfo* pWord =
1753               pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
1754         word.Word = pWord->Word;
1755         word.nCharset = pWord->nCharset;
1756         word.fWidth = m_pVT->GetWordWidth(*pWord);
1757         word.ptWord = m_pVT->InToOut(
1758             CPDF_Point(pWord->fWordX + pSection->m_SecInfo.rcSection.left,
1759                        pWord->fWordY + pSection->m_SecInfo.rcSection.top));
1760         word.fAscent = m_pVT->GetWordAscent(*pWord);
1761         word.fDescent = m_pVT->GetWordDescent(*pWord);
1762         if (pWord->pWordProps) {
1763           word.WordProps = *pWord->pWordProps;
1764         }
1765         word.nFontIndex = m_pVT->GetWordFontIndex(*pWord);
1766         word.fFontSize = m_pVT->GetWordFontSize(*pWord);
1767         return TRUE;
1768       }
1769     }
1770   }
1771   return FALSE;
1772 }
1773 FX_BOOL CPDF_VariableText_Iterator::SetWord(const CPVT_Word& word) {
1774   ASSERT(m_pVT != NULL);
1775   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1776     if (CPVT_WordInfo* pWord =
1777             pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
1778       if (pWord->pWordProps) {
1779         *pWord->pWordProps = word.WordProps;
1780       }
1781       return TRUE;
1782     }
1783   }
1784   return FALSE;
1785 }
1786 FX_BOOL CPDF_VariableText_Iterator::GetLine(CPVT_Line& line) const {
1787   ASSERT(m_pVT != NULL);
1788   line.lineplace = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex, -1);
1789   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1790     if (CLine* pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
1791       line.ptLine = m_pVT->InToOut(CPDF_Point(
1792           pLine->m_LineInfo.fLineX + pSection->m_SecInfo.rcSection.left,
1793           pLine->m_LineInfo.fLineY + pSection->m_SecInfo.rcSection.top));
1794       line.fLineWidth = pLine->m_LineInfo.fLineWidth;
1795       line.fLineAscent = pLine->m_LineInfo.fLineAscent;
1796       line.fLineDescent = pLine->m_LineInfo.fLineDescent;
1797       line.lineEnd = pLine->GetEndWordPlace();
1798       return TRUE;
1799     }
1800   }
1801   return FALSE;
1802 }
1803 FX_BOOL CPDF_VariableText_Iterator::GetSection(CPVT_Section& section) const {
1804   ASSERT(m_pVT != NULL);
1805   section.secplace = CPVT_WordPlace(m_CurPos.nSecIndex, 0, -1);
1806   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1807     section.rcSection = m_pVT->InToOut(pSection->m_SecInfo.rcSection);
1808     if (pSection->m_SecInfo.pSecProps) {
1809       section.SecProps = *pSection->m_SecInfo.pSecProps;
1810     }
1811     if (pSection->m_SecInfo.pWordProps) {
1812       section.WordProps = *pSection->m_SecInfo.pWordProps;
1813     }
1814     return TRUE;
1815   }
1816   return FALSE;
1817 }
1818 FX_BOOL CPDF_VariableText_Iterator::SetSection(const CPVT_Section& section) {
1819   ASSERT(m_pVT != NULL);
1820   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1821     if (pSection->m_SecInfo.pSecProps) {
1822       *pSection->m_SecInfo.pSecProps = section.SecProps;
1823     }
1824     if (pSection->m_SecInfo.pWordProps) {
1825       *pSection->m_SecInfo.pWordProps = section.WordProps;
1826     }
1827     return TRUE;
1828   }
1829   return FALSE;
1830 }