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