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