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