1 // Copyright 2014 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 "pageint.h" 8 9 #include "core/include/fpdfapi/fpdf_module.h" 10 #include "core/include/fpdfapi/fpdf_page.h" 11 12 CPDF_PageObject* CPDF_PageObject::Create(int type) { 13 switch (type) { 14 case PDFPAGE_TEXT: 15 return new CPDF_TextObject; 16 case PDFPAGE_IMAGE: 17 return new CPDF_ImageObject; 18 case PDFPAGE_PATH: 19 return new CPDF_PathObject; 20 case PDFPAGE_SHADING: 21 return new CPDF_ShadingObject; 22 case PDFPAGE_FORM: 23 return new CPDF_FormObject; 24 } 25 return NULL; 26 } 27 CPDF_PageObject::~CPDF_PageObject() {} 28 CPDF_PageObject* CPDF_PageObject::Clone() const { 29 CPDF_PageObject* pObj = Create(m_Type); 30 pObj->Copy(this); 31 return pObj; 32 } 33 void CPDF_PageObject::Copy(const CPDF_PageObject* pSrc) { 34 if (m_Type != pSrc->m_Type) { 35 return; 36 } 37 CopyData(pSrc); 38 CopyStates(*pSrc); 39 m_Left = pSrc->m_Left; 40 m_Right = pSrc->m_Right; 41 m_Top = pSrc->m_Top; 42 m_Bottom = pSrc->m_Bottom; 43 } 44 void CPDF_PageObject::AppendClipPath(CPDF_Path path, 45 int type, 46 FX_BOOL bAutoMerge) { 47 m_ClipPath.AppendPath(path, type, bAutoMerge); 48 } 49 void CPDF_PageObject::CopyClipPath(CPDF_PageObject* pObj) { 50 m_ClipPath = pObj->m_ClipPath; 51 } 52 void CPDF_PageObject::RemoveClipPath() { 53 m_ClipPath.SetNull(); 54 } 55 void CPDF_PageObject::RecalcBBox() { 56 switch (m_Type) { 57 case PDFPAGE_TEXT: 58 ((CPDF_TextObject*)this)->RecalcPositionData(); 59 break; 60 case PDFPAGE_PATH: 61 ((CPDF_PathObject*)this)->CalcBoundingBox(); 62 break; 63 case PDFPAGE_SHADING: 64 ((CPDF_ShadingObject*)this)->CalcBoundingBox(); 65 break; 66 } 67 } 68 void CPDF_PageObject::TransformClipPath(CFX_Matrix& matrix) { 69 if (m_ClipPath.IsNull()) { 70 return; 71 } 72 m_ClipPath.GetModify(); 73 m_ClipPath.Transform(matrix); 74 } 75 void CPDF_PageObject::TransformGeneralState(CFX_Matrix& matrix) { 76 if (m_GeneralState.IsNull()) { 77 return; 78 } 79 CPDF_GeneralStateData* pGS = m_GeneralState.GetModify(); 80 pGS->m_Matrix.Concat(matrix); 81 } 82 FX_RECT CPDF_PageObject::GetBBox(const CFX_Matrix* pMatrix) const { 83 CFX_FloatRect rect(m_Left, m_Bottom, m_Right, m_Top); 84 if (pMatrix) { 85 pMatrix->TransformRect(rect); 86 } 87 return rect.GetOutterRect(); 88 } 89 90 CPDF_TextObject::CPDF_TextObject() 91 : m_PosX(0), 92 m_PosY(0), 93 m_nChars(0), 94 m_pCharCodes(nullptr), 95 m_pCharPos(nullptr) { 96 m_Type = PDFPAGE_TEXT; 97 } 98 99 CPDF_TextObject::~CPDF_TextObject() { 100 if (m_nChars > 1) { 101 FX_Free(m_pCharCodes); 102 } 103 FX_Free(m_pCharPos); 104 } 105 106 void CPDF_TextObject::GetItemInfo(int index, CPDF_TextObjectItem* pInfo) const { 107 pInfo->m_CharCode = 108 m_nChars == 1 ? (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[index]; 109 pInfo->m_OriginX = index ? m_pCharPos[index - 1] : 0; 110 pInfo->m_OriginY = 0; 111 if (pInfo->m_CharCode == -1) { 112 return; 113 } 114 CPDF_Font* pFont = m_TextState.GetFont(); 115 if (pFont->GetFontType() != PDFFONT_CIDFONT) { 116 return; 117 } 118 if (!((CPDF_CIDFont*)pFont)->IsVertWriting()) { 119 return; 120 } 121 FX_WORD CID = ((CPDF_CIDFont*)pFont)->CIDFromCharCode(pInfo->m_CharCode); 122 pInfo->m_OriginY = pInfo->m_OriginX; 123 pInfo->m_OriginX = 0; 124 short vx, vy; 125 ((CPDF_CIDFont*)pFont)->GetVertOrigin(CID, vx, vy); 126 FX_FLOAT fontsize = m_TextState.GetFontSize(); 127 pInfo->m_OriginX -= fontsize * vx / 1000; 128 pInfo->m_OriginY -= fontsize * vy / 1000; 129 } 130 131 int CPDF_TextObject::CountChars() const { 132 if (m_nChars == 1) { 133 return 1; 134 } 135 int count = 0; 136 for (int i = 0; i < m_nChars; ++i) 137 if (m_pCharCodes[i] != (FX_DWORD)-1) { 138 ++count; 139 } 140 return count; 141 } 142 143 void CPDF_TextObject::GetCharInfo(int index, 144 FX_DWORD& charcode, 145 FX_FLOAT& kerning) const { 146 if (m_nChars == 1) { 147 charcode = (FX_DWORD)(uintptr_t)m_pCharCodes; 148 kerning = 0; 149 return; 150 } 151 int count = 0; 152 for (int i = 0; i < m_nChars; ++i) { 153 if (m_pCharCodes[i] != (FX_DWORD)-1) { 154 if (count == index) { 155 charcode = m_pCharCodes[i]; 156 if (i == m_nChars - 1 || m_pCharCodes[i + 1] != (FX_DWORD)-1) { 157 kerning = 0; 158 } else { 159 kerning = m_pCharPos[i]; 160 } 161 return; 162 } 163 ++count; 164 } 165 } 166 } 167 168 void CPDF_TextObject::GetCharInfo(int index, CPDF_TextObjectItem* pInfo) const { 169 if (m_nChars == 1) { 170 GetItemInfo(0, pInfo); 171 return; 172 } 173 int count = 0; 174 for (int i = 0; i < m_nChars; ++i) { 175 FX_DWORD charcode = m_pCharCodes[i]; 176 if (charcode == (FX_DWORD)-1) { 177 continue; 178 } 179 if (count == index) { 180 GetItemInfo(i, pInfo); 181 break; 182 } 183 ++count; 184 } 185 } 186 187 void CPDF_TextObject::CopyData(const CPDF_PageObject* pSrc) { 188 const CPDF_TextObject* pSrcObj = (const CPDF_TextObject*)pSrc; 189 if (m_nChars > 1) { 190 FX_Free(m_pCharCodes); 191 m_pCharCodes = nullptr; 192 } 193 FX_Free(m_pCharPos); 194 m_pCharPos = nullptr; 195 m_nChars = pSrcObj->m_nChars; 196 if (m_nChars > 1) { 197 m_pCharCodes = FX_Alloc(FX_DWORD, m_nChars); 198 m_pCharPos = FX_Alloc(FX_FLOAT, m_nChars - 1); 199 for (int i = 0; i < m_nChars; ++i) { 200 m_pCharCodes[i] = pSrcObj->m_pCharCodes[i]; 201 } 202 for (int i = 0; i < m_nChars - 1; ++i) { 203 m_pCharPos[i] = pSrcObj->m_pCharPos[i]; 204 } 205 } else { 206 m_pCharCodes = pSrcObj->m_pCharCodes; 207 } 208 m_PosX = pSrcObj->m_PosX; 209 m_PosY = pSrcObj->m_PosY; 210 } 211 212 void CPDF_TextObject::GetTextMatrix(CFX_Matrix* pMatrix) const { 213 FX_FLOAT* pTextMatrix = m_TextState.GetMatrix(); 214 pMatrix->Set(pTextMatrix[0], pTextMatrix[2], pTextMatrix[1], pTextMatrix[3], 215 m_PosX, m_PosY); 216 } 217 218 void CPDF_TextObject::SetSegments(const CFX_ByteString* pStrs, 219 FX_FLOAT* pKerning, 220 int nsegs) { 221 if (m_nChars > 1) { 222 FX_Free(m_pCharCodes); 223 m_pCharCodes = nullptr; 224 } 225 FX_Free(m_pCharPos); 226 m_pCharPos = nullptr; 227 CPDF_Font* pFont = m_TextState.GetFont(); 228 m_nChars = 0; 229 for (int i = 0; i < nsegs; ++i) { 230 m_nChars += pFont->CountChar(pStrs[i], pStrs[i].GetLength()); 231 } 232 m_nChars += nsegs - 1; 233 if (m_nChars > 1) { 234 m_pCharCodes = FX_Alloc(FX_DWORD, m_nChars); 235 m_pCharPos = FX_Alloc(FX_FLOAT, m_nChars - 1); 236 int index = 0; 237 for (int i = 0; i < nsegs; ++i) { 238 const FX_CHAR* segment = pStrs[i]; 239 int offset = 0, len = pStrs[i].GetLength(); 240 while (offset < len) { 241 m_pCharCodes[index++] = pFont->GetNextChar(segment, len, offset); 242 } 243 if (i != nsegs - 1) { 244 m_pCharPos[index - 1] = pKerning[i]; 245 m_pCharCodes[index++] = (FX_DWORD)-1; 246 } 247 } 248 } else { 249 int offset = 0; 250 m_pCharCodes = (FX_DWORD*)(uintptr_t)pFont->GetNextChar( 251 pStrs[0], pStrs[0].GetLength(), offset); 252 } 253 } 254 255 void CPDF_TextObject::SetText(const CFX_ByteString& str) { 256 SetSegments(&str, nullptr, 1); 257 RecalcPositionData(); 258 } 259 260 void CPDF_TextObject::SetEmpty() { 261 if (m_nChars > 1) { 262 FX_Free(m_pCharCodes); 263 } 264 if (m_nChars > 1) { 265 FX_Free(m_pCharPos); 266 } 267 m_nChars = 0; 268 m_pCharCodes = nullptr; 269 m_pCharPos = nullptr; 270 m_Left = m_Right = m_PosX; 271 m_Top = m_Bottom = m_PosY; 272 } 273 274 void CPDF_TextObject::SetText(CFX_ByteString* pStrs, 275 FX_FLOAT* pKerning, 276 int nSegs) { 277 SetSegments(pStrs, pKerning, nSegs); 278 RecalcPositionData(); 279 } 280 281 void CPDF_TextObject::SetText(int nChars, 282 FX_DWORD* pCharCodes, 283 FX_FLOAT* pKernings) { 284 if (m_nChars > 1) { 285 FX_Free(m_pCharCodes); 286 m_pCharCodes = nullptr; 287 } 288 FX_Free(m_pCharPos); 289 m_pCharPos = nullptr; 290 int nKernings = 0; 291 int i; 292 for (i = 0; i < nChars - 1; ++i) { 293 if (pKernings[i] != 0) { 294 ++nKernings; 295 } 296 } 297 m_nChars = nChars + nKernings; 298 if (m_nChars > 1) { 299 m_pCharCodes = FX_Alloc(FX_DWORD, m_nChars); 300 m_pCharPos = FX_Alloc(FX_FLOAT, m_nChars - 1); 301 for (int i = 0, index = 0; i < nChars; ++i) { 302 m_pCharCodes[index++] = pCharCodes[i]; 303 if (pKernings[i] != 0 && i != nChars - 1) { 304 m_pCharCodes[index] = (FX_DWORD)-1; 305 m_pCharPos[index - 1] = pKernings[i]; 306 ++index; 307 } 308 } 309 } else { 310 m_pCharCodes = (FX_DWORD*)(uintptr_t)pCharCodes[0]; 311 } 312 RecalcPositionData(); 313 } 314 315 FX_FLOAT CPDF_TextObject::GetCharWidth(FX_DWORD charcode) const { 316 FX_FLOAT fontsize = m_TextState.GetFontSize() / 1000; 317 CPDF_Font* pFont = m_TextState.GetFont(); 318 FX_BOOL bVertWriting = FALSE; 319 CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); 320 if (pCIDFont) { 321 bVertWriting = pCIDFont->IsVertWriting(); 322 } 323 if (!bVertWriting) 324 return pFont->GetCharWidthF(charcode, 0) * fontsize; 325 326 FX_WORD CID = pCIDFont->CIDFromCharCode(charcode); 327 return pCIDFont->GetVertWidth(CID) * fontsize; 328 } 329 330 FX_FLOAT CPDF_TextObject::GetSpaceCharWidth() const { 331 CPDF_Font* pFont = m_TextState.GetFont(); 332 FX_DWORD charCode = m_TextState.GetFont()->CharCodeFromUnicode(32); 333 if (charCode != (FX_DWORD)-1) { 334 return GetCharWidth(charCode); 335 } 336 FX_FLOAT fontSize = m_TextState.GetFontSize() / 4000.0f; 337 FX_BOOL bVertWriting = FALSE; 338 CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); 339 if (pCIDFont) { 340 bVertWriting = pCIDFont->IsVertWriting(); 341 } 342 FX_RECT fontRect; 343 pFont->GetFontBBox(fontRect); 344 fontSize *= 345 bVertWriting ? (FX_FLOAT)fontRect.Height() : (FX_FLOAT)fontRect.Width(); 346 return fontSize; 347 } 348 349 void CPDF_TextObject::GetCharRect(int index, CFX_FloatRect& rect) const { 350 CPDF_Font* pFont = m_TextState.GetFont(); 351 FX_BOOL bVertWriting = FALSE; 352 CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); 353 if (pCIDFont) { 354 bVertWriting = pCIDFont->IsVertWriting(); 355 } 356 FX_FLOAT fontsize = m_TextState.GetFontSize() / 1000; 357 int count = 0; 358 for (int i = 0; i < m_nChars; ++i) { 359 FX_DWORD charcode = 360 m_nChars == 1 ? (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[i]; 361 if (charcode == (FX_DWORD)-1) { 362 continue; 363 } 364 if (count != index) { 365 ++count; 366 continue; 367 } 368 FX_FLOAT curpos = i > 0 ? m_pCharPos[i - 1] : 0; 369 FX_RECT char_rect; 370 pFont->GetCharBBox(charcode, char_rect, 0); 371 if (!bVertWriting) { 372 rect.left = curpos + char_rect.left * fontsize; 373 rect.right = curpos + char_rect.right * fontsize; 374 rect.top = char_rect.top * fontsize; 375 rect.bottom = char_rect.bottom * fontsize; 376 } else { 377 FX_WORD CID = pCIDFont->CIDFromCharCode(charcode); 378 short vx, vy; 379 pCIDFont->GetVertOrigin(CID, vx, vy); 380 char_rect.left -= vx; 381 char_rect.right -= vx; 382 char_rect.top -= vy; 383 char_rect.bottom -= vy; 384 rect.left = char_rect.left * fontsize; 385 rect.right = char_rect.right * fontsize; 386 rect.top = curpos + char_rect.top * fontsize; 387 rect.bottom = curpos + char_rect.bottom * fontsize; 388 } 389 return; 390 } 391 } 392 393 void CPDF_TextObject::CalcPositionData(FX_FLOAT* pTextAdvanceX, 394 FX_FLOAT* pTextAdvanceY, 395 FX_FLOAT horz_scale, 396 int level) { 397 FX_FLOAT curpos = 0; 398 FX_FLOAT min_x = 10000 * 1.0f; 399 FX_FLOAT max_x = -10000 * 1.0f; 400 FX_FLOAT min_y = 10000 * 1.0f; 401 FX_FLOAT max_y = -10000 * 1.0f; 402 CPDF_Font* pFont = m_TextState.GetFont(); 403 FX_BOOL bVertWriting = FALSE; 404 CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); 405 if (pCIDFont) { 406 bVertWriting = pCIDFont->IsVertWriting(); 407 } 408 FX_FLOAT fontsize = m_TextState.GetFontSize(); 409 for (int i = 0; i < m_nChars; ++i) { 410 FX_DWORD charcode = 411 m_nChars == 1 ? (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[i]; 412 if (i > 0) { 413 if (charcode == (FX_DWORD)-1) { 414 curpos -= FXSYS_Mul(m_pCharPos[i - 1], fontsize) / 1000; 415 continue; 416 } 417 m_pCharPos[i - 1] = curpos; 418 } 419 FX_RECT char_rect; 420 pFont->GetCharBBox(charcode, char_rect, level); 421 FX_FLOAT charwidth; 422 if (!bVertWriting) { 423 if (min_y > char_rect.top) { 424 min_y = (FX_FLOAT)char_rect.top; 425 } 426 if (max_y < char_rect.top) { 427 max_y = (FX_FLOAT)char_rect.top; 428 } 429 if (min_y > char_rect.bottom) { 430 min_y = (FX_FLOAT)char_rect.bottom; 431 } 432 if (max_y < char_rect.bottom) { 433 max_y = (FX_FLOAT)char_rect.bottom; 434 } 435 FX_FLOAT char_left = curpos + char_rect.left * fontsize / 1000; 436 FX_FLOAT char_right = curpos + char_rect.right * fontsize / 1000; 437 if (min_x > char_left) { 438 min_x = char_left; 439 } 440 if (max_x < char_left) { 441 max_x = char_left; 442 } 443 if (min_x > char_right) { 444 min_x = char_right; 445 } 446 if (max_x < char_right) { 447 max_x = char_right; 448 } 449 charwidth = pFont->GetCharWidthF(charcode, level) * fontsize / 1000; 450 } else { 451 FX_WORD CID = pCIDFont->CIDFromCharCode(charcode); 452 short vx; 453 short vy; 454 pCIDFont->GetVertOrigin(CID, vx, vy); 455 char_rect.left -= vx; 456 char_rect.right -= vx; 457 char_rect.top -= vy; 458 char_rect.bottom -= vy; 459 if (min_x > char_rect.left) { 460 min_x = (FX_FLOAT)char_rect.left; 461 } 462 if (max_x < char_rect.left) { 463 max_x = (FX_FLOAT)char_rect.left; 464 } 465 if (min_x > char_rect.right) { 466 min_x = (FX_FLOAT)char_rect.right; 467 } 468 if (max_x < char_rect.right) { 469 max_x = (FX_FLOAT)char_rect.right; 470 } 471 FX_FLOAT char_top = curpos + char_rect.top * fontsize / 1000; 472 FX_FLOAT char_bottom = curpos + char_rect.bottom * fontsize / 1000; 473 if (min_y > char_top) { 474 min_y = char_top; 475 } 476 if (max_y < char_top) { 477 max_y = char_top; 478 } 479 if (min_y > char_bottom) { 480 min_y = char_bottom; 481 } 482 if (max_y < char_bottom) { 483 max_y = char_bottom; 484 } 485 charwidth = pCIDFont->GetVertWidth(CID) * fontsize / 1000; 486 } 487 curpos += charwidth; 488 if (charcode == ' ' && (!pCIDFont || pCIDFont->GetCharSize(32) == 1)) { 489 curpos += m_TextState.GetObject()->m_WordSpace; 490 } 491 curpos += m_TextState.GetObject()->m_CharSpace; 492 } 493 if (bVertWriting) { 494 if (pTextAdvanceX) { 495 *pTextAdvanceX = 0; 496 } 497 if (pTextAdvanceY) { 498 *pTextAdvanceY = curpos; 499 } 500 min_x = min_x * fontsize / 1000; 501 max_x = max_x * fontsize / 1000; 502 } else { 503 if (pTextAdvanceX) { 504 *pTextAdvanceX = FXSYS_Mul(curpos, horz_scale); 505 } 506 if (pTextAdvanceY) { 507 *pTextAdvanceY = 0; 508 } 509 min_y = min_y * fontsize / 1000; 510 max_y = max_y * fontsize / 1000; 511 } 512 CFX_Matrix matrix; 513 GetTextMatrix(&matrix); 514 m_Left = min_x; 515 m_Right = max_x; 516 m_Bottom = min_y; 517 m_Top = max_y; 518 matrix.TransformRect(m_Left, m_Right, m_Top, m_Bottom); 519 int textmode = m_TextState.GetObject()->m_TextMode; 520 if (textmode == 1 || textmode == 2 || textmode == 5 || textmode == 6) { 521 FX_FLOAT half_width = m_GraphState.GetObject()->m_LineWidth / 2; 522 m_Left -= half_width; 523 m_Right += half_width; 524 m_Top += half_width; 525 m_Bottom -= half_width; 526 } 527 } 528 529 void CPDF_TextObject::CalcCharPos(FX_FLOAT* pPosArray) const { 530 CPDF_Font* pFont = m_TextState.GetFont(); 531 FX_BOOL bVertWriting = FALSE; 532 CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); 533 if (pCIDFont) { 534 bVertWriting = pCIDFont->IsVertWriting(); 535 } 536 FX_FLOAT fontsize = m_TextState.GetFontSize(); 537 for (int i = 0, index = 0; i < m_nChars; ++i) { 538 FX_DWORD charcode = 539 m_nChars == 1 ? (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[i]; 540 if (charcode == (FX_DWORD)-1) { 541 continue; 542 } 543 pPosArray[index++] = i ? m_pCharPos[i - 1] : 0; 544 FX_FLOAT charwidth; 545 if (bVertWriting) { 546 FX_WORD CID = pCIDFont->CIDFromCharCode(charcode); 547 charwidth = pCIDFont->GetVertWidth(CID) * fontsize / 1000; 548 } else { 549 charwidth = pFont->GetCharWidthF(charcode) * fontsize / 1000; 550 } 551 pPosArray[index] = pPosArray[index - 1] + charwidth; 552 index++; 553 } 554 } 555 556 void CPDF_TextObject::Transform(const CFX_Matrix& matrix) { 557 m_TextState.GetModify(); 558 CFX_Matrix text_matrix; 559 GetTextMatrix(&text_matrix); 560 text_matrix.Concat(matrix); 561 FX_FLOAT* pTextMatrix = m_TextState.GetMatrix(); 562 pTextMatrix[0] = text_matrix.GetA(); 563 pTextMatrix[1] = text_matrix.GetC(); 564 pTextMatrix[2] = text_matrix.GetB(); 565 pTextMatrix[3] = text_matrix.GetD(); 566 m_PosX = text_matrix.GetE(); 567 m_PosY = text_matrix.GetF(); 568 CalcPositionData(nullptr, nullptr, 0); 569 } 570 571 void CPDF_TextObject::SetPosition(FX_FLOAT x, FX_FLOAT y) { 572 FX_FLOAT dx = x - m_PosX; 573 FX_FLOAT dy = y - m_PosY; 574 m_PosX = x; 575 m_PosY = y; 576 m_Left += dx; 577 m_Right += dx; 578 m_Top += dy; 579 m_Bottom += dy; 580 } 581 582 void CPDF_TextObject::SetData(int nChars, 583 FX_DWORD* pCharCodes, 584 FX_FLOAT* pCharPos, 585 FX_FLOAT x, 586 FX_FLOAT y) { 587 ASSERT(m_nChars == 0); 588 m_nChars = nChars; 589 m_PosX = x; 590 m_PosY = y; 591 if (nChars == 0) { 592 return; 593 } 594 if (nChars == 1) { 595 m_pCharCodes = (FX_DWORD*)(uintptr_t)*pCharCodes; 596 } else { 597 m_pCharCodes = FX_Alloc(FX_DWORD, nChars); 598 FXSYS_memcpy(m_pCharCodes, pCharCodes, sizeof(FX_DWORD) * nChars); 599 m_pCharPos = FX_Alloc(FX_FLOAT, nChars - 1); 600 FXSYS_memcpy(m_pCharPos, pCharPos, sizeof(FX_FLOAT) * (nChars - 1)); 601 } 602 RecalcPositionData(); 603 } 604 605 void CPDF_TextObject::SetTextState(CPDF_TextState TextState) { 606 m_TextState = TextState; 607 CalcPositionData(nullptr, nullptr, 0); 608 } 609 610 CPDF_ShadingObject::CPDF_ShadingObject() { 611 m_pShading = NULL; 612 m_Type = PDFPAGE_SHADING; 613 } 614 CPDF_ShadingObject::~CPDF_ShadingObject() {} 615 void CPDF_ShadingObject::CopyData(const CPDF_PageObject* pSrc) { 616 CPDF_ShadingObject* pSrcObj = (CPDF_ShadingObject*)pSrc; 617 m_pShading = pSrcObj->m_pShading; 618 if (m_pShading && m_pShading->m_pDocument) { 619 CPDF_DocPageData* pDocPageData = m_pShading->m_pDocument->GetPageData(); 620 m_pShading = (CPDF_ShadingPattern*)pDocPageData->GetPattern( 621 m_pShading->m_pShadingObj, m_pShading->m_bShadingObj, 622 &m_pShading->m_ParentMatrix); 623 } 624 m_Matrix = pSrcObj->m_Matrix; 625 } 626 void CPDF_ShadingObject::Transform(const CFX_Matrix& matrix) { 627 if (!m_ClipPath.IsNull()) { 628 m_ClipPath.GetModify(); 629 m_ClipPath.Transform(matrix); 630 } 631 m_Matrix.Concat(matrix); 632 if (!m_ClipPath.IsNull()) { 633 CalcBoundingBox(); 634 } else { 635 matrix.TransformRect(m_Left, m_Right, m_Top, m_Bottom); 636 } 637 } 638 void CPDF_ShadingObject::CalcBoundingBox() { 639 if (m_ClipPath.IsNull()) { 640 return; 641 } 642 CFX_FloatRect rect = m_ClipPath.GetClipBox(); 643 m_Left = rect.left; 644 m_Bottom = rect.bottom; 645 m_Right = rect.right; 646 m_Top = rect.top; 647 } 648 CPDF_FormObject::~CPDF_FormObject() { 649 delete m_pForm; 650 } 651 void CPDF_FormObject::Transform(const CFX_Matrix& matrix) { 652 m_FormMatrix.Concat(matrix); 653 CalcBoundingBox(); 654 } 655 void CPDF_FormObject::CopyData(const CPDF_PageObject* pSrc) { 656 const CPDF_FormObject* pSrcObj = (const CPDF_FormObject*)pSrc; 657 delete m_pForm; 658 m_pForm = pSrcObj->m_pForm->Clone(); 659 m_FormMatrix = pSrcObj->m_FormMatrix; 660 } 661 void CPDF_FormObject::CalcBoundingBox() { 662 CFX_FloatRect form_rect = m_pForm->CalcBoundingBox(); 663 form_rect.Transform(&m_FormMatrix); 664 m_Left = form_rect.left; 665 m_Bottom = form_rect.bottom; 666 m_Right = form_rect.right; 667 m_Top = form_rect.top; 668 } 669 CPDF_PageObjects::CPDF_PageObjects(FX_BOOL bReleaseMembers) 670 : m_pFormDict(nullptr), 671 m_pFormStream(nullptr), 672 m_pDocument(nullptr), 673 m_pPageResources(nullptr), 674 m_pResources(nullptr), 675 m_Transparency(0), 676 m_ObjectList(128), 677 m_bBackgroundAlphaNeeded(FALSE), 678 m_bHasImageMask(FALSE), 679 m_bReleaseMembers(bReleaseMembers), 680 m_pParser(nullptr), 681 m_ParseState(CONTENT_NOT_PARSED) {} 682 CPDF_PageObjects::~CPDF_PageObjects() { 683 delete m_pParser; 684 if (!m_bReleaseMembers) { 685 return; 686 } 687 FX_POSITION pos = m_ObjectList.GetHeadPosition(); 688 while (pos) { 689 delete (CPDF_PageObject*)m_ObjectList.GetNext(pos); 690 } 691 } 692 void CPDF_PageObjects::ContinueParse(IFX_Pause* pPause) { 693 if (!m_pParser) { 694 return; 695 } 696 m_pParser->Continue(pPause); 697 if (m_pParser->GetStatus() == CPDF_ContentParser::Done) { 698 m_ParseState = CONTENT_PARSED; 699 delete m_pParser; 700 m_pParser = NULL; 701 } 702 } 703 FX_POSITION CPDF_PageObjects::InsertObject(FX_POSITION posInsertAfter, 704 CPDF_PageObject* pNewObject) { 705 if (!posInsertAfter) { 706 return m_ObjectList.AddHead(pNewObject); 707 } 708 return m_ObjectList.InsertAfter(posInsertAfter, pNewObject); 709 } 710 int CPDF_PageObjects::GetObjectIndex(CPDF_PageObject* pObj) const { 711 int index = 0; 712 FX_POSITION pos = m_ObjectList.GetHeadPosition(); 713 while (pos) { 714 CPDF_PageObject* pThisObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos); 715 if (pThisObj == pObj) { 716 return index; 717 } 718 index++; 719 } 720 return -1; 721 } 722 CPDF_PageObject* CPDF_PageObjects::GetObjectByIndex(int index) const { 723 FX_POSITION pos = m_ObjectList.FindIndex(index); 724 return pos ? static_cast<CPDF_PageObject*>(m_ObjectList.GetAt(pos)) : nullptr; 725 } 726 void CPDF_PageObjects::Transform(const CFX_Matrix& matrix) { 727 FX_POSITION pos = m_ObjectList.GetHeadPosition(); 728 while (pos) { 729 CPDF_PageObject* pObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos); 730 pObj->Transform(matrix); 731 } 732 } 733 CFX_FloatRect CPDF_PageObjects::CalcBoundingBox() const { 734 if (m_ObjectList.GetCount() == 0) { 735 return CFX_FloatRect(0, 0, 0, 0); 736 } 737 FX_FLOAT left, right, top, bottom; 738 left = bottom = 1000000 * 1.0f; 739 right = top = -1000000 * 1.0f; 740 FX_POSITION pos = m_ObjectList.GetHeadPosition(); 741 while (pos) { 742 CPDF_PageObject* pObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos); 743 if (left > pObj->m_Left) { 744 left = pObj->m_Left; 745 } 746 if (right < pObj->m_Right) { 747 right = pObj->m_Right; 748 } 749 if (top < pObj->m_Top) { 750 top = pObj->m_Top; 751 } 752 if (bottom > pObj->m_Bottom) { 753 bottom = pObj->m_Bottom; 754 } 755 } 756 return CFX_FloatRect(left, bottom, right, top); 757 } 758 void CPDF_PageObjects::LoadTransInfo() { 759 if (!m_pFormDict) { 760 return; 761 } 762 CPDF_Dictionary* pGroup = m_pFormDict->GetDict("Group"); 763 if (!pGroup) { 764 return; 765 } 766 if (pGroup->GetString("S") != "Transparency") { 767 return; 768 } 769 m_Transparency |= PDFTRANS_GROUP; 770 if (pGroup->GetInteger("I")) { 771 m_Transparency |= PDFTRANS_ISOLATED; 772 } 773 if (pGroup->GetInteger("K")) { 774 m_Transparency |= PDFTRANS_KNOCKOUT; 775 } 776 } 777 void CPDF_PageObjects::ClearCacheObjects() { 778 m_ParseState = CONTENT_NOT_PARSED; 779 delete m_pParser; 780 m_pParser = NULL; 781 if (m_bReleaseMembers) { 782 FX_POSITION pos = m_ObjectList.GetHeadPosition(); 783 while (pos) { 784 delete (CPDF_PageObject*)m_ObjectList.GetNext(pos); 785 } 786 } 787 m_ObjectList.RemoveAll(); 788 } 789 CPDF_Page::CPDF_Page() { 790 m_pPageRender = NULL; 791 } 792 void CPDF_Page::Load(CPDF_Document* pDocument, 793 CPDF_Dictionary* pPageDict, 794 FX_BOOL bPageCache) { 795 m_pDocument = (CPDF_Document*)pDocument; 796 m_pFormDict = pPageDict; 797 if (bPageCache) { 798 m_pPageRender = 799 CPDF_ModuleMgr::Get()->GetRenderModule()->CreatePageCache(this); 800 } 801 if (!pPageDict) { 802 m_PageWidth = m_PageHeight = 100 * 1.0f; 803 m_pPageResources = m_pResources = NULL; 804 return; 805 } 806 CPDF_Object* pageAttr = GetPageAttr("Resources"); 807 m_pResources = pageAttr ? pageAttr->GetDict() : NULL; 808 m_pPageResources = m_pResources; 809 CPDF_Object* pRotate = GetPageAttr("Rotate"); 810 int rotate = 0; 811 if (pRotate) { 812 rotate = pRotate->GetInteger() / 90 % 4; 813 } 814 if (rotate < 0) { 815 rotate += 4; 816 } 817 CPDF_Array* pMediaBox = ToArray(GetPageAttr("MediaBox")); 818 CFX_FloatRect mediabox; 819 if (pMediaBox) { 820 mediabox = pMediaBox->GetRect(); 821 mediabox.Normalize(); 822 } 823 if (mediabox.IsEmpty()) { 824 mediabox = CFX_FloatRect(0, 0, 612, 792); 825 } 826 827 CPDF_Array* pCropBox = ToArray(GetPageAttr("CropBox")); 828 if (pCropBox) { 829 m_BBox = pCropBox->GetRect(); 830 m_BBox.Normalize(); 831 } 832 if (m_BBox.IsEmpty()) { 833 m_BBox = mediabox; 834 } else { 835 m_BBox.Intersect(mediabox); 836 } 837 if (rotate % 2) { 838 m_PageHeight = m_BBox.right - m_BBox.left; 839 m_PageWidth = m_BBox.top - m_BBox.bottom; 840 } else { 841 m_PageWidth = m_BBox.right - m_BBox.left; 842 m_PageHeight = m_BBox.top - m_BBox.bottom; 843 } 844 switch (rotate) { 845 case 0: 846 m_PageMatrix.Set(1.0f, 0, 0, 1.0f, -m_BBox.left, -m_BBox.bottom); 847 break; 848 case 1: 849 m_PageMatrix.Set(0, -1.0f, 1.0f, 0, -m_BBox.bottom, m_BBox.right); 850 break; 851 case 2: 852 m_PageMatrix.Set(-1.0f, 0, 0, -1.0f, m_BBox.right, m_BBox.top); 853 break; 854 case 3: 855 m_PageMatrix.Set(0, 1.0f, -1.0f, 0, m_BBox.top, -m_BBox.left); 856 break; 857 } 858 m_Transparency = PDFTRANS_ISOLATED; 859 LoadTransInfo(); 860 } 861 void CPDF_Page::StartParse(CPDF_ParseOptions* pOptions, FX_BOOL bReParse) { 862 if (bReParse) { 863 ClearCacheObjects(); 864 } 865 if (m_ParseState == CONTENT_PARSED || m_ParseState == CONTENT_PARSING) { 866 return; 867 } 868 m_pParser = new CPDF_ContentParser; 869 m_pParser->Start(this, pOptions); 870 m_ParseState = CONTENT_PARSING; 871 } 872 void CPDF_Page::ParseContent(CPDF_ParseOptions* pOptions, FX_BOOL bReParse) { 873 StartParse(pOptions, bReParse); 874 ContinueParse(NULL); 875 } 876 CPDF_Page::~CPDF_Page() { 877 if (m_pPageRender) { 878 IPDF_RenderModule* pModule = CPDF_ModuleMgr::Get()->GetRenderModule(); 879 pModule->DestroyPageCache(m_pPageRender); 880 } 881 } 882 CPDF_Object* FPDFAPI_GetPageAttr(CPDF_Dictionary* pPageDict, 883 const CFX_ByteStringC& name) { 884 int level = 0; 885 while (1) { 886 CPDF_Object* pObj = pPageDict->GetElementValue(name); 887 if (pObj) { 888 return pObj; 889 } 890 CPDF_Dictionary* pParent = pPageDict->GetDict("Parent"); 891 if (!pParent || pParent == pPageDict) { 892 return NULL; 893 } 894 pPageDict = pParent; 895 level++; 896 if (level == 1000) { 897 return NULL; 898 } 899 } 900 } 901 CPDF_Object* CPDF_Page::GetPageAttr(const CFX_ByteStringC& name) const { 902 return FPDFAPI_GetPageAttr(m_pFormDict, name); 903 } 904 CPDF_Form::CPDF_Form(CPDF_Document* pDoc, 905 CPDF_Dictionary* pPageResources, 906 CPDF_Stream* pFormStream, 907 CPDF_Dictionary* pParentResources) { 908 m_pDocument = pDoc; 909 m_pFormStream = pFormStream; 910 m_pFormDict = pFormStream ? pFormStream->GetDict() : NULL; 911 m_pResources = m_pFormDict->GetDict("Resources"); 912 m_pPageResources = pPageResources; 913 if (!m_pResources) { 914 m_pResources = pParentResources; 915 } 916 if (!m_pResources) { 917 m_pResources = pPageResources; 918 } 919 m_Transparency = 0; 920 LoadTransInfo(); 921 } 922 CPDF_Form::~CPDF_Form() {} 923 void CPDF_Form::StartParse(CPDF_AllStates* pGraphicStates, 924 CFX_Matrix* pParentMatrix, 925 CPDF_Type3Char* pType3Char, 926 CPDF_ParseOptions* pOptions, 927 int level) { 928 if (m_ParseState == CONTENT_PARSED || m_ParseState == CONTENT_PARSING) { 929 return; 930 } 931 m_pParser = new CPDF_ContentParser; 932 m_pParser->Start(this, pGraphicStates, pParentMatrix, pType3Char, pOptions, 933 level); 934 m_ParseState = CONTENT_PARSING; 935 } 936 void CPDF_Form::ParseContent(CPDF_AllStates* pGraphicStates, 937 CFX_Matrix* pParentMatrix, 938 CPDF_Type3Char* pType3Char, 939 CPDF_ParseOptions* pOptions, 940 int level) { 941 StartParse(pGraphicStates, pParentMatrix, pType3Char, pOptions, level); 942 ContinueParse(NULL); 943 } 944 CPDF_Form* CPDF_Form::Clone() const { 945 CPDF_Form* pClone = 946 new CPDF_Form(m_pDocument, m_pPageResources, m_pFormStream, m_pResources); 947 FX_POSITION pos = m_ObjectList.GetHeadPosition(); 948 while (pos) { 949 CPDF_PageObject* pObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos); 950 pClone->m_ObjectList.AddTail(pObj->Clone()); 951 } 952 return pClone; 953 } 954 void CPDF_Page::GetDisplayMatrix(CFX_Matrix& matrix, 955 int xPos, 956 int yPos, 957 int xSize, 958 int ySize, 959 int iRotate) const { 960 if (m_PageWidth == 0 || m_PageHeight == 0) { 961 return; 962 } 963 CFX_Matrix display_matrix; 964 int x0, y0, x1, y1, x2, y2; 965 iRotate %= 4; 966 switch (iRotate) { 967 case 0: 968 x0 = xPos; 969 y0 = yPos + ySize; 970 x1 = xPos; 971 y1 = yPos; 972 x2 = xPos + xSize; 973 y2 = yPos + ySize; 974 break; 975 case 1: 976 x0 = xPos; 977 y0 = yPos; 978 x1 = xPos + xSize; 979 y1 = yPos; 980 x2 = xPos; 981 y2 = yPos + ySize; 982 break; 983 case 2: 984 x0 = xPos + xSize; 985 y0 = yPos; 986 x1 = xPos + xSize; 987 y1 = yPos + ySize; 988 x2 = xPos; 989 y2 = yPos; 990 break; 991 case 3: 992 x0 = xPos + xSize; 993 y0 = yPos + ySize; 994 x1 = xPos; 995 y1 = yPos + ySize; 996 x2 = xPos + xSize; 997 y2 = yPos; 998 break; 999 } 1000 display_matrix.Set(FXSYS_Div((FX_FLOAT)(x2 - x0), m_PageWidth), 1001 FXSYS_Div((FX_FLOAT)(y2 - y0), m_PageWidth), 1002 FXSYS_Div((FX_FLOAT)(x1 - x0), m_PageHeight), 1003 FXSYS_Div((FX_FLOAT)(y1 - y0), m_PageHeight), (FX_FLOAT)x0, 1004 (FX_FLOAT)y0); 1005 matrix = m_PageMatrix; 1006 matrix.Concat(display_matrix); 1007 } 1008 CPDF_ParseOptions::CPDF_ParseOptions() { 1009 m_bTextOnly = FALSE; 1010 m_bMarkedContent = TRUE; 1011 m_bSeparateForm = TRUE; 1012 m_bDecodeInlineImage = FALSE; 1013 } 1014