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 32 CPDF_VariableText::Provider::Provider(IPVT_FontMap* pFontMap) 33 : m_pFontMap(pFontMap) { 34 ASSERT(m_pFontMap); 35 } 36 37 CPDF_VariableText::Provider::~Provider() {} 38 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 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 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 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 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 80 int32_t CPDF_VariableText::Provider::GetDefaultFontIndex() { 81 return 0; 82 } 83 84 CPDF_VariableText::Iterator::Iterator(CPDF_VariableText* pVT) 85 : m_CurPos(-1, -1, -1), m_pVT(pVT) {} 86 87 CPDF_VariableText::Iterator::~Iterator() {} 88 89 void CPDF_VariableText::Iterator::SetAt(int32_t nWordIndex) { 90 m_CurPos = m_pVT->WordIndexToWordPlace(nWordIndex); 91 } 92 93 void CPDF_VariableText::Iterator::SetAt(const CPVT_WordPlace& place) { 94 ASSERT(m_pVT); 95 m_CurPos = place; 96 } 97 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 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 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 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 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 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 165 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 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 203 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 221 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 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 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 260 CPDF_VariableText::~CPDF_VariableText() { 261 ResetAll(); 262 } 263 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 282 void CPDF_VariableText::ResetAll() { 283 m_bInitial = false; 284 ResetSectionArray(); 285 } 286 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 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 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 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 391 CPVT_WordPlace CPDF_VariableText::DeleteWord(const CPVT_WordPlace& place) { 392 return ClearRightWord(AdjustLineHeader(place, true)); 393 } 394 395 CPVT_WordPlace CPDF_VariableText::BackSpaceWord(const CPVT_WordPlace& place) { 396 return ClearLeftWord(AdjustLineHeader(place, true)); 397 } 398 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 447 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 458 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 478 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 506 CPVT_WordPlace CPDF_VariableText::GetBeginWordPlace() const { 507 return m_bInitial ? CPVT_WordPlace(0, 0, -1) : CPVT_WordPlace(); 508 } 509 510 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 516 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 533 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 550 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 593 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 614 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 635 CPVT_WordPlace CPDF_VariableText::GetLineBeginPlace( 636 const CPVT_WordPlace& place) const { 637 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1); 638 } 639 640 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 649 CPVT_WordPlace CPDF_VariableText::GetSectionBeginPlace( 650 const CPVT_WordPlace& place) const { 651 return CPVT_WordPlace(place.nSecIndex, 0, -1); 652 } 653 654 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 661 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 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 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 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 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 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 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 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 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 760 void CPDF_VariableText::SetPlateRect(const CFX_FloatRect& rect) { 761 m_rcPlate = rect; 762 } 763 764 void CPDF_VariableText::SetContentRect(const CPVT_FloatRect& rect) { 765 m_rcContent = rect; 766 } 767 768 CFX_FloatRect CPDF_VariableText::GetContentRect() const { 769 return InToOut(CPVT_FloatRect(m_rcContent)); 770 } 771 772 const CFX_FloatRect& CPDF_VariableText::GetPlateRect() const { 773 return m_rcPlate; 774 } 775 776 FX_FLOAT CPDF_VariableText::GetWordFontSize(const CPVT_WordInfo& WordInfo) { 777 return GetFontSize(); 778 } 779 780 int32_t CPDF_VariableText::GetWordFontIndex(const CPVT_WordInfo& WordInfo) { 781 return WordInfo.nFontIndex; 782 } 783 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 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 803 FX_FLOAT CPDF_VariableText::GetLineAscent(const CPVT_SectionInfo& SecInfo) { 804 return GetFontAscent(GetDefaultFontIndex(), GetFontSize()); 805 } 806 807 FX_FLOAT CPDF_VariableText::GetLineDescent(const CPVT_SectionInfo& SecInfo) { 808 return GetFontDescent(GetDefaultFontIndex(), GetFontSize()); 809 } 810 811 FX_FLOAT CPDF_VariableText::GetFontAscent(int32_t nFontIndex, 812 FX_FLOAT fFontSize) { 813 return (FX_FLOAT)GetTypeAscent(nFontIndex) * fFontSize * kFontScale; 814 } 815 816 FX_FLOAT CPDF_VariableText::GetFontDescent(int32_t nFontIndex, 817 FX_FLOAT fFontSize) { 818 return (FX_FLOAT)GetTypeDescent(nFontIndex) * fFontSize * kFontScale; 819 } 820 821 FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo& WordInfo, 822 FX_FLOAT fFontSize) { 823 return GetFontAscent(GetWordFontIndex(WordInfo), fFontSize); 824 } 825 826 FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo& WordInfo, 827 FX_FLOAT fFontSize) { 828 return GetFontDescent(GetWordFontIndex(WordInfo), fFontSize); 829 } 830 831 FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo& WordInfo) { 832 return GetFontAscent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo)); 833 } 834 835 FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo& WordInfo) { 836 return GetFontDescent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo)); 837 } 838 839 FX_FLOAT CPDF_VariableText::GetLineLeading(const CPVT_SectionInfo& SecInfo) { 840 return m_fLineLeading; 841 } 842 843 FX_FLOAT CPDF_VariableText::GetLineIndent(const CPVT_SectionInfo& SecInfo) { 844 return 0.0f; 845 } 846 847 int32_t CPDF_VariableText::GetAlignment(const CPVT_SectionInfo& SecInfo) { 848 return m_nAlignment; 849 } 850 851 FX_FLOAT CPDF_VariableText::GetCharSpace(const CPVT_WordInfo& WordInfo) { 852 return m_fCharSpace; 853 } 854 855 int32_t CPDF_VariableText::GetHorzScale(const CPVT_WordInfo& WordInfo) { 856 return m_nHorzScale; 857 } 858 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 870 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 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 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 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 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 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 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 959 void CPDF_VariableText::RearrangeAll() { 960 Rearrange(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace())); 961 } 962 963 void CPDF_VariableText::RearrangePart(const CPVT_WordRange& PlaceRange) { 964 Rearrange(PlaceRange); 965 } 966 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 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 1008 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 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 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 1074 int32_t CPDF_VariableText::GetTypeAscent(int32_t nFontIndex) { 1075 return m_pVTProvider ? m_pVTProvider->GetTypeAscent(nFontIndex) : 0; 1076 } 1077 1078 int32_t CPDF_VariableText::GetTypeDescent(int32_t nFontIndex) { 1079 return m_pVTProvider ? m_pVTProvider->GetTypeDescent(nFontIndex) : 0; 1080 } 1081 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 1090 int32_t CPDF_VariableText::GetDefaultFontIndex() { 1091 return m_pVTProvider ? m_pVTProvider->GetDefaultFontIndex() : -1; 1092 } 1093 1094 bool CPDF_VariableText::IsLatinWord(uint16_t word) { 1095 return m_pVTProvider ? m_pVTProvider->IsLatinWord(word) : false; 1096 } 1097 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 1104 void CPDF_VariableText::SetProvider(CPDF_VariableText::Provider* pProvider) { 1105 m_pVTProvider = pProvider; 1106 } 1107 1108 CFX_SizeF CPDF_VariableText::GetPlateSize() const { 1109 return CFX_SizeF(GetPlateWidth(), GetPlateHeight()); 1110 } 1111 1112 CFX_PointF CPDF_VariableText::GetBTPoint() const { 1113 return CFX_PointF(m_rcPlate.left, m_rcPlate.top); 1114 } 1115 1116 CFX_PointF CPDF_VariableText::GetETPoint() const { 1117 return CFX_PointF(m_rcPlate.right, m_rcPlate.bottom); 1118 } 1119 1120 CFX_PointF CPDF_VariableText::InToOut(const CFX_PointF& point) const { 1121 return CFX_PointF(point.x + GetBTPoint().x, GetBTPoint().y - point.y); 1122 } 1123 1124 CFX_PointF CPDF_VariableText::OutToIn(const CFX_PointF& point) const { 1125 return CFX_PointF(point.x - GetBTPoint().x, GetBTPoint().y - point.y); 1126 } 1127 1128 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 1135 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