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