Fix a few more warnings in chromium_code mode.
[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 FX_BYTE 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 (FX_INT32 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 (FX_INT32 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         FX_INT32 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     FX_INT32 nLeft = 0;
166     FX_INT32 nRight = m_LineArray.GetSize() - 1;
167     FX_INT32 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     FX_INT32 nLeft = 0;
192     FX_INT32 nRight = m_LineArray.GetSize() - 1;
193     FX_INT32 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     FX_INT32 nLeft = range.BeginPos.nWordIndex;
247     FX_INT32 nRight = range.EndPos.nWordIndex + 1;
248     FX_INT32 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(FX_INT32 nWordIndex)
279 {
280     for (FX_INT32 i = nWordIndex; i >= 0; i--) {
281         delete m_WordArray.GetAt(i);
282         m_WordArray.RemoveAt(i);
283     }
284 }
285 void CSection::ClearRightWords(FX_INT32 nWordIndex)
286 {
287     for (FX_INT32 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(FX_INT32 nBeginIndex, FX_INT32 nEndIndex)
293 {
294     for (FX_INT32 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_pSection(pSection), m_pVT(pSection->m_pVT), m_rcRet(0.0f, 0.0f, 0.0f, 0.0f)
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     FX_INT32 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 (FX_INT32 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     FX_INT32 nLineHead = 0;
595     FX_INT32 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     FX_INT32 nWordStartPos = 0;
601     FX_BOOL bFullWord = FALSE;
602     FX_INT32 nLineFullWordIndex = 0;
603     FX_INT32 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     FX_INT32 nTotalWords = m_pSection->m_WordArray.GetSize();
608     FX_BOOL bOpened = FALSE;
609     if (nTotalWords > 0) {
610         FX_INT32 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     FX_INT32 nTotalLines = m_pSection->m_LineArray.GetSize();
757     if (nTotalLines > 0) {
758         m_pSection->m_SecInfo.nTotalLine = nTotalLines;
759         for (FX_INT32 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 (FX_INT32 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_pVTProvider(NULL),
808     m_pVTIterator(NULL),
809     m_bInitial(FALSE),
810     m_bRichText(FALSE),
811     m_bMultiLine(FALSE),
812     m_bLimitWidth(FALSE),
813     m_bAutoFontSize(FALSE),
814     m_nLimitChar(0),
815     m_nCharArray(0),
816     m_nAlignment(0),
817     m_fCharSpace(0.0f),
818     m_fFontSize(0.0f),
819     m_nHorzScale(100),
820     m_wSubWord(0),
821     m_fLineLeading(0.0f)
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, FX_INT32 charset,
859         const CPVT_WordProps * pWordProps)
860 {
861     FX_INT32 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         FX_INT32 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     FX_INT32 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 (FX_INT32 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, FX_INT32 charset,
924         const CPVT_SecProps * pSecProps, const CPVT_WordProps * pProps)
925 {
926     CFX_WideString swText = text;
927     CPVT_WordPlace wp = place;
928     for (FX_INT32 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, FX_INT32 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     FX_INT32 nCharCount = 0;
1002     for (FX_INT32 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 FX_INT32 CPDF_VariableText::WordPlaceToWordIndex(const CPVT_WordPlace & place) const
1056 {
1057     CPVT_WordPlace newplace = place;
1058     UpdateWordPlace(newplace);
1059     FX_INT32 nIndex = 0;
1060     FX_INT32 i = 0;
1061     FX_INT32 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(FX_INT32 index) const
1076 {
1077     CPVT_WordPlace place = GetBeginWordPlace();
1078     FX_INT32 nOldIndex = 0 , nIndex = 0;
1079     FX_BOOL bFind = FALSE;
1080     for (FX_INT32 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     FX_INT32 nLeft = 0;
1163     FX_INT32 nRight = m_SectionArray.GetSize() - 1;
1164     FX_INT32 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 FX_INT32 CPDF_VariableText::GetTotalWords() const
1262 {
1263     FX_INT32 nTotal = 0;
1264     for (FX_INT32 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 (FX_INT32 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     FX_INT32 nSecIndex = FPDF_MAX(FPDF_MIN(place.nSecIndex, m_SectionArray.GetSize()), 0);
1283     CSection * pSection = FX_NEW CSection(this);
1284     if (!pSection) {
1285         return place;
1286     }
1287     pSection->m_SecInfo = secinfo;
1288     pSection->SecPlace.nSecIndex = nSecIndex;
1289     if (nSecIndex == m_SectionArray.GetSize()) {
1290         m_SectionArray.Add(pSection);
1291     } else {
1292         m_SectionArray.InsertAt(nSecIndex, pSection);
1293     }
1294     return place;
1295 }
1296 CPVT_WordPlace CPDF_VariableText::AddLine(const CPVT_WordPlace & place, const CPVT_LineInfo & lineinfo)
1297 {
1298     if (m_SectionArray.IsEmpty()) {
1299         return place;
1300     }
1301     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1302         return pSection->AddLine(lineinfo);
1303     }
1304     return place;
1305 }
1306 CPVT_WordPlace CPDF_VariableText::AddWord(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)
1307 {
1308     if (m_SectionArray.GetSize() <= 0) {
1309         return place;
1310     }
1311     CPVT_WordPlace newplace = place;
1312     newplace.nSecIndex = FPDF_MAX(FPDF_MIN(newplace.nSecIndex, m_SectionArray.GetSize() - 1), 0);
1313     if (CSection * pSection = m_SectionArray.GetAt(newplace.nSecIndex)) {
1314         return pSection->AddWord(newplace, wordinfo);
1315     }
1316     return place;
1317 }
1318 FX_BOOL CPDF_VariableText::GetWordInfo(const CPVT_WordPlace & place, CPVT_WordInfo & wordinfo)
1319 {
1320     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1321         if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {
1322             wordinfo = *pWord;
1323             return TRUE;
1324         }
1325     }
1326     return FALSE;
1327 }
1328 FX_BOOL CPDF_VariableText::SetWordInfo(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)
1329 {
1330     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1331         if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {
1332             *pWord = wordinfo;
1333             return TRUE;
1334         }
1335     }
1336     return FALSE;
1337 }
1338 FX_BOOL CPDF_VariableText::GetLineInfo(const CPVT_WordPlace & place, CPVT_LineInfo & lineinfo)
1339 {
1340     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1341         if (CLine * pLine = pSection->m_LineArray.GetAt(place.nLineIndex)) {
1342             lineinfo = pLine->m_LineInfo;
1343             return TRUE;
1344         }
1345     }
1346     return FALSE;
1347 }
1348 FX_BOOL CPDF_VariableText::GetSectionInfo(const CPVT_WordPlace & place, CPVT_SectionInfo & secinfo)
1349 {
1350     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1351         secinfo = pSection->m_SecInfo;
1352         return TRUE;
1353     }
1354     return FALSE;
1355 }
1356 CPDF_Rect CPDF_VariableText::GetContentRect() const
1357 {
1358     return InToOut(CPDF_EditContainer::GetContentRect());
1359 }
1360 FX_FLOAT CPDF_VariableText::GetWordFontSize(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)
1361 {
1362     return m_bRichText && WordInfo.pWordProps ? (WordInfo.pWordProps->nScriptType == PVTWORD_SCRIPT_NORMAL || bFactFontSize ? WordInfo.pWordProps->fFontSize : WordInfo.pWordProps->fFontSize * PVT_HALF) : GetFontSize();
1363 }
1364 FX_INT32 CPDF_VariableText::GetWordFontIndex(const CPVT_WordInfo & WordInfo)
1365 {
1366     return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nFontIndex : WordInfo.nFontIndex;
1367 }
1368 FX_FLOAT CPDF_VariableText::GetWordWidth(FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord,
1369         FX_FLOAT fCharSpace, FX_INT32 nHorzScale,
1370         FX_FLOAT fFontSize, FX_FLOAT fWordTail, FX_INT32 nWordStyle)
1371 {
1372     return (GetCharWidth(nFontIndex, Word, SubWord, nWordStyle) * fFontSize * PVT_FONTSCALE + fCharSpace) * nHorzScale * PVT_PERCENT + fWordTail;
1373 }
1374 FX_FLOAT CPDF_VariableText::GetWordWidth(const CPVT_WordInfo & WordInfo)
1375 {
1376     return GetWordWidth(GetWordFontIndex(WordInfo), WordInfo.Word, GetSubWord(), GetCharSpace(WordInfo), GetHorzScale(WordInfo),
1377                         GetWordFontSize(WordInfo), WordInfo.fWordTail,
1378                         WordInfo.pWordProps ? WordInfo.pWordProps->nWordStyle : 0);
1379 }
1380 FX_FLOAT CPDF_VariableText::GetLineAscent(const CPVT_SectionInfo & SecInfo)
1381 {
1382     return m_bRichText && SecInfo.pWordProps ? GetFontAscent(SecInfo.pWordProps->nFontIndex, SecInfo.pWordProps->fFontSize) :
1383            GetFontAscent(GetDefaultFontIndex(), GetFontSize());
1384 }
1385 FX_FLOAT CPDF_VariableText::GetLineDescent(const CPVT_SectionInfo & SecInfo)
1386 {
1387     return m_bRichText && SecInfo.pWordProps ? GetFontDescent(SecInfo.pWordProps->nFontIndex, SecInfo.pWordProps->fFontSize) :
1388            GetFontDescent(GetDefaultFontIndex(), GetFontSize());
1389 }
1390 FX_FLOAT CPDF_VariableText::GetFontAscent(FX_INT32 nFontIndex, FX_FLOAT fFontSize)
1391 {
1392     return (FX_FLOAT)GetTypeAscent(nFontIndex) * fFontSize * PVT_FONTSCALE;
1393 }
1394 FX_FLOAT CPDF_VariableText::GetFontDescent(FX_INT32 nFontIndex, FX_FLOAT fFontSize)
1395 {
1396     return (FX_FLOAT)GetTypeDescent(nFontIndex) * fFontSize * PVT_FONTSCALE;
1397 }
1398 FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize)
1399 {
1400     return GetFontAscent(GetWordFontIndex(WordInfo), fFontSize);
1401 }
1402 FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize)
1403 {
1404     return GetFontDescent(GetWordFontIndex(WordInfo), fFontSize);
1405 }
1406 FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)
1407 {
1408     return GetFontAscent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo, bFactFontSize));
1409 }
1410 FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)
1411 {
1412     return GetFontDescent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo, bFactFontSize));
1413 }
1414 FX_FLOAT CPDF_VariableText::GetLineLeading(const CPVT_SectionInfo & SecInfo)
1415 {
1416     return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineLeading : m_fLineLeading;
1417 }
1418 FX_FLOAT CPDF_VariableText::GetLineIndent(const CPVT_SectionInfo & SecInfo)
1419 {
1420     return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineIndent : 0.0f;
1421 }
1422 FX_INT32 CPDF_VariableText::GetAlignment(const CPVT_SectionInfo& SecInfo)
1423 {
1424     return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->nAlignment : this->m_nAlignment;
1425 }
1426 FX_FLOAT CPDF_VariableText::GetCharSpace(const CPVT_WordInfo & WordInfo)
1427 {
1428     return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->fCharSpace : m_fCharSpace;
1429 }
1430 FX_INT32 CPDF_VariableText::GetHorzScale(const CPVT_WordInfo & WordInfo)
1431 {
1432     return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nHorzScale : m_nHorzScale;
1433 }
1434 void CPDF_VariableText::ClearSectionRightWords(const CPVT_WordPlace & place)
1435 {
1436     CPVT_WordPlace wordplace = AjustLineHeader(place, TRUE);
1437     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1438         for (FX_INT32 w = pSection->m_WordArray.GetSize() - 1; w > wordplace.nWordIndex; w--) {
1439             delete pSection->m_WordArray.GetAt(w);
1440             pSection->m_WordArray.RemoveAt(w);
1441         }
1442     }
1443 }
1444 CPVT_WordPlace CPDF_VariableText::AjustLineHeader(const CPVT_WordPlace & place, FX_BOOL bPrevOrNext) const
1445 {
1446     if (place.nWordIndex < 0 && place.nLineIndex > 0) {
1447         if (bPrevOrNext) {
1448             return GetPrevWordPlace(place);
1449         } else {
1450             return GetNextWordPlace(place);
1451         }
1452     }
1453     return place;
1454 }
1455 FX_BOOL CPDF_VariableText::ClearEmptySection(const CPVT_WordPlace & place)
1456 {
1457     if (place.nSecIndex == 0 && m_SectionArray.GetSize() == 1) {
1458         return FALSE;
1459     }
1460     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1461         if (pSection->m_WordArray.GetSize() == 0) {
1462             delete pSection;
1463             m_SectionArray.RemoveAt(place.nSecIndex);
1464             return TRUE;
1465         }
1466     }
1467     return FALSE;
1468 }
1469 void CPDF_VariableText::ClearEmptySections(const CPVT_WordRange & PlaceRange)
1470 {
1471     CPVT_WordPlace wordplace;
1472     for (FX_INT32 s = PlaceRange.EndPos.nSecIndex; s > PlaceRange.BeginPos.nSecIndex; s--) {
1473         wordplace.nSecIndex = s;
1474         ClearEmptySection(wordplace);
1475     }
1476 }
1477 void CPDF_VariableText::LinkLatterSection(const CPVT_WordPlace & place)
1478 {
1479     CPVT_WordPlace oldplace = AjustLineHeader(place, TRUE);
1480     if (CSection * pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) {
1481         if (CSection * pSection = m_SectionArray.GetAt(oldplace.nSecIndex)) {
1482             for (FX_INT32 w = 0, sz = pNextSection->m_WordArray.GetSize(); w < sz; w++) {
1483                 if (CPVT_WordInfo * pWord = pNextSection->m_WordArray.GetAt(w)) {
1484                     oldplace.nWordIndex ++;
1485                     pSection->AddWord(oldplace, *pWord);
1486                 }
1487             }
1488         }
1489         delete pNextSection;
1490         m_SectionArray.RemoveAt(place.nSecIndex + 1);
1491     }
1492 }
1493 void CPDF_VariableText::ClearWords(const CPVT_WordRange & PlaceRange)
1494 {
1495     CPVT_WordRange NewRange;
1496     NewRange.BeginPos = AjustLineHeader(PlaceRange.BeginPos, TRUE);
1497     NewRange.EndPos = AjustLineHeader(PlaceRange.EndPos, TRUE);
1498     for (FX_INT32 s = NewRange.EndPos.nSecIndex; s >= NewRange.BeginPos.nSecIndex; s--) {
1499         if (CSection * pSection = m_SectionArray.GetAt(s)) {
1500             pSection->ClearWords(NewRange);
1501         }
1502     }
1503 }
1504 CPVT_WordPlace CPDF_VariableText::ClearLeftWord(const CPVT_WordPlace & place)
1505 {
1506     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1507         CPVT_WordPlace leftplace = this->GetPrevWordPlace(place);
1508         if (leftplace != place) {
1509             if (leftplace.nSecIndex != place.nSecIndex) {
1510                 if (pSection->m_WordArray.GetSize() == 0) {
1511                     this->ClearEmptySection(place);
1512                 } else {
1513                     this->LinkLatterSection(leftplace);
1514                 }
1515             } else {
1516                 pSection->ClearWord(place);
1517             }
1518         }
1519         return leftplace;
1520     }
1521     return place;
1522 }
1523 CPVT_WordPlace CPDF_VariableText::ClearRightWord(const CPVT_WordPlace & place)
1524 {
1525     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1526         CPVT_WordPlace rightplace = AjustLineHeader(this->GetNextWordPlace(place), FALSE);
1527         if (rightplace != place) {
1528             if(rightplace.nSecIndex != place.nSecIndex) {
1529                 LinkLatterSection(place);
1530             } else {
1531                 pSection->ClearWord(rightplace);
1532             }
1533         }
1534     }
1535     return place;
1536 }
1537 void CPDF_VariableText::RearrangeAll()
1538 {
1539     Rearrange(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
1540 }
1541 void CPDF_VariableText::RearrangePart(const CPVT_WordRange & PlaceRange)
1542 {
1543     Rearrange(PlaceRange);
1544 }
1545 CPVT_FloatRect CPDF_VariableText::Rearrange(const CPVT_WordRange & PlaceRange)
1546 {
1547     CPVT_FloatRect rcRet;
1548     if (IsValid()) {
1549         if (m_bAutoFontSize) {
1550             SetFontSize(GetAutoFontSize());
1551             rcRet = RearrangeSections(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
1552         } else {
1553             rcRet = RearrangeSections(PlaceRange);
1554         }
1555     }
1556     SetContentRect(rcRet);
1557     return rcRet;
1558 }
1559 FX_FLOAT CPDF_VariableText::GetAutoFontSize()
1560 {
1561     FX_INT32 nTotal = sizeof(gFontSizeSteps) / sizeof(FX_BYTE);
1562     if (IsMultiLine()) {
1563         nTotal /= 4;
1564     }
1565     if (nTotal <= 0) {
1566         return 0;
1567     }
1568     if (GetPlateWidth() <= 0) {
1569         return 0;
1570     }
1571     FX_INT32 nLeft = 0;
1572     FX_INT32 nRight = nTotal - 1;
1573     FX_INT32 nMid = nTotal / 2;
1574     while (nLeft <= nRight) {
1575         if (IsBigger(gFontSizeSteps[nMid])) {
1576             nRight = nMid - 1;
1577             nMid = (nLeft + nRight) / 2;
1578             continue;
1579         } else {
1580             nLeft = nMid + 1;
1581             nMid = (nLeft + nRight) / 2;
1582             continue;
1583         }
1584     }
1585     return (FX_FLOAT)gFontSizeSteps[nMid];
1586 }
1587 FX_BOOL CPDF_VariableText::IsBigger(FX_FLOAT fFontSize)
1588 {
1589     FX_BOOL bBigger =  FALSE;
1590     CPVT_Size szTotal;
1591     for (FX_INT32 s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
1592         if (CSection * pSection = m_SectionArray.GetAt(s)) {
1593             CPVT_Size size = pSection->GetSectionSize(fFontSize);
1594             szTotal.x = FPDF_MAX(size.x, szTotal.x);
1595             szTotal.y += size.y;
1596             if (IsFloatBigger(szTotal.x, GetPlateWidth())
1597                     || IsFloatBigger(szTotal.y, GetPlateHeight())
1598                ) {
1599                 bBigger = TRUE;
1600                 break;
1601             }
1602         }
1603     }
1604     return bBigger;
1605 }
1606 CPVT_FloatRect CPDF_VariableText::RearrangeSections(const CPVT_WordRange & PlaceRange)
1607 {
1608     CPVT_WordPlace place;
1609     FX_FLOAT fPosY = 0;
1610     FX_FLOAT fOldHeight;
1611     FX_INT32 nSSecIndex = PlaceRange.BeginPos.nSecIndex;
1612     FX_INT32 nESecIndex = PlaceRange.EndPos.nSecIndex;
1613     CPVT_FloatRect rcRet;
1614     for (FX_INT32 s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
1615         place.nSecIndex = s;
1616         if (CSection * pSection = m_SectionArray.GetAt(s)) {
1617             pSection->SecPlace = place;
1618             CPVT_FloatRect rcSec = pSection->m_SecInfo.rcSection;
1619             if (s >= nSSecIndex) {
1620                 if (s <= nESecIndex) {
1621                     rcSec = pSection->Rearrange();
1622                     rcSec.top += fPosY;
1623                     rcSec.bottom += fPosY;
1624                 } else {
1625                     fOldHeight = pSection->m_SecInfo.rcSection.bottom - pSection->m_SecInfo.rcSection.top;
1626                     rcSec.top = fPosY;
1627                     rcSec.bottom = fPosY + fOldHeight;
1628                 }
1629                 pSection->m_SecInfo.rcSection = rcSec;
1630                 pSection->ResetLinePlace();
1631             }
1632             if (s == 0) {
1633                 rcRet = rcSec;
1634             } else {
1635                 rcRet.left = FPDF_MIN(rcSec.left, rcRet.left);
1636                 rcRet.top = FPDF_MIN(rcSec.top, rcRet.top);
1637                 rcRet.right = FPDF_MAX(rcSec.right, rcRet.right);
1638                 rcRet.bottom = FPDF_MAX(rcSec.bottom, rcRet.bottom);
1639             }
1640             fPosY += rcSec.Height();
1641         }
1642     }
1643     return rcRet;
1644 }
1645 FX_INT32 CPDF_VariableText::GetCharWidth(FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord, FX_INT32 nWordStyle)
1646 {
1647     if (m_pVTProvider) {
1648         if (SubWord > 0) {
1649             return m_pVTProvider->GetCharWidth(nFontIndex, SubWord, nWordStyle);
1650         } else {
1651             return m_pVTProvider->GetCharWidth(nFontIndex, Word, nWordStyle);
1652         }
1653     }
1654     return 0;
1655 }
1656 FX_INT32 CPDF_VariableText::GetTypeAscent(FX_INT32 nFontIndex)
1657 {
1658     return m_pVTProvider ? m_pVTProvider->GetTypeAscent(nFontIndex) : 0;
1659 }
1660 FX_INT32 CPDF_VariableText::GetTypeDescent(FX_INT32 nFontIndex)
1661 {
1662     return m_pVTProvider ? m_pVTProvider->GetTypeDescent(nFontIndex) : 0;
1663 }
1664 FX_INT32 CPDF_VariableText::GetWordFontIndex(FX_WORD word, FX_INT32 charset, FX_INT32 nFontIndex)
1665 {
1666     return m_pVTProvider ? m_pVTProvider->GetWordFontIndex(word, charset, nFontIndex) : -1;
1667 }
1668 FX_INT32 CPDF_VariableText::GetDefaultFontIndex()
1669 {
1670     return m_pVTProvider ? m_pVTProvider->GetDefaultFontIndex() : -1;
1671 }
1672 FX_BOOL CPDF_VariableText::IsLatinWord(FX_WORD word)
1673 {
1674     return m_pVTProvider ? m_pVTProvider->IsLatinWord(word) : FALSE;
1675 }
1676 IPDF_VariableText_Iterator * CPDF_VariableText::GetIterator()
1677 {
1678     if (!m_pVTIterator) {
1679         return m_pVTIterator = FX_NEW CPDF_VariableText_Iterator(this);
1680     }
1681     return m_pVTIterator;
1682 }
1683 IPDF_VariableText_Provider*     CPDF_VariableText::SetProvider(IPDF_VariableText_Provider * pProvider)
1684 {
1685     IPDF_VariableText_Provider* pOld = m_pVTProvider;
1686     m_pVTProvider = pProvider;
1687     return pOld;
1688 }
1689 CPDF_VariableText_Iterator::CPDF_VariableText_Iterator(CPDF_VariableText * pVT):
1690     m_pVT(pVT),
1691     m_CurPos(-1, -1, -1)
1692 {
1693 }
1694 CPDF_VariableText_Iterator::~CPDF_VariableText_Iterator()
1695 {
1696 }
1697 void CPDF_VariableText_Iterator::SetAt(FX_INT32 nWordIndex)
1698 {
1699     ASSERT(m_pVT != NULL);
1700     m_CurPos = m_pVT->WordIndexToWordPlace(nWordIndex);
1701 }
1702 void CPDF_VariableText_Iterator::SetAt(const CPVT_WordPlace & place)
1703 {
1704     ASSERT(m_pVT != NULL);
1705     m_CurPos = place;
1706 }
1707 FX_BOOL CPDF_VariableText_Iterator::NextWord()
1708 {
1709     ASSERT(m_pVT != NULL);
1710     if (m_CurPos == m_pVT->GetEndWordPlace()) {
1711         return FALSE;
1712     }
1713     m_CurPos = m_pVT->GetNextWordPlace(m_CurPos);
1714     return TRUE;
1715 }
1716 FX_BOOL CPDF_VariableText_Iterator::PrevWord()
1717 {
1718     ASSERT(m_pVT != NULL);
1719     if (m_CurPos == m_pVT->GetBeginWordPlace()) {
1720         return FALSE;
1721     }
1722     m_CurPos = m_pVT->GetPrevWordPlace(m_CurPos);
1723     return TRUE;
1724 }
1725 FX_BOOL CPDF_VariableText_Iterator::NextLine()
1726 {
1727     ASSERT(m_pVT != NULL);
1728     if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1729         if (m_CurPos.nLineIndex < pSection->m_LineArray.GetSize() - 1) {
1730             m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex + 1, -1);
1731             return TRUE;
1732         } else {
1733             if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
1734                 m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
1735                 return TRUE;
1736             }
1737         }
1738     }
1739     return FALSE;
1740 }
1741 FX_BOOL CPDF_VariableText_Iterator::PrevLine()
1742 {
1743     ASSERT(m_pVT != NULL);
1744     if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1745         if (m_CurPos.nLineIndex > 0) {
1746             m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex - 1, -1);
1747             return TRUE;
1748         } else {
1749             if (m_CurPos.nSecIndex > 0) {
1750                 if (CSection * pLastSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex - 1)) {
1751                     m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, pLastSection->m_LineArray.GetSize() - 1, -1);
1752                     return TRUE;
1753                 }
1754             }
1755         }
1756     }
1757     return FALSE;
1758 }
1759 FX_BOOL CPDF_VariableText_Iterator::NextSection()
1760 {
1761     ASSERT(m_pVT != NULL);
1762     if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
1763         m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
1764         return TRUE;
1765     }
1766     return FALSE;
1767 }
1768 FX_BOOL CPDF_VariableText_Iterator::PrevSection()
1769 {
1770     ASSERT(m_pVT != NULL);
1771     if (m_CurPos.nSecIndex > 0) {
1772         m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, 0, -1);
1773         return TRUE;
1774     }
1775     return FALSE;
1776 }
1777 FX_BOOL CPDF_VariableText_Iterator::GetWord(CPVT_Word & word) const
1778 {
1779     ASSERT(m_pVT != NULL);
1780     word.WordPlace = m_CurPos;
1781     if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1782         if (CLine * pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
1783             if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
1784                 word.Word = pWord->Word;
1785                 word.nCharset = pWord->nCharset;
1786                 word.fWidth = m_pVT->GetWordWidth(*pWord);
1787                 word.ptWord = m_pVT->InToOut(
1788                                   CPDF_Point(pWord->fWordX + pSection->m_SecInfo.rcSection.left,
1789                                              pWord->fWordY + pSection->m_SecInfo.rcSection.top) );
1790                 word.fAscent = m_pVT->GetWordAscent(*pWord);
1791                 word.fDescent = m_pVT->GetWordDescent(*pWord);
1792                 if (pWord->pWordProps) {
1793                     word.WordProps = *pWord->pWordProps;
1794                 }
1795                 word.nFontIndex = m_pVT->GetWordFontIndex(*pWord);
1796                 word.fFontSize = m_pVT->GetWordFontSize(*pWord);
1797                 return TRUE;
1798             }
1799         }
1800     }
1801     return FALSE;
1802 }
1803 FX_BOOL CPDF_VariableText_Iterator::SetWord(const CPVT_Word & word)
1804 {
1805     ASSERT(m_pVT != NULL);
1806     if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1807         if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
1808             if (pWord->pWordProps) {
1809                 *pWord->pWordProps = word.WordProps;
1810             }
1811             return TRUE;
1812         }
1813     }
1814     return FALSE;
1815 }
1816 FX_BOOL CPDF_VariableText_Iterator::GetLine(CPVT_Line & line) const
1817 {
1818     ASSERT(m_pVT != NULL);
1819     line.lineplace = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex, -1);
1820     if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1821         if (CLine * pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
1822             line.ptLine = m_pVT->InToOut(
1823                               CPDF_Point(pLine->m_LineInfo.fLineX + pSection->m_SecInfo.rcSection.left,
1824                                          pLine->m_LineInfo.fLineY + pSection->m_SecInfo.rcSection.top) );
1825             line.fLineWidth = pLine->m_LineInfo.fLineWidth;
1826             line.fLineAscent = pLine->m_LineInfo.fLineAscent;
1827             line.fLineDescent = pLine->m_LineInfo.fLineDescent;
1828             line.lineEnd = pLine->GetEndWordPlace();
1829             return TRUE;
1830         }
1831     }
1832     return FALSE;
1833 }
1834 FX_BOOL CPDF_VariableText_Iterator::GetSection(CPVT_Section & section) const
1835 {
1836     ASSERT(m_pVT != NULL);
1837     section.secplace = CPVT_WordPlace(m_CurPos.nSecIndex, 0, -1);
1838     if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1839         section.rcSection = m_pVT->InToOut(pSection->m_SecInfo.rcSection);
1840         if (pSection->m_SecInfo.pSecProps) {
1841             section.SecProps = *pSection->m_SecInfo.pSecProps;
1842         }
1843         if (pSection->m_SecInfo.pWordProps) {
1844             section.WordProps = *pSection->m_SecInfo.pWordProps;
1845         }
1846         return TRUE;
1847     }
1848     return FALSE;
1849 }
1850 FX_BOOL CPDF_VariableText_Iterator::SetSection(const CPVT_Section & section)
1851 {
1852     ASSERT(m_pVT != NULL);
1853     if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1854         if (pSection->m_SecInfo.pSecProps) {
1855             *pSection->m_SecInfo.pSecProps = section.SecProps;
1856         }
1857         if (pSection->m_SecInfo.pWordProps) {
1858             *pSection->m_SecInfo.pWordProps = section.WordProps;
1859         }
1860         return TRUE;
1861     }
1862     return FALSE;
1863 }