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 "public/fpdfview.h" 8 9#include <memory> 10 11#include "core/include/fxcodec/fx_codec.h" 12#include "core/include/fxcrt/fx_safe_types.h" 13#include "fpdfsdk/include/fsdk_define.h" 14#include "fpdfsdk/include/fsdk_mgr.h" 15#include "fpdfsdk/include/fsdk_rendercontext.h" 16#include "fpdfsdk/include/javascript/IJavaScript.h" 17#include "public/fpdf_ext.h" 18#include "public/fpdf_progressive.h" 19#include "third_party/base/numerics/safe_conversions_impl.h" 20 21#ifdef PDF_ENABLE_XFA 22#include "core/include/fpdfapi/fpdf_module.h" 23#include "fpdfsdk/include/fpdfxfa/fpdfxfa_app.h" 24#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h" 25#include "fpdfsdk/include/fpdfxfa/fpdfxfa_page.h" 26#include "fpdfsdk/include/fpdfxfa/fpdfxfa_util.h" 27#include "public/fpdf_formfill.h" 28#endif // PDF_ENABLE_XFA 29 30UnderlyingDocumentType* UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc) { 31 return static_cast<UnderlyingDocumentType*>(doc); 32} 33 34FPDF_DOCUMENT FPDFDocumentFromUnderlying(UnderlyingDocumentType* doc) { 35 return static_cast<FPDF_DOCUMENT>(doc); 36} 37 38UnderlyingPageType* UnderlyingFromFPDFPage(FPDF_PAGE page) { 39 return static_cast<UnderlyingPageType*>(page); 40} 41 42CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) { 43#ifdef PDF_ENABLE_XFA 44 return doc ? UnderlyingFromFPDFDocument(doc)->GetPDFDoc() : nullptr; 45#else // PDF_ENABLE_XFA 46 return UnderlyingFromFPDFDocument(doc); 47#endif // PDF_ENABLE_XFA 48} 49 50FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) { 51#ifdef PDF_ENABLE_XFA 52 return doc ? FPDFDocumentFromUnderlying( 53 new CPDFXFA_Document(doc, CPDFXFA_App::GetInstance())) 54 : nullptr; 55#else // PDF_ENABLE_XFA 56 return FPDFDocumentFromUnderlying(doc); 57#endif // PDF_ENABLE_XFA 58} 59 60CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) { 61#ifdef PDF_ENABLE_XFA 62 return page ? UnderlyingFromFPDFPage(page)->GetPDFPage() : nullptr; 63#else // PDF_ENABLE_XFA 64 return UnderlyingFromFPDFPage(page); 65#endif // PDF_ENABLE_XFA 66} 67 68#ifdef PDF_ENABLE_XFA 69CFPDF_FileStream::CFPDF_FileStream(FPDF_FILEHANDLER* pFS) { 70 m_pFS = pFS; 71 m_nCurPos = 0; 72} 73 74IFX_FileStream* CFPDF_FileStream::Retain() { 75 return this; 76} 77 78void CFPDF_FileStream::Release() { 79 if (m_pFS && m_pFS->Release) 80 m_pFS->Release(m_pFS->clientData); 81 delete this; 82} 83 84FX_FILESIZE CFPDF_FileStream::GetSize() { 85 if (m_pFS && m_pFS->GetSize) 86 return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData); 87 return 0; 88} 89 90FX_BOOL CFPDF_FileStream::IsEOF() { 91 return m_nCurPos >= GetSize(); 92} 93 94FX_BOOL CFPDF_FileStream::ReadBlock(void* buffer, 95 FX_FILESIZE offset, 96 size_t size) { 97 if (!buffer || !size || !m_pFS->ReadBlock) 98 return FALSE; 99 100 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer, 101 (FPDF_DWORD)size) == 0) { 102 m_nCurPos = offset + size; 103 return TRUE; 104 } 105 return FALSE; 106} 107 108size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) { 109 if (!buffer || !size || !m_pFS->ReadBlock) 110 return 0; 111 112 FX_FILESIZE nSize = GetSize(); 113 if (m_nCurPos >= nSize) 114 return 0; 115 FX_FILESIZE dwAvail = nSize - m_nCurPos; 116 if (dwAvail < (FX_FILESIZE)size) 117 size = (size_t)dwAvail; 118 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer, 119 (FPDF_DWORD)size) == 0) { 120 m_nCurPos += size; 121 return size; 122 } 123 124 return 0; 125} 126 127FX_BOOL CFPDF_FileStream::WriteBlock(const void* buffer, 128 FX_FILESIZE offset, 129 size_t size) { 130 if (!m_pFS || !m_pFS->WriteBlock) 131 return FALSE; 132 133 if (m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer, 134 (FPDF_DWORD)size) == 0) { 135 m_nCurPos = offset + size; 136 return TRUE; 137 } 138 return FALSE; 139} 140 141FX_BOOL CFPDF_FileStream::Flush() { 142 if (!m_pFS || !m_pFS->Flush) 143 return TRUE; 144 145 return m_pFS->Flush(m_pFS->clientData) == 0; 146} 147#endif // PDF_ENABLE_XFA 148 149CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess) { 150 m_FileAccess = *pFileAccess; 151#ifdef PDF_ENABLE_XFA 152 m_BufferOffset = (FX_DWORD)-1; 153#endif // PDF_ENABLE_XFA 154} 155 156#ifdef PDF_ENABLE_XFA 157FX_BOOL CPDF_CustomAccess::GetByte(FX_DWORD pos, uint8_t& ch) { 158 if (pos >= m_FileAccess.m_FileLen) 159 return FALSE; 160 if (m_BufferOffset == (FX_DWORD)-1 || pos < m_BufferOffset || 161 pos >= m_BufferOffset + 512) { 162 // Need to read from file access 163 m_BufferOffset = pos; 164 int size = 512; 165 if (pos + 512 > m_FileAccess.m_FileLen) 166 size = m_FileAccess.m_FileLen - pos; 167 if (!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, m_BufferOffset, m_Buffer, 168 size)) 169 return FALSE; 170 } 171 ch = m_Buffer[pos - m_BufferOffset]; 172 return TRUE; 173} 174 175FX_BOOL CPDF_CustomAccess::GetBlock(FX_DWORD pos, 176 uint8_t* pBuf, 177 FX_DWORD size) { 178 if (pos + size > m_FileAccess.m_FileLen) 179 return FALSE; 180 return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, pos, pBuf, size); 181} 182#endif // PDF_ENABLE_XFA 183 184FX_BOOL CPDF_CustomAccess::ReadBlock(void* buffer, 185 FX_FILESIZE offset, 186 size_t size) { 187 if (offset < 0) { 188 return FALSE; 189 } 190 FX_SAFE_FILESIZE newPos = 191 pdfium::base::checked_cast<FX_FILESIZE, size_t>(size); 192 newPos += offset; 193 if (!newPos.IsValid() || newPos.ValueOrDie() > m_FileAccess.m_FileLen) { 194 return FALSE; 195 } 196 return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset, (uint8_t*)buffer, 197 size); 198} 199 200// 0 bit: FPDF_POLICY_MACHINETIME_ACCESS 201static FX_DWORD foxit_sandbox_policy = 0xFFFFFFFF; 202 203void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable) { 204 switch (policy) { 205 case FPDF_POLICY_MACHINETIME_ACCESS: { 206 if (enable) 207 foxit_sandbox_policy |= 0x01; 208 else 209 foxit_sandbox_policy &= 0xFFFFFFFE; 210 } break; 211 default: 212 break; 213 } 214} 215 216FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy) { 217 switch (policy) { 218 case FPDF_POLICY_MACHINETIME_ACCESS: 219 return !!(foxit_sandbox_policy & 0x01); 220 default: 221 return FALSE; 222 } 223} 224 225CCodec_ModuleMgr* g_pCodecModule = nullptr; 226 227DLLEXPORT void STDCALL FPDF_InitLibrary() { 228 FPDF_InitLibraryWithConfig(nullptr); 229} 230 231DLLEXPORT void STDCALL FPDF_InitLibraryWithConfig( 232 const FPDF_LIBRARY_CONFIG* cfg) { 233 g_pCodecModule = new CCodec_ModuleMgr(); 234 235 CFX_GEModule::Create(cfg ? cfg->m_pUserFontPaths : nullptr); 236 CFX_GEModule::Get()->SetCodecModule(g_pCodecModule); 237 238 CPDF_ModuleMgr::Create(); 239 CPDF_ModuleMgr* pModuleMgr = CPDF_ModuleMgr::Get(); 240 pModuleMgr->SetCodecModule(g_pCodecModule); 241 pModuleMgr->InitPageModule(); 242 pModuleMgr->InitRenderModule(); 243#ifdef PDF_ENABLE_XFA 244 CPDFXFA_App::GetInstance()->Initialize(); 245#else // PDF_ENABLE_XFA 246 pModuleMgr->LoadEmbeddedGB1CMaps(); 247 pModuleMgr->LoadEmbeddedJapan1CMaps(); 248 pModuleMgr->LoadEmbeddedCNS1CMaps(); 249 pModuleMgr->LoadEmbeddedKorea1CMaps(); 250#endif // PDF_ENABLE_XFA 251 if (cfg && cfg->version >= 2) 252 IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate); 253} 254 255DLLEXPORT void STDCALL FPDF_DestroyLibrary() { 256#ifdef PDF_ENABLE_XFA 257 CPDFXFA_App::ReleaseInstance(); 258#endif // PDF_ENABLE_XFA 259 CPDF_ModuleMgr::Destroy(); 260 CFX_GEModule::Destroy(); 261 262 delete g_pCodecModule; 263 g_pCodecModule = nullptr; 264} 265 266#ifndef _WIN32 267int g_LastError; 268void SetLastError(int err) { 269 g_LastError = err; 270} 271 272int GetLastError() { 273 return g_LastError; 274} 275#endif // _WIN32 276 277void ProcessParseError(FX_DWORD err_code) { 278 // Translate FPDFAPI error code to FPDFVIEW error code 279 switch (err_code) { 280 case PDFPARSE_ERROR_FILE: 281 err_code = FPDF_ERR_FILE; 282 break; 283 case PDFPARSE_ERROR_FORMAT: 284 err_code = FPDF_ERR_FORMAT; 285 break; 286 case PDFPARSE_ERROR_PASSWORD: 287 err_code = FPDF_ERR_PASSWORD; 288 break; 289 case PDFPARSE_ERROR_HANDLER: 290 err_code = FPDF_ERR_SECURITY; 291 break; 292 } 293 SetLastError(err_code); 294} 295 296DLLEXPORT void STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy, 297 FPDF_BOOL enable) { 298 return FSDK_SetSandBoxPolicy(policy, enable); 299} 300 301DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path, 302 FPDF_BYTESTRING password) { 303 // NOTE: the creation of the file needs to be by the embedder on the 304 // other side of this API. 305 IFX_FileRead* pFileAccess = FX_CreateFileRead((const FX_CHAR*)file_path); 306 if (!pFileAccess) { 307 return nullptr; 308 } 309 310 CPDF_Parser* pParser = new CPDF_Parser; 311 pParser->SetPassword(password); 312 313 FX_DWORD err_code = pParser->StartParse(pFileAccess); 314 if (err_code) { 315 delete pParser; 316 ProcessParseError(err_code); 317 return NULL; 318 } 319#ifdef PDF_ENABLE_XFA 320 CPDF_Document* pPDFDoc = pParser->GetDocument(); 321 if (!pPDFDoc) 322 return NULL; 323 324 CPDFXFA_App* pProvider = CPDFXFA_App::GetInstance(); 325 return new CPDFXFA_Document(pPDFDoc, pProvider); 326#else // PDF_ENABLE_XFA 327 return pParser->GetDocument(); 328#endif // PDF_ENABLE_XFA 329} 330 331#ifdef PDF_ENABLE_XFA 332DLLEXPORT FPDF_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document, 333 int* docType) { 334 if (!document) 335 return FALSE; 336 337 CPDF_Document* pdfDoc = 338 (static_cast<CPDFXFA_Document*>(document))->GetPDFDoc(); 339 if (!pdfDoc) 340 return FALSE; 341 342 CPDF_Dictionary* pRoot = pdfDoc->GetRoot(); 343 if (!pRoot) 344 return FALSE; 345 346 CPDF_Dictionary* pAcroForm = pRoot->GetDict("AcroForm"); 347 if (!pAcroForm) 348 return FALSE; 349 350 CPDF_Object* pXFA = pAcroForm->GetElement("XFA"); 351 if (!pXFA) 352 return FALSE; 353 354 FX_BOOL bDynamicXFA = pRoot->GetBoolean("NeedsRendering", FALSE); 355 356 if (bDynamicXFA) 357 *docType = DOCTYPE_DYNAMIC_XFA; 358 else 359 *docType = DOCTYPE_STATIC_XFA; 360 361 return TRUE; 362} 363 364DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document) { 365 return document && (static_cast<CPDFXFA_Document*>(document))->LoadXFADoc(); 366} 367#endif // PDF_ENABLE_XFA 368 369class CMemFile final : public IFX_FileRead { 370 public: 371 CMemFile(uint8_t* pBuf, FX_FILESIZE size) : m_pBuf(pBuf), m_size(size) {} 372 373 void Release() override { delete this; } 374 FX_FILESIZE GetSize() override { return m_size; } 375 FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override { 376 if (offset < 0) { 377 return FALSE; 378 } 379 FX_SAFE_FILESIZE newPos = 380 pdfium::base::checked_cast<FX_FILESIZE, size_t>(size); 381 newPos += offset; 382 if (!newPos.IsValid() || newPos.ValueOrDie() > (FX_DWORD)m_size) { 383 return FALSE; 384 } 385 FXSYS_memcpy(buffer, m_pBuf + offset, size); 386 return TRUE; 387 } 388 389 private: 390 ~CMemFile() override {} 391 392 uint8_t* const m_pBuf; 393 const FX_FILESIZE m_size; 394}; 395 396DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadMemDocument(const void* data_buf, 397 int size, 398 FPDF_BYTESTRING password) { 399 CPDF_Parser* pParser = new CPDF_Parser; 400 pParser->SetPassword(password); 401 CMemFile* pMemFile = new CMemFile((uint8_t*)data_buf, size); 402 FX_DWORD err_code = pParser->StartParse(pMemFile); 403 if (err_code) { 404 delete pParser; 405 ProcessParseError(err_code); 406 return NULL; 407 } 408 CPDF_Document* pDoc = NULL; 409 pDoc = pParser ? pParser->GetDocument() : NULL; 410 CheckUnSupportError(pDoc, err_code); 411 return FPDFDocumentFromCPDFDocument(pParser->GetDocument()); 412} 413 414DLLEXPORT FPDF_DOCUMENT STDCALL 415FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess, 416 FPDF_BYTESTRING password) { 417 CPDF_Parser* pParser = new CPDF_Parser; 418 pParser->SetPassword(password); 419 CPDF_CustomAccess* pFile = new CPDF_CustomAccess(pFileAccess); 420 FX_DWORD err_code = pParser->StartParse(pFile); 421 if (err_code) { 422 delete pParser; 423 ProcessParseError(err_code); 424 return NULL; 425 } 426 CPDF_Document* pDoc = NULL; 427 pDoc = pParser ? pParser->GetDocument() : NULL; 428 CheckUnSupportError(pDoc, err_code); 429 return FPDFDocumentFromCPDFDocument(pParser->GetDocument()); 430} 431 432DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc, 433 int* fileVersion) { 434 if (!fileVersion) 435 return FALSE; 436 437 *fileVersion = 0; 438 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc); 439 if (!pDoc) 440 return FALSE; 441 442 CPDF_Parser* pParser = pDoc->GetParser(); 443 if (!pParser) 444 return FALSE; 445 446 *fileVersion = pParser->GetFileVersion(); 447 return TRUE; 448} 449 450// jabdelmalek: changed return type from FX_DWORD to build on Linux (and match 451// header). 452DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document) { 453 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); 454 if (!pDoc) 455#ifndef PDF_ENABLE_XFA 456 return 0; 457#else // PDF_ENABLE_XFA 458 return (FX_DWORD)-1; 459#endif // PDF_ENABLE_XFA 460 461 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict(); 462 return pDict ? pDict->GetInteger("P") : (FX_DWORD)-1; 463} 464 465DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) { 466 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); 467 if (!pDoc) 468 return -1; 469 470 CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict(); 471 return pDict ? pDict->GetInteger("R") : -1; 472} 473 474DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document) { 475 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document); 476 return pDoc ? pDoc->GetPageCount() : 0; 477} 478 479DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document, 480 int page_index) { 481 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document); 482 if (!pDoc) 483 return nullptr; 484 485 if (page_index < 0 || page_index >= pDoc->GetPageCount()) 486 return nullptr; 487 488#ifdef PDF_ENABLE_XFA 489 return pDoc->GetPage(page_index); 490#else // PDF_ENABLE_XFA 491 CPDF_Dictionary* pDict = pDoc->GetPage(page_index); 492 if (!pDict) 493 return NULL; 494 CPDF_Page* pPage = new CPDF_Page; 495 pPage->Load(pDoc, pDict); 496 pPage->ParseContent(); 497 return pPage; 498#endif // PDF_ENABLE_XFA 499} 500 501DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page) { 502 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page); 503 return pPage ? pPage->GetPageWidth() : 0.0; 504} 505 506DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page) { 507 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page); 508 return pPage ? pPage->GetPageHeight() : 0.0; 509} 510 511void DropContext(void* data) { 512 delete (CRenderContext*)data; 513} 514 515#if defined(_DEBUG) || defined(DEBUG) 516#define DEBUG_TRACE 517#endif 518 519#if defined(_WIN32) 520DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc, 521 FPDF_PAGE page, 522 int start_x, 523 int start_y, 524 int size_x, 525 int size_y, 526 int rotate, 527 int flags) { 528 CPDF_Page* pPage = CPDFPageFromFPDFPage(page); 529 if (!pPage) 530 return; 531 532 CRenderContext* pContext = new CRenderContext; 533 pPage->SetPrivateData((void*)1, pContext, DropContext); 534 535#ifndef _WIN32_WCE 536 CFX_DIBitmap* pBitmap = nullptr; 537 FX_BOOL bBackgroundAlphaNeeded = pPage->BackgroundAlphaNeeded(); 538 FX_BOOL bHasImageMask = pPage->HasImageMask(); 539 if (bBackgroundAlphaNeeded || bHasImageMask) { 540 pBitmap = new CFX_DIBitmap; 541 pBitmap->Create(size_x, size_y, FXDIB_Argb); 542 pBitmap->Clear(0x00ffffff); 543#ifdef _SKIA_SUPPORT_ 544 pContext->m_pDevice = new CFX_SkiaDevice; 545 ((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap); 546#else 547 pContext->m_pDevice = new CFX_FxgeDevice; 548 ((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap); 549#endif 550 } else { 551 pContext->m_pDevice = new CFX_WindowsDevice(dc); 552 } 553 554 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y, 555 rotate, flags, TRUE, NULL); 556 557 if (bBackgroundAlphaNeeded || bHasImageMask) { 558 if (pBitmap) { 559 CFX_WindowsDevice WinDC(dc); 560 561 if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) { 562 CFX_DIBitmap* pDst = new CFX_DIBitmap; 563 int pitch = pBitmap->GetPitch(); 564 pDst->Create(size_x, size_y, FXDIB_Rgb32); 565 FXSYS_memset(pDst->GetBuffer(), -1, pitch * size_y); 566 pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0, 567 FXDIB_BLEND_NORMAL, NULL, FALSE, NULL); 568 WinDC.StretchDIBits(pDst, 0, 0, size_x, size_y); 569 delete pDst; 570 } else { 571 WinDC.SetDIBits(pBitmap, 0, 0); 572 } 573 } 574 } 575#else 576 // get clip region 577 RECT rect, cliprect; 578 rect.left = start_x; 579 rect.top = start_y; 580 rect.right = start_x + size_x; 581 rect.bottom = start_y + size_y; 582 GetClipBox(dc, &cliprect); 583 IntersectRect(&rect, &rect, &cliprect); 584 int width = rect.right - rect.left; 585 int height = rect.bottom - rect.top; 586 587#ifdef DEBUG_TRACE 588 { 589 char str[128]; 590 memset(str, 0, sizeof(str)); 591 FXSYS_snprintf(str, sizeof(str) - 1, "Rendering DIB %d x %d", width, 592 height); 593 CPDF_ModuleMgr::Get()->ReportError(999, str); 594 } 595#endif 596 597 // Create a DIB section 598 LPVOID pBuffer; 599 BITMAPINFOHEADER bmih; 600 FXSYS_memset(&bmih, 0, sizeof bmih); 601 bmih.biSize = sizeof bmih; 602 bmih.biBitCount = 24; 603 bmih.biHeight = -height; 604 bmih.biPlanes = 1; 605 bmih.biWidth = width; 606 pContext->m_hBitmap = CreateDIBSection(dc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, 607 &pBuffer, NULL, 0); 608 if (!pContext->m_hBitmap) { 609#if defined(DEBUG) || defined(_DEBUG) 610 char str[128]; 611 memset(str, 0, sizeof(str)); 612 FXSYS_snprintf(str, sizeof(str) - 1, 613 "Error CreateDIBSection: %d x %d, error code = %d", width, 614 height, GetLastError()); 615 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str); 616#else 617 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL); 618#endif 619 } 620 FXSYS_memset(pBuffer, 0xff, height * ((width * 3 + 3) / 4 * 4)); 621 622#ifdef DEBUG_TRACE 623 { CPDF_ModuleMgr::Get()->ReportError(999, "DIBSection created"); } 624#endif 625 626 // Create a device with this external buffer 627 pContext->m_pBitmap = new CFX_DIBitmap; 628 pContext->m_pBitmap->Create(width, height, FXDIB_Rgb, (uint8_t*)pBuffer); 629 pContext->m_pDevice = new CPDF_FxgeDevice; 630 ((CPDF_FxgeDevice*)pContext->m_pDevice)->Attach(pContext->m_pBitmap); 631 632#ifdef DEBUG_TRACE 633 CPDF_ModuleMgr::Get()->ReportError(999, "Ready for PDF rendering"); 634#endif 635 636 // output to bitmap device 637 FPDF_RenderPage_Retail(pContext, page, start_x - rect.left, 638 start_y - rect.top, size_x, size_y, rotate, flags); 639 640#ifdef DEBUG_TRACE 641 CPDF_ModuleMgr::Get()->ReportError(999, "Finished PDF rendering"); 642#endif 643 644 // Now output to real device 645 HDC hMemDC = CreateCompatibleDC(dc); 646 if (!hMemDC) { 647#if defined(DEBUG) || defined(_DEBUG) 648 char str[128]; 649 memset(str, 0, sizeof(str)); 650 FXSYS_snprintf(str, sizeof(str) - 1, 651 "Error CreateCompatibleDC. Error code = %d", GetLastError()); 652 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str); 653#else 654 CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL); 655#endif 656 } 657 658 HGDIOBJ hOldBitmap = SelectObject(hMemDC, pContext->m_hBitmap); 659 660#ifdef DEBUG_TRACE 661 CPDF_ModuleMgr::Get()->ReportError(999, "Ready for screen rendering"); 662#endif 663 664 BitBlt(dc, rect.left, rect.top, width, height, hMemDC, 0, 0, SRCCOPY); 665 SelectObject(hMemDC, hOldBitmap); 666 DeleteDC(hMemDC); 667 668#ifdef DEBUG_TRACE 669 CPDF_ModuleMgr::Get()->ReportError(999, "Finished screen rendering"); 670#endif 671 672#endif 673 if (bBackgroundAlphaNeeded || bHasImageMask) 674 delete pBitmap; 675 676 delete pContext; 677 pPage->RemovePrivateData((void*)1); 678} 679#endif 680 681DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap, 682 FPDF_PAGE page, 683 int start_x, 684 int start_y, 685 int size_x, 686 int size_y, 687 int rotate, 688 int flags) { 689 if (!bitmap) 690 return; 691 CPDF_Page* pPage = CPDFPageFromFPDFPage(page); 692 if (!pPage) 693 return; 694 CRenderContext* pContext = new CRenderContext; 695 pPage->SetPrivateData((void*)1, pContext, DropContext); 696#ifdef _SKIA_SUPPORT_ 697 pContext->m_pDevice = new CFX_SkiaDevice; 698 699 if (flags & FPDF_REVERSE_BYTE_ORDER) 700 ((CFX_SkiaDevice*)pContext->m_pDevice) 701 ->Attach((CFX_DIBitmap*)bitmap, 0, TRUE); 702 else 703 ((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap); 704#else 705 pContext->m_pDevice = new CFX_FxgeDevice; 706 707 if (flags & FPDF_REVERSE_BYTE_ORDER) 708 ((CFX_FxgeDevice*)pContext->m_pDevice) 709 ->Attach((CFX_DIBitmap*)bitmap, 0, TRUE); 710 else 711 ((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap); 712#endif 713 714 FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y, 715 rotate, flags, TRUE, NULL); 716 717 delete pContext; 718 pPage->RemovePrivateData((void*)1); 719} 720 721DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) { 722 if (!page) 723 return; 724#ifdef PDF_ENABLE_XFA 725 CPDFXFA_Page* pPage = (CPDFXFA_Page*)page; 726 pPage->Release(); 727#else // PDF_ENABLE_XFA 728 CPDFSDK_PageView* pPageView = 729 (CPDFSDK_PageView*)(((CPDF_Page*)page))->GetPrivateData((void*)page); 730 if (pPageView && pPageView->IsLocked()) { 731 pPageView->TakeOverPage(); 732 return; 733 } 734 delete (CPDF_Page*)page; 735#endif // PDF_ENABLE_XFA 736} 737 738DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document) { 739#ifdef PDF_ENABLE_XFA 740 delete UnderlyingFromFPDFDocument(document); 741#else // PDF_ENABLE_XFA 742 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); 743 if (!pDoc) 744 return; 745 CPDF_Parser* pParser = pDoc->GetParser(); 746 if (!pParser) { 747 delete pDoc; 748 return; 749 } 750 delete pParser; 751#endif // PDF_ENABLE_XFA 752} 753 754DLLEXPORT unsigned long STDCALL FPDF_GetLastError() { 755 return GetLastError(); 756} 757 758DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page, 759 int start_x, 760 int start_y, 761 int size_x, 762 int size_y, 763 int rotate, 764 int device_x, 765 int device_y, 766 double* page_x, 767 double* page_y) { 768 if (!page || !page_x || !page_y) 769 return; 770 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page); 771#ifdef PDF_ENABLE_XFA 772 pPage->DeviceToPage(start_x, start_y, size_x, size_y, rotate, device_x, 773 device_y, page_x, page_y); 774#else // PDF_ENABLE_XFA 775 CFX_Matrix page2device; 776 pPage->GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y, 777 rotate); 778 CFX_Matrix device2page; 779 device2page.SetReverse(page2device); 780 FX_FLOAT page_x_f, page_y_f; 781 device2page.Transform((FX_FLOAT)(device_x), (FX_FLOAT)(device_y), page_x_f, 782 page_y_f); 783 *page_x = (page_x_f); 784 *page_y = (page_y_f); 785#endif // PDF_ENABLE_XFA 786} 787 788DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page, 789 int start_x, 790 int start_y, 791 int size_x, 792 int size_y, 793 int rotate, 794 double page_x, 795 double page_y, 796 int* device_x, 797 int* device_y) { 798 if (!device_x || !device_y) 799 return; 800 UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page); 801 if (!pPage) 802 return; 803#ifdef PDF_ENABLE_XFA 804 pPage->PageToDevice(start_x, start_y, size_x, size_y, rotate, page_x, page_y, 805 device_x, device_y); 806#else // PDF_ENABLE_XFA 807 CFX_Matrix page2device; 808 pPage->GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y, 809 rotate); 810 FX_FLOAT device_x_f, device_y_f; 811 page2device.Transform(((FX_FLOAT)page_x), ((FX_FLOAT)page_y), device_x_f, 812 device_y_f); 813 *device_x = FXSYS_round(device_x_f); 814 *device_y = FXSYS_round(device_y_f); 815#endif // PDF_ENABLE_XFA 816} 817 818DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width, 819 int height, 820 int alpha) { 821 std::unique_ptr<CFX_DIBitmap> pBitmap(new CFX_DIBitmap); 822 if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32)) { 823 return NULL; 824 } 825 return pBitmap.release(); 826} 827 828DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width, 829 int height, 830 int format, 831 void* first_scan, 832 int stride) { 833 FXDIB_Format fx_format; 834 switch (format) { 835 case FPDFBitmap_Gray: 836 fx_format = FXDIB_8bppRgb; 837 break; 838 case FPDFBitmap_BGR: 839 fx_format = FXDIB_Rgb; 840 break; 841 case FPDFBitmap_BGRx: 842 fx_format = FXDIB_Rgb32; 843 break; 844 case FPDFBitmap_BGRA: 845 fx_format = FXDIB_Argb; 846 break; 847 default: 848 return NULL; 849 } 850 CFX_DIBitmap* pBitmap = new CFX_DIBitmap; 851 pBitmap->Create(width, height, fx_format, (uint8_t*)first_scan, stride); 852 return pBitmap; 853} 854 855DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap, 856 int left, 857 int top, 858 int width, 859 int height, 860 FPDF_DWORD color) { 861 if (!bitmap) 862 return; 863#ifdef _SKIA_SUPPORT_ 864 CFX_SkiaDevice device; 865#else 866 CFX_FxgeDevice device; 867#endif 868 device.Attach((CFX_DIBitmap*)bitmap); 869 if (!((CFX_DIBitmap*)bitmap)->HasAlpha()) 870 color |= 0xFF000000; 871 FX_RECT rect(left, top, left + width, top + height); 872 device.FillRect(&rect, color); 873} 874 875DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) { 876 return bitmap ? ((CFX_DIBitmap*)bitmap)->GetBuffer() : nullptr; 877} 878 879DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) { 880 return bitmap ? ((CFX_DIBitmap*)bitmap)->GetWidth() : 0; 881} 882 883DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) { 884 return bitmap ? ((CFX_DIBitmap*)bitmap)->GetHeight() : 0; 885} 886 887DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap) { 888 return bitmap ? ((CFX_DIBitmap*)bitmap)->GetPitch() : 0; 889} 890 891DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap) { 892 delete (CFX_DIBitmap*)bitmap; 893} 894 895void FPDF_RenderPage_Retail(CRenderContext* pContext, 896 FPDF_PAGE page, 897 int start_x, 898 int start_y, 899 int size_x, 900 int size_y, 901 int rotate, 902 int flags, 903 FX_BOOL bNeedToRestore, 904 IFSDK_PAUSE_Adapter* pause) { 905 CPDF_Page* pPage = CPDFPageFromFPDFPage(page); 906 if (!pPage) 907 return; 908 909 if (!pContext->m_pOptions) 910 pContext->m_pOptions = new CPDF_RenderOptions; 911 912 if (flags & FPDF_LCD_TEXT) 913 pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE; 914 else 915 pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE; 916 if (flags & FPDF_NO_NATIVETEXT) 917 pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT; 918 if (flags & FPDF_RENDER_LIMITEDIMAGECACHE) 919 pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE; 920 if (flags & FPDF_RENDER_FORCEHALFTONE) 921 pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE; 922#ifndef PDF_ENABLE_XFA 923 if (flags & FPDF_RENDER_NO_SMOOTHTEXT) 924 pContext->m_pOptions->m_Flags |= RENDER_NOTEXTSMOOTH; 925 if (flags & FPDF_RENDER_NO_SMOOTHIMAGE) 926 pContext->m_pOptions->m_Flags |= RENDER_NOIMAGESMOOTH; 927 if (flags & FPDF_RENDER_NO_SMOOTHPATH) 928 pContext->m_pOptions->m_Flags |= RENDER_NOPATHSMOOTH; 929#endif // PDF_ENABLE_XFA 930 // Grayscale output 931 if (flags & FPDF_GRAYSCALE) { 932 pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY; 933 pContext->m_pOptions->m_ForeColor = 0; 934 pContext->m_pOptions->m_BackColor = 0xffffff; 935 } 936 const CPDF_OCContext::UsageType usage = 937 (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View; 938 pContext->m_pOptions->m_AddFlags = flags >> 8; 939 pContext->m_pOptions->m_pOCContext = 940 new CPDF_OCContext(pPage->m_pDocument, usage); 941 942 CFX_Matrix matrix; 943 pPage->GetDisplayMatrix(matrix, start_x, start_y, size_x, size_y, rotate); 944 945 FX_RECT clip; 946 clip.left = start_x; 947 clip.right = start_x + size_x; 948 clip.top = start_y; 949 clip.bottom = start_y + size_y; 950 pContext->m_pDevice->SaveState(); 951 pContext->m_pDevice->SetClip_Rect(&clip); 952 953 pContext->m_pContext = new CPDF_RenderContext(pPage); 954 pContext->m_pContext->AppendObjectList(pPage, &matrix); 955 956 if (flags & FPDF_ANNOT) { 957 pContext->m_pAnnots = new CPDF_AnnotList(pPage); 958 FX_BOOL bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY; 959 pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext, bPrinting, 960 &matrix, TRUE, NULL); 961 } 962 963 pContext->m_pRenderer = new CPDF_ProgressiveRenderer( 964 pContext->m_pContext, pContext->m_pDevice, pContext->m_pOptions); 965 pContext->m_pRenderer->Start(pause); 966 if (bNeedToRestore) 967 pContext->m_pDevice->RestoreState(); 968} 969 970DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document, 971 int page_index, 972 double* width, 973 double* height) { 974 UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document); 975 if (!pDoc) 976 return FALSE; 977 978#ifdef PDF_ENABLE_XFA 979 int count = pDoc->GetPageCount(); 980 if (page_index < 0 || page_index >= count) 981 return FALSE; 982 CPDFXFA_Page* pPage = pDoc->GetPage(page_index); 983 if (!pPage) 984 return FALSE; 985 *width = pPage->GetPageWidth(); 986 *height = pPage->GetPageHeight(); 987#else // PDF_ENABLE_XFA 988 CPDF_Dictionary* pDict = pDoc->GetPage(page_index); 989 if (!pDict) 990 return FALSE; 991 CPDF_Page page; 992 page.Load(pDoc, pDict); 993 *width = page.GetPageWidth(); 994 *height = page.GetPageHeight(); 995#endif // PDF_ENABLE_XFA 996 997 return TRUE; 998} 999 1000DLLEXPORT FPDF_BOOL STDCALL 1001FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) { 1002 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); 1003 if (!pDoc) 1004 return TRUE; 1005 CPDF_ViewerPreferences viewRef(pDoc); 1006 return viewRef.PrintScaling(); 1007} 1008 1009DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) { 1010 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); 1011 if (!pDoc) 1012 return 1; 1013 CPDF_ViewerPreferences viewRef(pDoc); 1014 return viewRef.NumCopies(); 1015} 1016 1017DLLEXPORT FPDF_PAGERANGE STDCALL 1018FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) { 1019 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); 1020 if (!pDoc) 1021 return NULL; 1022 CPDF_ViewerPreferences viewRef(pDoc); 1023 return viewRef.PrintPageRange(); 1024} 1025 1026DLLEXPORT FPDF_DUPLEXTYPE STDCALL 1027FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) { 1028 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); 1029 if (!pDoc) 1030 return DuplexUndefined; 1031 CPDF_ViewerPreferences viewRef(pDoc); 1032 CFX_ByteString duplex = viewRef.Duplex(); 1033 if ("Simplex" == duplex) 1034 return Simplex; 1035 if ("DuplexFlipShortEdge" == duplex) 1036 return DuplexFlipShortEdge; 1037 if ("DuplexFlipLongEdge" == duplex) 1038 return DuplexFlipLongEdge; 1039 return DuplexUndefined; 1040} 1041 1042DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document) { 1043 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); 1044 if (!pDoc) 1045 return 0; 1046 1047 CPDF_Dictionary* pRoot = pDoc->GetRoot(); 1048 if (!pRoot) 1049 return 0; 1050 1051 CPDF_NameTree nameTree(pDoc, "Dests"); 1052 pdfium::base::CheckedNumeric<FPDF_DWORD> count = nameTree.GetCount(); 1053 CPDF_Dictionary* pDest = pRoot->GetDict("Dests"); 1054 if (pDest) 1055 count += pDest->GetCount(); 1056 1057 if (!count.IsValid()) 1058 return 0; 1059 1060 return count.ValueOrDie(); 1061} 1062 1063DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document, 1064 FPDF_BYTESTRING name) { 1065 if (!name || name[0] == 0) 1066 return nullptr; 1067 1068 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); 1069 if (!pDoc) 1070 return nullptr; 1071 1072 CPDF_NameTree name_tree(pDoc, "Dests"); 1073 return name_tree.LookupNamedDest(pDoc, name); 1074} 1075 1076#ifdef PDF_ENABLE_XFA 1077FPDF_RESULT FPDF_BStr_Init(FPDF_BSTR* str) { 1078 if (!str) 1079 return -1; 1080 1081 FXSYS_memset(str, 0, sizeof(FPDF_BSTR)); 1082 return 0; 1083} 1084 1085FPDF_RESULT FPDF_BStr_Set(FPDF_BSTR* str, FPDF_LPCSTR bstr, int length) { 1086 if (!str) 1087 return -1; 1088 if (!bstr || !length) 1089 return -1; 1090 if (length == -1) 1091 length = FXSYS_strlen(bstr); 1092 1093 if (length == 0) { 1094 if (str->str) { 1095 FX_Free(str->str); 1096 str->str = NULL; 1097 } 1098 str->len = 0; 1099 return 0; 1100 } 1101 1102 if (str->str && str->len < length) 1103 str->str = FX_Realloc(char, str->str, length + 1); 1104 else if (!str->str) 1105 str->str = FX_Alloc(char, length + 1); 1106 1107 str->str[length] = 0; 1108 if (str->str == NULL) 1109 return -1; 1110 1111 FXSYS_memcpy(str->str, bstr, length); 1112 str->len = length; 1113 1114 return 0; 1115} 1116 1117FPDF_RESULT FPDF_BStr_Clear(FPDF_BSTR* str) { 1118 if (!str) 1119 return -1; 1120 1121 if (str->str) { 1122 FX_Free(str->str); 1123 str->str = NULL; 1124 } 1125 str->len = 0; 1126 return 0; 1127} 1128#endif // PDF_ENABLE_XFA 1129 1130DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document, 1131 int index, 1132 void* buffer, 1133 long* buflen) { 1134 if (!buffer) 1135 *buflen = 0; 1136 1137 if (index < 0) 1138 return nullptr; 1139 1140 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); 1141 if (!pDoc) 1142 return nullptr; 1143 1144 CPDF_Dictionary* pRoot = pDoc->GetRoot(); 1145 if (!pRoot) 1146 return nullptr; 1147 1148 CPDF_Object* pDestObj = nullptr; 1149 CFX_ByteString bsName; 1150 CPDF_NameTree nameTree(pDoc, "Dests"); 1151 int count = nameTree.GetCount(); 1152 if (index >= count) { 1153 CPDF_Dictionary* pDest = pRoot->GetDict("Dests"); 1154 if (!pDest) 1155 return nullptr; 1156 1157 pdfium::base::CheckedNumeric<int> checked_count = count; 1158 checked_count += pDest->GetCount(); 1159 if (!checked_count.IsValid() || index >= checked_count.ValueOrDie()) 1160 return nullptr; 1161 1162 index -= count; 1163 int i = 0; 1164 for (const auto& it : *pDest) { 1165 bsName = it.first; 1166 pDestObj = it.second; 1167 if (!pDestObj) 1168 continue; 1169 if (i == index) 1170 break; 1171 i++; 1172 } 1173 } else { 1174 pDestObj = nameTree.LookupValue(index, bsName); 1175 } 1176 if (!pDestObj) 1177 return nullptr; 1178 if (CPDF_Dictionary* pDict = pDestObj->AsDictionary()) { 1179 pDestObj = pDict->GetArray("D"); 1180 if (!pDestObj) 1181 return nullptr; 1182 } 1183 if (!pDestObj->IsArray()) 1184 return nullptr; 1185 1186 CFX_WideString wsName = PDF_DecodeText(bsName); 1187 CFX_ByteString utf16Name = wsName.UTF16LE_Encode(); 1188 unsigned int len = utf16Name.GetLength(); 1189 if (!buffer) { 1190 *buflen = len; 1191 } else if (*buflen >= len) { 1192 memcpy(buffer, utf16Name.c_str(), len); 1193 *buflen = len; 1194 } else { 1195 *buflen = -1; 1196 } 1197 return (FPDF_DEST)pDestObj; 1198} 1199