• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CPDF_ImageRenderer()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 
~CPDF_ImageRenderer()51 CPDF_ImageRenderer::~CPDF_ImageRenderer() {
52   if (m_DeviceHandle)
53     m_pRenderStatus->m_pDevice->CancelDIBits(m_DeviceHandle);
54 }
55 
StartLoadDIBSource()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 
StartRenderDIBSource()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 
Start(CPDF_RenderStatus * pStatus,CPDF_PageObject * pObj,const CFX_Matrix * pObj2Device,bool bStdCS,int blendType)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 
Start(CPDF_RenderStatus * pStatus,const CFX_DIBSource * pDIBSource,FX_ARGB bitmap_argb,int bitmap_alpha,const CFX_Matrix * pImage2Device,uint32_t flags,bool bStdCS,int blendType)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 
NotDrawing() const229 bool CPDF_ImageRenderer::NotDrawing() const {
230   return m_pRenderStatus->m_bPrint &&
231          !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE);
232 }
233 
GetDrawRect() const234 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 
GetDrawMatrix(const FX_RECT & rect) const240 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 
CalculateDrawImage(CFX_FxgeDevice * pBitmapDevice1,CFX_FxgeDevice * pBitmapDevice2,const CFX_DIBSource * pDIBSource,CFX_Matrix * pNewMatrix,const FX_RECT & rect) const246 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 
DrawPatternImage(const CFX_Matrix * pObj2Device)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 
DrawMaskedImage()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 
StartDIBSource()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 
StartBitmapAlpha()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 
Continue(IFX_Pause * pPause)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