Fix warnings in android build, fix font rendering issue, fix issue 357588: wrong...
[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_fWordSpace(0.0f),
819     m_fFontSize(0.0f),
820     m_nHorzScale(100),
821     m_wSubWord(0),
822     m_fLineLeading(0.0f)
823 {
824 }
825 CPDF_VariableText::~CPDF_VariableText()
826 {
827     if (m_pVTIterator) {
828         delete m_pVTIterator;
829         m_pVTIterator = NULL;
830     }
831     ResetAll();
832 }
833 void CPDF_VariableText::Initialize()
834 {
835     if (!m_bInitial) {
836         CPVT_SectionInfo secinfo;
837         if (m_bRichText) {
838             secinfo.pSecProps = FX_NEW CPVT_SecProps(0.0f, 0.0f, 0);
839             secinfo.pWordProps = FX_NEW CPVT_WordProps(GetDefaultFontIndex(), PVT_DEFAULT_FONTSIZE, 0, 0, 0);
840         }
841         CPVT_WordPlace place;
842         place.nSecIndex = 0;
843         AddSection(place, secinfo);
844         CPVT_LineInfo lineinfo;
845         lineinfo.fLineAscent = GetFontAscent(GetDefaultFontIndex(), GetFontSize());
846         lineinfo.fLineDescent = GetFontDescent(GetDefaultFontIndex(), GetFontSize());
847         AddLine(place, lineinfo);
848         if (CSection * pSection = m_SectionArray.GetAt(0)) {
849             pSection->ResetLinePlace();
850         }
851         m_bInitial = TRUE;
852     }
853 }
854 void CPDF_VariableText::ResetAll()
855 {
856     m_bInitial = FALSE;
857     ResetSectionArray();
858 }
859 CPVT_WordPlace CPDF_VariableText::InsertWord(const CPVT_WordPlace & place, FX_WORD word, FX_INT32 charset,
860         const CPVT_WordProps * pWordProps)
861 {
862     FX_INT32 nTotlaWords = this->GetTotalWords();
863     if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar) {
864         return place;
865     }
866     if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray) {
867         return place;
868     }
869     CPVT_WordPlace newplace = place;
870     newplace.nWordIndex ++;
871     if (m_bRichText) {
872         CPVT_WordProps * pNewProps = pWordProps ? FX_NEW CPVT_WordProps(*pWordProps) : FX_NEW CPVT_WordProps();
873         if (pNewProps) {
874             pNewProps->nFontIndex = GetWordFontIndex(word, charset, pWordProps->nFontIndex);
875             return AddWord(newplace, CPVT_WordInfo(word, charset, -1, pNewProps));
876         }
877     } else {
878         FX_INT32 nFontIndex = GetSubWord() > 0 ? GetDefaultFontIndex() : GetWordFontIndex(word, charset, GetDefaultFontIndex());
879         return AddWord(newplace, CPVT_WordInfo(word, charset, nFontIndex, NULL));
880     }
881     return place;
882 }
883 CPVT_WordPlace CPDF_VariableText::InsertSection(const CPVT_WordPlace & place, const CPVT_SecProps * pSecProps,
884         const CPVT_WordProps * pWordProps)
885 {
886     FX_INT32 nTotlaWords = this->GetTotalWords();
887     if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar) {
888         return place;
889     }
890     if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray) {
891         return place;
892     }
893     if (!m_bMultiLine) {
894         return place;
895     }
896     CPVT_WordPlace wordplace = place;
897     UpdateWordPlace(wordplace);
898     CPVT_WordPlace newplace = place;
899     if (CSection * pSection = m_SectionArray.GetAt(wordplace.nSecIndex)) {
900         CPVT_WordPlace NewPlace(wordplace.nSecIndex + 1, 0, -1);
901         CPVT_SectionInfo secinfo;
902         if (m_bRichText) {
903             if (pSecProps) {
904                 secinfo.pSecProps = FX_NEW CPVT_SecProps(*pSecProps);
905             }
906             if (pWordProps) {
907                 secinfo.pWordProps = FX_NEW CPVT_WordProps(*pWordProps);
908             }
909         }
910         AddSection(NewPlace, secinfo);
911         newplace = NewPlace;
912         if (CSection * pNewSection = m_SectionArray.GetAt(NewPlace.nSecIndex)) {
913             for (FX_INT32 w = wordplace.nWordIndex + 1, sz = pSection->m_WordArray.GetSize(); w < sz; w++) {
914                 if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(w)) {
915                     NewPlace.nWordIndex++;
916                     pNewSection->AddWord(NewPlace, *pWord);
917                 }
918             }
919         }
920         ClearSectionRightWords(wordplace);
921     }
922     return newplace;
923 }
924 CPVT_WordPlace CPDF_VariableText::InsertText(const CPVT_WordPlace & place, FX_LPCWSTR text, FX_INT32 charset,
925         const CPVT_SecProps * pSecProps, const CPVT_WordProps * pProps)
926 {
927     CFX_WideString swText = text;
928     CPVT_WordPlace wp = place;
929     for (FX_INT32 i = 0, sz = swText.GetLength(); i < sz; i++) {
930         CPVT_WordPlace oldwp = wp;
931         FX_WORD word = swText.GetAt(i);
932         switch (word) {
933             case 0x0D:
934                 if (m_bMultiLine) {
935                     if (swText.GetAt(i + 1) == 0x0A) {
936                         i += 1;
937                     }
938                     wp = InsertSection(wp, pSecProps, pProps);
939                 }
940                 break;
941             case 0x0A:
942                 if (m_bMultiLine) {
943                     if (swText.GetAt(i + 1) == 0x0D) {
944                         i += 1;
945                     }
946                     wp = InsertSection(wp, pSecProps, pProps);
947                 }
948                 break;
949             case 0x09:
950                 word = 0x20;
951             default:
952                 wp = InsertWord(wp, word, charset, pProps);
953                 break;
954         }
955         if (wp == oldwp) {
956             break;
957         }
958     }
959     return wp;
960 }
961 CPVT_WordPlace CPDF_VariableText::DeleteWords(const CPVT_WordRange & PlaceRange)
962 {
963     FX_BOOL bLastSecPos = FALSE;
964     if (CSection * pSection = m_SectionArray.GetAt(PlaceRange.EndPos.nSecIndex)) {
965         bLastSecPos = (PlaceRange.EndPos == pSection->GetEndWordPlace());
966     }
967     ClearWords(PlaceRange);
968     if (PlaceRange.BeginPos.nSecIndex != PlaceRange.EndPos.nSecIndex) {
969         ClearEmptySections(PlaceRange);
970         if (!bLastSecPos) {
971             LinkLatterSection(PlaceRange.BeginPos);
972         }
973     }
974     return PlaceRange.BeginPos;
975 }
976 CPVT_WordPlace CPDF_VariableText::DeleteWord(const CPVT_WordPlace & place)
977 {
978     return ClearRightWord(AjustLineHeader(place, TRUE));
979 }
980 CPVT_WordPlace CPDF_VariableText::BackSpaceWord(const CPVT_WordPlace & place)
981 {
982     return ClearLeftWord(AjustLineHeader(place, TRUE));
983 }
984 void CPDF_VariableText::SetText(FX_LPCWSTR text, FX_INT32 charset, const CPVT_SecProps * pSecProps,
985                                 const CPVT_WordProps * pWordProps)
986 {
987     DeleteWords(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
988     CFX_WideString swText = text;
989     CPVT_WordPlace      wp(0, 0, -1);
990     CPVT_SectionInfo secinfo;
991     if (m_bRichText) {
992         if (pSecProps) {
993             secinfo.pSecProps = FX_NEW CPVT_SecProps(*pSecProps);
994         }
995         if (pWordProps) {
996             secinfo.pWordProps = FX_NEW CPVT_WordProps(*pWordProps);
997         }
998     }
999     if (CSection * pSection = m_SectionArray.GetAt(0)) {
1000         pSection->m_SecInfo = secinfo;
1001     }
1002     FX_INT32 nCharCount = 0;
1003     for (FX_INT32 i = 0, sz = swText.GetLength(); i < sz; i++) {
1004         if (m_nLimitChar > 0 && nCharCount >= m_nLimitChar) {
1005             break;
1006         }
1007         if (m_nCharArray > 0 && nCharCount >= m_nCharArray) {
1008             break;
1009         }
1010         FX_WORD word = swText.GetAt(i);
1011         switch (word) {
1012             case 0x0D:
1013                 if (m_bMultiLine) {
1014                     if (swText.GetAt(i + 1) == 0x0A) {
1015                         i += 1;
1016                     }
1017                     wp.nSecIndex ++;
1018                     wp.nLineIndex = 0;
1019                     wp.nWordIndex = -1;
1020                     AddSection(wp, secinfo);
1021                 }
1022                 break;
1023             case 0x0A:
1024                 if (m_bMultiLine) {
1025                     if (swText.GetAt(i + 1) == 0x0D) {
1026                         i += 1;
1027                     }
1028                     wp.nSecIndex ++;
1029                     wp.nLineIndex = 0;
1030                     wp.nWordIndex = -1;
1031                     AddSection(wp, secinfo);
1032                 }
1033                 break;
1034             case 0x09:
1035                 word = 0x20;
1036             default:
1037                 wp = InsertWord(wp, word, charset, pWordProps);
1038                 break;
1039         }
1040         nCharCount++;
1041     }
1042 }
1043 void CPDF_VariableText::UpdateWordPlace(CPVT_WordPlace & place) const
1044 {
1045     if (place.nSecIndex < 0) {
1046         place = GetBeginWordPlace();
1047     }
1048     if (place.nSecIndex >= m_SectionArray.GetSize()) {
1049         place = GetEndWordPlace();
1050     }
1051     place = AjustLineHeader(place, TRUE);
1052     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1053         pSection->UpdateWordPlace(place);
1054     }
1055 }
1056 FX_INT32 CPDF_VariableText::WordPlaceToWordIndex(const CPVT_WordPlace & place) const
1057 {
1058     CPVT_WordPlace newplace = place;
1059     UpdateWordPlace(newplace);
1060     FX_INT32 nIndex = 0;
1061     FX_INT32 i = 0;
1062     FX_INT32 sz = 0;
1063     for (i = 0, sz = m_SectionArray.GetSize(); i < sz && i < newplace.nSecIndex; i++) {
1064         if (CSection * pSection = m_SectionArray.GetAt(i)) {
1065             nIndex += pSection->m_WordArray.GetSize();
1066             if (i != m_SectionArray.GetSize() - 1) {
1067                 nIndex += PVT_RETURN_LENGTH;
1068             }
1069         }
1070     }
1071     if (i >= 0 && i < m_SectionArray.GetSize()) {
1072         nIndex += newplace.nWordIndex + PVT_RETURN_LENGTH;
1073     }
1074     return nIndex;
1075 }
1076 CPVT_WordPlace CPDF_VariableText::WordIndexToWordPlace(FX_INT32 index) const
1077 {
1078     CPVT_WordPlace place = GetBeginWordPlace();
1079     FX_INT32 nOldIndex = 0 , nIndex = 0;
1080     FX_BOOL bFind = FALSE;
1081     for (FX_INT32 i = 0, sz = m_SectionArray.GetSize(); i < sz; i++) {
1082         if (CSection * pSection = m_SectionArray.GetAt(i)) {
1083             nIndex += pSection->m_WordArray.GetSize();
1084             if (nIndex == index) {
1085                 place = pSection->GetEndWordPlace();
1086                 bFind = TRUE;
1087                 break;
1088             } else if (nIndex > index) {
1089                 place.nSecIndex = i;
1090                 place.nWordIndex = index - nOldIndex - 1;
1091                 pSection->UpdateWordPlace(place);
1092                 bFind = TRUE;
1093                 break;
1094             }
1095             if (i != m_SectionArray.GetSize() - 1) {
1096                 nIndex += PVT_RETURN_LENGTH;
1097             }
1098             nOldIndex = nIndex;
1099         }
1100     }
1101     if (!bFind) {
1102         place = GetEndWordPlace();
1103     }
1104     return place;
1105 }
1106 CPVT_WordPlace CPDF_VariableText::GetBeginWordPlace() const
1107 {
1108     return m_bInitial ? CPVT_WordPlace(0, 0, -1) : CPVT_WordPlace();
1109 }
1110 CPVT_WordPlace CPDF_VariableText::GetEndWordPlace() const
1111 {
1112     if (CSection * pSection = m_SectionArray.GetAt(m_SectionArray.GetSize() - 1)) {
1113         return pSection->GetEndWordPlace();
1114     }
1115     return CPVT_WordPlace();
1116 }
1117 CPVT_WordPlace CPDF_VariableText::GetPrevWordPlace(const CPVT_WordPlace & place) const
1118 {
1119     if( place.nSecIndex < 0) {
1120         return GetBeginWordPlace();
1121     }
1122     if (place.nSecIndex >= m_SectionArray.GetSize()) {
1123         return GetEndWordPlace();
1124     }
1125     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1126         if (place.WordCmp(pSection->GetBeginWordPlace()) <= 0) {
1127             if (CSection * pPrevSection = m_SectionArray.GetAt(place.nSecIndex - 1)) {
1128                 return pPrevSection->GetEndWordPlace();
1129             } else {
1130                 return GetBeginWordPlace();
1131             }
1132         } else {
1133             return pSection->GetPrevWordPlace(place);
1134         }
1135     }
1136     return place;
1137 }
1138 CPVT_WordPlace CPDF_VariableText::GetNextWordPlace(const CPVT_WordPlace & place) const
1139 {
1140     if (place.nSecIndex < 0) {
1141         return GetBeginWordPlace();
1142     }
1143     if (place.nSecIndex >= m_SectionArray.GetSize()) {
1144         return GetEndWordPlace();
1145     }
1146     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1147         if (place.WordCmp(pSection->GetEndWordPlace()) >= 0) {
1148             if (CSection * pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) {
1149                 return pNextSection->GetBeginWordPlace();
1150             } else {
1151                 return GetEndWordPlace();
1152             }
1153         } else {
1154             return pSection->GetNextWordPlace(place);
1155         }
1156     }
1157     return place;
1158 }
1159 CPVT_WordPlace CPDF_VariableText::SearchWordPlace(const CPDF_Point & point) const
1160 {
1161     CPDF_Point pt = OutToIn(point);
1162     CPVT_WordPlace place = GetBeginWordPlace();
1163     FX_INT32 nLeft = 0;
1164     FX_INT32 nRight = m_SectionArray.GetSize() - 1;
1165     FX_INT32 nMid = m_SectionArray.GetSize() / 2;
1166     FX_BOOL bUp = TRUE;
1167     FX_BOOL bDown = TRUE;
1168     while (nLeft <= nRight) {
1169         if (CSection * pSection = m_SectionArray.GetAt(nMid)) {
1170             if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.top)) {
1171                 bUp = FALSE;
1172             }
1173             if (IsFloatBigger(pSection->m_SecInfo.rcSection.bottom, pt.y)) {
1174                 bDown = FALSE;
1175             }
1176             if (IsFloatSmaller(pt.y, pSection->m_SecInfo.rcSection.top)) {
1177                 nRight = nMid - 1;
1178                 nMid = (nLeft + nRight) / 2;
1179                 continue;
1180             } else if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.bottom)) {
1181                 nLeft = nMid + 1;
1182                 nMid = (nLeft + nRight) / 2;
1183                 continue;
1184             } else {
1185                 place = pSection->SearchWordPlace(
1186                             CPDF_Point(pt.x - pSection->m_SecInfo.rcSection.left, pt.y - pSection->m_SecInfo.rcSection.top)
1187                         );
1188                 place.nSecIndex = nMid;
1189                 return place;
1190             }
1191         } else {
1192             break;
1193         }
1194     }
1195     if (bUp) {
1196         place = GetBeginWordPlace();
1197     }
1198     if (bDown) {
1199         place = GetEndWordPlace();
1200     }
1201     return place;
1202 }
1203 CPVT_WordPlace CPDF_VariableText::GetUpWordPlace(const CPVT_WordPlace & place, const CPDF_Point & point) const
1204 {
1205     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1206         CPVT_WordPlace temp =  place;
1207         CPDF_Point pt = OutToIn(point);
1208         if (temp.nLineIndex-- > 0) {
1209             return pSection->SearchWordPlace(pt.x - pSection->m_SecInfo.rcSection.left, temp);
1210         } else {
1211             if (temp.nSecIndex-- > 0) {
1212                 if (CSection * pLastSection = m_SectionArray.GetAt(temp.nSecIndex)) {
1213                     temp.nLineIndex = pLastSection->m_LineArray.GetSize() - 1;
1214                     return pLastSection->SearchWordPlace(pt.x - pLastSection->m_SecInfo.rcSection.left, temp);
1215                 }
1216             }
1217         }
1218     }
1219     return place;
1220 }
1221 CPVT_WordPlace CPDF_VariableText::GetDownWordPlace(const CPVT_WordPlace & place, const CPDF_Point & point) const
1222 {
1223     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1224         CPVT_WordPlace temp =  place;
1225         CPDF_Point pt = OutToIn(point);
1226         if (temp.nLineIndex++ < pSection->m_LineArray.GetSize() - 1) {
1227             return pSection->SearchWordPlace(pt.x - pSection->m_SecInfo.rcSection.left, temp);
1228         } else {
1229             if (temp.nSecIndex++ < m_SectionArray.GetSize() - 1) {
1230                 if (CSection * pNextSection = m_SectionArray.GetAt(temp.nSecIndex)) {
1231                     temp.nLineIndex = 0;
1232                     return pNextSection->SearchWordPlace(pt.x - pSection->m_SecInfo.rcSection.left, temp);
1233                 }
1234             }
1235         }
1236     }
1237     return place;
1238 }
1239 CPVT_WordPlace CPDF_VariableText::GetLineBeginPlace(const CPVT_WordPlace & place) const
1240 {
1241     return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);
1242 }
1243 CPVT_WordPlace CPDF_VariableText::GetLineEndPlace(const CPVT_WordPlace & place) const
1244 {
1245     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex))
1246         if (CLine * pLine = pSection->m_LineArray.GetAt(place.nLineIndex)) {
1247             return pLine->GetEndWordPlace();
1248         }
1249     return place;
1250 }
1251 CPVT_WordPlace CPDF_VariableText::GetSectionBeginPlace(const CPVT_WordPlace & place) const
1252 {
1253     return CPVT_WordPlace(place.nSecIndex, 0, -1);
1254 }
1255 CPVT_WordPlace CPDF_VariableText::GetSectionEndPlace(const CPVT_WordPlace & place) const
1256 {
1257     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1258         return pSection->GetEndWordPlace();
1259     }
1260     return place;
1261 }
1262 FX_INT32 CPDF_VariableText::GetTotalWords() const
1263 {
1264     FX_INT32 nTotal = 0;
1265     for (FX_INT32 i = 0, sz = m_SectionArray.GetSize(); i < sz; i++)
1266         if (CSection * pSection = m_SectionArray.GetAt(i)) {
1267             nTotal += (pSection->m_WordArray.GetSize() + PVT_RETURN_LENGTH);
1268         }
1269     return nTotal - PVT_RETURN_LENGTH;
1270 }
1271 void CPDF_VariableText::ResetSectionArray()
1272 {
1273     for (FX_INT32 s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
1274         delete m_SectionArray.GetAt(s);
1275     }
1276     m_SectionArray.RemoveAll();
1277 }
1278 CPVT_WordPlace CPDF_VariableText::AddSection(const CPVT_WordPlace & place, const CPVT_SectionInfo & secinfo)
1279 {
1280     if (IsValid() && !m_bMultiLine) {
1281         return place;
1282     }
1283     FX_INT32 nSecIndex = FPDF_MAX(FPDF_MIN(place.nSecIndex, m_SectionArray.GetSize()), 0);
1284     CSection * pSection = FX_NEW CSection(this);
1285     if (!pSection) {
1286         return place;
1287     }
1288     pSection->m_SecInfo = secinfo;
1289     pSection->SecPlace.nSecIndex = nSecIndex;
1290     if (nSecIndex == m_SectionArray.GetSize()) {
1291         m_SectionArray.Add(pSection);
1292     } else {
1293         m_SectionArray.InsertAt(nSecIndex, pSection);
1294     }
1295     return place;
1296 }
1297 CPVT_WordPlace CPDF_VariableText::AddLine(const CPVT_WordPlace & place, const CPVT_LineInfo & lineinfo)
1298 {
1299     if (m_SectionArray.IsEmpty()) {
1300         return place;
1301     }
1302     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1303         return pSection->AddLine(lineinfo);
1304     }
1305     return place;
1306 }
1307 CPVT_WordPlace CPDF_VariableText::AddWord(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)
1308 {
1309     if (m_SectionArray.GetSize() <= 0) {
1310         return place;
1311     }
1312     CPVT_WordPlace newplace = place;
1313     newplace.nSecIndex = FPDF_MAX(FPDF_MIN(newplace.nSecIndex, m_SectionArray.GetSize() - 1), 0);
1314     if (CSection * pSection = m_SectionArray.GetAt(newplace.nSecIndex)) {
1315         return pSection->AddWord(newplace, wordinfo);
1316     }
1317     return place;
1318 }
1319 FX_BOOL CPDF_VariableText::GetWordInfo(const CPVT_WordPlace & place, CPVT_WordInfo & wordinfo)
1320 {
1321     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1322         if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {
1323             wordinfo = *pWord;
1324             return TRUE;
1325         }
1326     }
1327     return FALSE;
1328 }
1329 FX_BOOL CPDF_VariableText::SetWordInfo(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)
1330 {
1331     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1332         if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {
1333             *pWord = wordinfo;
1334             return TRUE;
1335         }
1336     }
1337     return FALSE;
1338 }
1339 FX_BOOL CPDF_VariableText::GetLineInfo(const CPVT_WordPlace & place, CPVT_LineInfo & lineinfo)
1340 {
1341     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1342         if (CLine * pLine = pSection->m_LineArray.GetAt(place.nLineIndex)) {
1343             lineinfo = pLine->m_LineInfo;
1344             return TRUE;
1345         }
1346     }
1347     return FALSE;
1348 }
1349 FX_BOOL CPDF_VariableText::GetSectionInfo(const CPVT_WordPlace & place, CPVT_SectionInfo & secinfo)
1350 {
1351     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1352         secinfo = pSection->m_SecInfo;
1353         return TRUE;
1354     }
1355     return FALSE;
1356 }
1357 CPDF_Rect CPDF_VariableText::GetContentRect() const
1358 {
1359     return InToOut(CPDF_EditContainer::GetContentRect());
1360 }
1361 FX_FLOAT CPDF_VariableText::GetWordFontSize(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)
1362 {
1363     return m_bRichText && WordInfo.pWordProps ? (WordInfo.pWordProps->nScriptType == PVTWORD_SCRIPT_NORMAL || bFactFontSize ? WordInfo.pWordProps->fFontSize : WordInfo.pWordProps->fFontSize * PVT_HALF) : GetFontSize();
1364 }
1365 FX_INT32 CPDF_VariableText::GetWordFontIndex(const CPVT_WordInfo & WordInfo)
1366 {
1367     return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nFontIndex : WordInfo.nFontIndex;
1368 }
1369 FX_FLOAT CPDF_VariableText::GetWordWidth(FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord,
1370         FX_FLOAT fCharSpace, FX_INT32 nHorzScale,
1371         FX_FLOAT fFontSize, FX_FLOAT fWordTail, FX_INT32 nWordStyle)
1372 {
1373     return (GetCharWidth(nFontIndex, Word, SubWord, nWordStyle) * fFontSize * PVT_FONTSCALE + fCharSpace) * nHorzScale * PVT_PERCENT + fWordTail;
1374 }
1375 FX_FLOAT CPDF_VariableText::GetWordWidth(const CPVT_WordInfo & WordInfo)
1376 {
1377     return GetWordWidth(GetWordFontIndex(WordInfo), WordInfo.Word, GetSubWord(), GetCharSpace(WordInfo), GetHorzScale(WordInfo),
1378                         GetWordFontSize(WordInfo), WordInfo.fWordTail,
1379                         WordInfo.pWordProps ? WordInfo.pWordProps->nWordStyle : 0);
1380 }
1381 FX_FLOAT CPDF_VariableText::GetLineAscent(const CPVT_SectionInfo & SecInfo)
1382 {
1383     return m_bRichText && SecInfo.pWordProps ? GetFontAscent(SecInfo.pWordProps->nFontIndex, SecInfo.pWordProps->fFontSize) :
1384            GetFontAscent(GetDefaultFontIndex(), GetFontSize());
1385 }
1386 FX_FLOAT CPDF_VariableText::GetLineDescent(const CPVT_SectionInfo & SecInfo)
1387 {
1388     return m_bRichText && SecInfo.pWordProps ? GetFontDescent(SecInfo.pWordProps->nFontIndex, SecInfo.pWordProps->fFontSize) :
1389            GetFontDescent(GetDefaultFontIndex(), GetFontSize());
1390 }
1391 FX_FLOAT CPDF_VariableText::GetFontAscent(FX_INT32 nFontIndex, FX_FLOAT fFontSize)
1392 {
1393     return (FX_FLOAT)GetTypeAscent(nFontIndex) * fFontSize * PVT_FONTSCALE;
1394 }
1395 FX_FLOAT CPDF_VariableText::GetFontDescent(FX_INT32 nFontIndex, FX_FLOAT fFontSize)
1396 {
1397     return (FX_FLOAT)GetTypeDescent(nFontIndex) * fFontSize * PVT_FONTSCALE;
1398 }
1399 FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize)
1400 {
1401     return GetFontAscent(GetWordFontIndex(WordInfo), fFontSize);
1402 }
1403 FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize)
1404 {
1405     return GetFontDescent(GetWordFontIndex(WordInfo), fFontSize);
1406 }
1407 FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)
1408 {
1409     return GetFontAscent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo, bFactFontSize));
1410 }
1411 FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)
1412 {
1413     return GetFontDescent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo, bFactFontSize));
1414 }
1415 FX_FLOAT CPDF_VariableText::GetLineLeading(const CPVT_SectionInfo & SecInfo)
1416 {
1417     return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineLeading : m_fLineLeading;
1418 }
1419 FX_FLOAT CPDF_VariableText::GetLineIndent(const CPVT_SectionInfo & SecInfo)
1420 {
1421     return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineIndent : 0.0f;
1422 }
1423 FX_INT32 CPDF_VariableText::GetAlignment(const CPVT_SectionInfo& SecInfo)
1424 {
1425     return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->nAlignment : this->m_nAlignment;
1426 }
1427 FX_FLOAT CPDF_VariableText::GetCharSpace(const CPVT_WordInfo & WordInfo)
1428 {
1429     return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->fCharSpace : m_fCharSpace;
1430 }
1431 FX_INT32 CPDF_VariableText::GetHorzScale(const CPVT_WordInfo & WordInfo)
1432 {
1433     return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nHorzScale : m_nHorzScale;
1434 }
1435 void CPDF_VariableText::ClearSectionRightWords(const CPVT_WordPlace & place)
1436 {
1437     CPVT_WordPlace wordplace = AjustLineHeader(place, TRUE);
1438     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1439         for (FX_INT32 w = pSection->m_WordArray.GetSize() - 1; w > wordplace.nWordIndex; w--) {
1440             delete pSection->m_WordArray.GetAt(w);
1441             pSection->m_WordArray.RemoveAt(w);
1442         }
1443     }
1444 }
1445 CPVT_WordPlace CPDF_VariableText::AjustLineHeader(const CPVT_WordPlace & place, FX_BOOL bPrevOrNext) const
1446 {
1447     if (place.nWordIndex < 0 && place.nLineIndex > 0) {
1448         if (bPrevOrNext) {
1449             return GetPrevWordPlace(place);
1450         } else {
1451             return GetNextWordPlace(place);
1452         }
1453     }
1454     return place;
1455 }
1456 FX_BOOL CPDF_VariableText::ClearEmptySection(const CPVT_WordPlace & place)
1457 {
1458     if (place.nSecIndex == 0 && m_SectionArray.GetSize() == 1) {
1459         return FALSE;
1460     }
1461     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1462         if (pSection->m_WordArray.GetSize() == 0) {
1463             delete pSection;
1464             m_SectionArray.RemoveAt(place.nSecIndex);
1465             return TRUE;
1466         }
1467     }
1468     return FALSE;
1469 }
1470 void CPDF_VariableText::ClearEmptySections(const CPVT_WordRange & PlaceRange)
1471 {
1472     CPVT_WordPlace wordplace;
1473     for (FX_INT32 s = PlaceRange.EndPos.nSecIndex; s > PlaceRange.BeginPos.nSecIndex; s--) {
1474         wordplace.nSecIndex = s;
1475         ClearEmptySection(wordplace);
1476     }
1477 }
1478 void CPDF_VariableText::LinkLatterSection(const CPVT_WordPlace & place)
1479 {
1480     CPVT_WordPlace oldplace = AjustLineHeader(place, TRUE);
1481     if (CSection * pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) {
1482         if (CSection * pSection = m_SectionArray.GetAt(oldplace.nSecIndex)) {
1483             for (FX_INT32 w = 0, sz = pNextSection->m_WordArray.GetSize(); w < sz; w++) {
1484                 if (CPVT_WordInfo * pWord = pNextSection->m_WordArray.GetAt(w)) {
1485                     oldplace.nWordIndex ++;
1486                     pSection->AddWord(oldplace, *pWord);
1487                 }
1488             }
1489         }
1490         delete pNextSection;
1491         m_SectionArray.RemoveAt(place.nSecIndex + 1);
1492     }
1493 }
1494 void CPDF_VariableText::ClearWords(const CPVT_WordRange & PlaceRange)
1495 {
1496     CPVT_WordRange NewRange;
1497     NewRange.BeginPos = AjustLineHeader(PlaceRange.BeginPos, TRUE);
1498     NewRange.EndPos = AjustLineHeader(PlaceRange.EndPos, TRUE);
1499     for (FX_INT32 s = NewRange.EndPos.nSecIndex; s >= NewRange.BeginPos.nSecIndex; s--) {
1500         if (CSection * pSection = m_SectionArray.GetAt(s)) {
1501             pSection->ClearWords(NewRange);
1502         }
1503     }
1504 }
1505 CPVT_WordPlace CPDF_VariableText::ClearLeftWord(const CPVT_WordPlace & place)
1506 {
1507     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1508         CPVT_WordPlace leftplace = this->GetPrevWordPlace(place);
1509         if (leftplace != place) {
1510             if (leftplace.nSecIndex != place.nSecIndex) {
1511                 if (pSection->m_WordArray.GetSize() == 0) {
1512                     this->ClearEmptySection(place);
1513                 } else {
1514                     this->LinkLatterSection(leftplace);
1515                 }
1516             } else {
1517                 pSection->ClearWord(place);
1518             }
1519         }
1520         return leftplace;
1521     }
1522     return place;
1523 }
1524 CPVT_WordPlace CPDF_VariableText::ClearRightWord(const CPVT_WordPlace & place)
1525 {
1526     if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1527         CPVT_WordPlace rightplace = AjustLineHeader(this->GetNextWordPlace(place), FALSE);
1528         if (rightplace != place) {
1529             if(rightplace.nSecIndex != place.nSecIndex) {
1530                 LinkLatterSection(place);
1531             } else {
1532                 pSection->ClearWord(rightplace);
1533             }
1534         }
1535     }
1536     return place;
1537 }
1538 void CPDF_VariableText::RearrangeAll()
1539 {
1540     Rearrange(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
1541 }
1542 void CPDF_VariableText::RearrangePart(const CPVT_WordRange & PlaceRange)
1543 {
1544     Rearrange(PlaceRange);
1545 }
1546 CPVT_FloatRect CPDF_VariableText::Rearrange(const CPVT_WordRange & PlaceRange)
1547 {
1548     CPVT_FloatRect rcRet;
1549     if (IsValid()) {
1550         if (m_bAutoFontSize) {
1551             SetFontSize(GetAutoFontSize());
1552             rcRet = RearrangeSections(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
1553         } else {
1554             rcRet = RearrangeSections(PlaceRange);
1555         }
1556     }
1557     SetContentRect(rcRet);
1558     return rcRet;
1559 }
1560 FX_FLOAT CPDF_VariableText::GetAutoFontSize()
1561 {
1562     FX_INT32 nTotal = sizeof(gFontSizeSteps) / sizeof(FX_BYTE);
1563     if (IsMultiLine()) {
1564         nTotal /= 4;
1565     }
1566     if (nTotal <= 0) {
1567         return 0;
1568     }
1569     if (GetPlateWidth() <= 0) {
1570         return 0;
1571     }
1572     FX_INT32 nLeft = 0;
1573     FX_INT32 nRight = nTotal - 1;
1574     FX_INT32 nMid = nTotal / 2;
1575     while (nLeft <= nRight) {
1576         if (IsBigger(gFontSizeSteps[nMid])) {
1577             nRight = nMid - 1;
1578             nMid = (nLeft + nRight) / 2;
1579             continue;
1580         } else {
1581             nLeft = nMid + 1;
1582             nMid = (nLeft + nRight) / 2;
1583             continue;
1584         }
1585     }
1586     return (FX_FLOAT)gFontSizeSteps[nMid];
1587 }
1588 FX_BOOL CPDF_VariableText::IsBigger(FX_FLOAT fFontSize)
1589 {
1590     FX_BOOL bBigger =  FALSE;
1591     CPVT_Size szTotal;
1592     for (FX_INT32 s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
1593         if (CSection * pSection = m_SectionArray.GetAt(s)) {
1594             CPVT_Size size = pSection->GetSectionSize(fFontSize);
1595             szTotal.x = FPDF_MAX(size.x, szTotal.x);
1596             szTotal.y += size.y;
1597             if (IsFloatBigger(szTotal.x, GetPlateWidth())
1598                     || IsFloatBigger(szTotal.y, GetPlateHeight())
1599                ) {
1600                 bBigger = TRUE;
1601                 break;
1602             }
1603         }
1604     }
1605     return bBigger;
1606 }
1607 CPVT_FloatRect CPDF_VariableText::RearrangeSections(const CPVT_WordRange & PlaceRange)
1608 {
1609     CPVT_WordPlace place;
1610     FX_FLOAT fPosY = 0;
1611     FX_FLOAT fOldHeight;
1612     FX_INT32 nSSecIndex = PlaceRange.BeginPos.nSecIndex;
1613     FX_INT32 nESecIndex = PlaceRange.EndPos.nSecIndex;
1614     CPVT_FloatRect rcRet;
1615     for (FX_INT32 s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
1616         place.nSecIndex = s;
1617         if (CSection * pSection = m_SectionArray.GetAt(s)) {
1618             pSection->SecPlace = place;
1619             CPVT_FloatRect rcSec = pSection->m_SecInfo.rcSection;
1620             if (s >= nSSecIndex) {
1621                 if (s <= nESecIndex) {
1622                     rcSec = pSection->Rearrange();
1623                     rcSec.top += fPosY;
1624                     rcSec.bottom += fPosY;
1625                 } else {
1626                     fOldHeight = pSection->m_SecInfo.rcSection.bottom - pSection->m_SecInfo.rcSection.top;
1627                     rcSec.top = fPosY;
1628                     rcSec.bottom = fPosY + fOldHeight;
1629                 }
1630                 pSection->m_SecInfo.rcSection = rcSec;
1631                 pSection->ResetLinePlace();
1632             }
1633             if (s == 0) {
1634                 rcRet = rcSec;
1635             } else {
1636                 rcRet.left = FPDF_MIN(rcSec.left, rcRet.left);
1637                 rcRet.top = FPDF_MIN(rcSec.top, rcRet.top);
1638                 rcRet.right = FPDF_MAX(rcSec.right, rcRet.right);
1639                 rcRet.bottom = FPDF_MAX(rcSec.bottom, rcRet.bottom);
1640             }
1641             fPosY += rcSec.Height();
1642         }
1643     }
1644     return rcRet;
1645 }
1646 FX_INT32 CPDF_VariableText::GetCharWidth(FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord, FX_INT32 nWordStyle)
1647 {
1648     if (m_pVTProvider) {
1649         if (SubWord > 0) {
1650             return m_pVTProvider->GetCharWidth(nFontIndex, SubWord, nWordStyle);
1651         } else {
1652             return m_pVTProvider->GetCharWidth(nFontIndex, Word, nWordStyle);
1653         }
1654     }
1655     return 0;
1656 }
1657 FX_INT32 CPDF_VariableText::GetTypeAscent(FX_INT32 nFontIndex)
1658 {
1659     return m_pVTProvider ? m_pVTProvider->GetTypeAscent(nFontIndex) : 0;
1660 }
1661 FX_INT32 CPDF_VariableText::GetTypeDescent(FX_INT32 nFontIndex)
1662 {
1663     return m_pVTProvider ? m_pVTProvider->GetTypeDescent(nFontIndex) : 0;
1664 }
1665 FX_INT32 CPDF_VariableText::GetWordFontIndex(FX_WORD word, FX_INT32 charset, FX_INT32 nFontIndex)
1666 {
1667     return m_pVTProvider ? m_pVTProvider->GetWordFontIndex(word, charset, nFontIndex) : -1;
1668 }
1669 FX_INT32 CPDF_VariableText::GetDefaultFontIndex()
1670 {
1671     return m_pVTProvider ? m_pVTProvider->GetDefaultFontIndex() : -1;
1672 }
1673 FX_BOOL CPDF_VariableText::IsLatinWord(FX_WORD word)
1674 {
1675     return m_pVTProvider ? m_pVTProvider->IsLatinWord(word) : FALSE;
1676 }
1677 IPDF_VariableText_Iterator * CPDF_VariableText::GetIterator()
1678 {
1679     if (!m_pVTIterator) {
1680         return m_pVTIterator = FX_NEW CPDF_VariableText_Iterator(this);
1681     }
1682     return m_pVTIterator;
1683 }
1684 IPDF_VariableText_Provider*     CPDF_VariableText::SetProvider(IPDF_VariableText_Provider * pProvider)
1685 {
1686     IPDF_VariableText_Provider* pOld = m_pVTProvider;
1687     m_pVTProvider = pProvider;
1688     return pOld;
1689 }
1690 CPDF_VariableText_Iterator::CPDF_VariableText_Iterator(CPDF_VariableText * pVT):
1691     m_pVT(pVT),
1692     m_CurPos(-1, -1, -1)
1693 {
1694 }
1695 CPDF_VariableText_Iterator::~CPDF_VariableText_Iterator()
1696 {
1697 }
1698 void CPDF_VariableText_Iterator::SetAt(FX_INT32 nWordIndex)
1699 {
1700     ASSERT(m_pVT != NULL);
1701     m_CurPos = m_pVT->WordIndexToWordPlace(nWordIndex);
1702 }
1703 void CPDF_VariableText_Iterator::SetAt(const CPVT_WordPlace & place)
1704 {
1705     ASSERT(m_pVT != NULL);
1706     m_CurPos = place;
1707 }
1708 FX_BOOL CPDF_VariableText_Iterator::NextWord()
1709 {
1710     ASSERT(m_pVT != NULL);
1711     if (m_CurPos == m_pVT->GetEndWordPlace()) {
1712         return FALSE;
1713     }
1714     m_CurPos = m_pVT->GetNextWordPlace(m_CurPos);
1715     return TRUE;
1716 }
1717 FX_BOOL CPDF_VariableText_Iterator::PrevWord()
1718 {
1719     ASSERT(m_pVT != NULL);
1720     if (m_CurPos == m_pVT->GetBeginWordPlace()) {
1721         return FALSE;
1722     }
1723     m_CurPos = m_pVT->GetPrevWordPlace(m_CurPos);
1724     return TRUE;
1725 }
1726 FX_BOOL CPDF_VariableText_Iterator::NextLine()
1727 {
1728     ASSERT(m_pVT != NULL);
1729     if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1730         if (m_CurPos.nLineIndex < pSection->m_LineArray.GetSize() - 1) {
1731             m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex + 1, -1);
1732             return TRUE;
1733         } else {
1734             if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
1735                 m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
1736                 return TRUE;
1737             }
1738         }
1739     }
1740     return FALSE;
1741 }
1742 FX_BOOL CPDF_VariableText_Iterator::PrevLine()
1743 {
1744     ASSERT(m_pVT != NULL);
1745     if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1746         if (m_CurPos.nLineIndex > 0) {
1747             m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex - 1, -1);
1748             return TRUE;
1749         } else {
1750             if (m_CurPos.nSecIndex > 0) {
1751                 if (CSection * pLastSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex - 1)) {
1752                     m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, pLastSection->m_LineArray.GetSize() - 1, -1);
1753                     return TRUE;
1754                 }
1755             }
1756         }
1757     }
1758     return FALSE;
1759 }
1760 FX_BOOL CPDF_VariableText_Iterator::NextSection()
1761 {
1762     ASSERT(m_pVT != NULL);
1763     if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
1764         m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
1765         return TRUE;
1766     }
1767     return FALSE;
1768 }
1769 FX_BOOL CPDF_VariableText_Iterator::PrevSection()
1770 {
1771     ASSERT(m_pVT != NULL);
1772     if (m_CurPos.nSecIndex > 0) {
1773         m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, 0, -1);
1774         return TRUE;
1775     }
1776     return FALSE;
1777 }
1778 FX_BOOL CPDF_VariableText_Iterator::GetWord(CPVT_Word & word) const
1779 {
1780     ASSERT(m_pVT != NULL);
1781     word.WordPlace = m_CurPos;
1782     if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1783         if (CLine * pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
1784             if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
1785                 word.Word = pWord->Word;
1786                 word.nCharset = pWord->nCharset;
1787                 word.fWidth = m_pVT->GetWordWidth(*pWord);
1788                 word.ptWord = m_pVT->InToOut(
1789                                   CPDF_Point(pWord->fWordX + pSection->m_SecInfo.rcSection.left,
1790                                              pWord->fWordY + pSection->m_SecInfo.rcSection.top) );
1791                 word.fAscent = m_pVT->GetWordAscent(*pWord);
1792                 word.fDescent = m_pVT->GetWordDescent(*pWord);
1793                 if (pWord->pWordProps) {
1794                     word.WordProps = *pWord->pWordProps;
1795                 }
1796                 word.nFontIndex = m_pVT->GetWordFontIndex(*pWord);
1797                 word.fFontSize = m_pVT->GetWordFontSize(*pWord);
1798                 return TRUE;
1799             }
1800         }
1801     }
1802     return FALSE;
1803 }
1804 FX_BOOL CPDF_VariableText_Iterator::SetWord(const CPVT_Word & word)
1805 {
1806     ASSERT(m_pVT != NULL);
1807     if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1808         if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
1809             if (pWord->pWordProps) {
1810                 *pWord->pWordProps = word.WordProps;
1811             }
1812             return TRUE;
1813         }
1814     }
1815     return FALSE;
1816 }
1817 FX_BOOL CPDF_VariableText_Iterator::GetLine(CPVT_Line & line) const
1818 {
1819     ASSERT(m_pVT != NULL);
1820     line.lineplace = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex, -1);
1821     if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1822         if (CLine * pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
1823             line.ptLine = m_pVT->InToOut(
1824                               CPDF_Point(pLine->m_LineInfo.fLineX + pSection->m_SecInfo.rcSection.left,
1825                                          pLine->m_LineInfo.fLineY + pSection->m_SecInfo.rcSection.top) );
1826             line.fLineWidth = pLine->m_LineInfo.fLineWidth;
1827             line.fLineAscent = pLine->m_LineInfo.fLineAscent;
1828             line.fLineDescent = pLine->m_LineInfo.fLineDescent;
1829             line.lineEnd = pLine->GetEndWordPlace();
1830             return TRUE;
1831         }
1832     }
1833     return FALSE;
1834 }
1835 FX_BOOL CPDF_VariableText_Iterator::GetSection(CPVT_Section & section) const
1836 {
1837     ASSERT(m_pVT != NULL);
1838     section.secplace = CPVT_WordPlace(m_CurPos.nSecIndex, 0, -1);
1839     if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1840         section.rcSection = m_pVT->InToOut(pSection->m_SecInfo.rcSection);
1841         if (pSection->m_SecInfo.pSecProps) {
1842             section.SecProps = *pSection->m_SecInfo.pSecProps;
1843         }
1844         if (pSection->m_SecInfo.pWordProps) {
1845             section.WordProps = *pSection->m_SecInfo.pWordProps;
1846         }
1847         return TRUE;
1848     }
1849     return FALSE;
1850 }
1851 FX_BOOL CPDF_VariableText_Iterator::SetSection(const CPVT_Section & section)
1852 {
1853     ASSERT(m_pVT != NULL);
1854     if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1855         if (pSection->m_SecInfo.pSecProps) {
1856             *pSection->m_SecInfo.pSecProps = section.SecProps;
1857         }
1858         if (pSection->m_SecInfo.pWordProps) {
1859             *pSection->m_SecInfo.pWordProps = section.WordProps;
1860         }
1861         return TRUE;
1862     }
1863     return FALSE;
1864 }