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