Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cpvt_variabletext.cpp
Go to the documentation of this file.
1// Copyright 2016 The PDFium Authors
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/cpvt_variabletext.h"
8
9#include <algorithm>
10#include <utility>
11
12#include "core/fpdfapi/font/cpdf_font.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/ipvt_fontmap.h"
17#include "core/fxcrt/fx_codepage.h"
18#include "core/fxcrt/fx_safe_types.h"
19#include "core/fxcrt/stl_util.h"
20#include "third_party/base/check.h"
21
22namespace {
23
24constexpr float kFontScale = 0.001f;
25constexpr uint8_t kReturnLength = 1;
26
27constexpr uint8_t kFontSizeSteps[] = {4, 6, 8, 9, 10, 12, 14, 18, 20,
28 25, 30, 35, 40, 45, 50, 55, 60, 70,
29 80, 90, 100, 110, 120, 130, 144};
30
31} // namespace
32
35 DCHECK(m_pFontMap);
36}
37
39
40int CPVT_VariableText::Provider::GetCharWidth(int32_t nFontIndex,
41 uint16_t word) {
42 RetainPtr<CPDF_Font> pPDFFont = m_pFontMap->GetPDFFont(nFontIndex);
43 if (!pPDFFont)
44 return 0;
45
46 uint32_t charcode = pPDFFont->CharCodeFromUnicode(word);
47 if (charcode == CPDF_Font::kInvalidCharCode)
48 return 0;
49
50 return pPDFFont->GetCharWidthF(charcode);
51}
52
53int32_t CPVT_VariableText::Provider::GetTypeAscent(int32_t nFontIndex) {
54 RetainPtr<CPDF_Font> pPDFFont = m_pFontMap->GetPDFFont(nFontIndex);
55 return pPDFFont ? pPDFFont->GetTypeAscent() : 0;
56}
57
58int32_t CPVT_VariableText::Provider::GetTypeDescent(int32_t nFontIndex) {
59 RetainPtr<CPDF_Font> pPDFFont = m_pFontMap->GetPDFFont(nFontIndex);
60 return pPDFFont ? pPDFFont->GetTypeDescent() : 0;
61}
62
64 FX_Charset charset,
65 int32_t nFontIndex) {
66 if (RetainPtr<CPDF_Font> pDefFont = m_pFontMap->GetPDFFont(0)) {
67 if (pDefFont->CharCodeFromUnicode(word) != CPDF_Font::kInvalidCharCode)
68 return 0;
69 }
70 if (RetainPtr<CPDF_Font> pSysFont = m_pFontMap->GetPDFFont(1)) {
71 if (pSysFont->CharCodeFromUnicode(word) != CPDF_Font::kInvalidCharCode)
72 return 1;
73 }
74 return -1;
75}
76
78 return 0;
79}
80
82 DCHECK(m_pVT);
83}
84
86
87void CPVT_VariableText::Iterator::SetAt(int32_t nWordIndex) {
88 m_CurPos = m_pVT->WordIndexToWordPlace(nWordIndex);
89}
90
92 m_CurPos = place;
93}
94
96 if (m_CurPos == m_pVT->GetEndWordPlace())
97 return false;
98
99 m_CurPos = m_pVT->GetNextWordPlace(m_CurPos);
100 return true;
101}
102
104 if (!fxcrt::IndexInBounds(m_pVT->m_SectionArray, m_CurPos.nSecIndex))
105 return false;
106
107 CPVT_Section* pSection = m_pVT->m_SectionArray[m_CurPos.nSecIndex].get();
108 if (m_CurPos.nLineIndex < pSection->GetLineArraySize() - 1) {
109 m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex + 1, -1);
110 return true;
111 }
112 if (m_CurPos.nSecIndex <
113 fxcrt::CollectionSize<int32_t>(m_pVT->m_SectionArray) - 1) {
114 m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
115 return true;
116 }
117 return false;
118}
119
121 word.WordPlace = m_CurPos;
122 if (!fxcrt::IndexInBounds(m_pVT->m_SectionArray, m_CurPos.nSecIndex))
123 return false;
124
125 CPVT_Section* pSection = m_pVT->m_SectionArray[m_CurPos.nSecIndex].get();
126 if (!pSection->GetLineFromArray(m_CurPos.nLineIndex))
127 return false;
128
129 const CPVT_WordInfo* pInfo = pSection->GetWordFromArray(m_CurPos.nWordIndex);
130 if (!pInfo)
131 return false;
132
133 word.Word = pInfo->Word;
134 word.nCharset = pInfo->nCharset;
135 word.fWidth = m_pVT->GetWordWidth(*pInfo);
136 word.ptWord =
137 m_pVT->InToOut(CFX_PointF(pInfo->fWordX + pSection->GetRect().left,
138 pInfo->fWordY + pSection->GetRect().top));
139 word.fAscent = m_pVT->GetWordAscent(*pInfo);
140 word.fDescent = m_pVT->GetWordDescent(*pInfo);
141 word.nFontIndex = pInfo->nFontIndex;
142 word.fFontSize = m_pVT->GetWordFontSize();
143 return true;
144}
145
147 DCHECK(m_pVT);
148 line.lineplace = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex, -1);
149 if (!fxcrt::IndexInBounds(m_pVT->m_SectionArray, m_CurPos.nSecIndex))
150 return false;
151
152 CPVT_Section* pSection = m_pVT->m_SectionArray[m_CurPos.nSecIndex].get();
153 const CPVT_Section::Line* pLine =
154 pSection->GetLineFromArray(m_CurPos.nLineIndex);
155 if (!pLine)
156 return false;
157
158 line.ptLine = m_pVT->InToOut(
159 CFX_PointF(pLine->m_LineInfo.fLineX + pSection->GetRect().left,
160 pLine->m_LineInfo.fLineY + pSection->GetRect().top));
164 line.lineEnd = pLine->GetEndWordPlace();
165 return true;
166}
167
170
172
174 if (m_bInitialized)
175 return;
176
177 CPVT_WordPlace place;
178 place.nSecIndex = 0;
179 AddSection(place);
180
181 CPVT_LineInfo lineinfo;
184 AddLine(place, lineinfo);
185
186 if (!m_SectionArray.empty())
187 m_SectionArray.front()->ResetLinePlace();
188
189 m_bInitialized = true;
190}
191
193 uint16_t word,
194 FX_Charset charset) {
195 int32_t nTotalWords = GetTotalWords();
196 if (m_nLimitChar > 0 && nTotalWords >= m_nLimitChar)
197 return place;
198 if (m_nCharArray > 0 && nTotalWords >= m_nCharArray)
199 return place;
200
201 CPVT_WordPlace newplace = place;
202 newplace.nWordIndex++;
203 int32_t nFontIndex =
205 : GetWordFontIndex(word, charset, GetDefaultFontIndex());
206 return AddWord(newplace, CPVT_WordInfo(word, charset, nFontIndex));
207}
208
210 int32_t nTotalWords = GetTotalWords();
211 if (m_nLimitChar > 0 && nTotalWords >= m_nLimitChar)
212 return place;
213 if (m_nCharArray > 0 && nTotalWords >= m_nCharArray)
214 return place;
215 if (!m_bMultiLine)
216 return place;
217
218 CPVT_WordPlace wordplace = place;
219 UpdateWordPlace(wordplace);
220 if (!fxcrt::IndexInBounds(m_SectionArray, wordplace.nSecIndex))
221 return place;
222
223 CPVT_Section* pSection = m_SectionArray[wordplace.nSecIndex].get();
224 CPVT_WordPlace NewPlace(wordplace.nSecIndex + 1, 0, -1);
225 AddSection(NewPlace);
226 CPVT_WordPlace result = NewPlace;
227 if (fxcrt::IndexInBounds(m_SectionArray, NewPlace.nSecIndex)) {
228 CPVT_Section* pNewSection = m_SectionArray[NewPlace.nSecIndex].get();
229 for (int32_t w = wordplace.nWordIndex + 1; w < pSection->GetWordArraySize();
230 ++w) {
231 NewPlace.nWordIndex++;
232 pNewSection->AddWord(NewPlace, *pSection->GetWordFromArray(w));
233 }
234 }
235 ClearSectionRightWords(wordplace);
236 return result;
237}
238
240 const CPVT_WordRange& PlaceRange) {
241 bool bLastSecPos =
242 fxcrt::IndexInBounds(m_SectionArray, PlaceRange.EndPos.nSecIndex) &&
243 PlaceRange.EndPos ==
244 m_SectionArray[PlaceRange.EndPos.nSecIndex]->GetEndWordPlace();
245
246 ClearWords(PlaceRange);
247 if (PlaceRange.BeginPos.nSecIndex != PlaceRange.EndPos.nSecIndex) {
248 ClearEmptySections(PlaceRange);
249 if (!bLastSecPos)
250 LinkLatterSection(PlaceRange.BeginPos);
251 }
252 return PlaceRange.BeginPos;
253}
254
256 return ClearRightWord(PrevLineHeaderPlace(place));
257}
258
260 return ClearLeftWord(PrevLineHeaderPlace(place));
261}
262
263void CPVT_VariableText::SetText(const WideString& swText) {
265 CPVT_WordPlace wp(0, 0, -1);
266 if (!m_SectionArray.empty())
267 m_SectionArray.front()->SetRect(CPVT_FloatRect());
268
269 FX_SAFE_INT32 nCharCount = 0;
270 for (size_t i = 0, sz = swText.GetLength(); i < sz; i++) {
271 if (m_nLimitChar > 0 && nCharCount.ValueOrDie() >= m_nLimitChar)
272 break;
273 if (m_nCharArray > 0 && nCharCount.ValueOrDie() >= m_nCharArray)
274 break;
275
276 uint16_t word = swText[i];
277 switch (word) {
278 case 0x0D:
279 if (m_bMultiLine) {
280 if (i + 1 < sz && swText[i + 1] == 0x0A)
281 i++;
282 wp.AdvanceSection();
283 AddSection(wp);
284 }
285 break;
286 case 0x0A:
287 if (m_bMultiLine) {
288 if (i + 1 < sz && swText[i + 1] == 0x0D)
289 i++;
290 wp.AdvanceSection();
291 AddSection(wp);
292 }
293 break;
294 case 0x09:
295 word = 0x20;
296 [[fallthrough]];
297 default:
298 wp = InsertWord(wp, word, FX_Charset::kDefault);
299 break;
300 }
301 nCharCount++;
302 }
303}
304
306 if (place.nSecIndex < 0)
307 place = GetBeginWordPlace();
308 if (static_cast<size_t>(place.nSecIndex) >= m_SectionArray.size())
309 place = GetEndWordPlace();
310
311 place = PrevLineHeaderPlace(place);
312 if (fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
313 m_SectionArray[place.nSecIndex]->UpdateWordPlace(place);
314}
315
317 const CPVT_WordPlace& place) const {
318 CPVT_WordPlace newplace = place;
319 UpdateWordPlace(newplace);
320 int32_t nIndex = 0;
321 int32_t i = 0;
322 int32_t sz = 0;
323 for (i = 0, sz = fxcrt::CollectionSize<int32_t>(m_SectionArray);
324 i < sz && i < newplace.nSecIndex; i++) {
325 CPVT_Section* pSection = m_SectionArray[i].get();
326 nIndex += pSection->GetWordArraySize();
327 if (i != sz - 1)
328 nIndex += kReturnLength;
329 }
330 if (fxcrt::IndexInBounds(m_SectionArray, i))
331 nIndex += newplace.nWordIndex + kReturnLength;
332 return nIndex;
333}
334
337 int32_t nOldIndex = 0;
338 int32_t nIndex = 0;
339 bool bFound = false;
340 for (size_t i = 0; i < m_SectionArray.size(); ++i) {
341 CPVT_Section* pSection = m_SectionArray[i].get();
342 nIndex += pSection->GetWordArraySize();
343 if (nIndex == index) {
344 place = pSection->GetEndWordPlace();
345 bFound = true;
346 break;
347 }
348 if (nIndex > index) {
349 place.nSecIndex = pdfium::base::checked_cast<int32_t>(i);
350 place.nWordIndex = index - nOldIndex - 1;
351 pSection->UpdateWordPlace(place);
352 bFound = true;
353 break;
354 }
355 if (i != m_SectionArray.size() - 1)
356 nIndex += kReturnLength;
357 nOldIndex = nIndex;
358 }
359 if (!bFound)
360 place = GetEndWordPlace();
361 return place;
362}
363
365 return m_bInitialized ? CPVT_WordPlace(0, 0, -1) : CPVT_WordPlace();
366}
367
369 if (m_SectionArray.empty())
370 return CPVT_WordPlace();
371 return m_SectionArray.back()->GetEndWordPlace();
372}
373
375 const CPVT_WordPlace& place) const {
376 if (place.nSecIndex < 0)
377 return GetBeginWordPlace();
378 if (static_cast<size_t>(place.nSecIndex) >= m_SectionArray.size())
379 return GetEndWordPlace();
380
381 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
382 if (place > pSection->GetBeginWordPlace())
383 return pSection->GetPrevWordPlace(place);
384 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex - 1))
385 return GetBeginWordPlace();
386 return m_SectionArray[place.nSecIndex - 1]->GetEndWordPlace();
387}
388
390 const CPVT_WordPlace& place) const {
391 if (place.nSecIndex < 0)
392 return GetBeginWordPlace();
393 if (static_cast<size_t>(place.nSecIndex) >= m_SectionArray.size())
394 return GetEndWordPlace();
395
396 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
397 if (place < pSection->GetEndWordPlace())
398 return pSection->GetNextWordPlace(place);
399 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex + 1))
400 return GetEndWordPlace();
401 return m_SectionArray[place.nSecIndex + 1]->GetBeginWordPlace();
402}
403
405 const CFX_PointF& point) const {
406 CFX_PointF pt = OutToIn(point);
408 int32_t nLeft = 0;
409 int32_t nRight = fxcrt::CollectionSize<int32_t>(m_SectionArray) - 1;
410 int32_t nMid = fxcrt::CollectionSize<int32_t>(m_SectionArray) / 2;
411 bool bUp = true;
412 bool bDown = true;
413 while (nLeft <= nRight) {
414 if (!fxcrt::IndexInBounds(m_SectionArray, nMid))
415 break;
416 CPVT_Section* pSection = m_SectionArray[nMid].get();
417 if (FXSYS_IsFloatBigger(pt.y, pSection->GetRect().top))
418 bUp = false;
419 if (FXSYS_IsFloatBigger(pSection->GetRect().bottom, pt.y))
420 bDown = false;
421 if (FXSYS_IsFloatSmaller(pt.y, pSection->GetRect().top)) {
422 nRight = nMid - 1;
423 nMid = (nLeft + nRight) / 2;
424 continue;
425 }
426 if (FXSYS_IsFloatBigger(pt.y, pSection->GetRect().bottom)) {
427 nLeft = nMid + 1;
428 nMid = (nLeft + nRight) / 2;
429 continue;
430 }
431 place = pSection->SearchWordPlace(CFX_PointF(
432 pt.x - pSection->GetRect().left, pt.y - pSection->GetRect().top));
433 place.nSecIndex = nMid;
434 return place;
435 }
436 if (bUp)
437 place = GetBeginWordPlace();
438 if (bDown)
439 place = GetEndWordPlace();
440 return place;
441}
442
444 const CPVT_WordPlace& place,
445 const CFX_PointF& point) const {
446 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
447 return place;
448
449 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
450 CPVT_WordPlace temp = place;
451 CFX_PointF pt = OutToIn(point);
452 if (temp.nLineIndex-- > 0) {
453 return pSection->SearchWordPlace(pt.x - pSection->GetRect().left, temp);
454 }
455 if (temp.nSecIndex-- > 0) {
456 if (fxcrt::IndexInBounds(m_SectionArray, temp.nSecIndex)) {
457 CPVT_Section* pLastSection = m_SectionArray[temp.nSecIndex].get();
458 temp.nLineIndex = pLastSection->GetLineArraySize() - 1;
459 return pLastSection->SearchWordPlace(pt.x - pLastSection->GetRect().left,
460 temp);
461 }
462 }
463 return place;
464}
465
467 const CPVT_WordPlace& place,
468 const CFX_PointF& point) const {
469 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
470 return place;
471
472 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
473 CPVT_WordPlace temp = place;
474 CFX_PointF pt = OutToIn(point);
475 if (temp.nLineIndex++ < pSection->GetLineArraySize() - 1) {
476 return pSection->SearchWordPlace(pt.x - pSection->GetRect().left, temp);
477 }
479 if (!fxcrt::IndexInBounds(m_SectionArray, temp.nSecIndex))
480 return place;
481
482 return m_SectionArray[temp.nSecIndex]->SearchWordPlace(
483 pt.x - pSection->GetRect().left, temp);
484}
485
490
492 const CPVT_WordPlace& place) const {
493 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
494 return place;
495
496 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
497 const CPVT_Section::Line* pLine =
499 if (!pLine)
500 return place;
501
502 return pLine->GetEndWordPlace();
503}
504
509
511 const CPVT_WordPlace& place) const {
512 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
513 return place;
514
515 return m_SectionArray[place.nSecIndex]->GetEndWordPlace();
516}
517
519 int32_t nTotal = 0;
520 for (const auto& pSection : m_SectionArray) {
521 nTotal += pSection->GetWordArraySize() + kReturnLength;
522 }
523 return nTotal - kReturnLength;
524}
525
526CPVT_WordPlace CPVT_VariableText::AddSection(const CPVT_WordPlace& place) {
527 if (IsValid() && !m_bMultiLine)
528 return place;
529
530 int32_t nSecIndex = std::clamp(
531 place.nSecIndex, 0, fxcrt::CollectionSize<int32_t>(m_SectionArray));
532
533 auto pSection = std::make_unique<CPVT_Section>(this);
534 pSection->SetRect(CPVT_FloatRect());
535 pSection->SetPlaceIndex(nSecIndex);
536 m_SectionArray.insert(m_SectionArray.begin() + nSecIndex,
537 std::move(pSection));
538 return place;
539}
540
542 const CPVT_LineInfo& lineinfo) {
543 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
544 return place;
545
546 return m_SectionArray[place.nSecIndex]->AddLine(lineinfo);
547}
548
550 const CPVT_WordInfo& wordinfo) {
551 if (m_SectionArray.empty())
552 return place;
553
554 CPVT_WordPlace newplace = place;
555 newplace.nSecIndex =
556 std::clamp(newplace.nSecIndex, 0,
557 fxcrt::CollectionSize<int32_t>(m_SectionArray) - 1);
558 return m_SectionArray[newplace.nSecIndex]->AddWord(newplace, wordinfo);
559}
560
562 m_rcPlate = rect;
563}
564
566 return InToOut(m_rcContent);
567}
568
570 return m_rcPlate;
571}
572
573float CPVT_VariableText::GetWordFontSize() const {
574 return GetFontSize();
575}
576
577float CPVT_VariableText::GetWordWidth(int32_t nFontIndex,
578 uint16_t Word,
579 uint16_t SubWord,
580 float fFontSize,
581 float fWordTail) const {
582 return GetCharWidth(nFontIndex, Word, SubWord) * fFontSize * kFontScale +
583 fWordTail;
584}
585
586float CPVT_VariableText::GetWordWidth(const CPVT_WordInfo& WordInfo) const {
587 return GetWordWidth(WordInfo.nFontIndex, WordInfo.Word, GetSubWord(),
588 GetWordFontSize(), WordInfo.fWordTail);
589}
590
594
598
599float CPVT_VariableText::GetFontAscent(int32_t nFontIndex,
600 float fFontSize) const {
601 float ascent = m_pVTProvider ? m_pVTProvider->GetTypeAscent(nFontIndex) : 0;
602 return ascent * fFontSize * kFontScale;
603}
604
605float CPVT_VariableText::GetFontDescent(int32_t nFontIndex,
606 float fFontSize) const {
607 float descent = m_pVTProvider ? m_pVTProvider->GetTypeDescent(nFontIndex) : 0;
608 return descent * fFontSize * kFontScale;
609}
610
612 float fFontSize) const {
613 return GetFontAscent(WordInfo.nFontIndex, fFontSize);
614}
615
617 float fFontSize) const {
618 return GetFontDescent(WordInfo.nFontIndex, fFontSize);
619}
620
621float CPVT_VariableText::GetWordAscent(const CPVT_WordInfo& WordInfo) const {
622 return GetFontAscent(WordInfo.nFontIndex, GetWordFontSize());
623}
624
625float CPVT_VariableText::GetWordDescent(const CPVT_WordInfo& WordInfo) const {
626 return GetFontDescent(WordInfo.nFontIndex, GetWordFontSize());
627}
628
630 return m_fLineLeading;
631}
632
634 return 0.0f;
635}
636
637void CPVT_VariableText::ClearSectionRightWords(const CPVT_WordPlace& place) {
638 CPVT_WordPlace wordplace = PrevLineHeaderPlace(place);
639 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
640 return;
641
642 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
643 pSection->EraseWordsFrom(wordplace.nWordIndex + 1);
644}
645
647 const CPVT_WordPlace& place) const {
648 if (place.nWordIndex < 0 && place.nLineIndex > 0)
649 return GetPrevWordPlace(place);
650 return place;
651}
652
654 const CPVT_WordPlace& place) const {
655 if (place.nWordIndex < 0 && place.nLineIndex > 0)
656 return GetNextWordPlace(place);
657 return place;
658}
659
660bool CPVT_VariableText::ClearEmptySection(const CPVT_WordPlace& place) {
661 if (place.nSecIndex == 0 && m_SectionArray.size() == 1)
662 return false;
663
664 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
665 return false;
666
667 if (m_SectionArray[place.nSecIndex]->GetWordArraySize() != 0)
668 return false;
669
670 m_SectionArray.erase(m_SectionArray.begin() + place.nSecIndex);
671 return true;
672}
673
674void CPVT_VariableText::ClearEmptySections(const CPVT_WordRange& PlaceRange) {
675 CPVT_WordPlace wordplace;
676 for (int32_t s = PlaceRange.EndPos.nSecIndex;
677 s > PlaceRange.BeginPos.nSecIndex; s--) {
678 wordplace.nSecIndex = s;
679 ClearEmptySection(wordplace);
680 }
681}
682
683void CPVT_VariableText::LinkLatterSection(const CPVT_WordPlace& place) {
685 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex + 1))
686 return;
687
688 CPVT_Section* pNextSection = m_SectionArray[place.nSecIndex + 1].get();
689 if (fxcrt::IndexInBounds(m_SectionArray, oldplace.nSecIndex)) {
690 CPVT_Section* pSection = m_SectionArray[oldplace.nSecIndex].get();
691 for (int32_t i = 0; i < pNextSection->GetWordArraySize(); ++i) {
692 oldplace.nWordIndex++;
693 pSection->AddWord(oldplace, *pNextSection->GetWordFromArray(i));
694 }
695 }
696 m_SectionArray.erase(m_SectionArray.begin() + place.nSecIndex + 1);
697}
698
699void CPVT_VariableText::ClearWords(const CPVT_WordRange& PlaceRange) {
700 CPVT_WordRange NewRange;
701 NewRange.BeginPos = PrevLineHeaderPlace(PlaceRange.BeginPos);
702 NewRange.EndPos = PrevLineHeaderPlace(PlaceRange.EndPos);
703 for (int32_t s = NewRange.EndPos.nSecIndex; s >= NewRange.BeginPos.nSecIndex;
704 s--) {
705 if (fxcrt::IndexInBounds(m_SectionArray, s))
706 m_SectionArray[s]->ClearWords(NewRange);
707 }
708}
709
710CPVT_WordPlace CPVT_VariableText::ClearLeftWord(const CPVT_WordPlace& place) {
711 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
712 return place;
713
714 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
715 CPVT_WordPlace leftplace = GetPrevWordPlace(place);
716 if (leftplace == place)
717 return place;
718
719 if (leftplace.nSecIndex != place.nSecIndex) {
720 if (pSection->GetWordArraySize() == 0)
721 ClearEmptySection(place);
722 else
723 LinkLatterSection(leftplace);
724 } else {
725 pSection->ClearWord(place);
726 }
727 return leftplace;
728}
729
730CPVT_WordPlace CPVT_VariableText::ClearRightWord(const CPVT_WordPlace& place) {
731 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
732 return place;
733
734 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
736 if (rightplace == place)
737 return place;
738
739 if (rightplace.nSecIndex != place.nSecIndex)
740 LinkLatterSection(place);
741 else
742 pSection->ClearWord(rightplace);
743 return place;
744}
745
749
751 Rearrange(PlaceRange);
752}
753
754void CPVT_VariableText::Rearrange(const CPVT_WordRange& PlaceRange) {
755 CPVT_FloatRect rcRet;
756 if (IsValid()) {
757 if (m_bAutoFontSize) {
758 SetFontSize(GetAutoFontSize());
759 rcRet = RearrangeSections(
761 } else {
762 rcRet = RearrangeSections(PlaceRange);
763 }
764 }
765 m_rcContent = rcRet;
766}
767
768float CPVT_VariableText::GetAutoFontSize() {
769 int32_t nTotal = sizeof(kFontSizeSteps) / sizeof(uint8_t);
770 if (IsMultiLine())
771 nTotal /= 4;
772 if (nTotal <= 0)
773 return 0;
774 if (GetPlateWidth() <= 0)
775 return 0;
776
777 int32_t nLeft = 0;
778 int32_t nRight = nTotal - 1;
779 int32_t nMid = nTotal / 2;
780 while (nLeft <= nRight) {
781 if (IsBigger(kFontSizeSteps[nMid]))
782 nRight = nMid - 1;
783 else
784 nLeft = nMid + 1;
785 nMid = (nLeft + nRight) / 2;
786 }
787 return (float)kFontSizeSteps[nMid];
788}
789
790bool CPVT_VariableText::IsBigger(float fFontSize) const {
791 CFX_SizeF szTotal;
792 for (const auto& pSection : m_SectionArray) {
793 CFX_SizeF size = pSection->GetSectionSize(fFontSize);
794 szTotal.width = std::max(size.width, szTotal.width);
795 szTotal.height += size.height;
796 if (FXSYS_IsFloatBigger(szTotal.width, GetPlateWidth()) ||
797 FXSYS_IsFloatBigger(szTotal.height, GetPlateHeight())) {
798 return true;
799 }
800 }
801 return false;
802}
803
804CPVT_FloatRect CPVT_VariableText::RearrangeSections(
805 const CPVT_WordRange& PlaceRange) {
806 float fPosY = 0;
807 CPVT_FloatRect rcRet;
808 for (int32_t s = 0, sz = fxcrt::CollectionSize<int32_t>(m_SectionArray);
809 s < sz; s++) {
810 CPVT_WordPlace place;
811 place.nSecIndex = s;
812 CPVT_Section* pSection = m_SectionArray[s].get();
813 pSection->SetPlace(place);
814 CPVT_FloatRect rcSec = pSection->GetRect();
815 if (s >= PlaceRange.BeginPos.nSecIndex) {
816 if (s <= PlaceRange.EndPos.nSecIndex) {
817 rcSec = pSection->Rearrange();
818 rcSec.top += fPosY;
819 rcSec.bottom += fPosY;
820 } else {
821 float fOldHeight = pSection->GetRect().bottom - pSection->GetRect().top;
822 rcSec.top = fPosY;
823 rcSec.bottom = fPosY + fOldHeight;
824 }
825 pSection->SetRect(rcSec);
826 pSection->ResetLinePlace();
827 }
828 if (s == 0) {
829 rcRet = rcSec;
830 } else {
831 rcRet.left = std::min(rcSec.left, rcRet.left);
832 rcRet.top = std::min(rcSec.top, rcRet.top);
833 rcRet.right = std::max(rcSec.right, rcRet.right);
834 rcRet.bottom = std::max(rcSec.bottom, rcRet.bottom);
835 }
836 fPosY += rcSec.Height();
837 }
838 return rcRet;
839}
840
841int CPVT_VariableText::GetCharWidth(int32_t nFontIndex,
842 uint16_t Word,
843 uint16_t SubWord) const {
844 if (!m_pVTProvider)
845 return 0;
846 uint16_t word = SubWord ? SubWord : Word;
847 return m_pVTProvider->GetCharWidth(nFontIndex, word);
848}
849
850int32_t CPVT_VariableText::GetWordFontIndex(uint16_t word,
851 FX_Charset charset,
852 int32_t nFontIndex) {
853 return m_pVTProvider
854 ? m_pVTProvider->GetWordFontIndex(word, charset, nFontIndex)
855 : -1;
856}
857
859 return m_pVTProvider ? m_pVTProvider->GetDefaultFontIndex() : -1;
860}
861
863 if (!m_pVTIterator)
864 m_pVTIterator = std::make_unique<CPVT_VariableText::Iterator>(this);
865 return m_pVTIterator.get();
866}
867
869 m_pVTProvider = pProvider;
870}
871
872CFX_PointF CPVT_VariableText::GetBTPoint() const {
873 return CFX_PointF(m_rcPlate.left, m_rcPlate.top);
874}
875
876CFX_PointF CPVT_VariableText::GetETPoint() const {
877 return CFX_PointF(m_rcPlate.right, m_rcPlate.bottom);
878}
879
880CFX_PointF CPVT_VariableText::InToOut(const CFX_PointF& point) const {
881 return CFX_PointF(point.x + GetBTPoint().x, GetBTPoint().y - point.y);
882}
883
884CFX_PointF CPVT_VariableText::OutToIn(const CFX_PointF& point) const {
885 return CFX_PointF(point.x - GetBTPoint().x, GetBTPoint().y - point.y);
886}
887
888CFX_FloatRect CPVT_VariableText::InToOut(const CPVT_FloatRect& rect) const {
889 CFX_PointF ptLeftTop = InToOut(CFX_PointF(rect.left, rect.top));
890 CFX_PointF ptRightBottom = InToOut(CFX_PointF(rect.right, rect.bottom));
891 return CFX_FloatRect(ptLeftTop.x, ptRightBottom.y, ptRightBottom.x,
892 ptLeftTop.y);
893}
CFX_FloatRect & operator=(const CFX_FloatRect &that)=default
static constexpr uint32_t kInvalidCharCode
Definition cpdf_font.h:63
float Height() const
CPVT_FloatRect()=default
CPVT_WordPlace lineplace
Definition cpvt_line.h:17
float fLineWidth
Definition cpvt_line.h:20
CPVT_WordPlace lineEnd
Definition cpvt_line.h:18
float fLineAscent
Definition cpvt_line.h:21
float fLineDescent
Definition cpvt_line.h:22
CPVT_WordPlace GetEndWordPlace() const
CPVT_LineInfo m_LineInfo
int32_t GetWordArraySize() const
void ClearWord(const CPVT_WordPlace &place)
void EraseWordsFrom(int32_t index)
CPVT_FloatRect Rearrange()
CPVT_WordPlace GetEndWordPlace() const
const Line * GetLineFromArray(int32_t index) const
void SetRect(const CPVT_FloatRect &rect)
void UpdateWordPlace(CPVT_WordPlace &place) const
const CPVT_FloatRect & GetRect() const
CPVT_WordPlace GetBeginWordPlace() const
void SetPlace(const CPVT_WordPlace &place)
void ResetLinePlace()
CPVT_WordPlace SearchWordPlace(const CFX_PointF &point) const
CPVT_WordPlace GetPrevWordPlace(const CPVT_WordPlace &place) const
const CPVT_WordInfo * GetWordFromArray(int32_t index) const
CPVT_WordPlace AddWord(const CPVT_WordPlace &place, const CPVT_WordInfo &wordinfo)
CPVT_WordPlace GetNextWordPlace(const CPVT_WordPlace &place) const
int32_t GetLineArraySize() const
void SetAt(int32_t nWordIndex)
bool GetWord(CPVT_Word &word) const
bool GetLine(CPVT_Line &line) const
Iterator(CPVT_VariableText *pVT)
void SetAt(const CPVT_WordPlace &place)
virtual int32_t GetTypeDescent(int32_t nFontIndex)
virtual int GetCharWidth(int32_t nFontIndex, uint16_t word)
virtual int32_t GetWordFontIndex(uint16_t word, FX_Charset charset, int32_t nFontIndex)
Provider(IPVT_FontMap *pFontMap)
virtual int32_t GetTypeAscent(int32_t nFontIndex)
virtual int32_t GetDefaultFontIndex()
void SetPlateRect(const CFX_FloatRect &rect)
CPVT_WordPlace GetLineEndPlace(const CPVT_WordPlace &place) const
CPVT_WordPlace NextLineHeaderPlace(const CPVT_WordPlace &place) const
CPVT_WordPlace PrevLineHeaderPlace(const CPVT_WordPlace &place) const
CFX_PointF GetBTPoint() const
CPVT_WordPlace GetBeginWordPlace() const
CPVT_WordPlace GetEndWordPlace() const
CPVT_WordPlace InsertSection(const CPVT_WordPlace &place)
int32_t WordPlaceToWordIndex(const CPVT_WordPlace &place) const
CFX_PointF GetETPoint() const
CPVT_WordPlace GetLineBeginPlace(const CPVT_WordPlace &place) const
float GetFontAscent(int32_t nFontIndex, float fFontSize) const
float GetWordWidth(const CPVT_WordInfo &WordInfo) const
float GetWordWidth(int32_t nFontIndex, uint16_t Word, uint16_t SubWord, float fFontSize, float fWordTail) const
float GetWordDescent(const CPVT_WordInfo &WordInfo) const
CFX_FloatRect GetContentRect() const
float GetFontDescent(int32_t nFontIndex, float fFontSize) const
CPVT_WordPlace InsertWord(const CPVT_WordPlace &place, uint16_t word, FX_Charset charset)
CFX_PointF OutToIn(const CFX_PointF &point) const
CPVT_VariableText(Provider *Provider)
CFX_PointF InToOut(const CFX_PointF &point) const
void SetText(const WideString &text)
void SetProvider(Provider *pProvider)
float GetWordAscent(const CPVT_WordInfo &WordInfo, float fFontSize) const
CPVT_VariableText::Iterator * GetIterator()
const CFX_FloatRect & GetPlateRect() const
float GetPlateWidth() const
CPVT_WordPlace WordIndexToWordPlace(int32_t index) const
CPVT_WordPlace DeleteWords(const CPVT_WordRange &PlaceRange)
CPVT_WordPlace GetUpWordPlace(const CPVT_WordPlace &place, const CFX_PointF &point) const
CPVT_WordPlace GetNextWordPlace(const CPVT_WordPlace &place) const
CPVT_WordPlace GetSectionBeginPlace(const CPVT_WordPlace &place) const
CPVT_WordPlace SearchWordPlace(const CFX_PointF &point) const
CPVT_WordPlace GetPrevWordPlace(const CPVT_WordPlace &place) const
CFX_FloatRect InToOut(const CPVT_FloatRect &rect) const
CPVT_WordPlace DeleteWord(const CPVT_WordPlace &place)
float GetWordDescent(const CPVT_WordInfo &WordInfo, float fFontSize) const
void UpdateWordPlace(CPVT_WordPlace &place) const
void RearrangePart(const CPVT_WordRange &PlaceRange)
float GetFontSize() const
CPVT_WordPlace BackSpaceWord(const CPVT_WordPlace &place)
float GetWordAscent(const CPVT_WordInfo &WordInfo) const
int32_t GetTotalWords() const
uint16_t GetSubWord() const
void SetFontSize(float fFontSize)
CPVT_WordPlace GetDownWordPlace(const CPVT_WordPlace &place, const CFX_PointF &point) const
CPVT_WordPlace GetSectionEndPlace(const CPVT_WordPlace &place) const
uint16_t Word
Definition cpvt_word.h:19
CPVT_WordPlace WordPlace
Definition cpvt_word.h:21
int32_t nFontIndex
Definition cpvt_word.h:26
FX_Charset nCharset
Definition cpvt_word.h:20
FX_Charset
Definition fx_codepage.h:70
#define FXSYS_IsFloatBigger(fa, fb)
Definition fx_system.h:36
#define FXSYS_IsFloatSmaller(fa, fb)
Definition fx_system.h:38
int32_t nFontIndex
FX_Charset nCharset
CPVT_WordInfo(uint16_t word, FX_Charset charset, int32_t fontIndex)
bool operator>(const CPVT_WordPlace &wp) const
CPVT_WordPlace(int32_t other_nSecIndex, int32_t other_nLineIndex, int32_t other_nWordIndex)
bool operator<(const CPVT_WordPlace &wp) const
bool operator==(const CPVT_WordPlace &wp) const
CPVT_WordPlace()=default
CPVT_WordRange(const CPVT_WordPlace &begin, const CPVT_WordPlace &end)
CPVT_WordPlace BeginPos
CPVT_WordPlace EndPos