7#include "core/fpdfdoc/cpvt_variabletext.h"
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"
24constexpr float kFontScale = 0.001f;
25constexpr uint8_t kReturnLength = 1;
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};
46 uint32_t charcode = pPDFFont->CharCodeFromUnicode(word);
50 return pPDFFont->GetCharWidthF(charcode);
55 return pPDFFont ? pPDFFont->GetTypeAscent() : 0;
60 return pPDFFont ? pPDFFont->GetTypeDescent() : 0;
66 if (RetainPtr<CPDF_Font> pDefFont = m_pFontMap->GetPDFFont(0)) {
70 if (RetainPtr<CPDF_Font> pSysFont = m_pFontMap->GetPDFFont(1)) {
88 m_CurPos = m_pVT->WordIndexToWordPlace(nWordIndex);
96 if (m_CurPos == m_pVT->GetEndWordPlace())
99 m_CurPos = m_pVT->GetNextWordPlace(m_CurPos);
104 if (!fxcrt::IndexInBounds(m_pVT->m_SectionArray, m_CurPos.nSecIndex))
107 CPVT_Section* pSection = m_pVT->m_SectionArray[m_CurPos.nSecIndex].get();
112 if (m_CurPos.nSecIndex <
113 fxcrt::CollectionSize<int32_t>(m_pVT->m_SectionArray) - 1) {
122 if (!fxcrt::IndexInBounds(m_pVT->m_SectionArray, m_CurPos.nSecIndex))
125 CPVT_Section* pSection = m_pVT->m_SectionArray[m_CurPos.nSecIndex].get();
135 word.fWidth = m_pVT->GetWordWidth(*pInfo);
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);
142 word.fFontSize = m_pVT->GetWordFontSize();
149 if (!fxcrt::IndexInBounds(m_pVT->m_SectionArray, m_CurPos.nSecIndex))
152 CPVT_Section* pSection = m_pVT->m_SectionArray[m_CurPos.nSecIndex].get();
153 const CPVT_Section::
Line* pLine =
158 line.ptLine = m_pVT->InToOut(
159 CFX_PointF(pLine->m_LineInfo.fLineX + pSection->GetRect().left,
160 pLine->m_LineInfo.fLineY + pSection->GetRect().top));
184 AddLine(place, lineinfo);
186 if (!m_SectionArray.empty())
187 m_SectionArray.front()->ResetLinePlace();
189 m_bInitialized =
true;
196 if (m_nLimitChar > 0 && nTotalWords >= m_nLimitChar)
198 if (m_nCharArray > 0 && nTotalWords >= m_nCharArray)
211 if (m_nLimitChar > 0 && nTotalWords >= m_nLimitChar)
213 if (m_nCharArray > 0 && nTotalWords >= m_nCharArray)
220 if (!fxcrt::IndexInBounds(m_SectionArray, wordplace.nSecIndex))
223 CPVT_Section* pSection = m_SectionArray[wordplace.nSecIndex].get();
225 AddSection(NewPlace);
227 if (fxcrt::IndexInBounds(m_SectionArray, NewPlace.nSecIndex)) {
228 CPVT_Section* pNewSection = m_SectionArray[NewPlace.nSecIndex].get();
235 ClearSectionRightWords(wordplace);
242 fxcrt::IndexInBounds(m_SectionArray, PlaceRange.EndPos.nSecIndex) &&
244 m_SectionArray[PlaceRange.EndPos.nSecIndex]->GetEndWordPlace();
246 ClearWords(PlaceRange);
248 ClearEmptySections(PlaceRange);
266 if (!m_SectionArray.empty())
267 m_SectionArray.front()->SetRect(CPVT_FloatRect());
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)
273 if (m_nCharArray > 0 && nCharCount.ValueOrDie() >= m_nCharArray)
276 uint16_t word = swText[i];
280 if (i + 1 < sz && swText[i + 1] == 0x0A)
288 if (i + 1 < sz && swText[i + 1] == 0x0D)
298 wp = InsertWord(wp, word, FX_Charset::kDefault);
308 if (
static_cast<size_t>(place.nSecIndex) >= m_SectionArray.size())
312 if (fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
313 m_SectionArray[place.nSecIndex]->UpdateWordPlace(place);
323 for (i = 0, sz = fxcrt::CollectionSize<int32_t>(m_SectionArray);
325 CPVT_Section* pSection = m_SectionArray[i].get();
328 nIndex += kReturnLength;
330 if (fxcrt::IndexInBounds(m_SectionArray, i))
337 int32_t nOldIndex = 0;
340 for (size_t i = 0; i < m_SectionArray.size(); ++i) {
341 CPVT_Section* pSection = m_SectionArray[i].get();
343 if (nIndex == index) {
348 if (nIndex > index) {
349 place
.nSecIndex = pdfium::base::checked_cast<int32_t>(i);
355 if (i != m_SectionArray.size() - 1)
356 nIndex += kReturnLength;
369 if (m_SectionArray.empty())
371 return m_SectionArray.back()->GetEndWordPlace();
378 if (
static_cast<size_t>(place.nSecIndex) >= m_SectionArray.size())
381 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
384 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex - 1))
386 return m_SectionArray[place.nSecIndex - 1]->GetEndWordPlace();
393 if (
static_cast<size_t>(place.nSecIndex) >= m_SectionArray.size())
396 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
399 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex + 1))
401 return m_SectionArray[place.nSecIndex + 1]->GetBeginWordPlace();
405 const CFX_PointF& point)
const {
406 CFX_PointF pt = OutToIn(point);
409 int32_t nRight = fxcrt::CollectionSize<int32_t>(m_SectionArray) - 1;
410 int32_t nMid = fxcrt::CollectionSize<int32_t>(m_SectionArray) / 2;
413 while (nLeft <= nRight) {
414 if (!fxcrt::IndexInBounds(m_SectionArray, nMid))
416 CPVT_Section* pSection = m_SectionArray[nMid].get();
423 nMid = (nLeft + nRight) / 2;
428 nMid = (nLeft + nRight) / 2;
445 const CFX_PointF& point)
const {
446 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
449 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
451 CFX_PointF pt = OutToIn(point);
456 if (fxcrt::IndexInBounds(m_SectionArray, temp.nSecIndex)) {
457 CPVT_Section* pLastSection = m_SectionArray[temp.nSecIndex].get();
468 const CFX_PointF& point)
const {
469 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
472 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
474 CFX_PointF pt = OutToIn(point);
479 if (!fxcrt::IndexInBounds(m_SectionArray, temp.nSecIndex))
482 return m_SectionArray[temp.nSecIndex]->SearchWordPlace(
483 pt.x - pSection->GetRect().left, temp);
493 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
496 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
497 const CPVT_Section::
Line* pLine =
512 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
515 return m_SectionArray[place.nSecIndex]->GetEndWordPlace();
520 for (
const auto& pSection : m_SectionArray) {
521 nTotal += pSection->GetWordArraySize() + kReturnLength;
523 return nTotal - kReturnLength;
530 int32_t nSecIndex = std::clamp(
531 place.nSecIndex, 0, fxcrt::CollectionSize<int32_t>(m_SectionArray));
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));
543 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
546 return m_SectionArray[place.nSecIndex]->AddLine(lineinfo);
551 if (m_SectionArray.empty())
556 std::clamp(newplace.nSecIndex, 0,
557 fxcrt::CollectionSize<int32_t>(m_SectionArray) - 1);
558 return m_SectionArray[newplace.nSecIndex]->AddWord(newplace, wordinfo);
581 float fWordTail)
const {
582 return GetCharWidth(nFontIndex, Word, SubWord) * fFontSize * kFontScale +
600 float fFontSize)
const {
601 float ascent = m_pVTProvider ? m_pVTProvider->GetTypeAscent(nFontIndex) : 0;
602 return ascent * fFontSize * kFontScale;
606 float fFontSize)
const {
607 float descent = m_pVTProvider ? m_pVTProvider->GetTypeDescent(nFontIndex) : 0;
608 return descent * fFontSize * kFontScale;
612 float fFontSize)
const {
617 float fFontSize)
const {
630 return m_fLineLeading;
639 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
642 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
661 if (place.nSecIndex == 0 && m_SectionArray.size() == 1)
664 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
667 if (m_SectionArray[place.nSecIndex]->GetWordArraySize() != 0)
670 m_SectionArray.erase(m_SectionArray.begin() + place.nSecIndex);
679 ClearEmptySection(wordplace);
685 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex + 1))
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();
696 m_SectionArray.erase(m_SectionArray.begin() + place.nSecIndex + 1);
705 if (fxcrt::IndexInBounds(m_SectionArray, s))
706 m_SectionArray[s]->ClearWords(NewRange);
711 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
714 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
716 if (leftplace
== place)
721 ClearEmptySection(place);
723 LinkLatterSection(leftplace);
731 if (!fxcrt::IndexInBounds(m_SectionArray, place.nSecIndex))
734 CPVT_Section* pSection = m_SectionArray[place.nSecIndex].get();
736 if (rightplace
== place)
740 LinkLatterSection(place);
751 Rearrange(PlaceRange);
755 CPVT_FloatRect rcRet;
757 if (m_bAutoFontSize) {
759 rcRet = RearrangeSections(
762 rcRet = RearrangeSections(PlaceRange);
769 int32_t nTotal =
sizeof(kFontSizeSteps) /
sizeof(uint8_t);
778 int32_t nRight = nTotal - 1;
779 int32_t nMid = nTotal / 2;
780 while (nLeft <= nRight) {
781 if (IsBigger(kFontSizeSteps[nMid]))
785 nMid = (nLeft + nRight) / 2;
787 return (
float)kFontSizeSteps[nMid];
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;
807 CPVT_FloatRect rcRet;
808 for (int32_t s = 0, sz = fxcrt::CollectionSize<int32_t>(m_SectionArray);
812 CPVT_Section* pSection = m_SectionArray[s].get();
823 rcSec
.bottom = fPosY + fOldHeight;
843 uint16_t SubWord)
const {
846 uint16_t word = SubWord ? SubWord : Word;
847 return m_pVTProvider->GetCharWidth(nFontIndex, word);
852 int32_t nFontIndex) {
854 ? m_pVTProvider->GetWordFontIndex(word, charset, nFontIndex)
859 return m_pVTProvider ? m_pVTProvider->GetDefaultFontIndex() : -1;
864 m_pVTIterator = std::make_unique<CPVT_VariableText::Iterator>(
this);
865 return m_pVTIterator.get();
869 m_pVTProvider = pProvider;
873 return CFX_PointF(m_rcPlate
.left, m_rcPlate
.top);
881 return CFX_PointF(point.x + GetBTPoint().x, GetBTPoint().y - point.y);
885 return CFX_PointF(point.x - GetBTPoint().x, GetBTPoint().y - point.y);
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,
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()
#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)