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