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_render.h" 8 #include "../../../include/fpdfapi/fpdf_module.h" 9 #include "../fpdf_page/pageint.h" 10 #include "../../../include/fxge/fx_ge.h" 11 #include "../../../include/fxcodec/fx_codec.h" 12 #include "render_int.h" 13 CPDF_DocRenderData::CPDF_DocRenderData(CPDF_Document* pPDFDoc) 14 : m_pPDFDoc(pPDFDoc) 15 , m_pFontCache(NULL) 16 { 17 } 18 CPDF_DocRenderData::~CPDF_DocRenderData() 19 { 20 Clear(TRUE); 21 } 22 void CPDF_DocRenderData::Clear(FX_BOOL bRelease) 23 { 24 FX_POSITION pos; 25 { 26 pos = m_Type3FaceMap.GetStartPosition(); 27 while (pos) { 28 CPDF_Font* pFont; 29 CPDF_CountedObject<CPDF_Type3Cache*>* cache; 30 m_Type3FaceMap.GetNextAssoc(pos, pFont, cache); 31 if (bRelease || cache->m_nCount < 2) { 32 delete cache->m_Obj; 33 delete cache; 34 m_Type3FaceMap.RemoveKey(pFont); 35 } 36 } 37 } 38 #ifndef _FPDFAPI_MINI_ 39 { 40 pos = m_TransferFuncMap.GetStartPosition(); 41 while (pos) { 42 CPDF_Object* key; 43 CPDF_CountedObject<CPDF_TransferFunc*>* value; 44 m_TransferFuncMap.GetNextAssoc(pos, key, value); 45 if (bRelease || value->m_nCount < 2) { 46 delete value->m_Obj; 47 delete value; 48 m_TransferFuncMap.RemoveKey(key); 49 } 50 } 51 } 52 #endif 53 if (m_pFontCache) { 54 if (bRelease) { 55 delete m_pFontCache; 56 m_pFontCache = NULL; 57 } else { 58 m_pFontCache->FreeCache(FALSE); 59 } 60 } 61 } 62 FX_BOOL CPDF_DocRenderData::Initialize() 63 { 64 m_pFontCache = FX_NEW CFX_FontCache; 65 return TRUE; 66 } 67 CPDF_Type3Cache* CPDF_DocRenderData::GetCachedType3(CPDF_Type3Font* pFont) 68 { 69 CPDF_CountedObject<CPDF_Type3Cache*>* pCache; 70 if (!m_Type3FaceMap.Lookup(pFont, pCache)) { 71 CPDF_Type3Cache* pType3 = FX_NEW CPDF_Type3Cache(pFont); 72 pCache = FX_NEW CPDF_CountedObject<CPDF_Type3Cache*>; 73 pCache->m_Obj = pType3; 74 pCache->m_nCount = 1; 75 m_Type3FaceMap.SetAt(pFont, pCache); 76 } 77 pCache->m_nCount++; 78 return pCache->m_Obj; 79 } 80 void CPDF_DocRenderData::ReleaseCachedType3(CPDF_Type3Font* pFont) 81 { 82 CPDF_CountedObject<CPDF_Type3Cache*>* pCache; 83 if (!m_Type3FaceMap.Lookup(pFont, pCache)) { 84 return; 85 } 86 pCache->m_nCount--; 87 } 88 class CPDF_RenderModule : public CPDF_RenderModuleDef 89 { 90 public: 91 virtual ~CPDF_RenderModule() {} 92 virtual FX_BOOL Installed() 93 { 94 return TRUE; 95 } 96 virtual CPDF_DocRenderData* CreateDocData(CPDF_Document* pDoc); 97 virtual void DestroyDocData(CPDF_DocRenderData* p); 98 virtual void ClearDocData(CPDF_DocRenderData* p); 99 virtual CPDF_DocRenderData* GetRenderData() 100 { 101 return &m_RenderData; 102 } 103 virtual CPDF_PageRenderCache* CreatePageCache(CPDF_Page* pPage) 104 { 105 return FX_NEW CPDF_PageRenderCache(pPage); 106 } 107 virtual void DestroyPageCache(CPDF_PageRenderCache* pCache); 108 virtual CPDF_RenderConfig* GetConfig() 109 { 110 return &m_RenderConfig; 111 } 112 private: 113 CPDF_DocRenderData m_RenderData; 114 CPDF_RenderConfig m_RenderConfig; 115 }; 116 CPDF_DocRenderData* CPDF_RenderModule::CreateDocData(CPDF_Document* pDoc) 117 { 118 CPDF_DocRenderData* pData = FX_NEW CPDF_DocRenderData(pDoc); 119 pData->Initialize(); 120 return pData; 121 } 122 void CPDF_RenderModule::DestroyDocData(CPDF_DocRenderData* pDocData) 123 { 124 delete pDocData; 125 } 126 void CPDF_RenderModule::ClearDocData(CPDF_DocRenderData* p) 127 { 128 if (p) { 129 p->Clear(FALSE); 130 } 131 } 132 void CPDF_RenderModule::DestroyPageCache(CPDF_PageRenderCache* pCache) 133 { 134 delete pCache; 135 } 136 void CPDF_ModuleMgr::InitRenderModule() 137 { 138 if (m_pRenderModule) { 139 delete m_pRenderModule; 140 } 141 m_pRenderModule = FX_NEW CPDF_RenderModule; 142 } 143 CPDF_RenderOptions::CPDF_RenderOptions() 144 : m_ColorMode(RENDER_COLOR_NORMAL) 145 , m_Flags(RENDER_CLEARTYPE) 146 , m_Interpolation(0) 147 , m_AddFlags(0) 148 , m_pOCContext(NULL) 149 , m_dwLimitCacheSize(1024 * 1024 * 100) 150 , m_HalftoneLimit(-1) 151 { 152 #if defined(_FPDFAPI_MINI_) 153 m_Flags |= RENDER_LIMITEDIMAGECACHE; 154 #endif 155 } 156 FX_ARGB CPDF_RenderOptions::TranslateColor(FX_ARGB argb) const 157 { 158 if (m_ColorMode == RENDER_COLOR_NORMAL) { 159 return argb; 160 } 161 if (m_ColorMode == RENDER_COLOR_ALPHA) { 162 return argb; 163 } 164 int a, r, g, b; 165 ArgbDecode(argb, a, r, g, b); 166 int gray = FXRGB2GRAY(r, g, b); 167 if (m_ColorMode == RENDER_COLOR_TWOCOLOR) { 168 int color = (r - gray) * (r - gray) + (g - gray) * (g - gray) + (b - gray) * (b - gray); 169 if (gray < 35 && color < 20) { 170 return ArgbEncode(a, m_ForeColor); 171 } 172 if (gray > 221 && color < 20) { 173 return ArgbEncode(a, m_BackColor); 174 } 175 return argb; 176 } 177 int fr = FXSYS_GetRValue(m_ForeColor); 178 int fg = FXSYS_GetGValue(m_ForeColor); 179 int fb = FXSYS_GetBValue(m_ForeColor); 180 int br = FXSYS_GetRValue(m_BackColor); 181 int bg = FXSYS_GetGValue(m_BackColor); 182 int bb = FXSYS_GetBValue(m_BackColor); 183 r = (br - fr) * gray / 255 + fr; 184 g = (bg - fg) * gray / 255 + fg; 185 b = (bb - fb) * gray / 255 + fb; 186 return ArgbEncode(a, r, g, b); 187 } 188 CPDF_RenderStatus::CPDF_RenderStatus() 189 { 190 m_pContext = NULL; 191 m_bStopped = FALSE; 192 m_Level = 0; 193 m_pDevice = NULL; 194 m_pCurObj = NULL; 195 m_pStopObj = NULL; 196 m_HalftoneLimit = 0; 197 m_pObjectRenderer = NULL; 198 m_bPrint = FALSE; 199 m_Transparency = 0; 200 m_DitherBits = 0; 201 m_bDropObjects = FALSE; 202 m_bStdCS = FALSE; 203 m_GroupFamily = 0; 204 m_bLoadMask = FALSE; 205 m_pType3Char = NULL; 206 m_T3FillColor = 0; 207 m_pFormResource = NULL; 208 m_pPageResource = NULL; 209 m_curBlend = FXDIB_BLEND_NORMAL; 210 } 211 CPDF_RenderStatus::~CPDF_RenderStatus() 212 { 213 if (m_pObjectRenderer) { 214 delete m_pObjectRenderer; 215 } 216 } 217 FX_BOOL CPDF_RenderStatus::Initialize(int level, CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, 218 const CFX_AffineMatrix* pDeviceMatrix, const CPDF_PageObject* pStopObj, 219 const CPDF_RenderStatus* pParentState, const CPDF_GraphicStates* pInitialStates, 220 const CPDF_RenderOptions* pOptions, int transparency, FX_BOOL bDropObjects, 221 CPDF_Dictionary* pFormResource, FX_BOOL bStdCS, CPDF_Type3Char* pType3Char, 222 FX_ARGB fill_color, FX_DWORD GroupFamily, 223 FX_BOOL bLoadMask) 224 { 225 m_Level = level; 226 m_pContext = pContext; 227 m_pDevice = pDevice; 228 m_DitherBits = pDevice->GetDeviceCaps(FXDC_DITHER_BITS); 229 m_bPrint = m_pDevice->GetDeviceClass() != FXDC_DISPLAY; 230 if (pDeviceMatrix) { 231 m_DeviceMatrix = *pDeviceMatrix; 232 } 233 m_pStopObj = pStopObj; 234 if (pOptions) { 235 m_Options = *pOptions; 236 } 237 m_bDropObjects = bDropObjects; 238 m_bStdCS = bStdCS; 239 m_T3FillColor = fill_color; 240 m_pType3Char = pType3Char; 241 m_GroupFamily = GroupFamily; 242 m_bLoadMask = bLoadMask; 243 m_pFormResource = pFormResource; 244 m_pPageResource = m_pContext->m_pPageResources; 245 if (pInitialStates && !m_pType3Char) { 246 m_InitialStates.CopyStates(*pInitialStates); 247 if (pParentState) { 248 CPDF_ColorStateData* pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)m_InitialStates.m_ColorState; 249 CPDF_ColorStateData* pParentData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)pParentState->m_InitialStates.m_ColorState; 250 if (!pColorData || pColorData->m_FillColor.IsNull()) { 251 CPDF_ColorStateData* pData = m_InitialStates.m_ColorState.GetModify(); 252 pData->m_FillRGB = pParentData->m_FillRGB; 253 pData->m_FillColor.Copy(&pParentData->m_FillColor); 254 } 255 if (!pColorData || pColorData->m_StrokeColor.IsNull()) { 256 CPDF_ColorStateData* pData = m_InitialStates.m_ColorState.GetModify(); 257 pData->m_StrokeRGB = pParentData->m_FillRGB; 258 pData->m_StrokeColor.Copy(&pParentData->m_StrokeColor); 259 } 260 } 261 } else { 262 m_InitialStates.DefaultStates(); 263 } 264 #if defined(_FPDFAPI_MINI_)||defined(_FXCORE_LIMITED_CPU_) 265 m_HalftoneLimit = CPDF_ModuleMgr::Get()->GetRenderModule()->GetConfig()->m_HalftoneLimit; 266 if (pOptions && pOptions->m_HalftoneLimit >= 0) { 267 m_HalftoneLimit = pOptions->m_HalftoneLimit; 268 } 269 #endif 270 m_pObjectRenderer = NULL; 271 m_Transparency = transparency; 272 return TRUE; 273 } 274 void CPDF_RenderStatus::RenderObjectList(const CPDF_PageObjects* pObjs, const CFX_AffineMatrix* pObj2Device) 275 { 276 if (m_Level > 32) { 277 return; 278 } 279 CFX_FloatRect clip_rect = m_pDevice->GetClipBox(); 280 CFX_AffineMatrix device2object; 281 device2object.SetReverse(*pObj2Device); 282 device2object.TransformRect(clip_rect); 283 int index = 0; 284 FX_POSITION pos = pObjs->GetFirstObjectPosition(); 285 while(pos) { 286 index ++; 287 CPDF_PageObject* pCurObj = pObjs->GetNextObject(pos); 288 if (pCurObj == m_pStopObj) { 289 m_bStopped = TRUE; 290 return; 291 } 292 if (!pCurObj) { 293 continue; 294 } 295 if(pCurObj == NULL || pCurObj->m_Left > clip_rect.right || pCurObj->m_Right < clip_rect.left || 296 pCurObj->m_Bottom > clip_rect.top || pCurObj->m_Top < clip_rect.bottom) { 297 continue; 298 } 299 RenderSingleObject(pCurObj, pObj2Device); 300 if (m_bStopped) { 301 return; 302 } 303 } 304 } 305 void CPDF_RenderStatus::RenderSingleObject(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device) 306 { 307 if (m_Level > 32) { 308 return; 309 } 310 m_pCurObj = pObj; 311 if (m_Options.m_pOCContext && pObj->m_ContentMark.NotNull()) 312 if (!m_Options.m_pOCContext->CheckObjectVisible(pObj)) { 313 return; 314 } 315 ProcessClipPath(pObj->m_ClipPath, pObj2Device); 316 if (ProcessTransparency(pObj, pObj2Device)) { 317 return; 318 } 319 ProcessObjectNoClip(pObj, pObj2Device); 320 } 321 FX_BOOL CPDF_RenderStatus::ContinueSingleObject(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, IFX_Pause* pPause) 322 { 323 if (m_pObjectRenderer) { 324 if (m_pObjectRenderer->Continue(pPause)) { 325 return TRUE; 326 } 327 if (!m_pObjectRenderer->m_Result) { 328 DrawObjWithBackground(pObj, pObj2Device); 329 } 330 #ifdef _FPDFAPI_MINI_ 331 if (m_DitherBits) { 332 DitherObjectArea(pObj, pObj2Device); 333 } 334 #endif 335 delete m_pObjectRenderer; 336 m_pObjectRenderer = NULL; 337 return FALSE; 338 } 339 m_pCurObj = pObj; 340 if (m_Options.m_pOCContext && pObj->m_ContentMark.NotNull()) 341 if (!m_Options.m_pOCContext->CheckObjectVisible(pObj)) { 342 return FALSE; 343 } 344 ProcessClipPath(pObj->m_ClipPath, pObj2Device); 345 if (ProcessTransparency(pObj, pObj2Device)) { 346 return FALSE; 347 } 348 if (pObj->m_Type == PDFPAGE_IMAGE) { 349 m_pObjectRenderer = IPDF_ObjectRenderer::Create(pObj->m_Type); 350 if (!m_pObjectRenderer->Start(this, pObj, pObj2Device, FALSE)) { 351 if (!m_pObjectRenderer->m_Result) { 352 DrawObjWithBackground(pObj, pObj2Device); 353 } 354 #ifdef _FPDFAPI_MINI_ 355 if (m_DitherBits) { 356 DitherObjectArea(pObj, pObj2Device); 357 } 358 #endif 359 delete m_pObjectRenderer; 360 m_pObjectRenderer = NULL; 361 return FALSE; 362 } 363 return ContinueSingleObject(pObj, pObj2Device, pPause); 364 } 365 ProcessObjectNoClip(pObj, pObj2Device); 366 return FALSE; 367 } 368 IPDF_ObjectRenderer* IPDF_ObjectRenderer::Create(int type) 369 { 370 IPDF_ObjectRenderer* pRenderer = NULL; 371 if (type == PDFPAGE_IMAGE) { 372 pRenderer = FX_NEW CPDF_ImageRenderer; 373 } 374 return pRenderer; 375 } 376 FX_BOOL CPDF_RenderStatus::GetObjectClippedRect(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bLogical, FX_RECT &rect) const 377 { 378 rect = pObj->GetBBox(pObj2Device); 379 FX_RECT rtClip = m_pDevice->GetClipBox(); 380 if (!bLogical) { 381 CFX_Matrix dCTM = m_pDevice->GetCTM(); 382 FX_FLOAT a = FXSYS_fabs(dCTM.a); 383 FX_FLOAT d = FXSYS_fabs(dCTM.d); 384 if (a != 1.0f || d != 1.0f) { 385 rect.right = rect.left + (FX_INT32)FXSYS_ceil((FX_FLOAT)rect.Width() * a); 386 rect.bottom = rect.top + (FX_INT32)FXSYS_ceil((FX_FLOAT)rect.Height() * d); 387 rtClip.right = rtClip.left + (FX_INT32)FXSYS_ceil((FX_FLOAT)rtClip.Width() * a); 388 rtClip.bottom = rtClip.top + (FX_INT32)FXSYS_ceil((FX_FLOAT)rtClip.Height() * d); 389 } 390 } 391 rect.Intersect(rtClip); 392 return rect.IsEmpty(); 393 } 394 void CPDF_RenderStatus::DitherObjectArea(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device) 395 { 396 CFX_DIBitmap* pBitmap = m_pDevice->GetBitmap(); 397 if (pBitmap == NULL) { 398 return; 399 } 400 FX_RECT rect; 401 if (GetObjectClippedRect(pObj, pObj2Device, FALSE, rect)) { 402 return; 403 } 404 if (m_DitherBits == 2) { 405 static FX_ARGB pal[4] = {0, 85, 170, 255}; 406 pBitmap->DitherFS(pal, 4, &rect); 407 } else if (m_DitherBits == 3) { 408 static FX_ARGB pal[8] = {0, 36, 73, 109, 146, 182, 219, 255}; 409 pBitmap->DitherFS(pal, 8, &rect); 410 } else if (m_DitherBits == 4) { 411 static FX_ARGB pal[16] = {0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255}; 412 pBitmap->DitherFS(pal, 16, &rect); 413 } 414 } 415 void CPDF_RenderStatus::ProcessObjectNoClip(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device) 416 { 417 FX_BOOL bRet = FALSE; 418 switch (pObj->m_Type) { 419 case PDFPAGE_TEXT: 420 bRet = ProcessText((CPDF_TextObject*)pObj, pObj2Device, NULL); 421 break; 422 case PDFPAGE_PATH: 423 bRet = ProcessPath((CPDF_PathObject*)pObj, pObj2Device); 424 break; 425 case PDFPAGE_IMAGE: 426 bRet = ProcessImage((CPDF_ImageObject*)pObj, pObj2Device); 427 break; 428 case PDFPAGE_SHADING: 429 bRet = ProcessShading((CPDF_ShadingObject*)pObj, pObj2Device); 430 break; 431 case PDFPAGE_FORM: 432 bRet = ProcessForm((CPDF_FormObject*)pObj, pObj2Device); 433 break; 434 #if defined(_FPDFAPI_MINI_) 435 case PDFPAGE_INLINES: 436 bRet = ProcessInlines((CPDF_InlineImages*)pObj, pObj2Device); 437 break; 438 #endif 439 } 440 if (!bRet) { 441 DrawObjWithBackground(pObj, pObj2Device); 442 } 443 } 444 FX_BOOL CPDF_RenderStatus::DrawObjWithBlend(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device) 445 { 446 FX_BOOL bRet = FALSE; 447 switch (pObj->m_Type) { 448 case PDFPAGE_PATH: 449 bRet = ProcessPath((CPDF_PathObject*)pObj, pObj2Device); 450 break; 451 case PDFPAGE_IMAGE: 452 bRet = ProcessImage((CPDF_ImageObject *)pObj, pObj2Device); 453 break; 454 case PDFPAGE_FORM: 455 bRet = ProcessForm((CPDF_FormObject*)pObj, pObj2Device); 456 break; 457 } 458 return bRet; 459 } 460 void CPDF_RenderStatus::GetScaledMatrix(CFX_Matrix &matrix) const 461 { 462 CFX_Matrix dCTM = m_pDevice->GetCTM(); 463 matrix.a *= FXSYS_fabs(dCTM.a); 464 matrix.d *= FXSYS_fabs(dCTM.d); 465 } 466 void CPDF_RenderStatus::DrawObjWithBackground(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device) 467 { 468 #if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_) 469 FX_RECT rect; 470 if (GetObjectClippedRect(pObj, pObj2Device, FALSE, rect)) { 471 return; 472 } 473 int res = 300; 474 if (pObj->m_Type == PDFPAGE_IMAGE && m_pDevice->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) { 475 res = 0; 476 } 477 CPDF_ScaledRenderBuffer buffer; 478 if (!buffer.Initialize(m_pContext, m_pDevice, &rect, pObj, &m_Options, res)) { 479 return; 480 } 481 CFX_AffineMatrix matrix = *pObj2Device; 482 matrix.Concat(*buffer.GetMatrix()); 483 GetScaledMatrix(matrix); 484 CPDF_Dictionary* pFormResource = NULL; 485 if (pObj->m_Type == PDFPAGE_FORM) { 486 CPDF_FormObject* pFormObj = (CPDF_FormObject*)pObj; 487 if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) { 488 pFormResource = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources")); 489 } 490 } 491 CPDF_RenderStatus status; 492 status.Initialize(m_Level + 1, m_pContext, buffer.GetDevice(), buffer.GetMatrix(), NULL, NULL, NULL, &m_Options, m_Transparency, m_bDropObjects, pFormResource); 493 status.RenderSingleObject(pObj, &matrix); 494 buffer.OutputToDevice(); 495 #endif 496 } 497 FX_BOOL CPDF_RenderStatus::ProcessForm(CPDF_FormObject* pFormObj, const CFX_AffineMatrix* pObj2Device) 498 { 499 CPDF_Dictionary* pOC = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("OC")); 500 if (pOC && m_Options.m_pOCContext && !m_Options.m_pOCContext->CheckOCGVisible(pOC)) { 501 return TRUE; 502 } 503 CFX_AffineMatrix matrix = pFormObj->m_FormMatrix; 504 matrix.Concat(*pObj2Device); 505 CPDF_Dictionary* pResources = NULL; 506 if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) { 507 pResources = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources")); 508 } 509 CPDF_RenderStatus status; 510 status.Initialize(m_Level + 1, m_pContext, m_pDevice, NULL, m_pStopObj, 511 this, pFormObj, &m_Options, m_Transparency, m_bDropObjects, pResources, TRUE); 512 status.m_curBlend = m_curBlend; 513 m_pDevice->SaveState(); 514 status.RenderObjectList(pFormObj->m_pForm, &matrix); 515 m_bStopped = status.m_bStopped; 516 m_pDevice->RestoreState(); 517 return TRUE; 518 } 519 FX_BOOL IsAvailableMatrix(const CFX_AffineMatrix& matrix) 520 { 521 if (matrix.a == 0 || matrix.d == 0) { 522 return matrix.b != 0 && matrix.c != 0; 523 } 524 if (matrix.b == 0 || matrix.c == 0) { 525 return matrix.a != 0 && matrix.d != 0; 526 } 527 return TRUE; 528 } 529 FX_BOOL CPDF_RenderStatus::ProcessPath(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device) 530 { 531 int FillType = pPathObj->m_FillType; 532 FX_BOOL bStroke = pPathObj->m_bStroke; 533 ProcessPathPattern(pPathObj, pObj2Device, FillType, bStroke); 534 if (FillType == 0 && !bStroke) { 535 return TRUE; 536 } 537 FX_DWORD fill_argb = 0; 538 if (FillType) { 539 fill_argb = GetFillArgb(pPathObj); 540 } 541 FX_DWORD stroke_argb = 0; 542 if (bStroke) { 543 stroke_argb = GetStrokeArgb(pPathObj); 544 } 545 CFX_AffineMatrix path_matrix = pPathObj->m_Matrix; 546 path_matrix.Concat(*pObj2Device); 547 if (!IsAvailableMatrix(path_matrix)) { 548 return TRUE; 549 } 550 if (FillType && (m_Options.m_Flags & RENDER_RECT_AA)) { 551 FillType |= FXFILL_RECT_AA; 552 } 553 if (m_Options.m_Flags & RENDER_FILL_FULLCOVER) { 554 FillType |= FXFILL_FULLCOVER; 555 } 556 if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) { 557 FillType |= FXFILL_NOPATHSMOOTH; 558 } 559 if (bStroke) { 560 FillType |= FX_FILL_STROKE; 561 } 562 #if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_) 563 const CPDF_GeneralStateData* pGeneralData = ((CPDF_PageObject*)pPathObj)->m_GeneralState; 564 if (pGeneralData && pGeneralData->m_StrokeAdjust) { 565 FillType |= FX_STROKE_ADJUST; 566 } 567 #endif 568 if (m_pType3Char) { 569 FillType |= FX_FILL_TEXT_MODE; 570 } 571 CFX_GraphStateData graphState(*pPathObj->m_GraphState); 572 if (m_Options.m_Flags & RENDER_THINLINE) { 573 graphState.m_LineWidth = 0; 574 } 575 return m_pDevice->DrawPath(pPathObj->m_Path, &path_matrix, &graphState, fill_argb, stroke_argb, FillType, 0, NULL, m_curBlend); 576 } 577 CPDF_TransferFunc* CPDF_RenderStatus::GetTransferFunc(CPDF_Object* pObj) const 578 { 579 ASSERT(pObj != NULL); 580 CPDF_DocRenderData* pDocCache = m_pContext->m_pDocument->GetRenderData(); 581 if (!pDocCache) { 582 return NULL; 583 } 584 return pDocCache->GetTransferFunc(pObj); 585 } 586 FX_ARGB CPDF_RenderStatus::GetFillArgb(const CPDF_PageObject* pObj, FX_BOOL bType3) const 587 { 588 CPDF_ColorStateData* pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)pObj->m_ColorState; 589 if (m_pType3Char && !bType3 && (!m_pType3Char->m_bColored || (m_pType3Char->m_bColored && (!pColorData || pColorData->m_FillColor.IsNull())))) { 590 return m_T3FillColor; 591 } else if (!pColorData || pColorData->m_FillColor.IsNull()) { 592 pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)m_InitialStates.m_ColorState; 593 } 594 FX_COLORREF rgb = pColorData->m_FillRGB; 595 if (rgb == (FX_DWORD) - 1) { 596 return 0; 597 } 598 const CPDF_GeneralStateData* pGeneralData = pObj->m_GeneralState; 599 int alpha; 600 if (pGeneralData) { 601 alpha = (FX_INT32)(pGeneralData->m_FillAlpha * 255); 602 #ifndef _FPDFAPI_MINI_ 603 if (pGeneralData->m_pTR) { 604 if (!pGeneralData->m_pTransferFunc) { 605 ((CPDF_GeneralStateData*)pGeneralData)->m_pTransferFunc = GetTransferFunc(pGeneralData->m_pTR); 606 } 607 if (pGeneralData->m_pTransferFunc) { 608 rgb = pGeneralData->m_pTransferFunc->TranslateColor(rgb); 609 } 610 } 611 #endif 612 } else { 613 alpha = 255; 614 } 615 return m_Options.TranslateColor(ArgbEncode(alpha, rgb)); 616 } 617 FX_ARGB CPDF_RenderStatus::GetStrokeArgb(const CPDF_PageObject* pObj) const 618 { 619 CPDF_ColorStateData* pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)pObj->m_ColorState; 620 if (m_pType3Char && (!m_pType3Char->m_bColored || (m_pType3Char->m_bColored && (!pColorData || pColorData->m_StrokeColor.IsNull())))) { 621 return m_T3FillColor; 622 } else if (!pColorData || pColorData->m_StrokeColor.IsNull()) { 623 pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)m_InitialStates.m_ColorState; 624 } 625 FX_COLORREF rgb = pColorData->m_StrokeRGB; 626 if (rgb == (FX_DWORD) - 1) { 627 return 0; 628 } 629 const CPDF_GeneralStateData* pGeneralData = pObj->m_GeneralState; 630 int alpha; 631 if (pGeneralData) { 632 alpha = (FX_INT32)(pGeneralData->m_StrokeAlpha * 255); 633 #ifndef _FPDFAPI_MINI_ 634 if (pGeneralData->m_pTR) { 635 if (!pGeneralData->m_pTransferFunc) { 636 ((CPDF_GeneralStateData*)pGeneralData)->m_pTransferFunc = GetTransferFunc(pGeneralData->m_pTR); 637 } 638 if (pGeneralData->m_pTransferFunc) { 639 rgb = pGeneralData->m_pTransferFunc->TranslateColor(rgb); 640 } 641 } 642 #endif 643 } else { 644 alpha = 255; 645 } 646 return m_Options.TranslateColor(ArgbEncode(alpha, rgb)); 647 } 648 void CPDF_RenderStatus::ProcessClipPath(CPDF_ClipPath ClipPath, const CFX_AffineMatrix* pObj2Device) 649 { 650 if (ClipPath.IsNull()) { 651 if (m_LastClipPath.IsNull()) { 652 return; 653 } 654 m_pDevice->RestoreState(TRUE); 655 m_LastClipPath.SetNull(); 656 return; 657 } 658 if (m_LastClipPath == ClipPath) { 659 return; 660 } 661 m_LastClipPath = ClipPath; 662 m_pDevice->RestoreState(TRUE); 663 int nClipPath = ClipPath.GetPathCount(); 664 int i; 665 for (i = 0; i < nClipPath; i++) { 666 const CFX_PathData* pPathData = ClipPath.GetPath(i); 667 if (pPathData == NULL) { 668 continue; 669 } 670 if (pPathData->GetPointCount() == 0) { 671 CFX_PathData EmptyPath; 672 EmptyPath.AppendRect(-1, -1, 0, 0); 673 int fill_mode = FXFILL_WINDING; 674 m_pDevice->SetClip_PathFill(&EmptyPath, NULL, fill_mode); 675 } else { 676 int ClipType = ClipPath.GetClipType(i); 677 m_pDevice->SetClip_PathFill(pPathData, pObj2Device, ClipType); 678 } 679 } 680 int textcount = ClipPath.GetTextCount(); 681 if (textcount == 0) { 682 return; 683 } 684 if (m_pDevice->GetDeviceClass() == FXDC_DISPLAY && !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)) { 685 return; 686 } 687 CFX_PathData* pTextClippingPath = NULL; 688 for (i = 0; i < textcount; i ++) { 689 CPDF_TextObject* pText = ClipPath.GetText(i); 690 if (pText == NULL) { 691 if (pTextClippingPath) { 692 int fill_mode = FXFILL_WINDING; 693 if (m_Options.m_Flags & RENDER_NOTEXTSMOOTH) { 694 fill_mode |= FXFILL_NOPATHSMOOTH; 695 } 696 m_pDevice->SetClip_PathFill(pTextClippingPath, NULL, fill_mode); 697 delete pTextClippingPath; 698 pTextClippingPath = NULL; 699 } 700 } else { 701 if (pTextClippingPath == NULL) { 702 pTextClippingPath = FX_NEW CFX_PathData; 703 } 704 ProcessText(pText, pObj2Device, pTextClippingPath); 705 } 706 } 707 if (pTextClippingPath) { 708 delete pTextClippingPath; 709 } 710 } 711 void CPDF_RenderStatus::DrawClipPath(CPDF_ClipPath ClipPath, const CFX_AffineMatrix* pObj2Device) 712 { 713 if (ClipPath.IsNull()) { 714 return; 715 } 716 int fill_mode = 0; 717 if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) { 718 fill_mode |= FXFILL_NOPATHSMOOTH; 719 } 720 int nClipPath = ClipPath.GetPathCount(); 721 int i; 722 for (i = 0; i < nClipPath; i++) { 723 const CFX_PathData* pPathData = ClipPath.GetPath(i); 724 if (pPathData == NULL) { 725 continue; 726 } 727 CFX_GraphStateData stroke_state; 728 if (m_Options.m_Flags & RENDER_THINLINE) { 729 stroke_state.m_LineWidth = 0; 730 } 731 m_pDevice->DrawPath(pPathData, pObj2Device, &stroke_state, 0, 0xffff0000, fill_mode); 732 } 733 } 734 FX_BOOL CPDF_RenderStatus::SelectClipPath(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke) 735 { 736 CFX_AffineMatrix path_matrix = pPathObj->m_Matrix; 737 path_matrix.Concat(*pObj2Device); 738 if (bStroke) { 739 CFX_GraphStateData graphState(*pPathObj->m_GraphState); 740 if (m_Options.m_Flags & RENDER_THINLINE) { 741 graphState.m_LineWidth = 0; 742 } 743 return m_pDevice->SetClip_PathStroke(pPathObj->m_Path, &path_matrix, &graphState); 744 } 745 int fill_mode = pPathObj->m_FillType; 746 if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) { 747 fill_mode |= FXFILL_NOPATHSMOOTH; 748 } 749 return m_pDevice->SetClip_PathFill(pPathObj->m_Path, &path_matrix, fill_mode); 750 } 751 FX_BOOL CPDF_RenderStatus::ProcessTransparency(const CPDF_PageObject* pPageObj, const CFX_AffineMatrix* pObj2Device) 752 { 753 const CPDF_GeneralStateData* pGeneralState = pPageObj->m_GeneralState; 754 int blend_type = pGeneralState ? pGeneralState->m_BlendType : FXDIB_BLEND_NORMAL; 755 if (blend_type == FXDIB_BLEND_UNSUPPORTED) { 756 return TRUE; 757 } 758 CPDF_Dictionary* pSMaskDict = pGeneralState ? (CPDF_Dictionary*)pGeneralState->m_pSoftMask : NULL; 759 if (pSMaskDict) { 760 if (pPageObj->m_Type == PDFPAGE_IMAGE && 761 ((CPDF_ImageObject*)pPageObj)->m_pImage->GetDict()->KeyExist(FX_BSTRC("SMask"))) { 762 pSMaskDict = NULL; 763 } 764 } 765 CPDF_Dictionary* pFormResource = NULL; 766 FX_FLOAT group_alpha = 1.0f; 767 int Transparency = m_Transparency; 768 FX_BOOL bGroupTransparent = FALSE; 769 if (pPageObj->m_Type == PDFPAGE_FORM) { 770 CPDF_FormObject* pFormObj = (CPDF_FormObject*)pPageObj; 771 const CPDF_GeneralStateData *pStateData = pFormObj->m_GeneralState.GetObject(); 772 if (pStateData) { 773 group_alpha = pStateData->m_FillAlpha; 774 } 775 Transparency = pFormObj->m_pForm->m_Transparency; 776 bGroupTransparent = Transparency & PDFTRANS_ISOLATED ? TRUE : FALSE; 777 if (pFormObj->m_pForm->m_pFormDict) { 778 pFormResource = pFormObj->m_pForm->m_pFormDict->GetDict("Resources"); 779 } 780 } 781 FX_BOOL bTextClip = FALSE; 782 if (pPageObj->m_ClipPath.NotNull() && pPageObj->m_ClipPath.GetTextCount() && 783 m_pDevice->GetDeviceClass() == FXDC_DISPLAY && !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)) { 784 bTextClip = TRUE; 785 } 786 if ((m_Options.m_Flags & RENDER_OVERPRINT) && pPageObj->m_Type == PDFPAGE_IMAGE && pGeneralState && pGeneralState->m_FillOP && pGeneralState->m_StrokeOP) { 787 CPDF_Document* pDocument = NULL; 788 CPDF_Page* pPage = NULL; 789 if (m_pContext->m_pPageCache) { 790 pPage = m_pContext->m_pPageCache->GetPage(); 791 pDocument = pPage->m_pDocument; 792 } else { 793 pDocument = ((CPDF_ImageObject*)pPageObj)->m_pImage->GetDocument(); 794 } 795 CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : NULL; 796 CPDF_Object* pCSObj = ((CPDF_ImageObject*)pPageObj)->m_pImage->GetStream()->GetDict()->GetElementValue(FX_BSTRC("ColorSpace")); 797 CPDF_ColorSpace* pColorSpace = pDocument->LoadColorSpace(pCSObj, pPageResources); 798 if (pColorSpace) { 799 int format = pColorSpace->GetFamily(); 800 if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION || format == PDFCS_DEVICEN) { 801 blend_type = FXDIB_BLEND_DARKEN; 802 } 803 pDocument->GetPageData()->ReleaseColorSpace(pCSObj); 804 } 805 } 806 if (pSMaskDict == NULL && group_alpha == 1.0f && blend_type == FXDIB_BLEND_NORMAL && !bTextClip && !bGroupTransparent) { 807 return FALSE; 808 } 809 FX_BOOL isolated = Transparency & PDFTRANS_ISOLATED; 810 if (m_bPrint) { 811 FX_BOOL bRet = FALSE; 812 int rendCaps = m_pDevice->GetRenderCaps(); 813 if (!((Transparency & PDFTRANS_ISOLATED) || pSMaskDict || bTextClip) && (rendCaps & FXRC_BLEND_MODE)) { 814 int oldBlend = m_curBlend; 815 m_curBlend = blend_type; 816 bRet = DrawObjWithBlend(pPageObj, pObj2Device); 817 m_curBlend = oldBlend; 818 } 819 if (!bRet) { 820 DrawObjWithBackground(pPageObj, pObj2Device); 821 } 822 return TRUE; 823 } 824 FX_RECT rect = pPageObj->GetBBox(pObj2Device); 825 rect.Intersect(m_pDevice->GetClipBox()); 826 if (rect.IsEmpty()) { 827 return TRUE; 828 } 829 CFX_Matrix deviceCTM = m_pDevice->GetCTM(); 830 FX_FLOAT scaleX = FXSYS_abs(deviceCTM.a); 831 FX_FLOAT scaleY = FXSYS_abs(deviceCTM.d); 832 int width = FXSYS_round((FX_FLOAT)rect.Width() * scaleX); 833 int height = FXSYS_round((FX_FLOAT)rect.Height() * scaleY); 834 CFX_FxgeDevice bitmap_device; 835 CFX_DIBitmap* oriDevice = NULL; 836 if (!isolated && (m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) { 837 oriDevice = FX_NEW CFX_DIBitmap; 838 if (!m_pDevice->CreateCompatibleBitmap(oriDevice, width, height)) { 839 return TRUE; 840 } 841 m_pDevice->GetDIBits(oriDevice, rect.left, rect.top); 842 } 843 if (!bitmap_device.Create(width, height, FXDIB_Argb, 0, oriDevice)) { 844 return TRUE; 845 } 846 CFX_DIBitmap* bitmap = bitmap_device.GetBitmap(); 847 bitmap->Clear(0); 848 CFX_AffineMatrix new_matrix = *pObj2Device; 849 new_matrix.TranslateI(-rect.left, -rect.top); 850 new_matrix.Scale(scaleX, scaleY); 851 CFX_DIBitmap* pTextMask = NULL; 852 if (bTextClip) { 853 pTextMask = FX_NEW CFX_DIBitmap; 854 if (!pTextMask->Create(width, height, FXDIB_8bppMask)) { 855 delete pTextMask; 856 return TRUE; 857 } 858 pTextMask->Clear(0); 859 CFX_FxgeDevice text_device; 860 text_device.Attach(pTextMask); 861 for (FX_DWORD i = 0; i < pPageObj->m_ClipPath.GetTextCount(); i ++) { 862 CPDF_TextObject* textobj = pPageObj->m_ClipPath.GetText(i); 863 if (textobj == NULL) { 864 break; 865 } 866 CFX_AffineMatrix text_matrix; 867 textobj->GetTextMatrix(&text_matrix); 868 CPDF_TextRenderer::DrawTextPath(&text_device, textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos, 869 textobj->m_TextState.GetFont(), textobj->m_TextState.GetFontSize(), 870 &text_matrix, &new_matrix, textobj->m_GraphState, (FX_ARGB) - 1, 0, NULL); 871 } 872 } 873 CPDF_RenderStatus bitmap_render; 874 bitmap_render.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL, 875 m_pStopObj, NULL, NULL, &m_Options, 0, m_bDropObjects, pFormResource, TRUE); 876 bitmap_render.ProcessObjectNoClip(pPageObj, &new_matrix); 877 m_bStopped = bitmap_render.m_bStopped; 878 if (pSMaskDict) { 879 CFX_AffineMatrix smask_matrix; 880 FXSYS_memcpy32(&smask_matrix, pGeneralState->m_SMaskMatrix, sizeof smask_matrix); 881 smask_matrix.Concat(*pObj2Device); 882 CFX_DIBSource* pSMaskSource = LoadSMask(pSMaskDict, &rect, &smask_matrix); 883 if (pSMaskSource) { 884 bitmap->MultiplyAlpha(pSMaskSource); 885 delete pSMaskSource; 886 } 887 } 888 if (pTextMask) { 889 bitmap->MultiplyAlpha(pTextMask); 890 delete pTextMask; 891 pTextMask = NULL; 892 } 893 if (Transparency & PDFTRANS_GROUP && group_alpha != 1.0f) { 894 bitmap->MultiplyAlpha((FX_INT32)(group_alpha * 255)); 895 } 896 Transparency = m_Transparency; 897 if (pPageObj->m_Type == PDFPAGE_FORM) { 898 Transparency |= PDFTRANS_GROUP; 899 } 900 CompositeDIBitmap(bitmap, rect.left, rect.top, 0, 255, blend_type, Transparency); 901 if (oriDevice) { 902 delete oriDevice; 903 } 904 return TRUE; 905 } 906 CFX_DIBitmap* CPDF_RenderStatus::GetBackdrop(const CPDF_PageObject* pObj, const FX_RECT& rect, int& left, int& top, 907 FX_BOOL bBackAlphaRequired) 908 { 909 FX_RECT bbox = rect; 910 bbox.Intersect(m_pDevice->GetClipBox()); 911 left = bbox.left; 912 top = bbox.top; 913 CFX_Matrix deviceCTM = m_pDevice->GetCTM(); 914 FX_FLOAT scaleX = FXSYS_abs(deviceCTM.a); 915 FX_FLOAT scaleY = FXSYS_abs(deviceCTM.d); 916 int width = FXSYS_round(bbox.Width() * scaleX); 917 int height = FXSYS_round(bbox.Height() * scaleY); 918 CFX_DIBitmap* pBackdrop = FX_NEW CFX_DIBitmap; 919 if (bBackAlphaRequired && !m_bDropObjects) { 920 pBackdrop->Create(width, height, FXDIB_Argb); 921 } else { 922 m_pDevice->CreateCompatibleBitmap(pBackdrop, width, height); 923 } 924 if (pBackdrop->GetBuffer() == NULL) { 925 delete pBackdrop; 926 return NULL; 927 } 928 FX_BOOL bNeedDraw; 929 if (pBackdrop->HasAlpha()) { 930 bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT); 931 } else { 932 bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS); 933 } 934 if (!bNeedDraw) { 935 m_pDevice->GetDIBits(pBackdrop, left, top); 936 return pBackdrop; 937 } 938 CFX_AffineMatrix FinalMatrix = m_DeviceMatrix; 939 FinalMatrix.TranslateI(-left, -top); 940 FinalMatrix.Scale(scaleX, scaleY); 941 pBackdrop->Clear(pBackdrop->HasAlpha() ? 0 : 0xffffffff); 942 CFX_FxgeDevice device; 943 device.Attach(pBackdrop); 944 m_pContext->Render(&device, pObj, &m_Options, &FinalMatrix); 945 return pBackdrop; 946 } 947 void CPDF_RenderContext::GetBackground(CFX_DIBitmap* pBuffer, const CPDF_PageObject* pObj, 948 const CPDF_RenderOptions* pOptions, CFX_AffineMatrix* pFinalMatrix) 949 { 950 CFX_FxgeDevice device; 951 device.Attach(pBuffer); 952 if (m_pBackgroundDraw) { 953 m_pBackgroundDraw->OnDrawBackground(&device, pFinalMatrix); 954 } else { 955 FX_RECT rect(0, 0, device.GetWidth(), device.GetHeight()); 956 device.FillRect(&rect, 0xffffffff); 957 } 958 Render(&device, pObj, pOptions, pFinalMatrix); 959 } 960 CPDF_GraphicStates* CPDF_RenderStatus::CloneObjStates(const CPDF_GraphicStates* pSrcStates, FX_BOOL bStroke) 961 { 962 if (!pSrcStates) { 963 return NULL; 964 } 965 CPDF_GraphicStates* pStates = FX_NEW CPDF_GraphicStates; 966 if (!pStates) { 967 return NULL; 968 } 969 pStates->CopyStates(*pSrcStates); 970 CPDF_Color* pObjColor = bStroke ? pSrcStates->m_ColorState.GetStrokeColor() : 971 pSrcStates->m_ColorState.GetFillColor(); 972 if (!pObjColor->IsNull()) { 973 CPDF_ColorStateData* pColorData = pStates->m_ColorState.GetModify(); 974 pColorData->m_FillRGB = bStroke ? pSrcStates->m_ColorState.GetObject()->m_StrokeRGB : 975 pSrcStates->m_ColorState.GetObject()->m_FillRGB; 976 pColorData->m_StrokeRGB = pColorData->m_FillRGB; 977 } 978 return pStates; 979 } 980 CPDF_RenderContext::CPDF_RenderContext() 981 { 982 } 983 void CPDF_RenderContext::Create(CPDF_Document* pDoc, CPDF_PageRenderCache* pPageCache, 984 CPDF_Dictionary* pPageResources, FX_BOOL bFirstLayer) 985 { 986 m_pBackgroundDraw = NULL; 987 m_pDocument = pDoc; 988 m_pPageResources = pPageResources; 989 m_pPageCache = pPageCache; 990 m_bFirstLayer = bFirstLayer; 991 } 992 void CPDF_RenderContext::Create(CPDF_Page* pPage, FX_BOOL bFirstLayer) 993 { 994 m_pBackgroundDraw = NULL; 995 m_pDocument = pPage->m_pDocument; 996 m_pPageResources = pPage->m_pPageResources; 997 m_pPageCache = pPage->GetRenderCache(); 998 m_bFirstLayer = bFirstLayer; 999 } 1000 CPDF_RenderContext::~CPDF_RenderContext() 1001 { 1002 } 1003 void CPDF_RenderContext::Clear() 1004 { 1005 m_pDocument = NULL; 1006 m_pPageResources = NULL; 1007 m_pPageCache = NULL; 1008 m_pBackgroundDraw = NULL; 1009 m_bFirstLayer = TRUE; 1010 m_ContentList.RemoveAll(); 1011 } 1012 void CPDF_RenderContext::AppendObjectList(CPDF_PageObjects* pObjs, const CFX_AffineMatrix* pObject2Device) 1013 { 1014 _PDF_RenderItem* pItem = m_ContentList.AddSpace(); 1015 pItem->m_pObjectList = pObjs; 1016 if (pObject2Device) { 1017 pItem->m_Matrix = *pObject2Device; 1018 } else { 1019 pItem->m_Matrix.SetIdentity(); 1020 } 1021 } 1022 void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice, const CPDF_RenderOptions* pOptions, 1023 const CFX_AffineMatrix* pLastMatrix) 1024 { 1025 Render(pDevice, NULL, pOptions, pLastMatrix); 1026 } 1027 void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice, const CPDF_PageObject* pStopObj, 1028 const CPDF_RenderOptions* pOptions, const CFX_AffineMatrix* pLastMatrix) 1029 { 1030 int count = m_ContentList.GetSize(); 1031 for (int j = 0; j < count; j ++) { 1032 pDevice->SaveState(); 1033 _PDF_RenderItem* pItem = m_ContentList.GetDataPtr(j); 1034 if (pLastMatrix) { 1035 CFX_AffineMatrix FinalMatrix = pItem->m_Matrix; 1036 FinalMatrix.Concat(*pLastMatrix); 1037 CPDF_RenderStatus status; 1038 status.Initialize(0, this, pDevice, pLastMatrix, pStopObj, NULL, NULL, pOptions, 1039 pItem->m_pObjectList->m_Transparency, FALSE, NULL); 1040 status.RenderObjectList(pItem->m_pObjectList, &FinalMatrix); 1041 #if !defined(_FPDFAPI_MINI_) 1042 if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) { 1043 m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize); 1044 } 1045 #endif 1046 if (status.m_bStopped) { 1047 pDevice->RestoreState(); 1048 break; 1049 } 1050 } else { 1051 CPDF_RenderStatus status; 1052 status.Initialize(0, this, pDevice, NULL, pStopObj, NULL, NULL, pOptions, 1053 pItem->m_pObjectList->m_Transparency, FALSE, NULL); 1054 status.RenderObjectList(pItem->m_pObjectList, &pItem->m_Matrix); 1055 #if !defined(_FPDFAPI_MINI_) 1056 if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) { 1057 m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize); 1058 } 1059 #endif 1060 if (status.m_bStopped) { 1061 pDevice->RestoreState(); 1062 break; 1063 } 1064 } 1065 pDevice->RestoreState(); 1066 } 1067 } 1068 void CPDF_RenderContext::DrawObjectList(CFX_RenderDevice* pDevice, CPDF_PageObjects* pObjs, 1069 const CFX_AffineMatrix* pObject2Device, const CPDF_RenderOptions* pOptions) 1070 { 1071 AppendObjectList(pObjs, pObject2Device); 1072 Render(pDevice, pOptions); 1073 } 1074 CPDF_ProgressiveRenderer::CPDF_ProgressiveRenderer() 1075 { 1076 m_pRenderer = NULL; 1077 m_pContext = NULL; 1078 m_pDevice = NULL; 1079 m_Status = Ready; 1080 } 1081 CPDF_ProgressiveRenderer::~CPDF_ProgressiveRenderer() 1082 { 1083 Clear(); 1084 } 1085 void CPDF_ProgressiveRenderer::Clear() 1086 { 1087 if (m_pRenderer) { 1088 delete m_pRenderer; 1089 m_pDevice->RestoreState(); 1090 m_pRenderer = NULL; 1091 } 1092 m_Status = Ready; 1093 } 1094 void CPDF_ProgressiveRenderer::Start(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, 1095 const CPDF_RenderOptions* pOptions, IFX_Pause* pPause, FX_BOOL bDropObjects) 1096 { 1097 if (m_Status != Ready) { 1098 m_Status = Failed; 1099 return; 1100 } 1101 m_pContext = pContext; 1102 m_pDevice = pDevice; 1103 m_pOptions = pOptions; 1104 m_bDropObjects = bDropObjects; 1105 if (pContext == NULL || pDevice == NULL) { 1106 m_Status = Failed; 1107 return; 1108 } 1109 m_Status = ToBeContinued; 1110 m_ObjectPos = NULL; 1111 m_LayerIndex = 0; 1112 m_ObjectIndex = 0; 1113 m_PrevLastPos = NULL; 1114 Continue(pPause); 1115 } 1116 #ifdef _FPDFAPI_MINI_ 1117 #define RENDER_STEP_LIMIT 20 1118 #else 1119 #define RENDER_STEP_LIMIT 100 1120 #endif 1121 void CPDF_ProgressiveRenderer::Continue(IFX_Pause* pPause) 1122 { 1123 if (m_Status != ToBeContinued) { 1124 return; 1125 } 1126 FX_DWORD nLayers = m_pContext->m_ContentList.GetSize(); 1127 for (; m_LayerIndex < nLayers; m_LayerIndex ++) { 1128 _PDF_RenderItem* pItem = m_pContext->m_ContentList.GetDataPtr(m_LayerIndex); 1129 FX_POSITION LastPos = pItem->m_pObjectList->GetLastObjectPosition(); 1130 if (m_ObjectPos == NULL) { 1131 if (LastPos == m_PrevLastPos) { 1132 if (!pItem->m_pObjectList->IsParsed()) { 1133 pItem->m_pObjectList->ContinueParse(pPause); 1134 if (!pItem->m_pObjectList->IsParsed()) { 1135 return; 1136 } 1137 LastPos = pItem->m_pObjectList->GetLastObjectPosition(); 1138 } 1139 } 1140 if (LastPos == m_PrevLastPos) { 1141 if (m_pRenderer) { 1142 delete m_pRenderer; 1143 m_pRenderer = NULL; 1144 m_pDevice->RestoreState(); 1145 m_ObjectPos = NULL; 1146 m_PrevLastPos = NULL; 1147 } 1148 continue; 1149 } 1150 if (m_PrevLastPos) { 1151 m_ObjectPos = m_PrevLastPos; 1152 pItem->m_pObjectList->GetNextObject(m_ObjectPos); 1153 } else { 1154 m_ObjectPos = pItem->m_pObjectList->GetFirstObjectPosition(); 1155 } 1156 m_PrevLastPos = LastPos; 1157 } 1158 if (m_pRenderer == NULL) { 1159 m_ObjectPos = pItem->m_pObjectList->GetFirstObjectPosition(); 1160 m_ObjectIndex = 0; 1161 m_pRenderer = FX_NEW CPDF_RenderStatus(); 1162 m_pRenderer->Initialize(0, m_pContext, m_pDevice, NULL, NULL, NULL, NULL, 1163 m_pOptions, pItem->m_pObjectList->m_Transparency, m_bDropObjects, NULL); 1164 m_pDevice->SaveState(); 1165 m_ClipRect = m_pDevice->GetClipBox(); 1166 CFX_AffineMatrix device2object; 1167 device2object.SetReverse(pItem->m_Matrix); 1168 device2object.TransformRect(m_ClipRect); 1169 } 1170 int objs_to_go = CPDF_ModuleMgr::Get()->GetRenderModule()->GetConfig()->m_RenderStepLimit; 1171 while (m_ObjectPos) { 1172 CPDF_PageObject* pCurObj = pItem->m_pObjectList->GetObjectAt(m_ObjectPos); 1173 if (pCurObj && pCurObj->m_Left <= m_ClipRect.right && pCurObj->m_Right >= m_ClipRect.left && 1174 pCurObj->m_Bottom <= m_ClipRect.top && pCurObj->m_Top >= m_ClipRect.bottom) { 1175 if (m_pRenderer->ContinueSingleObject(pCurObj, &pItem->m_Matrix, pPause)) { 1176 return; 1177 } 1178 #if !defined(_FPDFAPI_MINI_) 1179 if (pCurObj->m_Type == PDFPAGE_IMAGE && m_pRenderer->m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) { 1180 m_pContext->GetPageCache()->CacheOptimization(m_pRenderer->m_Options.m_dwLimitCacheSize); 1181 } 1182 #endif 1183 if (pCurObj->m_Type == PDFPAGE_FORM || pCurObj->m_Type == PDFPAGE_SHADING) { 1184 objs_to_go = 0; 1185 } else { 1186 objs_to_go --; 1187 } 1188 } 1189 m_ObjectIndex ++; 1190 pItem->m_pObjectList->GetNextObject(m_ObjectPos); 1191 if (objs_to_go == 0) { 1192 if (pPause && pPause->NeedToPauseNow()) { 1193 return; 1194 } 1195 objs_to_go = CPDF_ModuleMgr::Get()->GetRenderModule()->GetConfig()->m_RenderStepLimit; 1196 } 1197 } 1198 if (!pItem->m_pObjectList->IsParsed()) { 1199 return; 1200 } 1201 delete m_pRenderer; 1202 m_pRenderer = NULL; 1203 m_pDevice->RestoreState(); 1204 m_ObjectPos = NULL; 1205 m_PrevLastPos = NULL; 1206 if (pPause && pPause->NeedToPauseNow()) { 1207 m_LayerIndex++; 1208 return; 1209 } 1210 } 1211 m_Status = Done; 1212 } 1213 int CPDF_ProgressiveRenderer::EstimateProgress() 1214 { 1215 if (!m_pContext) { 1216 return 0; 1217 } 1218 FX_DWORD nLayers = m_pContext->m_ContentList.GetSize(); 1219 int nTotal = 0, nRendered = 0; 1220 for (FX_DWORD layer = 0; layer < nLayers; layer ++) { 1221 _PDF_RenderItem* pItem = m_pContext->m_ContentList.GetDataPtr(layer); 1222 int nObjs = pItem->m_pObjectList->CountObjects(); 1223 if (layer == m_LayerIndex) { 1224 nRendered += m_ObjectIndex; 1225 } else if (layer < m_LayerIndex) { 1226 nRendered += nObjs; 1227 } 1228 nTotal += nObjs; 1229 } 1230 if (nTotal == 0) { 1231 return 0; 1232 } 1233 return 100 * nRendered / nTotal; 1234 } 1235 CPDF_TransferFunc* CPDF_DocRenderData::GetTransferFunc(CPDF_Object* pObj) 1236 { 1237 if (pObj == NULL) { 1238 return NULL; 1239 } 1240 CPDF_CountedObject<CPDF_TransferFunc*>* pTransferCounter; 1241 if (!m_TransferFuncMap.Lookup(pObj, pTransferCounter)) { 1242 CPDF_TransferFunc* pTransfer = NULL; 1243 CPDF_Function* pFuncs[3] = {NULL, NULL, NULL}; 1244 FX_BOOL bUniTransfer = TRUE; 1245 int i; 1246 FX_BOOL bIdentity = TRUE; 1247 if (pObj->GetType() == PDFOBJ_ARRAY) { 1248 bUniTransfer = FALSE; 1249 CPDF_Array* pArray = (CPDF_Array*)pObj; 1250 if (pArray->GetCount() < 3) { 1251 return NULL; 1252 } 1253 for (FX_DWORD i = 0; i < 3; i ++) { 1254 pFuncs[2 - i] = CPDF_Function::Load(pArray->GetElementValue(i)); 1255 if (pFuncs[2 - i] == NULL) { 1256 return NULL; 1257 } 1258 } 1259 } else { 1260 pFuncs[0] = CPDF_Function::Load(pObj); 1261 if (pFuncs[0] == NULL) { 1262 return NULL; 1263 } 1264 } 1265 pTransfer = FX_NEW CPDF_TransferFunc; 1266 pTransfer->m_pPDFDoc = m_pPDFDoc; 1267 pTransferCounter = FX_NEW CPDF_CountedObject<CPDF_TransferFunc*>; 1268 pTransferCounter->m_nCount = 1; 1269 pTransferCounter->m_Obj = pTransfer; 1270 m_TransferFuncMap.SetAt(pObj, pTransferCounter); 1271 static const int kMaxOutputs = 16; 1272 FX_FLOAT output[kMaxOutputs]; 1273 FXSYS_memset32(output, 0, sizeof(output)); 1274 FX_FLOAT input; 1275 int noutput; 1276 for (int v = 0; v < 256; v ++) { 1277 input = (FX_FLOAT)v / 255.0f; 1278 if (bUniTransfer) { 1279 if (pFuncs[0] && pFuncs[0]->CountOutputs() <= kMaxOutputs) { 1280 pFuncs[0]->Call(&input, 1, output, noutput); 1281 } 1282 int o = FXSYS_round(output[0] * 255); 1283 if (o != v) { 1284 bIdentity = FALSE; 1285 } 1286 for (i = 0; i < 3; i ++) { 1287 pTransfer->m_Samples[i * 256 + v] = o; 1288 } 1289 } else 1290 for (i = 0; i < 3; i ++) { 1291 if (pFuncs[i] && pFuncs[i]->CountOutputs() <= kMaxOutputs) { 1292 pFuncs[i]->Call(&input, 1, output, noutput); 1293 int o = FXSYS_round(output[0] * 255); 1294 if (o != v) { 1295 bIdentity = FALSE; 1296 } 1297 pTransfer->m_Samples[i * 256 + v] = o; 1298 } else { 1299 pTransfer->m_Samples[i * 256 + v] = v; 1300 } 1301 } 1302 } 1303 for (i = 0; i < 3; i ++) 1304 if (pFuncs[i]) { 1305 delete pFuncs[i]; 1306 } 1307 pTransfer->m_bIdentity = bIdentity; 1308 } 1309 pTransferCounter->m_nCount++; 1310 return pTransferCounter->m_Obj; 1311 } 1312 void CPDF_DocRenderData::ReleaseTransferFunc(CPDF_Object* pObj) 1313 { 1314 CPDF_CountedObject<CPDF_TransferFunc*>* pTransferCounter; 1315 if (!m_TransferFuncMap.Lookup(pObj, pTransferCounter)) { 1316 return; 1317 } 1318 pTransferCounter->m_nCount--; 1319 } 1320 CPDF_RenderConfig::CPDF_RenderConfig() 1321 { 1322 m_HalftoneLimit = 0; 1323 #ifdef _FPDFAPI_MINI_ 1324 m_RenderStepLimit = 20; 1325 #else 1326 m_RenderStepLimit = 100; 1327 #endif 1328 } 1329 CPDF_RenderConfig::~CPDF_RenderConfig() 1330 { 1331 } 1332 CPDF_DeviceBuffer::CPDF_DeviceBuffer() 1333 { 1334 m_pBitmap = NULL; 1335 m_pDevice = NULL; 1336 m_pContext = NULL; 1337 m_pObject = NULL; 1338 } 1339 CPDF_DeviceBuffer::~CPDF_DeviceBuffer() 1340 { 1341 if (m_pBitmap) { 1342 delete m_pBitmap; 1343 } 1344 } 1345 FX_BOOL CPDF_DeviceBuffer::Initialize(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, FX_RECT* pRect, 1346 const CPDF_PageObject* pObj, int max_dpi) 1347 { 1348 m_pDevice = pDevice; 1349 m_pContext = pContext; 1350 m_Rect = *pRect; 1351 m_pObject = pObj; 1352 m_Matrix.TranslateI(-pRect->left, -pRect->top); 1353 #if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ 1354 int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE); 1355 int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE); 1356 if (horz_size && vert_size && max_dpi) { 1357 int dpih = pDevice->GetDeviceCaps(FXDC_PIXEL_WIDTH) * 254 / (horz_size * 10); 1358 int dpiv = pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10); 1359 if (dpih > max_dpi) { 1360 m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f); 1361 } 1362 if (dpiv > max_dpi) { 1363 m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv); 1364 } 1365 } 1366 #ifdef _FPDFAPI_MINI_ 1367 m_Matrix.Scale(0.5f, 0.5f); 1368 #endif 1369 #endif 1370 CFX_Matrix ctm = m_pDevice->GetCTM(); 1371 FX_FLOAT fScaleX = FXSYS_fabs(ctm.a); 1372 FX_FLOAT fScaleY = FXSYS_fabs(ctm.d); 1373 m_Matrix.Concat(fScaleX, 0, 0, fScaleY, 0, 0); 1374 CFX_FloatRect rect(*pRect); 1375 m_Matrix.TransformRect(rect); 1376 FX_RECT bitmap_rect = rect.GetOutterRect(); 1377 m_pBitmap = FX_NEW CFX_DIBitmap; 1378 m_pBitmap->Create(bitmap_rect.Width(), bitmap_rect.Height(), FXDIB_Argb); 1379 return TRUE; 1380 } 1381 void CPDF_DeviceBuffer::OutputToDevice() 1382 { 1383 if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) { 1384 if (m_Matrix.a == 1.0f && m_Matrix.d == 1.0f) { 1385 m_pDevice->SetDIBits(m_pBitmap, m_Rect.left, m_Rect.top); 1386 } else { 1387 m_pDevice->StretchDIBits(m_pBitmap, m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height()); 1388 } 1389 } else { 1390 #if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_) 1391 CFX_DIBitmap buffer; 1392 m_pDevice->CreateCompatibleBitmap(&buffer, m_pBitmap->GetWidth(), m_pBitmap->GetHeight()); 1393 m_pContext->GetBackground(&buffer, m_pObject, NULL, &m_Matrix); 1394 buffer.CompositeBitmap(0, 0, buffer.GetWidth(), buffer.GetHeight(), m_pBitmap, 0, 0); 1395 m_pDevice->StretchDIBits(&buffer, m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height()); 1396 #endif 1397 } 1398 } 1399 CPDF_ScaledRenderBuffer::CPDF_ScaledRenderBuffer() 1400 { 1401 m_pBitmapDevice = NULL; 1402 } 1403 CPDF_ScaledRenderBuffer::~CPDF_ScaledRenderBuffer() 1404 { 1405 if (m_pBitmapDevice) { 1406 delete m_pBitmapDevice; 1407 } 1408 } 1409 #ifndef _FPDFAPI_MINI_ 1410 #define _FPDFAPI_IMAGESIZE_LIMIT_ (30 * 1024 * 1024) 1411 #else 1412 #define _FPDFAPI_IMAGESIZE_LIMIT_ (10 * 1024 * 1024) 1413 #endif 1414 FX_BOOL CPDF_ScaledRenderBuffer::Initialize(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, FX_RECT* pRect, 1415 const CPDF_PageObject* pObj, const CPDF_RenderOptions *pOptions, int max_dpi) 1416 { 1417 FXSYS_assert(pRect != NULL); 1418 m_pDevice = pDevice; 1419 if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) { 1420 return TRUE; 1421 } 1422 m_pContext = pContext; 1423 m_Rect = *pRect; 1424 m_pObject = pObj; 1425 m_Matrix.TranslateI(-pRect->left, -pRect->top); 1426 int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE); 1427 int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE); 1428 if (horz_size && vert_size && max_dpi) { 1429 int dpih = pDevice->GetDeviceCaps(FXDC_PIXEL_WIDTH) * 254 / (horz_size * 10); 1430 int dpiv = pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10); 1431 if (dpih > max_dpi) { 1432 m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f); 1433 } 1434 if (dpiv > max_dpi) { 1435 m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv); 1436 } 1437 } 1438 m_pBitmapDevice = FX_NEW CFX_FxgeDevice; 1439 FXDIB_Format dibFormat = FXDIB_Rgb; 1440 FX_INT32 bpp = 24; 1441 if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_ALPHA_OUTPUT) { 1442 dibFormat = FXDIB_Argb; 1443 bpp = 32; 1444 } 1445 CFX_FloatRect rect; 1446 FX_INT32 iWidth, iHeight, iPitch; 1447 while (1) { 1448 rect = *pRect; 1449 m_Matrix.TransformRect(rect); 1450 FX_RECT bitmap_rect = rect.GetOutterRect(); 1451 iWidth = bitmap_rect.Width(); 1452 iHeight = bitmap_rect.Height(); 1453 iPitch = (iWidth * bpp + 31) / 32 * 4; 1454 if (iWidth * iHeight < 1) { 1455 return FALSE; 1456 } 1457 if (iPitch * iHeight <= _FPDFAPI_IMAGESIZE_LIMIT_ && 1458 m_pBitmapDevice->Create(iWidth, iHeight, dibFormat)) { 1459 break; 1460 } 1461 m_Matrix.Scale(0.5f, 0.5f); 1462 } 1463 #if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_) 1464 m_pContext->GetBackground(m_pBitmapDevice->GetBitmap(), m_pObject, pOptions, &m_Matrix); 1465 #endif 1466 return TRUE; 1467 } 1468 void CPDF_ScaledRenderBuffer::OutputToDevice() 1469 { 1470 if (m_pBitmapDevice) { 1471 m_pDevice->StretchDIBits(m_pBitmapDevice->GetBitmap(), m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height()); 1472 } 1473 } 1474 FX_BOOL IPDF_OCContext::CheckObjectVisible(const CPDF_PageObject* pObj) 1475 { 1476 const CPDF_ContentMarkData* pData = pObj->m_ContentMark; 1477 int nItems = pData->CountItems(); 1478 for (int i = 0; i < nItems; i ++) { 1479 CPDF_ContentMarkItem& item = pData->GetItem(i); 1480 if (item.GetName() == FX_BSTRC("OC") && item.GetParamType() == CPDF_ContentMarkItem::PropertiesDict) { 1481 CPDF_Dictionary* pOCG = (CPDF_Dictionary*)item.GetParam(); 1482 if (!CheckOCGVisible(pOCG)) { 1483 return FALSE; 1484 } 1485 } 1486 } 1487 return TRUE; 1488 } 1489