7#include "core/fpdfdoc/cpvt_variabletext.h"
13#include "core/fpdfapi/font/cpdf_font.h"
14#include "core/fpdfdoc/cpvt_section.h"
15#include "core/fpdfdoc/cpvt_word.h"
16#include "core/fpdfdoc/cpvt_wordinfo.h"
17#include "core/fpdfdoc/ipvt_fontmap.h"
18#include "core/fxcrt/check.h"
19#include "core/fxcrt/compiler_specific.h"
20#include "core/fxcrt/fx_codepage.h"
21#include "core/fxcrt/fx_safe_types.h"
22#include "core/fxcrt/stl_util.h"
26constexpr float kFontScale = 0.001f;
27constexpr uint8_t kReturnLength = 1;
29constexpr auto kFontSizeSteps =
fxcrt::ToArray<
const uint8_t>(
30 {4, 6, 8, 9, 10, 12, 14, 18, 20, 25, 30, 35, 40,
31 45, 50, 55, 60, 70, 80, 90, 100, 110, 120, 130, 144});
48 uint32_t charcode = pPDFFont->CharCodeFromUnicode(word);
52 return pPDFFont->GetCharWidthF(charcode);
57 return pPDFFont ? pPDFFont->GetTypeAscent() : 0;
62 return pPDFFont ? pPDFFont->GetTypeDescent() : 0;
68 if (RetainPtr<CPDF_Font> pDefFont = m_pFontMap->GetPDFFont(0)) {
72 if (RetainPtr<CPDF_Font> pSysFont = m_pFontMap->GetPDFFont(1)) {
90 m_CurPos = m_pVT->WordIndexToWordPlace(nWordIndex);
98 if (m_CurPos == m_pVT->GetEndWordPlace())
101 m_CurPos = m_pVT->GetNextWordPlace(m_CurPos);
106 if (!fxcrt::IndexInBounds(m_pVT->m_SectionArray, m_CurPos.nSecIndex))
109 CPVT_Section* pSection = m_pVT->m_SectionArray[m_CurPos.nSecIndex].get();
114 if (m_CurPos.nSecIndex <
115 fxcrt::CollectionSize<int32_t>(m_pVT->m_SectionArray) - 1) {
124 if (!fxcrt::IndexInBounds(m_pVT->m_SectionArray, m_CurPos.nSecIndex))
127 CPVT_Section* pSection = m_pVT->m_SectionArray[m_CurPos.nSecIndex].get();
137 word.fWidth = m_pVT->GetWordWidth(*pInfo);
139 m_pVT->InToOut(CFX_PointF(pInfo->fWordX + pSection->GetRect().left,
140 pInfo->fWordY + pSection->GetRect().top));
141 word.fAscent = m_pVT->GetWordAscent(*pInfo);
142 word.fDescent = m_pVT->GetWordDescent(*pInfo);
144 word.fFontSize = m_pVT->GetWordFontSize();
151 if (!fxcrt::IndexInBounds(m_pVT->m_SectionArray, m_CurPos.nSecIndex))
154 CPVT_Section* pSection = m_pVT->m_SectionArray[m_CurPos.nSecIndex].get();
155 const CPVT_Section::
Line* pLine =
160 line.ptLine = m_pVT->InToOut(
161 CFX_PointF(pLine->m_LineInfo.fLineX + pSection->GetRect().left,
162 pLine->m_LineInfo.fLineY + pSection->GetRect().top));
186 AddLine(place, lineinfo);
188 if (!m_SectionArray.empty())
189 m_SectionArray.front()->ResetLinePlace();
191 m_bInitialized =
true;
198 if (m_nLimitChar > 0 && nTotalWords >= m_nLimitChar)
200 if (m_nCharArray > 0 && nTotalWords >= m_nCharArray)
213 if (m_nLimitChar > 0 && nTotalWords >= m_nLimitChar)
215 if (m_nCharArray > 0 && nTotalWords >= m_nCharArray)
222 if (!fxcrt::IndexInBounds(m_SectionArray, wordplace.nSecIndex))
225 CPVT_Section* pSection = m_SectionArray[wordplace.nSecIndex].get();
227 AddSection(NewPlace);
229 if (fxcrt::IndexInBounds(m_SectionArray, NewPlace.nSecIndex)) {
230 CPVT_Section* pNewSection = m_SectionArray[NewPlace.nSecIndex].get();
237 ClearSectionRightWords(wordplace);
244 fxcrt::IndexInBounds(m_SectionArray, PlaceRange.EndPos.nSecIndex) &&
246 m_SectionArray[PlaceRange.EndPos.nSecIndex]->GetEndWordPlace();
248 ClearWords(PlaceRange);
250 ClearEmptySections(PlaceRange);
268 if (!m_SectionArray.empty())
269 m_SectionArray.front()->SetRect(CPVT_FloatRect());
272 for (size_t i = 0, sz = swText.GetLength(); i < sz; i++) {
273 if (m_nLimitChar > 0 && nCharCount.ValueOrDie() >= m_nLimitChar)
275 if (m_nCharArray > 0 && nCharCount.ValueOrDie() >= m_nCharArray)
278 uint16_t word = swText[i];
282 if (i + 1 < sz && swText[i + 1] == 0x0A)
290 if (i + 1 < sz && swText[i + 1] == 0x0D)
300 wp = InsertWord(wp, word, FX_Charset::kDefault);
310 if (
static_cast<size_t>(place.nSecIndex) >= m_SectionArray.size())
314 if (fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
315 m_SectionArray[place.nSecIndex]->UpdateWordPlace(place);
325 for (i = 0, sz = fxcrt::CollectionSize<int32_t>(m_SectionArray);
327 CPVT_Section* pSection = m_SectionArray[i].get();
330 nIndex += kReturnLength;
332 if (fxcrt::IndexInBounds(m_SectionArray, i))
339 int32_t nOldIndex = 0;
342 for (size_t i = 0; i < m_SectionArray.size(); ++i) {
343 CPVT_Section* pSection = m_SectionArray[i].get();
345 if (nIndex == index) {
350 if (nIndex > index) {
357 if (i != m_SectionArray.size() - 1)
358 nIndex += kReturnLength;
371 if (m_SectionArray.empty())
373 return m_SectionArray.back()->GetEndWordPlace();
380 if (
static_cast<size_t>(place.nSecIndex) >= m_SectionArray.size())
383 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
386 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex - 1))
388 return m_SectionArray[place.nSecIndex - 1]->GetEndWordPlace();
395 if (
static_cast<size_t>(place.nSecIndex) >= m_SectionArray.size())
398 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
401 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex + 1))
403 return m_SectionArray[place.nSecIndex + 1]->GetBeginWordPlace();
411 int32_t nRight = fxcrt::CollectionSize<int32_t>(m_SectionArray) - 1;
412 int32_t nMid = fxcrt::CollectionSize<int32_t>(m_SectionArray) / 2;
415 while (nLeft <= nRight) {
416 if (!fxcrt::IndexInBounds(m_SectionArray, nMid))
418 CPVT_Section* pSection = m_SectionArray[nMid].get();
425 nMid = (nLeft + nRight) / 2;
430 nMid = (nLeft + nRight) / 2;
448 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
451 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
458 if (fxcrt::IndexInBounds(m_SectionArray, temp.nSecIndex)) {
459 CPVT_Section* pLastSection = m_SectionArray[temp.nSecIndex].get();
471 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
474 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
481 if (!fxcrt::IndexInBounds(m_SectionArray, temp.nSecIndex))
484 return m_SectionArray[temp.nSecIndex]->SearchWordPlace(
485 pt.x - pSection->GetRect().left, temp);
495 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
498 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
499 const CPVT_Section::
Line* pLine =
514 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
517 return m_SectionArray[place.nSecIndex]->GetEndWordPlace();
522 for (
const auto& pSection : m_SectionArray) {
523 nTotal += pSection->GetWordArraySize() + kReturnLength;
525 return nTotal - kReturnLength;
532 int32_t nSecIndex = std::clamp(
533 place.nSecIndex, 0, fxcrt::CollectionSize<int32_t>(m_SectionArray));
535 auto pSection =
std::make_unique<CPVT_Section>(
this);
536 pSection->SetRect(CPVT_FloatRect
());
537 pSection->SetPlaceIndex(nSecIndex);
538 m_SectionArray.insert(m_SectionArray.begin() + nSecIndex,
539 std::move(pSection));
545 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
548 return m_SectionArray[place.nSecIndex]->AddLine(lineinfo);
553 if (m_SectionArray.empty())
558 std::clamp(newplace.nSecIndex, 0,
559 fxcrt::CollectionSize<int32_t>(m_SectionArray) - 1);
560 return m_SectionArray[newplace.nSecIndex]->AddWord(newplace, wordinfo);
583 float fWordTail)
const {
584 return GetCharWidth(nFontIndex, Word, SubWord) * fFontSize * kFontScale +
602 float fFontSize)
const {
603 float ascent = m_pVTProvider ? m_pVTProvider->GetTypeAscent(nFontIndex) : 0;
604 return ascent * fFontSize * kFontScale;
608 float fFontSize)
const {
609 float descent = m_pVTProvider ? m_pVTProvider->GetTypeDescent(nFontIndex) : 0;
610 return descent * fFontSize * kFontScale;
614 float fFontSize)
const {
619 float fFontSize)
const {
632 return m_fLineLeading;
641 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
644 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
663 if (place.nSecIndex == 0 && m_SectionArray.size() == 1)
666 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
669 if (m_SectionArray[place.nSecIndex]->GetWordArraySize() != 0)
672 m_SectionArray.erase(m_SectionArray.begin() + place.nSecIndex);
681 ClearEmptySection(wordplace);
687 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex + 1))
690 CPVT_Section* pNextSection = m_SectionArray[place.nSecIndex + 1].get();
691 if (fxcrt::IndexInBounds(m_SectionArray, oldplace.nSecIndex)) {
692 CPVT_Section* pSection = m_SectionArray[oldplace.nSecIndex].get();
698 m_SectionArray.erase(m_SectionArray.begin() + place.nSecIndex + 1);
707 if (fxcrt::IndexInBounds(m_SectionArray, s))
708 m_SectionArray[s]->ClearWords(NewRange);
713 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
716 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
718 if (leftplace
== place)
723 ClearEmptySection(place);
725 LinkLatterSection(leftplace);
733 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
736 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
738 if (rightplace
== place)
742 LinkLatterSection(place);
753 Rearrange(PlaceRange);
757 CPVT_FloatRect rcRet;
759 if (m_bAutoFontSize) {
761 rcRet = RearrangeSections(
764 rcRet = RearrangeSections(PlaceRange);
771 int32_t nTotal =
sizeof(kFontSizeSteps) /
sizeof(uint8_t);
781 int32_t nRight = nTotal - 1;
782 int32_t nMid = nTotal / 2;
783 while (nLeft <= nRight) {
784 if (IsBigger(kFontSizeSteps[nMid])) {
789 nMid = (nLeft + nRight) / 2;
791 return static_cast<
float>(kFontSizeSteps[nMid]);
796 for (
const auto& pSection : m_SectionArray) {
797 CFX_SizeF size = pSection->GetSectionSize(fFontSize);
798 szTotal.width = std::max(size.width, szTotal.width);
799 szTotal.height += size.height;
811 CPVT_FloatRect rcRet;
812 for (int32_t s = 0, sz = fxcrt::CollectionSize<int32_t>(m_SectionArray);
816 CPVT_Section* pSection = m_SectionArray[s].get();
827 rcSec
.bottom = fPosY + fOldHeight;
847 uint16_t SubWord)
const {
850 uint16_t word = SubWord ? SubWord : Word;
851 return m_pVTProvider->GetCharWidth(nFontIndex, word);
856 int32_t nFontIndex) {
858 ? m_pVTProvider->GetWordFontIndex(word, charset, nFontIndex)
863 return m_pVTProvider ? m_pVTProvider->GetDefaultFontIndex() : -1;
868 m_pVTIterator = std::make_unique<CPVT_VariableText::Iterator>(
this);
869 return m_pVTIterator.get();
873 m_pVTProvider = pProvider;
877 return CFX_PointF(m_rcPlate
.left, m_rcPlate
.top);
885 return CFX_PointF(point.x + GetBTPoint().x, GetBTPoint().y - point.y);
889 return CFX_PointF(point.x - GetBTPoint().x, GetBTPoint().y - point.y);
893 CFX_PointF ptLeftTop = InToOut(CFX_PointF(rect.left, rect.top));
894 CFX_PointF ptRightBottom = InToOut(CFX_PointF(rect.right, rect.bottom));
895 return CFX_FloatRect(ptLeftTop.x, ptRightBottom.y, ptRightBottom.x,
CFX_FloatRect & operator=(const CFX_FloatRect &that)=default
static constexpr uint32_t kInvalidCharCode
CPVT_WordPlace GetEndWordPlace() const
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)
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
int32_t GetDefaultFontIndex()
CFX_PTemplate< float > CFX_PointF
CFX_STemplate< float > CFX_SizeF
pdfium::CheckedNumeric< int32_t > FX_SAFE_INT32
#define FXSYS_IsFloatBigger(fa, fb)
#define FXSYS_IsFloatSmaller(fa, fb)
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_WordRange(const CPVT_WordPlace &begin, const CPVT_WordPlace &end)
fxcrt::WideString WideString