• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 "core/fpdfdoc/cpdf_variabletext.h"
8 
9 #include <algorithm>
10 
11 #include "core/fpdfapi/font/cpdf_font.h"
12 #include "core/fpdfdoc/cline.h"
13 #include "core/fpdfdoc/cpvt_section.h"
14 #include "core/fpdfdoc/cpvt_word.h"
15 #include "core/fpdfdoc/cpvt_wordinfo.h"
16 #include "core/fpdfdoc/csection.h"
17 #include "core/fpdfdoc/ipvt_fontmap.h"
18 #include "third_party/base/ptr_util.h"
19 
20 namespace {
21 
22 const float kFontScale = 0.001f;
23 const uint8_t kReturnLength = 1;
24 const float kScalePercent = 0.01f;
25 
26 const uint8_t gFontSizeSteps[] = {4,  6,  8,   9,   10,  12,  14, 18, 20,
27                                   25, 30, 35,  40,  45,  50,  55, 60, 70,
28                                   80, 90, 100, 110, 120, 130, 144};
29 
30 }  // namespace
31 
Provider(IPVT_FontMap * pFontMap)32 CPDF_VariableText::Provider::Provider(IPVT_FontMap* pFontMap)
33     : m_pFontMap(pFontMap) {
34   ASSERT(m_pFontMap);
35 }
36 
~Provider()37 CPDF_VariableText::Provider::~Provider() {}
38 
GetCharWidth(int32_t nFontIndex,uint16_t word)39 int32_t CPDF_VariableText::Provider::GetCharWidth(int32_t nFontIndex,
40                                                   uint16_t word) {
41   if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) {
42     uint32_t charcode = pPDFFont->CharCodeFromUnicode(word);
43     if (charcode != CPDF_Font::kInvalidCharCode)
44       return pPDFFont->GetCharWidthF(charcode);
45   }
46   return 0;
47 }
48 
GetTypeAscent(int32_t nFontIndex)49 int32_t CPDF_VariableText::Provider::GetTypeAscent(int32_t nFontIndex) {
50   if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex))
51     return pPDFFont->GetTypeAscent();
52   return 0;
53 }
54 
GetTypeDescent(int32_t nFontIndex)55 int32_t CPDF_VariableText::Provider::GetTypeDescent(int32_t nFontIndex) {
56   if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex))
57     return pPDFFont->GetTypeDescent();
58   return 0;
59 }
60 
GetWordFontIndex(uint16_t word,int32_t charset,int32_t nFontIndex)61 int32_t CPDF_VariableText::Provider::GetWordFontIndex(uint16_t word,
62                                                       int32_t charset,
63                                                       int32_t nFontIndex) {
64   if (CPDF_Font* pDefFont = m_pFontMap->GetPDFFont(0)) {
65     if (pDefFont->CharCodeFromUnicode(word) != CPDF_Font::kInvalidCharCode)
66       return 0;
67   }
68   if (CPDF_Font* pSysFont = m_pFontMap->GetPDFFont(1)) {
69     if (pSysFont->CharCodeFromUnicode(word) != CPDF_Font::kInvalidCharCode)
70       return 1;
71   }
72   return -1;
73 }
74 
IsLatinWord(uint16_t word)75 bool CPDF_VariableText::Provider::IsLatinWord(uint16_t word) {
76   return (word >= 0x61 && word <= 0x7A) || (word >= 0x41 && word <= 0x5A) ||
77          word == 0x2D || word == 0x27;
78 }
79 
GetDefaultFontIndex()80 int32_t CPDF_VariableText::Provider::GetDefaultFontIndex() {
81   return 0;
82 }
83 
Iterator(CPDF_VariableText * pVT)84 CPDF_VariableText::Iterator::Iterator(CPDF_VariableText* pVT)
85     : m_CurPos(-1, -1, -1), m_pVT(pVT) {}
86 
~Iterator()87 CPDF_VariableText::Iterator::~Iterator() {}
88 
SetAt(int32_t nWordIndex)89 void CPDF_VariableText::Iterator::SetAt(int32_t nWordIndex) {
90   m_CurPos = m_pVT->WordIndexToWordPlace(nWordIndex);
91 }
92 
SetAt(const CPVT_WordPlace & place)93 void CPDF_VariableText::Iterator::SetAt(const CPVT_WordPlace& place) {
94   ASSERT(m_pVT);
95   m_CurPos = place;
96 }
97 
NextWord()98 bool CPDF_VariableText::Iterator::NextWord() {
99   if (m_CurPos == m_pVT->GetEndWordPlace())
100     return false;
101 
102   m_CurPos = m_pVT->GetNextWordPlace(m_CurPos);
103   return true;
104 }
105 
PrevWord()106 bool CPDF_VariableText::Iterator::PrevWord() {
107   if (m_CurPos == m_pVT->GetBeginWordPlace())
108     return false;
109 
110   m_CurPos = m_pVT->GetPrevWordPlace(m_CurPos);
111   return true;
112 }
113 
NextLine()114 bool CPDF_VariableText::Iterator::NextLine() {
115   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
116     if (m_CurPos.nLineIndex < pSection->m_LineArray.GetSize() - 1) {
117       m_CurPos =
118           CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex + 1, -1);
119       return true;
120     }
121     if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
122       m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
123       return true;
124     }
125   }
126   return false;
127 }
128 
PrevLine()129 bool CPDF_VariableText::Iterator::PrevLine() {
130   if (m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
131     if (m_CurPos.nLineIndex > 0) {
132       m_CurPos =
133           CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex - 1, -1);
134       return true;
135     }
136     if (m_CurPos.nSecIndex > 0) {
137       if (CSection* pLastSection =
138               m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex - 1)) {
139         m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1,
140                                   pLastSection->m_LineArray.GetSize() - 1, -1);
141         return true;
142       }
143     }
144   }
145   return false;
146 }
147 
NextSection()148 bool CPDF_VariableText::Iterator::NextSection() {
149   if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
150     m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
151     return true;
152   }
153   return false;
154 }
155 
PrevSection()156 bool CPDF_VariableText::Iterator::PrevSection() {
157   ASSERT(m_pVT);
158   if (m_CurPos.nSecIndex > 0) {
159     m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, 0, -1);
160     return true;
161   }
162   return false;
163 }
164 
GetWord(CPVT_Word & word) const165 bool CPDF_VariableText::Iterator::GetWord(CPVT_Word& word) const {
166   word.WordPlace = m_CurPos;
167   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
168     if (pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
169       if (CPVT_WordInfo* pWord =
170               pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
171         word.Word = pWord->Word;
172         word.nCharset = pWord->nCharset;
173         word.fWidth = m_pVT->GetWordWidth(*pWord);
174         word.ptWord = m_pVT->InToOut(
175             CFX_PointF(pWord->fWordX + pSection->m_SecInfo.rcSection.left,
176                        pWord->fWordY + pSection->m_SecInfo.rcSection.top));
177         word.fAscent = m_pVT->GetWordAscent(*pWord);
178         word.fDescent = m_pVT->GetWordDescent(*pWord);
179         if (pWord->pWordProps)
180           word.WordProps = *pWord->pWordProps;
181 
182         word.nFontIndex = m_pVT->GetWordFontIndex(*pWord);
183         word.fFontSize = m_pVT->GetWordFontSize(*pWord);
184         return true;
185       }
186     }
187   }
188   return false;
189 }
190 
SetWord(const CPVT_Word & word)191 bool CPDF_VariableText::Iterator::SetWord(const CPVT_Word& word) {
192   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
193     if (CPVT_WordInfo* pWord =
194             pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
195       if (pWord->pWordProps)
196         *pWord->pWordProps = word.WordProps;
197       return true;
198     }
199   }
200   return false;
201 }
202 
GetLine(CPVT_Line & line) const203 bool CPDF_VariableText::Iterator::GetLine(CPVT_Line& line) const {
204   ASSERT(m_pVT);
205   line.lineplace = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex, -1);
206   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
207     if (CLine* pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
208       line.ptLine = m_pVT->InToOut(CFX_PointF(
209           pLine->m_LineInfo.fLineX + pSection->m_SecInfo.rcSection.left,
210           pLine->m_LineInfo.fLineY + pSection->m_SecInfo.rcSection.top));
211       line.fLineWidth = pLine->m_LineInfo.fLineWidth;
212       line.fLineAscent = pLine->m_LineInfo.fLineAscent;
213       line.fLineDescent = pLine->m_LineInfo.fLineDescent;
214       line.lineEnd = pLine->GetEndWordPlace();
215       return true;
216     }
217   }
218   return false;
219 }
220 
GetSection(CPVT_Section & section) const221 bool CPDF_VariableText::Iterator::GetSection(CPVT_Section& section) const {
222   section.secplace = CPVT_WordPlace(m_CurPos.nSecIndex, 0, -1);
223   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
224     section.rcSection = m_pVT->InToOut(pSection->m_SecInfo.rcSection);
225     if (pSection->m_SecInfo.pSecProps)
226       section.SecProps = *pSection->m_SecInfo.pSecProps;
227     if (pSection->m_SecInfo.pWordProps)
228       section.WordProps = *pSection->m_SecInfo.pWordProps;
229     return true;
230   }
231   return false;
232 }
233 
SetSection(const CPVT_Section & section)234 bool CPDF_VariableText::Iterator::SetSection(const CPVT_Section& section) {
235   if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
236     if (pSection->m_SecInfo.pSecProps)
237       *pSection->m_SecInfo.pSecProps = section.SecProps;
238     if (pSection->m_SecInfo.pWordProps)
239       *pSection->m_SecInfo.pWordProps = section.WordProps;
240     return true;
241   }
242   return false;
243 }
244 
CPDF_VariableText()245 CPDF_VariableText::CPDF_VariableText()
246     : m_nLimitChar(0),
247       m_nCharArray(0),
248       m_bMultiLine(false),
249       m_bLimitWidth(false),
250       m_bAutoFontSize(false),
251       m_nAlignment(0),
252       m_fLineLeading(0.0f),
253       m_fCharSpace(0.0f),
254       m_nHorzScale(100),
255       m_wSubWord(0),
256       m_fFontSize(0.0f),
257       m_bInitial(false),
258       m_pVTProvider(nullptr) {}
259 
~CPDF_VariableText()260 CPDF_VariableText::~CPDF_VariableText() {
261   ResetAll();
262 }
263 
Initialize()264 void CPDF_VariableText::Initialize() {
265   if (!m_bInitial) {
266     CPVT_SectionInfo secinfo;
267     CPVT_WordPlace place;
268     place.nSecIndex = 0;
269     AddSection(place, secinfo);
270     CPVT_LineInfo lineinfo;
271     lineinfo.fLineAscent = GetFontAscent(GetDefaultFontIndex(), GetFontSize());
272     lineinfo.fLineDescent =
273         GetFontDescent(GetDefaultFontIndex(), GetFontSize());
274     AddLine(place, lineinfo);
275     if (CSection* pSection = m_SectionArray.GetAt(0))
276       pSection->ResetLinePlace();
277 
278     m_bInitial = true;
279   }
280 }
281 
ResetAll()282 void CPDF_VariableText::ResetAll() {
283   m_bInitial = false;
284   ResetSectionArray();
285 }
286 
InsertWord(const CPVT_WordPlace & place,uint16_t word,int32_t charset,const CPVT_WordProps * pWordProps)287 CPVT_WordPlace CPDF_VariableText::InsertWord(const CPVT_WordPlace& place,
288                                              uint16_t word,
289                                              int32_t charset,
290                                              const CPVT_WordProps* pWordProps) {
291   int32_t nTotlaWords = GetTotalWords();
292   if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar)
293     return place;
294   if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray)
295     return place;
296 
297   CPVT_WordPlace newplace = place;
298   newplace.nWordIndex++;
299   int32_t nFontIndex =
300       GetSubWord() > 0 ? GetDefaultFontIndex()
301                        : GetWordFontIndex(word, charset, GetDefaultFontIndex());
302   return AddWord(newplace, CPVT_WordInfo(word, charset, nFontIndex, nullptr));
303 }
304 
InsertSection(const CPVT_WordPlace & place,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps)305 CPVT_WordPlace CPDF_VariableText::InsertSection(
306     const CPVT_WordPlace& place,
307     const CPVT_SecProps* pSecProps,
308     const CPVT_WordProps* pWordProps) {
309   int32_t nTotlaWords = GetTotalWords();
310   if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar)
311     return place;
312   if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray)
313     return place;
314   if (!m_bMultiLine)
315     return place;
316 
317   CPVT_WordPlace wordplace = place;
318   UpdateWordPlace(wordplace);
319   CPVT_WordPlace newplace = place;
320   if (CSection* pSection = m_SectionArray.GetAt(wordplace.nSecIndex)) {
321     CPVT_WordPlace NewPlace(wordplace.nSecIndex + 1, 0, -1);
322     CPVT_SectionInfo secinfo;
323     AddSection(NewPlace, secinfo);
324     newplace = NewPlace;
325     if (CSection* pNewSection = m_SectionArray.GetAt(NewPlace.nSecIndex)) {
326       for (int32_t w = wordplace.nWordIndex + 1,
327                    sz = pSection->m_WordArray.GetSize();
328            w < sz; w++) {
329         if (CPVT_WordInfo* pWord = pSection->m_WordArray.GetAt(w)) {
330           NewPlace.nWordIndex++;
331           pNewSection->AddWord(NewPlace, *pWord);
332         }
333       }
334     }
335     ClearSectionRightWords(wordplace);
336   }
337   return newplace;
338 }
339 
InsertText(const CPVT_WordPlace & place,const FX_WCHAR * text)340 CPVT_WordPlace CPDF_VariableText::InsertText(const CPVT_WordPlace& place,
341                                              const FX_WCHAR* text) {
342   CFX_WideString swText = text;
343   CPVT_WordPlace wp = place;
344   for (int32_t i = 0, sz = swText.GetLength(); i < sz; i++) {
345     CPVT_WordPlace oldwp = wp;
346     uint16_t word = swText.GetAt(i);
347     switch (word) {
348       case 0x0D:
349         if (m_bMultiLine) {
350           if (swText.GetAt(i + 1) == 0x0A)
351             i += 1;
352 
353           wp = InsertSection(wp, nullptr, nullptr);
354         }
355         break;
356       case 0x0A:
357         if (m_bMultiLine) {
358           if (swText.GetAt(i + 1) == 0x0D)
359             i += 1;
360 
361           wp = InsertSection(wp, nullptr, nullptr);
362         }
363         break;
364       case 0x09:
365         word = 0x20;
366       default:
367         wp = InsertWord(wp, word, FXFONT_DEFAULT_CHARSET, nullptr);
368         break;
369     }
370     if (wp == oldwp)
371       break;
372   }
373   return wp;
374 }
375 
DeleteWords(const CPVT_WordRange & PlaceRange)376 CPVT_WordPlace CPDF_VariableText::DeleteWords(
377     const CPVT_WordRange& PlaceRange) {
378   bool bLastSecPos = false;
379   if (CSection* pSection = m_SectionArray.GetAt(PlaceRange.EndPos.nSecIndex))
380     bLastSecPos = (PlaceRange.EndPos == pSection->GetEndWordPlace());
381 
382   ClearWords(PlaceRange);
383   if (PlaceRange.BeginPos.nSecIndex != PlaceRange.EndPos.nSecIndex) {
384     ClearEmptySections(PlaceRange);
385     if (!bLastSecPos)
386       LinkLatterSection(PlaceRange.BeginPos);
387   }
388   return PlaceRange.BeginPos;
389 }
390 
DeleteWord(const CPVT_WordPlace & place)391 CPVT_WordPlace CPDF_VariableText::DeleteWord(const CPVT_WordPlace& place) {
392   return ClearRightWord(AdjustLineHeader(place, true));
393 }
394 
BackSpaceWord(const CPVT_WordPlace & place)395 CPVT_WordPlace CPDF_VariableText::BackSpaceWord(const CPVT_WordPlace& place) {
396   return ClearLeftWord(AdjustLineHeader(place, true));
397 }
398 
SetText(const CFX_WideString & swText)399 void CPDF_VariableText::SetText(const CFX_WideString& swText) {
400   DeleteWords(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
401   CPVT_WordPlace wp(0, 0, -1);
402   CPVT_SectionInfo secinfo;
403   if (CSection* pSection = m_SectionArray.GetAt(0))
404     pSection->m_SecInfo = secinfo;
405 
406   int32_t nCharCount = 0;
407   for (int32_t i = 0, sz = swText.GetLength(); i < sz; i++) {
408     if (m_nLimitChar > 0 && nCharCount >= m_nLimitChar)
409       break;
410     if (m_nCharArray > 0 && nCharCount >= m_nCharArray)
411       break;
412 
413     uint16_t word = swText.GetAt(i);
414     switch (word) {
415       case 0x0D:
416         if (m_bMultiLine) {
417           if (swText.GetAt(i + 1) == 0x0A)
418             i += 1;
419 
420           wp.nSecIndex++;
421           wp.nLineIndex = 0;
422           wp.nWordIndex = -1;
423           AddSection(wp, secinfo);
424         }
425         break;
426       case 0x0A:
427         if (m_bMultiLine) {
428           if (swText.GetAt(i + 1) == 0x0D)
429             i += 1;
430 
431           wp.nSecIndex++;
432           wp.nLineIndex = 0;
433           wp.nWordIndex = -1;
434           AddSection(wp, secinfo);
435         }
436         break;
437       case 0x09:
438         word = 0x20;
439       default:
440         wp = InsertWord(wp, word, FXFONT_DEFAULT_CHARSET, nullptr);
441         break;
442     }
443     nCharCount++;
444   }
445 }
446 
UpdateWordPlace(CPVT_WordPlace & place) const447 void CPDF_VariableText::UpdateWordPlace(CPVT_WordPlace& place) const {
448   if (place.nSecIndex < 0)
449     place = GetBeginWordPlace();
450   if (place.nSecIndex >= m_SectionArray.GetSize())
451     place = GetEndWordPlace();
452 
453   place = AdjustLineHeader(place, true);
454   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex))
455     pSection->UpdateWordPlace(place);
456 }
457 
WordPlaceToWordIndex(const CPVT_WordPlace & place) const458 int32_t CPDF_VariableText::WordPlaceToWordIndex(
459     const CPVT_WordPlace& place) const {
460   CPVT_WordPlace newplace = place;
461   UpdateWordPlace(newplace);
462   int32_t nIndex = 0;
463   int32_t i = 0;
464   int32_t sz = 0;
465   for (i = 0, sz = m_SectionArray.GetSize(); i < sz && i < newplace.nSecIndex;
466        i++) {
467     if (CSection* pSection = m_SectionArray.GetAt(i)) {
468       nIndex += pSection->m_WordArray.GetSize();
469       if (i != m_SectionArray.GetSize() - 1)
470         nIndex += kReturnLength;
471     }
472   }
473   if (i >= 0 && i < m_SectionArray.GetSize())
474     nIndex += newplace.nWordIndex + kReturnLength;
475   return nIndex;
476 }
477 
WordIndexToWordPlace(int32_t index) const478 CPVT_WordPlace CPDF_VariableText::WordIndexToWordPlace(int32_t index) const {
479   CPVT_WordPlace place = GetBeginWordPlace();
480   int32_t nOldIndex = 0, nIndex = 0;
481   bool bFind = false;
482   for (int32_t i = 0, sz = m_SectionArray.GetSize(); i < sz; i++) {
483     if (CSection* pSection = m_SectionArray.GetAt(i)) {
484       nIndex += pSection->m_WordArray.GetSize();
485       if (nIndex == index) {
486         place = pSection->GetEndWordPlace();
487         bFind = true;
488         break;
489       } else if (nIndex > index) {
490         place.nSecIndex = i;
491         place.nWordIndex = index - nOldIndex - 1;
492         pSection->UpdateWordPlace(place);
493         bFind = true;
494         break;
495       }
496       if (i != m_SectionArray.GetSize() - 1)
497         nIndex += kReturnLength;
498       nOldIndex = nIndex;
499     }
500   }
501   if (!bFind)
502     place = GetEndWordPlace();
503   return place;
504 }
505 
GetBeginWordPlace() const506 CPVT_WordPlace CPDF_VariableText::GetBeginWordPlace() const {
507   return m_bInitial ? CPVT_WordPlace(0, 0, -1) : CPVT_WordPlace();
508 }
509 
GetEndWordPlace() const510 CPVT_WordPlace CPDF_VariableText::GetEndWordPlace() const {
511   if (CSection* pSection = m_SectionArray.GetAt(m_SectionArray.GetSize() - 1))
512     return pSection->GetEndWordPlace();
513   return CPVT_WordPlace();
514 }
515 
GetPrevWordPlace(const CPVT_WordPlace & place) const516 CPVT_WordPlace CPDF_VariableText::GetPrevWordPlace(
517     const CPVT_WordPlace& place) const {
518   if (place.nSecIndex < 0)
519     return GetBeginWordPlace();
520   if (place.nSecIndex >= m_SectionArray.GetSize())
521     return GetEndWordPlace();
522   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
523     if (place.WordCmp(pSection->GetBeginWordPlace()) <= 0) {
524       if (CSection* pPrevSection = m_SectionArray.GetAt(place.nSecIndex - 1))
525         return pPrevSection->GetEndWordPlace();
526       return GetBeginWordPlace();
527     }
528     return pSection->GetPrevWordPlace(place);
529   }
530   return place;
531 }
532 
GetNextWordPlace(const CPVT_WordPlace & place) const533 CPVT_WordPlace CPDF_VariableText::GetNextWordPlace(
534     const CPVT_WordPlace& place) const {
535   if (place.nSecIndex < 0)
536     return GetBeginWordPlace();
537   if (place.nSecIndex >= m_SectionArray.GetSize())
538     return GetEndWordPlace();
539   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
540     if (place.WordCmp(pSection->GetEndWordPlace()) >= 0) {
541       if (CSection* pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1))
542         return pNextSection->GetBeginWordPlace();
543       return GetEndWordPlace();
544     }
545     return pSection->GetNextWordPlace(place);
546   }
547   return place;
548 }
549 
SearchWordPlace(const CFX_PointF & point) const550 CPVT_WordPlace CPDF_VariableText::SearchWordPlace(
551     const CFX_PointF& point) const {
552   CFX_PointF pt = OutToIn(point);
553   CPVT_WordPlace place = GetBeginWordPlace();
554   int32_t nLeft = 0;
555   int32_t nRight = m_SectionArray.GetSize() - 1;
556   int32_t nMid = m_SectionArray.GetSize() / 2;
557   bool bUp = true;
558   bool bDown = true;
559   while (nLeft <= nRight) {
560     if (CSection* pSection = m_SectionArray.GetAt(nMid)) {
561       if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.top)) {
562         bUp = false;
563       }
564       if (IsFloatBigger(pSection->m_SecInfo.rcSection.bottom, pt.y)) {
565         bDown = false;
566       }
567       if (IsFloatSmaller(pt.y, pSection->m_SecInfo.rcSection.top)) {
568         nRight = nMid - 1;
569         nMid = (nLeft + nRight) / 2;
570         continue;
571       } else if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.bottom)) {
572         nLeft = nMid + 1;
573         nMid = (nLeft + nRight) / 2;
574         continue;
575       } else {
576         place = pSection->SearchWordPlace(
577             CFX_PointF(pt.x - pSection->m_SecInfo.rcSection.left,
578                        pt.y - pSection->m_SecInfo.rcSection.top));
579         place.nSecIndex = nMid;
580         return place;
581       }
582     } else {
583       break;
584     }
585   }
586   if (bUp)
587     place = GetBeginWordPlace();
588   if (bDown)
589     place = GetEndWordPlace();
590   return place;
591 }
592 
GetUpWordPlace(const CPVT_WordPlace & place,const CFX_PointF & point) const593 CPVT_WordPlace CPDF_VariableText::GetUpWordPlace(
594     const CPVT_WordPlace& place,
595     const CFX_PointF& point) const {
596   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
597     CPVT_WordPlace temp = place;
598     CFX_PointF pt = OutToIn(point);
599     if (temp.nLineIndex-- > 0) {
600       return pSection->SearchWordPlace(
601           pt.x - pSection->m_SecInfo.rcSection.left, temp);
602     }
603     if (temp.nSecIndex-- > 0) {
604       if (CSection* pLastSection = m_SectionArray.GetAt(temp.nSecIndex)) {
605         temp.nLineIndex = pLastSection->m_LineArray.GetSize() - 1;
606         return pLastSection->SearchWordPlace(
607             pt.x - pLastSection->m_SecInfo.rcSection.left, temp);
608       }
609     }
610   }
611   return place;
612 }
613 
GetDownWordPlace(const CPVT_WordPlace & place,const CFX_PointF & point) const614 CPVT_WordPlace CPDF_VariableText::GetDownWordPlace(
615     const CPVT_WordPlace& place,
616     const CFX_PointF& point) const {
617   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
618     CPVT_WordPlace temp = place;
619     CFX_PointF pt = OutToIn(point);
620     if (temp.nLineIndex++ < pSection->m_LineArray.GetSize() - 1) {
621       return pSection->SearchWordPlace(
622           pt.x - pSection->m_SecInfo.rcSection.left, temp);
623     }
624     if (temp.nSecIndex++ < m_SectionArray.GetSize() - 1) {
625       if (CSection* pNextSection = m_SectionArray.GetAt(temp.nSecIndex)) {
626         temp.nLineIndex = 0;
627         return pNextSection->SearchWordPlace(
628             pt.x - pSection->m_SecInfo.rcSection.left, temp);
629       }
630     }
631   }
632   return place;
633 }
634 
GetLineBeginPlace(const CPVT_WordPlace & place) const635 CPVT_WordPlace CPDF_VariableText::GetLineBeginPlace(
636     const CPVT_WordPlace& place) const {
637   return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);
638 }
639 
GetLineEndPlace(const CPVT_WordPlace & place) const640 CPVT_WordPlace CPDF_VariableText::GetLineEndPlace(
641     const CPVT_WordPlace& place) const {
642   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
643     if (CLine* pLine = pSection->m_LineArray.GetAt(place.nLineIndex))
644       return pLine->GetEndWordPlace();
645   }
646   return place;
647 }
648 
GetSectionBeginPlace(const CPVT_WordPlace & place) const649 CPVT_WordPlace CPDF_VariableText::GetSectionBeginPlace(
650     const CPVT_WordPlace& place) const {
651   return CPVT_WordPlace(place.nSecIndex, 0, -1);
652 }
653 
GetSectionEndPlace(const CPVT_WordPlace & place) const654 CPVT_WordPlace CPDF_VariableText::GetSectionEndPlace(
655     const CPVT_WordPlace& place) const {
656   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex))
657     return pSection->GetEndWordPlace();
658   return place;
659 }
660 
GetTotalWords() const661 int32_t CPDF_VariableText::GetTotalWords() const {
662   int32_t nTotal = 0;
663   for (int32_t i = 0, sz = m_SectionArray.GetSize(); i < sz; i++) {
664     if (CSection* pSection = m_SectionArray.GetAt(i))
665       nTotal += (pSection->m_WordArray.GetSize() + kReturnLength);
666   }
667 
668   return nTotal - kReturnLength;
669 }
670 
ResetSectionArray()671 void CPDF_VariableText::ResetSectionArray() {
672   for (int32_t s = 0, sz = m_SectionArray.GetSize(); s < sz; s++)
673     delete m_SectionArray.GetAt(s);
674 
675   m_SectionArray.RemoveAll();
676 }
677 
AddSection(const CPVT_WordPlace & place,const CPVT_SectionInfo & secinfo)678 CPVT_WordPlace CPDF_VariableText::AddSection(const CPVT_WordPlace& place,
679                                              const CPVT_SectionInfo& secinfo) {
680   if (IsValid() && !m_bMultiLine)
681     return place;
682 
683   int32_t nSecIndex =
684       std::max(std::min(place.nSecIndex, m_SectionArray.GetSize()), 0);
685   CSection* pSection = new CSection(this);
686   pSection->m_SecInfo = secinfo;
687   pSection->SecPlace.nSecIndex = nSecIndex;
688   if (nSecIndex == m_SectionArray.GetSize())
689     m_SectionArray.Add(pSection);
690   else
691     m_SectionArray.InsertAt(nSecIndex, pSection);
692 
693   return place;
694 }
695 
AddLine(const CPVT_WordPlace & place,const CPVT_LineInfo & lineinfo)696 CPVT_WordPlace CPDF_VariableText::AddLine(const CPVT_WordPlace& place,
697                                           const CPVT_LineInfo& lineinfo) {
698   if (m_SectionArray.IsEmpty())
699     return place;
700   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex))
701     return pSection->AddLine(lineinfo);
702   return place;
703 }
704 
AddWord(const CPVT_WordPlace & place,const CPVT_WordInfo & wordinfo)705 CPVT_WordPlace CPDF_VariableText::AddWord(const CPVT_WordPlace& place,
706                                           const CPVT_WordInfo& wordinfo) {
707   if (m_SectionArray.GetSize() <= 0) {
708     return place;
709   }
710   CPVT_WordPlace newplace = place;
711   newplace.nSecIndex =
712       std::max(std::min(newplace.nSecIndex, m_SectionArray.GetSize() - 1), 0);
713   if (CSection* pSection = m_SectionArray.GetAt(newplace.nSecIndex))
714     return pSection->AddWord(newplace, wordinfo);
715   return place;
716 }
717 
GetWordInfo(const CPVT_WordPlace & place,CPVT_WordInfo & wordinfo)718 bool CPDF_VariableText::GetWordInfo(const CPVT_WordPlace& place,
719                                     CPVT_WordInfo& wordinfo) {
720   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
721     if (CPVT_WordInfo* pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {
722       wordinfo = *pWord;
723       return true;
724     }
725   }
726   return false;
727 }
728 
SetWordInfo(const CPVT_WordPlace & place,const CPVT_WordInfo & wordinfo)729 bool CPDF_VariableText::SetWordInfo(const CPVT_WordPlace& place,
730                                     const CPVT_WordInfo& wordinfo) {
731   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
732     if (CPVT_WordInfo* pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {
733       *pWord = wordinfo;
734       return true;
735     }
736   }
737   return false;
738 }
739 
GetLineInfo(const CPVT_WordPlace & place,CPVT_LineInfo & lineinfo)740 bool CPDF_VariableText::GetLineInfo(const CPVT_WordPlace& place,
741                                     CPVT_LineInfo& lineinfo) {
742   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
743     if (CLine* pLine = pSection->m_LineArray.GetAt(place.nLineIndex)) {
744       lineinfo = pLine->m_LineInfo;
745       return true;
746     }
747   }
748   return false;
749 }
750 
GetSectionInfo(const CPVT_WordPlace & place,CPVT_SectionInfo & secinfo)751 bool CPDF_VariableText::GetSectionInfo(const CPVT_WordPlace& place,
752                                        CPVT_SectionInfo& secinfo) {
753   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
754     secinfo = pSection->m_SecInfo;
755     return true;
756   }
757   return false;
758 }
759 
SetPlateRect(const CFX_FloatRect & rect)760 void CPDF_VariableText::SetPlateRect(const CFX_FloatRect& rect) {
761   m_rcPlate = rect;
762 }
763 
SetContentRect(const CPVT_FloatRect & rect)764 void CPDF_VariableText::SetContentRect(const CPVT_FloatRect& rect) {
765   m_rcContent = rect;
766 }
767 
GetContentRect() const768 CFX_FloatRect CPDF_VariableText::GetContentRect() const {
769   return InToOut(CPVT_FloatRect(m_rcContent));
770 }
771 
GetPlateRect() const772 const CFX_FloatRect& CPDF_VariableText::GetPlateRect() const {
773   return m_rcPlate;
774 }
775 
GetWordFontSize(const CPVT_WordInfo & WordInfo)776 FX_FLOAT CPDF_VariableText::GetWordFontSize(const CPVT_WordInfo& WordInfo) {
777   return GetFontSize();
778 }
779 
GetWordFontIndex(const CPVT_WordInfo & WordInfo)780 int32_t CPDF_VariableText::GetWordFontIndex(const CPVT_WordInfo& WordInfo) {
781   return WordInfo.nFontIndex;
782 }
783 
GetWordWidth(int32_t nFontIndex,uint16_t Word,uint16_t SubWord,FX_FLOAT fCharSpace,int32_t nHorzScale,FX_FLOAT fFontSize,FX_FLOAT fWordTail)784 FX_FLOAT CPDF_VariableText::GetWordWidth(int32_t nFontIndex,
785                                          uint16_t Word,
786                                          uint16_t SubWord,
787                                          FX_FLOAT fCharSpace,
788                                          int32_t nHorzScale,
789                                          FX_FLOAT fFontSize,
790                                          FX_FLOAT fWordTail) {
791   return (GetCharWidth(nFontIndex, Word, SubWord) * fFontSize * kFontScale +
792           fCharSpace) *
793              nHorzScale * kScalePercent +
794          fWordTail;
795 }
796 
GetWordWidth(const CPVT_WordInfo & WordInfo)797 FX_FLOAT CPDF_VariableText::GetWordWidth(const CPVT_WordInfo& WordInfo) {
798   return GetWordWidth(GetWordFontIndex(WordInfo), WordInfo.Word, GetSubWord(),
799                       GetCharSpace(WordInfo), GetHorzScale(WordInfo),
800                       GetWordFontSize(WordInfo), WordInfo.fWordTail);
801 }
802 
GetLineAscent(const CPVT_SectionInfo & SecInfo)803 FX_FLOAT CPDF_VariableText::GetLineAscent(const CPVT_SectionInfo& SecInfo) {
804   return GetFontAscent(GetDefaultFontIndex(), GetFontSize());
805 }
806 
GetLineDescent(const CPVT_SectionInfo & SecInfo)807 FX_FLOAT CPDF_VariableText::GetLineDescent(const CPVT_SectionInfo& SecInfo) {
808   return GetFontDescent(GetDefaultFontIndex(), GetFontSize());
809 }
810 
GetFontAscent(int32_t nFontIndex,FX_FLOAT fFontSize)811 FX_FLOAT CPDF_VariableText::GetFontAscent(int32_t nFontIndex,
812                                           FX_FLOAT fFontSize) {
813   return (FX_FLOAT)GetTypeAscent(nFontIndex) * fFontSize * kFontScale;
814 }
815 
GetFontDescent(int32_t nFontIndex,FX_FLOAT fFontSize)816 FX_FLOAT CPDF_VariableText::GetFontDescent(int32_t nFontIndex,
817                                            FX_FLOAT fFontSize) {
818   return (FX_FLOAT)GetTypeDescent(nFontIndex) * fFontSize * kFontScale;
819 }
820 
GetWordAscent(const CPVT_WordInfo & WordInfo,FX_FLOAT fFontSize)821 FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo& WordInfo,
822                                           FX_FLOAT fFontSize) {
823   return GetFontAscent(GetWordFontIndex(WordInfo), fFontSize);
824 }
825 
GetWordDescent(const CPVT_WordInfo & WordInfo,FX_FLOAT fFontSize)826 FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo& WordInfo,
827                                            FX_FLOAT fFontSize) {
828   return GetFontDescent(GetWordFontIndex(WordInfo), fFontSize);
829 }
830 
GetWordAscent(const CPVT_WordInfo & WordInfo)831 FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo& WordInfo) {
832   return GetFontAscent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo));
833 }
834 
GetWordDescent(const CPVT_WordInfo & WordInfo)835 FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo& WordInfo) {
836   return GetFontDescent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo));
837 }
838 
GetLineLeading(const CPVT_SectionInfo & SecInfo)839 FX_FLOAT CPDF_VariableText::GetLineLeading(const CPVT_SectionInfo& SecInfo) {
840   return m_fLineLeading;
841 }
842 
GetLineIndent(const CPVT_SectionInfo & SecInfo)843 FX_FLOAT CPDF_VariableText::GetLineIndent(const CPVT_SectionInfo& SecInfo) {
844   return 0.0f;
845 }
846 
GetAlignment(const CPVT_SectionInfo & SecInfo)847 int32_t CPDF_VariableText::GetAlignment(const CPVT_SectionInfo& SecInfo) {
848   return m_nAlignment;
849 }
850 
GetCharSpace(const CPVT_WordInfo & WordInfo)851 FX_FLOAT CPDF_VariableText::GetCharSpace(const CPVT_WordInfo& WordInfo) {
852   return m_fCharSpace;
853 }
854 
GetHorzScale(const CPVT_WordInfo & WordInfo)855 int32_t CPDF_VariableText::GetHorzScale(const CPVT_WordInfo& WordInfo) {
856   return m_nHorzScale;
857 }
858 
ClearSectionRightWords(const CPVT_WordPlace & place)859 void CPDF_VariableText::ClearSectionRightWords(const CPVT_WordPlace& place) {
860   CPVT_WordPlace wordplace = AdjustLineHeader(place, true);
861   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
862     for (int32_t w = pSection->m_WordArray.GetSize() - 1;
863          w > wordplace.nWordIndex; w--) {
864       delete pSection->m_WordArray.GetAt(w);
865       pSection->m_WordArray.RemoveAt(w);
866     }
867   }
868 }
869 
AdjustLineHeader(const CPVT_WordPlace & place,bool bPrevOrNext) const870 CPVT_WordPlace CPDF_VariableText::AdjustLineHeader(const CPVT_WordPlace& place,
871                                                    bool bPrevOrNext) const {
872   if (place.nWordIndex < 0 && place.nLineIndex > 0)
873     return bPrevOrNext ? GetPrevWordPlace(place) : GetNextWordPlace(place);
874   return place;
875 }
876 
ClearEmptySection(const CPVT_WordPlace & place)877 bool CPDF_VariableText::ClearEmptySection(const CPVT_WordPlace& place) {
878   if (place.nSecIndex == 0 && m_SectionArray.GetSize() == 1)
879     return false;
880   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
881     if (pSection->m_WordArray.GetSize() == 0) {
882       delete pSection;
883       m_SectionArray.RemoveAt(place.nSecIndex);
884       return true;
885     }
886   }
887   return false;
888 }
889 
ClearEmptySections(const CPVT_WordRange & PlaceRange)890 void CPDF_VariableText::ClearEmptySections(const CPVT_WordRange& PlaceRange) {
891   CPVT_WordPlace wordplace;
892   for (int32_t s = PlaceRange.EndPos.nSecIndex;
893        s > PlaceRange.BeginPos.nSecIndex; s--) {
894     wordplace.nSecIndex = s;
895     ClearEmptySection(wordplace);
896   }
897 }
898 
LinkLatterSection(const CPVT_WordPlace & place)899 void CPDF_VariableText::LinkLatterSection(const CPVT_WordPlace& place) {
900   CPVT_WordPlace oldplace = AdjustLineHeader(place, true);
901   if (CSection* pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) {
902     if (CSection* pSection = m_SectionArray.GetAt(oldplace.nSecIndex)) {
903       for (int32_t w = 0, sz = pNextSection->m_WordArray.GetSize(); w < sz;
904            w++) {
905         if (CPVT_WordInfo* pWord = pNextSection->m_WordArray.GetAt(w)) {
906           oldplace.nWordIndex++;
907           pSection->AddWord(oldplace, *pWord);
908         }
909       }
910     }
911     delete pNextSection;
912     m_SectionArray.RemoveAt(place.nSecIndex + 1);
913   }
914 }
915 
ClearWords(const CPVT_WordRange & PlaceRange)916 void CPDF_VariableText::ClearWords(const CPVT_WordRange& PlaceRange) {
917   CPVT_WordRange NewRange;
918   NewRange.BeginPos = AdjustLineHeader(PlaceRange.BeginPos, true);
919   NewRange.EndPos = AdjustLineHeader(PlaceRange.EndPos, true);
920   for (int32_t s = NewRange.EndPos.nSecIndex; s >= NewRange.BeginPos.nSecIndex;
921        s--) {
922     if (CSection* pSection = m_SectionArray.GetAt(s))
923       pSection->ClearWords(NewRange);
924   }
925 }
926 
ClearLeftWord(const CPVT_WordPlace & place)927 CPVT_WordPlace CPDF_VariableText::ClearLeftWord(const CPVT_WordPlace& place) {
928   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
929     CPVT_WordPlace leftplace = GetPrevWordPlace(place);
930     if (leftplace != place) {
931       if (leftplace.nSecIndex != place.nSecIndex) {
932         if (pSection->m_WordArray.GetSize() == 0)
933           ClearEmptySection(place);
934         else
935           LinkLatterSection(leftplace);
936       } else {
937         pSection->ClearWord(place);
938       }
939     }
940     return leftplace;
941   }
942   return place;
943 }
944 
ClearRightWord(const CPVT_WordPlace & place)945 CPVT_WordPlace CPDF_VariableText::ClearRightWord(const CPVT_WordPlace& place) {
946   if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) {
947     CPVT_WordPlace rightplace =
948         AdjustLineHeader(GetNextWordPlace(place), false);
949     if (rightplace != place) {
950       if (rightplace.nSecIndex != place.nSecIndex)
951         LinkLatterSection(place);
952       else
953         pSection->ClearWord(rightplace);
954     }
955   }
956   return place;
957 }
958 
RearrangeAll()959 void CPDF_VariableText::RearrangeAll() {
960   Rearrange(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
961 }
962 
RearrangePart(const CPVT_WordRange & PlaceRange)963 void CPDF_VariableText::RearrangePart(const CPVT_WordRange& PlaceRange) {
964   Rearrange(PlaceRange);
965 }
966 
Rearrange(const CPVT_WordRange & PlaceRange)967 CPVT_FloatRect CPDF_VariableText::Rearrange(const CPVT_WordRange& PlaceRange) {
968   CPVT_FloatRect rcRet;
969   if (IsValid()) {
970     if (m_bAutoFontSize) {
971       SetFontSize(GetAutoFontSize());
972       rcRet = RearrangeSections(
973           CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
974     } else {
975       rcRet = RearrangeSections(PlaceRange);
976     }
977   }
978   SetContentRect(rcRet);
979   return rcRet;
980 }
981 
GetAutoFontSize()982 FX_FLOAT CPDF_VariableText::GetAutoFontSize() {
983   int32_t nTotal = sizeof(gFontSizeSteps) / sizeof(uint8_t);
984   if (IsMultiLine())
985     nTotal /= 4;
986   if (nTotal <= 0)
987     return 0;
988   if (GetPlateWidth() <= 0)
989     return 0;
990 
991   int32_t nLeft = 0;
992   int32_t nRight = nTotal - 1;
993   int32_t nMid = nTotal / 2;
994   while (nLeft <= nRight) {
995     if (IsBigger(gFontSizeSteps[nMid])) {
996       nRight = nMid - 1;
997       nMid = (nLeft + nRight) / 2;
998       continue;
999     } else {
1000       nLeft = nMid + 1;
1001       nMid = (nLeft + nRight) / 2;
1002       continue;
1003     }
1004   }
1005   return (FX_FLOAT)gFontSizeSteps[nMid];
1006 }
1007 
IsBigger(FX_FLOAT fFontSize) const1008 bool CPDF_VariableText::IsBigger(FX_FLOAT fFontSize) const {
1009   CFX_SizeF szTotal;
1010   for (int32_t s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
1011     if (CSection* pSection = m_SectionArray.GetAt(s)) {
1012       CFX_SizeF size = pSection->GetSectionSize(fFontSize);
1013       szTotal.width = std::max(size.width, szTotal.width);
1014       szTotal.height += size.height;
1015       if (IsFloatBigger(szTotal.width, GetPlateWidth()) ||
1016           IsFloatBigger(szTotal.height, GetPlateHeight())) {
1017         return true;
1018       }
1019     }
1020   }
1021   return false;
1022 }
1023 
RearrangeSections(const CPVT_WordRange & PlaceRange)1024 CPVT_FloatRect CPDF_VariableText::RearrangeSections(
1025     const CPVT_WordRange& PlaceRange) {
1026   CPVT_WordPlace place;
1027   FX_FLOAT fPosY = 0;
1028   FX_FLOAT fOldHeight;
1029   int32_t nSSecIndex = PlaceRange.BeginPos.nSecIndex;
1030   int32_t nESecIndex = PlaceRange.EndPos.nSecIndex;
1031   CPVT_FloatRect rcRet;
1032   for (int32_t s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
1033     place.nSecIndex = s;
1034     if (CSection* pSection = m_SectionArray.GetAt(s)) {
1035       pSection->SecPlace = place;
1036       CPVT_FloatRect rcSec = pSection->m_SecInfo.rcSection;
1037       if (s >= nSSecIndex) {
1038         if (s <= nESecIndex) {
1039           rcSec = pSection->Rearrange();
1040           rcSec.top += fPosY;
1041           rcSec.bottom += fPosY;
1042         } else {
1043           fOldHeight = pSection->m_SecInfo.rcSection.bottom -
1044                        pSection->m_SecInfo.rcSection.top;
1045           rcSec.top = fPosY;
1046           rcSec.bottom = fPosY + fOldHeight;
1047         }
1048         pSection->m_SecInfo.rcSection = rcSec;
1049         pSection->ResetLinePlace();
1050       }
1051       if (s == 0) {
1052         rcRet = rcSec;
1053       } else {
1054         rcRet.left = std::min(rcSec.left, rcRet.left);
1055         rcRet.top = std::min(rcSec.top, rcRet.top);
1056         rcRet.right = std::max(rcSec.right, rcRet.right);
1057         rcRet.bottom = std::max(rcSec.bottom, rcRet.bottom);
1058       }
1059       fPosY += rcSec.Height();
1060     }
1061   }
1062   return rcRet;
1063 }
1064 
GetCharWidth(int32_t nFontIndex,uint16_t Word,uint16_t SubWord)1065 int32_t CPDF_VariableText::GetCharWidth(int32_t nFontIndex,
1066                                         uint16_t Word,
1067                                         uint16_t SubWord) {
1068   if (!m_pVTProvider)
1069     return 0;
1070   uint16_t word = SubWord ? SubWord : Word;
1071   return m_pVTProvider->GetCharWidth(nFontIndex, word);
1072 }
1073 
GetTypeAscent(int32_t nFontIndex)1074 int32_t CPDF_VariableText::GetTypeAscent(int32_t nFontIndex) {
1075   return m_pVTProvider ? m_pVTProvider->GetTypeAscent(nFontIndex) : 0;
1076 }
1077 
GetTypeDescent(int32_t nFontIndex)1078 int32_t CPDF_VariableText::GetTypeDescent(int32_t nFontIndex) {
1079   return m_pVTProvider ? m_pVTProvider->GetTypeDescent(nFontIndex) : 0;
1080 }
1081 
GetWordFontIndex(uint16_t word,int32_t charset,int32_t nFontIndex)1082 int32_t CPDF_VariableText::GetWordFontIndex(uint16_t word,
1083                                             int32_t charset,
1084                                             int32_t nFontIndex) {
1085   return m_pVTProvider
1086              ? m_pVTProvider->GetWordFontIndex(word, charset, nFontIndex)
1087              : -1;
1088 }
1089 
GetDefaultFontIndex()1090 int32_t CPDF_VariableText::GetDefaultFontIndex() {
1091   return m_pVTProvider ? m_pVTProvider->GetDefaultFontIndex() : -1;
1092 }
1093 
IsLatinWord(uint16_t word)1094 bool CPDF_VariableText::IsLatinWord(uint16_t word) {
1095   return m_pVTProvider ? m_pVTProvider->IsLatinWord(word) : false;
1096 }
1097 
GetIterator()1098 CPDF_VariableText::Iterator* CPDF_VariableText::GetIterator() {
1099   if (!m_pVTIterator)
1100     m_pVTIterator = pdfium::MakeUnique<CPDF_VariableText::Iterator>(this);
1101   return m_pVTIterator.get();
1102 }
1103 
SetProvider(CPDF_VariableText::Provider * pProvider)1104 void CPDF_VariableText::SetProvider(CPDF_VariableText::Provider* pProvider) {
1105   m_pVTProvider = pProvider;
1106 }
1107 
GetPlateSize() const1108 CFX_SizeF CPDF_VariableText::GetPlateSize() const {
1109   return CFX_SizeF(GetPlateWidth(), GetPlateHeight());
1110 }
1111 
GetBTPoint() const1112 CFX_PointF CPDF_VariableText::GetBTPoint() const {
1113   return CFX_PointF(m_rcPlate.left, m_rcPlate.top);
1114 }
1115 
GetETPoint() const1116 CFX_PointF CPDF_VariableText::GetETPoint() const {
1117   return CFX_PointF(m_rcPlate.right, m_rcPlate.bottom);
1118 }
1119 
InToOut(const CFX_PointF & point) const1120 CFX_PointF CPDF_VariableText::InToOut(const CFX_PointF& point) const {
1121   return CFX_PointF(point.x + GetBTPoint().x, GetBTPoint().y - point.y);
1122 }
1123 
OutToIn(const CFX_PointF & point) const1124 CFX_PointF CPDF_VariableText::OutToIn(const CFX_PointF& point) const {
1125   return CFX_PointF(point.x - GetBTPoint().x, GetBTPoint().y - point.y);
1126 }
1127 
InToOut(const CPVT_FloatRect & rect) const1128 CFX_FloatRect CPDF_VariableText::InToOut(const CPVT_FloatRect& rect) const {
1129   CFX_PointF ptLeftTop = InToOut(CFX_PointF(rect.left, rect.top));
1130   CFX_PointF ptRightBottom = InToOut(CFX_PointF(rect.right, rect.bottom));
1131   return CFX_FloatRect(ptLeftTop.x, ptRightBottom.y, ptRightBottom.x,
1132                        ptLeftTop.y);
1133 }
1134 
OutToIn(const CFX_FloatRect & rect) const1135 CPVT_FloatRect CPDF_VariableText::OutToIn(const CFX_FloatRect& rect) const {
1136   CFX_PointF ptLeftTop = OutToIn(CFX_PointF(rect.left, rect.top));
1137   CFX_PointF ptRightBottom = OutToIn(CFX_PointF(rect.right, rect.bottom));
1138   return CPVT_FloatRect(ptLeftTop.x, ptLeftTop.y, ptRightBottom.x,
1139                         ptRightBottom.y);
1140 }
1141