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