1 // Copyright 2016 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 "core/fpdfapi/render/cpdf_imagerenderer.h" 8 9 #include <algorithm> 10 #include <memory> 11 12 #include "core/fpdfapi/page/cpdf_docpagedata.h" 13 #include "core/fpdfapi/page/cpdf_image.h" 14 #include "core/fpdfapi/page/cpdf_imageobject.h" 15 #include "core/fpdfapi/page/cpdf_page.h" 16 #include "core/fpdfapi/page/cpdf_pageobject.h" 17 #include "core/fpdfapi/page/cpdf_shadingpattern.h" 18 #include "core/fpdfapi/page/cpdf_tilingpattern.h" 19 #include "core/fpdfapi/parser/cpdf_array.h" 20 #include "core/fpdfapi/parser/cpdf_dictionary.h" 21 #include "core/fpdfapi/parser/cpdf_document.h" 22 #include "core/fpdfapi/render/cpdf_dibsource.h" 23 #include "core/fpdfapi/render/cpdf_pagerendercache.h" 24 #include "core/fpdfapi/render/cpdf_rendercontext.h" 25 #include "core/fpdfapi/render/cpdf_renderstatus.h" 26 #include "core/fpdfapi/render/cpdf_transferfunc.h" 27 #include "core/fpdfdoc/cpdf_occontext.h" 28 #include "core/fxcrt/fx_safe_types.h" 29 #include "core/fxcrt/maybe_owned.h" 30 #include "core/fxge/cfx_defaultrenderdevice.h" 31 #include "core/fxge/cfx_pathdata.h" 32 #include "core/fxge/dib/cfx_dibitmap.h" 33 #include "core/fxge/dib/cfx_dibsource.h" 34 #include "core/fxge/dib/cfx_imagestretcher.h" 35 #include "core/fxge/dib/cfx_imagetransformer.h" 36 #include "third_party/base/ptr_util.h" 37 #include "third_party/base/stl_util.h" 38 39 #ifdef _SKIA_SUPPORT_ 40 #include "core/fxge/skia/fx_skia_device.h" 41 #endif 42 43 CPDF_ImageRenderer::CPDF_ImageRenderer() 44 : m_pRenderStatus(nullptr), 45 m_pImageObject(nullptr), 46 m_Status(0), 47 m_pObj2Device(nullptr), 48 m_bPatternColor(false), 49 m_pPattern(nullptr), 50 m_bStdCS(false), 51 m_BlendType(FXDIB_BLEND_NORMAL), 52 m_Result(true) {} 53 54 CPDF_ImageRenderer::~CPDF_ImageRenderer() {} 55 56 bool CPDF_ImageRenderer::StartLoadDIBSource() { 57 CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); 58 FX_RECT image_rect = image_rect_f.GetOuterRect(); 59 if (!image_rect.Valid()) 60 return false; 61 62 if (m_Loader.Start(m_pImageObject.Get(), 63 m_pRenderStatus->GetContext()->GetPageCache(), m_bStdCS, 64 m_pRenderStatus->GetGroupFamily(), 65 m_pRenderStatus->GetLoadMask(), m_pRenderStatus.Get())) { 66 m_Status = 4; 67 return true; 68 } 69 return false; 70 } 71 72 bool CPDF_ImageRenderer::StartRenderDIBSource() { 73 if (!m_Loader.m_pBitmap) 74 return false; 75 76 CPDF_GeneralState& state = m_pImageObject->m_GeneralState; 77 m_BitmapAlpha = FXSYS_round(255 * state.GetFillAlpha()); 78 m_pDIBSource = m_Loader.m_pBitmap; 79 if (m_pRenderStatus->GetRenderOptions()->ColorModeIs( 80 CPDF_RenderOptions::kAlpha) && 81 !m_Loader.m_pMask) { 82 return StartBitmapAlpha(); 83 } 84 if (state.GetTR()) { 85 if (!state.GetTransferFunc()) 86 state.SetTransferFunc(m_pRenderStatus->GetTransferFunc(state.GetTR())); 87 88 if (state.GetTransferFunc() && !state.GetTransferFunc()->GetIdentity()) { 89 m_pDIBSource = m_Loader.m_pBitmap = 90 state.GetTransferFunc()->TranslateImage(m_Loader.m_pBitmap); 91 if (m_Loader.m_bCached && m_Loader.m_pMask) 92 m_Loader.m_pMask = m_Loader.m_pMask->Clone(nullptr); 93 m_Loader.m_bCached = false; 94 } 95 } 96 m_FillArgb = 0; 97 m_bPatternColor = false; 98 m_pPattern = nullptr; 99 if (m_pDIBSource->IsAlphaMask()) { 100 const CPDF_Color* pColor = m_pImageObject->m_ColorState.GetFillColor(); 101 if (pColor && pColor->IsPattern()) { 102 m_pPattern = pColor->GetPattern(); 103 if (m_pPattern) 104 m_bPatternColor = true; 105 } 106 m_FillArgb = m_pRenderStatus->GetFillArgb(m_pImageObject.Get()); 107 } else if (m_pRenderStatus->GetRenderOptions()->ColorModeIs( 108 CPDF_RenderOptions::kGray)) { 109 RetainPtr<CFX_DIBitmap> pClone = m_pDIBSource->Clone(nullptr); 110 if (!pClone) 111 return false; 112 113 pClone->ConvertColorScale(0xffffff, 0); 114 m_pDIBSource = pClone; 115 } 116 m_Flags = 0; 117 if (m_pRenderStatus->GetRenderOptions()->HasFlag(RENDER_FORCE_DOWNSAMPLE)) 118 m_Flags |= RENDER_FORCE_DOWNSAMPLE; 119 else if (m_pRenderStatus->GetRenderOptions()->HasFlag(RENDER_FORCE_HALFTONE)) 120 m_Flags |= RENDER_FORCE_HALFTONE; 121 122 if (m_pRenderStatus->GetRenderDevice()->GetDeviceClass() != FXDC_DISPLAY) 123 HandleFilters(); 124 125 if (m_pRenderStatus->GetRenderOptions()->HasFlag(RENDER_NOIMAGESMOOTH)) 126 m_Flags |= FXDIB_NOSMOOTH; 127 else if (m_pImageObject->GetImage()->IsInterpol()) 128 m_Flags |= FXDIB_INTERPOL; 129 130 if (m_Loader.m_pMask) 131 return DrawMaskedImage(); 132 133 if (m_bPatternColor) 134 return DrawPatternImage(m_pObj2Device.Get()); 135 136 if (m_BitmapAlpha != 255 || !state.HasRef() || !state.GetFillOP() || 137 state.GetOPMode() != 0 || state.GetBlendType() != FXDIB_BLEND_NORMAL || 138 state.GetStrokeAlpha() != 1.0f || state.GetFillAlpha() != 1.0f) { 139 return StartDIBSource(); 140 } 141 CPDF_Document* pDocument = nullptr; 142 CPDF_Page* pPage = nullptr; 143 if (auto* pPageCache = m_pRenderStatus->GetContext()->GetPageCache()) { 144 pPage = pPageCache->GetPage(); 145 pDocument = pPage->m_pDocument.Get(); 146 } else { 147 pDocument = m_pImageObject->GetImage()->GetDocument(); 148 } 149 CPDF_Dictionary* pPageResources = 150 pPage ? pPage->m_pPageResources.Get() : nullptr; 151 CPDF_Object* pCSObj = 152 m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor( 153 "ColorSpace"); 154 CPDF_ColorSpace* pColorSpace = 155 pDocument->LoadColorSpace(pCSObj, pPageResources); 156 if (!pColorSpace) 157 return StartDIBSource(); 158 int format = pColorSpace->GetFamily(); 159 if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION || 160 format == PDFCS_DEVICEN) { 161 m_BlendType = FXDIB_BLEND_DARKEN; 162 } 163 pDocument->GetPageData()->ReleaseColorSpace(pCSObj); 164 return StartDIBSource(); 165 } 166 167 bool CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, 168 CPDF_ImageObject* pImageObject, 169 const CFX_Matrix* pObj2Device, 170 bool bStdCS, 171 int blendType) { 172 ASSERT(pImageObject); 173 m_pRenderStatus = pStatus; 174 m_bStdCS = bStdCS; 175 m_pImageObject = pImageObject; 176 m_BlendType = blendType; 177 m_pObj2Device = pObj2Device; 178 CPDF_Dictionary* pOC = m_pImageObject->GetImage()->GetOC(); 179 if (pOC && m_pRenderStatus->GetRenderOptions()->GetOCContext() && 180 !m_pRenderStatus->GetRenderOptions()->GetOCContext()->CheckOCGVisible( 181 pOC)) { 182 return false; 183 } 184 m_ImageMatrix = m_pImageObject->matrix(); 185 m_ImageMatrix.Concat(*pObj2Device); 186 if (StartLoadDIBSource()) 187 return true; 188 return StartRenderDIBSource(); 189 } 190 191 bool CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, 192 const RetainPtr<CFX_DIBSource>& pDIBSource, 193 FX_ARGB bitmap_argb, 194 int bitmap_alpha, 195 const CFX_Matrix* pImage2Device, 196 uint32_t flags, 197 bool bStdCS, 198 int blendType) { 199 m_pRenderStatus = pStatus; 200 m_pDIBSource = pDIBSource; 201 m_FillArgb = bitmap_argb; 202 m_BitmapAlpha = bitmap_alpha; 203 m_ImageMatrix = *pImage2Device; 204 m_Flags = flags; 205 m_bStdCS = bStdCS; 206 m_BlendType = blendType; 207 return StartDIBSource(); 208 } 209 210 bool CPDF_ImageRenderer::NotDrawing() const { 211 return m_pRenderStatus->IsPrint() && 212 !(m_pRenderStatus->GetRenderDevice()->GetRenderCaps() & 213 FXRC_BLEND_MODE); 214 } 215 216 FX_RECT CPDF_ImageRenderer::GetDrawRect() const { 217 FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOuterRect(); 218 rect.Intersect(m_pRenderStatus->GetRenderDevice()->GetClipBox()); 219 return rect; 220 } 221 222 CFX_Matrix CPDF_ImageRenderer::GetDrawMatrix(const FX_RECT& rect) const { 223 CFX_Matrix new_matrix = m_ImageMatrix; 224 new_matrix.Translate(-rect.left, -rect.top); 225 return new_matrix; 226 } 227 228 void CPDF_ImageRenderer::CalculateDrawImage( 229 CFX_DefaultRenderDevice* pBitmapDevice1, 230 CFX_DefaultRenderDevice* pBitmapDevice2, 231 const RetainPtr<CFX_DIBSource>& pDIBSource, 232 CFX_Matrix* pNewMatrix, 233 const FX_RECT& rect) const { 234 CPDF_RenderStatus bitmap_render; 235 bitmap_render.Initialize(m_pRenderStatus->GetContext(), pBitmapDevice2, 236 nullptr, nullptr, nullptr, nullptr, nullptr, 0, 237 m_pRenderStatus->GetDropObjects(), nullptr, true); 238 CPDF_ImageRenderer image_render; 239 if (image_render.Start(&bitmap_render, pDIBSource, 0xffffffff, 255, 240 pNewMatrix, m_Flags, true, FXDIB_BLEND_NORMAL)) { 241 image_render.Continue(nullptr); 242 } 243 if (m_Loader.m_MatteColor == 0xffffffff) 244 return; 245 int matte_r = FXARGB_R(m_Loader.m_MatteColor); 246 int matte_g = FXARGB_G(m_Loader.m_MatteColor); 247 int matte_b = FXARGB_B(m_Loader.m_MatteColor); 248 for (int row = 0; row < rect.Height(); row++) { 249 uint8_t* dest_scan = 250 const_cast<uint8_t*>(pBitmapDevice1->GetBitmap()->GetScanline(row)); 251 const uint8_t* mask_scan = pBitmapDevice2->GetBitmap()->GetScanline(row); 252 for (int col = 0; col < rect.Width(); col++) { 253 int alpha = *mask_scan++; 254 if (!alpha) { 255 dest_scan += 4; 256 continue; 257 } 258 int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; 259 *dest_scan++ = pdfium::clamp(orig, 0, 255); 260 orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; 261 *dest_scan++ = pdfium::clamp(orig, 0, 255); 262 orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; 263 *dest_scan++ = pdfium::clamp(orig, 0, 255); 264 dest_scan++; 265 } 266 } 267 } 268 269 bool CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device) { 270 if (NotDrawing()) { 271 m_Result = false; 272 return false; 273 } 274 275 FX_RECT rect = GetDrawRect(); 276 if (rect.IsEmpty()) 277 return false; 278 279 CFX_Matrix new_matrix = GetDrawMatrix(rect); 280 CFX_DefaultRenderDevice bitmap_device1; 281 if (!bitmap_device1.Create(rect.Width(), rect.Height(), FXDIB_Rgb32, nullptr)) 282 return true; 283 284 bitmap_device1.GetBitmap()->Clear(0xffffff); 285 CPDF_RenderStatus bitmap_render; 286 bitmap_render.Initialize(m_pRenderStatus->GetContext(), &bitmap_device1, 287 nullptr, nullptr, nullptr, nullptr, 288 m_pRenderStatus->GetRenderOptions(), 0, 289 m_pRenderStatus->GetDropObjects(), nullptr, true); 290 CFX_Matrix patternDevice = *pObj2Device; 291 patternDevice.Translate(static_cast<float>(-rect.left), 292 static_cast<float>(-rect.top)); 293 if (CPDF_TilingPattern* pTilingPattern = m_pPattern->AsTilingPattern()) { 294 bitmap_render.DrawTilingPattern(pTilingPattern, m_pImageObject.Get(), 295 &patternDevice, false); 296 } else if (CPDF_ShadingPattern* pShadingPattern = 297 m_pPattern->AsShadingPattern()) { 298 bitmap_render.DrawShadingPattern(pShadingPattern, m_pImageObject.Get(), 299 &patternDevice, false); 300 } 301 302 CFX_DefaultRenderDevice bitmap_device2; 303 if (!bitmap_device2.Create(rect.Width(), rect.Height(), FXDIB_8bppRgb, 304 nullptr)) { 305 return true; 306 } 307 bitmap_device2.GetBitmap()->Clear(0); 308 CalculateDrawImage(&bitmap_device1, &bitmap_device2, m_pDIBSource, 309 &new_matrix, rect); 310 bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); 311 bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); 312 bitmap_device1.GetBitmap()->MultiplyAlpha(255); 313 m_pRenderStatus->GetRenderDevice()->SetDIBitsWithBlend( 314 bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); 315 return false; 316 } 317 318 bool CPDF_ImageRenderer::DrawMaskedImage() { 319 if (NotDrawing()) { 320 m_Result = false; 321 return false; 322 } 323 324 FX_RECT rect = GetDrawRect(); 325 if (rect.IsEmpty()) 326 return false; 327 328 CFX_Matrix new_matrix = GetDrawMatrix(rect); 329 CFX_DefaultRenderDevice bitmap_device1; 330 if (!bitmap_device1.Create(rect.Width(), rect.Height(), FXDIB_Rgb32, nullptr)) 331 return true; 332 333 #if defined _SKIA_SUPPORT_ 334 bitmap_device1.Clear(0xffffff); 335 #else 336 bitmap_device1.GetBitmap()->Clear(0xffffff); 337 #endif 338 CPDF_RenderStatus bitmap_render; 339 bitmap_render.Initialize(m_pRenderStatus->GetContext(), &bitmap_device1, 340 nullptr, nullptr, nullptr, nullptr, nullptr, 0, 341 m_pRenderStatus->GetDropObjects(), nullptr, true); 342 CPDF_ImageRenderer image_render; 343 if (image_render.Start(&bitmap_render, m_pDIBSource, 0, 255, &new_matrix, 344 m_Flags, true, FXDIB_BLEND_NORMAL)) { 345 image_render.Continue(nullptr); 346 } 347 CFX_DefaultRenderDevice bitmap_device2; 348 if (!bitmap_device2.Create(rect.Width(), rect.Height(), FXDIB_8bppRgb, 349 nullptr)) 350 return true; 351 352 #if defined _SKIA_SUPPORT_ 353 bitmap_device2.Clear(0); 354 #else 355 bitmap_device2.GetBitmap()->Clear(0); 356 #endif 357 CalculateDrawImage(&bitmap_device1, &bitmap_device2, m_Loader.m_pMask, 358 &new_matrix, rect); 359 #ifdef _SKIA_SUPPORT_ 360 m_pRenderStatus->GetRenderDevice()->SetBitsWithMask( 361 bitmap_device1.GetBitmap(), bitmap_device2.GetBitmap(), rect.left, 362 rect.top, m_BitmapAlpha, m_BlendType); 363 #else 364 bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); 365 bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); 366 if (m_BitmapAlpha < 255) 367 bitmap_device1.GetBitmap()->MultiplyAlpha(m_BitmapAlpha); 368 m_pRenderStatus->GetRenderDevice()->SetDIBitsWithBlend( 369 bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); 370 #endif // _SKIA_SUPPORT_ 371 return false; 372 } 373 374 bool CPDF_ImageRenderer::StartDIBSource() { 375 if (!(m_Flags & RENDER_FORCE_DOWNSAMPLE) && m_pDIBSource->GetBPP() > 1) { 376 FX_SAFE_SIZE_T image_size = m_pDIBSource->GetBPP(); 377 image_size /= 8; 378 image_size *= m_pDIBSource->GetWidth(); 379 image_size *= m_pDIBSource->GetHeight(); 380 if (!image_size.IsValid()) 381 return false; 382 383 if (image_size.ValueOrDie() > FPDF_HUGE_IMAGE_SIZE && 384 !(m_Flags & RENDER_FORCE_HALFTONE)) { 385 m_Flags |= RENDER_FORCE_DOWNSAMPLE; 386 } 387 } 388 #ifdef _SKIA_SUPPORT_ 389 RetainPtr<CFX_DIBitmap> premultiplied = m_pDIBSource->Clone(nullptr); 390 if (m_pDIBSource->HasAlpha()) 391 CFX_SkiaDeviceDriver::PreMultiply(premultiplied); 392 if (m_pRenderStatus->GetRenderDevice()->StartDIBitsWithBlend( 393 premultiplied, m_BitmapAlpha, m_FillArgb, &m_ImageMatrix, m_Flags, 394 &m_DeviceHandle, m_BlendType)) { 395 if (m_DeviceHandle) { 396 m_Status = 3; 397 return true; 398 } 399 return false; 400 } 401 #else 402 if (m_pRenderStatus->GetRenderDevice()->StartDIBitsWithBlend( 403 m_pDIBSource, m_BitmapAlpha, m_FillArgb, &m_ImageMatrix, m_Flags, 404 &m_DeviceHandle, m_BlendType)) { 405 if (m_DeviceHandle) { 406 m_Status = 3; 407 return true; 408 } 409 return false; 410 } 411 #endif 412 CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); 413 FX_RECT image_rect = image_rect_f.GetOuterRect(); 414 int dest_width = image_rect.Width(); 415 int dest_height = image_rect.Height(); 416 if ((fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) || 417 (fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) { 418 if (NotDrawing()) { 419 m_Result = false; 420 return false; 421 } 422 423 FX_RECT clip_box = m_pRenderStatus->GetRenderDevice()->GetClipBox(); 424 clip_box.Intersect(image_rect); 425 m_Status = 2; 426 m_pTransformer = pdfium::MakeUnique<CFX_ImageTransformer>( 427 m_pDIBSource, &m_ImageMatrix, m_Flags, &clip_box); 428 return true; 429 } 430 if (m_ImageMatrix.a < 0) 431 dest_width = -dest_width; 432 433 if (m_ImageMatrix.d > 0) 434 dest_height = -dest_height; 435 436 int dest_left = dest_width > 0 ? image_rect.left : image_rect.right; 437 int dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom; 438 if (m_pDIBSource->IsOpaqueImage() && m_BitmapAlpha == 255) { 439 if (m_pRenderStatus->GetRenderDevice()->StretchDIBitsWithFlagsAndBlend( 440 m_pDIBSource, dest_left, dest_top, dest_width, dest_height, m_Flags, 441 m_BlendType)) { 442 return false; 443 } 444 } 445 if (m_pDIBSource->IsAlphaMask()) { 446 if (m_BitmapAlpha != 255) 447 m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); 448 if (m_pRenderStatus->GetRenderDevice()->StretchBitMaskWithFlags( 449 m_pDIBSource, dest_left, dest_top, dest_width, dest_height, 450 m_FillArgb, m_Flags)) { 451 return false; 452 } 453 } 454 if (NotDrawing()) { 455 m_Result = false; 456 return true; 457 } 458 459 FX_RECT clip_box = m_pRenderStatus->GetRenderDevice()->GetClipBox(); 460 FX_RECT dest_rect = clip_box; 461 dest_rect.Intersect(image_rect); 462 FX_RECT dest_clip( 463 dest_rect.left - image_rect.left, dest_rect.top - image_rect.top, 464 dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top); 465 RetainPtr<CFX_DIBitmap> pStretched = 466 m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip); 467 if (pStretched) { 468 m_pRenderStatus->CompositeDIBitmap(pStretched, dest_rect.left, 469 dest_rect.top, m_FillArgb, m_BitmapAlpha, 470 m_BlendType, false); 471 } 472 return false; 473 } 474 475 bool CPDF_ImageRenderer::StartBitmapAlpha() { 476 if (m_pDIBSource->IsOpaqueImage()) { 477 CFX_PathData path; 478 path.AppendRect(0, 0, 1, 1); 479 path.Transform(&m_ImageMatrix); 480 uint32_t fill_color = 481 ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha); 482 m_pRenderStatus->GetRenderDevice()->DrawPath(&path, nullptr, nullptr, 483 fill_color, 0, FXFILL_WINDING); 484 return false; 485 } 486 RetainPtr<CFX_DIBSource> pAlphaMask; 487 if (m_pDIBSource->IsAlphaMask()) 488 pAlphaMask = m_pDIBSource; 489 else 490 pAlphaMask = m_pDIBSource->CloneAlphaMask(); 491 492 if (fabs(m_ImageMatrix.b) >= 0.5f || fabs(m_ImageMatrix.c) >= 0.5f) { 493 int left; 494 int top; 495 RetainPtr<CFX_DIBitmap> pTransformed = 496 pAlphaMask->TransformTo(&m_ImageMatrix, &left, &top); 497 if (!pTransformed) 498 return true; 499 500 m_pRenderStatus->GetRenderDevice()->SetBitMask( 501 pTransformed, left, top, 502 ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha)); 503 return false; 504 } 505 CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); 506 FX_RECT image_rect = image_rect_f.GetOuterRect(); 507 int dest_width = 508 m_ImageMatrix.a > 0 ? image_rect.Width() : -image_rect.Width(); 509 int dest_height = 510 m_ImageMatrix.d > 0 ? -image_rect.Height() : image_rect.Height(); 511 int left = dest_width > 0 ? image_rect.left : image_rect.right; 512 int top = dest_height > 0 ? image_rect.top : image_rect.bottom; 513 m_pRenderStatus->GetRenderDevice()->StretchBitMask( 514 pAlphaMask, left, top, dest_width, dest_height, 515 ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha)); 516 return false; 517 } 518 519 bool CPDF_ImageRenderer::Continue(IFX_PauseIndicator* pPause) { 520 if (m_Status == 2) { 521 if (m_pTransformer->Continue(pPause)) 522 return true; 523 524 RetainPtr<CFX_DIBitmap> pBitmap = m_pTransformer->DetachBitmap(); 525 if (!pBitmap) 526 return false; 527 528 if (pBitmap->IsAlphaMask()) { 529 if (m_BitmapAlpha != 255) 530 m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); 531 m_Result = m_pRenderStatus->GetRenderDevice()->SetBitMask( 532 pBitmap, m_pTransformer->result().left, m_pTransformer->result().top, 533 m_FillArgb); 534 } else { 535 if (m_BitmapAlpha != 255) 536 pBitmap->MultiplyAlpha(m_BitmapAlpha); 537 m_Result = m_pRenderStatus->GetRenderDevice()->SetDIBitsWithBlend( 538 pBitmap, m_pTransformer->result().left, m_pTransformer->result().top, 539 m_BlendType); 540 } 541 return false; 542 } 543 if (m_Status == 3) { 544 return m_pRenderStatus->GetRenderDevice()->ContinueDIBits( 545 m_DeviceHandle.get(), pPause); 546 } 547 548 if (m_Status == 4) { 549 if (m_Loader.Continue(pPause, m_pRenderStatus.Get())) 550 return true; 551 552 if (StartRenderDIBSource()) 553 return Continue(pPause); 554 } 555 return false; 556 } 557 558 void CPDF_ImageRenderer::HandleFilters() { 559 CPDF_Object* pFilters = 560 m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor( 561 "Filter"); 562 if (!pFilters) 563 return; 564 565 if (pFilters->IsName()) { 566 ByteString bsDecodeType = pFilters->GetString(); 567 if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode") 568 m_Flags |= FXRENDER_IMAGE_LOSSY; 569 return; 570 } 571 572 CPDF_Array* pArray = pFilters->AsArray(); 573 if (!pArray) 574 return; 575 576 for (size_t i = 0; i < pArray->GetCount(); i++) { 577 ByteString bsDecodeType = pArray->GetStringAt(i); 578 if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode") { 579 m_Flags |= FXRENDER_IMAGE_LOSSY; 580 break; 581 } 582 } 583 } 584