Home | History | Annotate | Download | only in render
      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