b7c8ed80f6b8fcfb9e99a9bf4cd7cf791659f5f1
[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(AjustLineHeader(place, TRUE));
964 }
965 CPVT_WordPlace CPDF_VariableText::BackSpaceWord(const CPVT_WordPlace& place) {
966   return ClearLeftWord(AjustLineHeader(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 = AjustLineHeader(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 = AjustLineHeader(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::AjustLineHeader(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 = AjustLineHeader(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 = AjustLineHeader(PlaceRange.BeginPos, TRUE);
1488   NewRange.EndPos = AjustLineHeader(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 = AjustLineHeader(GetNextWordPlace(place), FALSE);
1517     if (rightplace != place) {
1518       if (rightplace.nSecIndex != place.nSecIndex) {
1519         LinkLatterSection(place);
1520       } else {
1521         pSection->ClearWord(rightplace);
1522       }
1523     }
1524   }
1525   return place;
1526 }
1527 void CPDF_VariableText::RearrangeAll() {
1528   Rearrange(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
1529 }
1530 void CPDF_VariableText::RearrangePart(const CPVT_WordRange& PlaceRange) {
1531   Rearrange(PlaceRange);
1532 }
1533 CPVT_FloatRect CPDF_VariableText::Rearrange(const CPVT_WordRange& PlaceRange) {
1534   CPVT_FloatRect rcRet;
1535   if (IsValid()) {
1536     if (m_bAutoFontSize) {
1537       SetFontSize(GetAutoFontSize());
1538       rcRet = RearrangeSections(
1539           CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
1540     } else {
1541       rcRet = RearrangeSections(PlaceRange);
1542     }
1543   }
1544   SetContentRect(rcRet);
1545   return rcRet;
1546 }
1547 FX_FLOAT CPDF_VariableText::GetAutoFontSize() {
1548   int32_t nTotal = sizeof(gFontSizeSteps) / sizeof(uint8_t);
1549   if (IsMultiLine()) {
1550     nTotal /= 4;
1551   }
1552   if (nTotal <= 0) {
1553     return 0;
1554   }
1555   if (GetPlateWidth() <= 0) {
1556     return 0;
1557   }
1558   int32_t nLeft = 0;
1559   int32_t nRight = nTotal - 1;
1560   int32_t nMid = nTotal / 2;
1561   while (nLeft <= nRight) {
1562     if (IsBigger(gFontSizeSteps[nMid])) {
1563       nRight = nMid - 1;
1564       nMid = (nLeft + nRight) / 2;
1565       continue;
1566     } else {
1567       nLeft = nMid + 1;
1568       nMid = (nLeft + nRight) / 2;
1569       continue;
1570     }
1571   }
1572   return (FX_FLOAT)gFontSizeSteps[nMid];
1573 }
1574 FX_BOOL CPDF_VariableText::IsBigger(FX_FLOAT fFontSize) {
1575   FX_BOOL bBigger = FALSE;
1576   CPVT_Size szTotal;
1577   for (int32_t s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
1578     if (CSection* pSection = m_SectionArray.GetAt(s)) {
1579       CPVT_Size size = pSection->GetSectionSize(fFontSize);
1580       szTotal.x = FPDF_MAX(size.x, szTotal.x);
1581       szTotal.y += size.y;
1582       if (IsFloatBigger(szTotal.x, GetPlateWidth()) ||
1583           IsFloatBigger(szTotal.y, GetPlateHeight())) {
1584         bBigger = TRUE;
1585         break;
1586       }
1587     }
1588   }
1589   return bBigger;
1590 }
1591 CPVT_FloatRect CPDF_VariableText::RearrangeSections(
1592     const CPVT_WordRange& PlaceRange) {
1593   CPVT_WordPlace place;
1594   FX_FLOAT fPosY = 0;
1595   FX_FLOAT fOldHeight;
1596   int32_t nSSecIndex = PlaceRange.BeginPos.nSecIndex;
1597   int32_t nESecIndex = PlaceRange.EndPos.nSecIndex;
1598   CPVT_FloatRect rcRet;
1599   for (int32_t s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
1600     place.nSecIndex = s;
1601     if (CSection* pSection = m_SectionArray.GetAt(s)) {
1602       pSection->SecPlace = place;
1603       CPVT_FloatRect rcSec = pSection->m_SecInfo.rcSection;
1604       if (s >= nSSecIndex) {
1605         if (s <= nESecIndex) {
1606           rcSec = pSection->Rearrange();
1607           rcSec.top += fPosY;
1608           rcSec.bottom += fPosY;
1609         } else {
1610           fOldHeight = pSection->m_SecInfo.rcSection.bottom -
1611                        pSection->m_SecInfo.rcSection.top;
1612           rcSec.top = fPosY;
1613           rcSec.bottom = fPosY + fOldHeight;
1614         }
1615         pSection->m_SecInfo.rcSection = rcSec;
1616         pSection->ResetLinePlace();
1617       }
1618       if (s == 0) {
1619         rcRet = rcSec;
1620       } else {
1621         rcRet.left = FPDF_MIN(rcSec.left, rcRet.left);
1622         rcRet.top = FPDF_MIN(rcSec.top, rcRet.top);
1623         rcRet.right = FPDF_MAX(rcSec.right, rcRet.right);
1624         rcRet.bottom = FPDF_MAX(rcSec.bottom, rcRet.bottom);
1625       }
1626       fPosY += rcSec.Height();
1627     }
1628   }
1629   return rcRet;
1630 }
1631 int32_t CPDF_VariableText::GetCharWidth(int32_t nFontIndex,
1632                                         FX_WORD Word,
1633                                         FX_WORD SubWord,
1634                                         int32_t nWordStyle) {
1635   if (!m_pVTProvider) {
1636     return 0;
1637   }
1638   if (SubWord > 0) {
1639     return m_pVTProvider->GetCharWidth(nFontIndex, SubWord, nWordStyle);
1640   }
1641   return m_pVTProvider->GetCharWidth(nFontIndex, Word, nWordStyle);
1642 }
1643 int32_t CPDF_VariableText::GetTypeAscent(int32_t nFontIndex) {
1644   return m_pVTProvider ? m_pVTProvider->GetTypeAscent(nFontIndex) : 0;
1645 }
1646 int32_t CPDF_VariableText::GetTypeDescent(int32_t nFontIndex) {
1647   return m_pVTProvider ? m_pVTProvider->GetTypeDescent(nFontIndex) : 0;
1648 }
1649 int32_t CPDF_VariableText::GetWordFontIndex(FX_WORD word,
1650                                             int32_t charset,
1651                                             int32_t nFontIndex) {
1652   return m_pVTProvider
1653              ? m_pVTProvider->GetWordFontIndex(word, charset, nFontIndex)
1654              : -1;
1655 }
1656 int32_t CPDF_VariableText::GetDefaultFontIndex() {
1657   return m_pVTProvider ? m_pVTProvider->GetDefaultFontIndex() : -1;
1658 }
1659 FX_BOOL CPDF_VariableText::IsLatinWord(FX_WORD word) {
1660   return m_pVTProvider ? m_pVTProvider->IsLatinWord(word) : FALSE;
1661 }
1662 IPDF_VariableText_Iterator* CPDF_VariableText::GetIterator() {
1663   if (!m_pVTIterator) {
1664     m_pVTIterator = new CPDF_VariableText_Iterator(this);
1665   }
1666   return m_pVTIterator;
1667 }
1668 IPDF_VariableText_Provider* CPDF_VariableText::SetProvider(
1669     IPDF_VariableText_Provider* pProvider) {
1670   IPDF_VariableText_Provider* pOld = m_pVTProvider;
1671   m_pVTProvider = pProvider;
1672   return pOld;
1673 }
1674 CPDF_VariableText_Iterator::CPDF_VariableText_Iterator(CPDF_VariableText* pVT)
1675     : m_CurPos(-1, -1, -1), m_pVT(pVT) {}
1676 CPDF_VariableText_Iterator::~CPDF_VariableText_Iterator() {}
1677 void CPDF_VariableText_Iterator::SetAt(int32_t nWordIndex) {
1678   ASSERT(m_pVT != NULL);
1679   m_CurPos = m_pVT->WordIndexToWordPlace(nWordIndex);
1680 }
1681 void CPDF_VariableText_Iterator::SetAt(const CPVT_WordPlace& place) {
1682   ASSERT(m_pVT != NULL);
1683   m_CurPos = place;
1684 }
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 }
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 }
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 }
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 }
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 }
1738 FX_BOOL CPDF_VariableText_Iterator::PrevSection() {
1739   ASSERT(m_pVT != NULL);
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 }
1746 FX_BOOL CPDF_VariableText_Iterator::GetWord(CPVT_Word& word) const {
1747   ASSERT(m_pVT != NULL);
1748   word.WordPlace = m_CurPos;
1749   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1750     if (pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
1751       if (CPVT_WordInfo* pWord =
1752               pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
1753         word.Word = pWord->Word;
1754         word.nCharset = pWord->nCharset;
1755         word.fWidth = m_pVT->GetWordWidth(*pWord);
1756         word.ptWord = m_pVT->InToOut(
1757             CPDF_Point(pWord->fWordX + pSection->m_SecInfo.rcSection.left,
1758                        pWord->fWordY + pSection->m_SecInfo.rcSection.top));
1759         word.fAscent = m_pVT->GetWordAscent(*pWord);
1760         word.fDescent = m_pVT->GetWordDescent(*pWord);
1761         if (pWord->pWordProps) {
1762           word.WordProps = *pWord->pWordProps;
1763         }
1764         word.nFontIndex = m_pVT->GetWordFontIndex(*pWord);
1765         word.fFontSize = m_pVT->GetWordFontSize(*pWord);
1766         return TRUE;
1767       }
1768     }
1769   }
1770   return FALSE;
1771 }
1772 FX_BOOL CPDF_VariableText_Iterator::SetWord(const CPVT_Word& word) {
1773   ASSERT(m_pVT != NULL);
1774   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1775     if (CPVT_WordInfo* pWord =
1776             pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
1777       if (pWord->pWordProps) {
1778         *pWord->pWordProps = word.WordProps;
1779       }
1780       return TRUE;
1781     }
1782   }
1783   return FALSE;
1784 }
1785 FX_BOOL CPDF_VariableText_Iterator::GetLine(CPVT_Line& line) const {
1786   ASSERT(m_pVT != NULL);
1787   line.lineplace = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex, -1);
1788   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1789     if (CLine* pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
1790       line.ptLine = m_pVT->InToOut(CPDF_Point(
1791           pLine->m_LineInfo.fLineX + pSection->m_SecInfo.rcSection.left,
1792           pLine->m_LineInfo.fLineY + pSection->m_SecInfo.rcSection.top));
1793       line.fLineWidth = pLine->m_LineInfo.fLineWidth;
1794       line.fLineAscent = pLine->m_LineInfo.fLineAscent;
1795       line.fLineDescent = pLine->m_LineInfo.fLineDescent;
1796       line.lineEnd = pLine->GetEndWordPlace();
1797       return TRUE;
1798     }
1799   }
1800   return FALSE;
1801 }
1802 FX_BOOL CPDF_VariableText_Iterator::GetSection(CPVT_Section& section) const {
1803   ASSERT(m_pVT != NULL);
1804   section.secplace = CPVT_WordPlace(m_CurPos.nSecIndex, 0, -1);
1805   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1806     section.rcSection = m_pVT->InToOut(pSection->m_SecInfo.rcSection);
1807     if (pSection->m_SecInfo.pSecProps) {
1808       section.SecProps = *pSection->m_SecInfo.pSecProps;
1809     }
1810     if (pSection->m_SecInfo.pWordProps) {
1811       section.WordProps = *pSection->m_SecInfo.pWordProps;
1812     }
1813     return TRUE;
1814   }
1815   return FALSE;
1816 }
1817 FX_BOOL CPDF_VariableText_Iterator::SetSection(const CPVT_Section& section) {
1818   ASSERT(m_pVT != NULL);
1819   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1820     if (pSection->m_SecInfo.pSecProps) {
1821       *pSection->m_SecInfo.pSecProps = section.SecProps;
1822     }
1823     if (pSection->m_SecInfo.pWordProps) {
1824       *pSection->m_SecInfo.pWordProps = section.WordProps;
1825     }
1826     return TRUE;
1827   }
1828   return FALSE;
1829 }