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