Home | History | Annotate | Download | only in fxfa
      1 // Copyright 2018 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 "xfa/fxfa/cxfa_imagerenderer.h"
      8 
      9 #include "core/fxge/cfx_renderdevice.h"
     10 #include "core/fxge/dib/cfx_dibsource.h"
     11 #include "core/fxge/dib/cfx_imagerenderer.h"
     12 #include "core/fxge/dib/cfx_imagetransformer.h"
     13 #include "third_party/base/ptr_util.h"
     14 
     15 CXFA_ImageRenderer::CXFA_ImageRenderer(
     16     CFX_RenderDevice* pDevice,
     17     const RetainPtr<CFX_DIBSource>& pDIBSource,
     18     const CFX_Matrix* pImage2Device)
     19     : m_pDevice(pDevice),
     20       m_ImageMatrix(*pImage2Device),
     21       m_pDIBSource(pDIBSource) {}
     22 
     23 CXFA_ImageRenderer::~CXFA_ImageRenderer() {}
     24 
     25 bool CXFA_ImageRenderer::Start() {
     26   if (m_pDevice->StartDIBitsWithBlend(m_pDIBSource, 255, 0, &m_ImageMatrix,
     27                                       FXDIB_INTERPOL, &m_DeviceHandle,
     28                                       FXDIB_BLEND_NORMAL)) {
     29     if (m_DeviceHandle) {
     30       m_Status = 3;
     31       return true;
     32     }
     33     return false;
     34   }
     35   CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect();
     36   FX_RECT image_rect = image_rect_f.GetOuterRect();
     37   int dest_width = image_rect.Width();
     38   int dest_height = image_rect.Height();
     39   if ((fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) ||
     40       (fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) {
     41     RetainPtr<CFX_DIBSource> pDib = m_pDIBSource;
     42     if (m_pDIBSource->HasAlpha() &&
     43         !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE) &&
     44         !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
     45       m_pCloneConvert = m_pDIBSource->CloneConvert(FXDIB_Rgb);
     46       if (!m_pCloneConvert)
     47         return false;
     48 
     49       pDib = m_pCloneConvert;
     50     }
     51     FX_RECT clip_box = m_pDevice->GetClipBox();
     52     clip_box.Intersect(image_rect);
     53     m_Status = 2;
     54     m_pTransformer = pdfium::MakeUnique<CFX_ImageTransformer>(
     55         pDib, &m_ImageMatrix, FXDIB_INTERPOL, &clip_box);
     56     return true;
     57   }
     58   if (m_ImageMatrix.a < 0)
     59     dest_width = -dest_width;
     60   if (m_ImageMatrix.d > 0)
     61     dest_height = -dest_height;
     62   int dest_left, dest_top;
     63   dest_left = dest_width > 0 ? image_rect.left : image_rect.right;
     64   dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom;
     65   if (m_pDIBSource->IsOpaqueImage()) {
     66     if (m_pDevice->StretchDIBitsWithFlagsAndBlend(
     67             m_pDIBSource, dest_left, dest_top, dest_width, dest_height,
     68             FXDIB_INTERPOL, FXDIB_BLEND_NORMAL)) {
     69       return false;
     70     }
     71   }
     72   if (m_pDIBSource->IsAlphaMask()) {
     73     if (m_pDevice->StretchBitMaskWithFlags(m_pDIBSource, dest_left, dest_top,
     74                                            dest_width, dest_height, 0,
     75                                            FXDIB_INTERPOL)) {
     76       return false;
     77     }
     78   }
     79 
     80   FX_RECT clip_box = m_pDevice->GetClipBox();
     81   FX_RECT dest_rect = clip_box;
     82   dest_rect.Intersect(image_rect);
     83   FX_RECT dest_clip(
     84       dest_rect.left - image_rect.left, dest_rect.top - image_rect.top,
     85       dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top);
     86   RetainPtr<CFX_DIBitmap> pStretched = m_pDIBSource->StretchTo(
     87       dest_width, dest_height, FXDIB_INTERPOL, &dest_clip);
     88   if (pStretched)
     89     CompositeDIBitmap(pStretched, dest_rect.left, dest_rect.top);
     90 
     91   return false;
     92 }
     93 
     94 bool CXFA_ImageRenderer::Continue() {
     95   if (m_Status == 2) {
     96     if (m_pTransformer->Continue(nullptr))
     97       return true;
     98 
     99     RetainPtr<CFX_DIBitmap> pBitmap = m_pTransformer->DetachBitmap();
    100     if (!pBitmap)
    101       return false;
    102 
    103     if (pBitmap->IsAlphaMask()) {
    104       m_pDevice->SetBitMask(pBitmap, m_pTransformer->result().left,
    105                             m_pTransformer->result().top, 0);
    106     } else {
    107       m_pDevice->SetDIBitsWithBlend(pBitmap, m_pTransformer->result().left,
    108                                     m_pTransformer->result().top,
    109                                     FXDIB_BLEND_NORMAL);
    110     }
    111     return false;
    112   }
    113   if (m_Status == 3)
    114     return m_pDevice->ContinueDIBits(m_DeviceHandle.get(), nullptr);
    115 
    116   return false;
    117 }
    118 
    119 void CXFA_ImageRenderer::CompositeDIBitmap(
    120     const RetainPtr<CFX_DIBitmap>& pDIBitmap,
    121     int left,
    122     int top) {
    123   if (!pDIBitmap)
    124     return;
    125 
    126   if (!pDIBitmap->IsAlphaMask()) {
    127     if (m_pDevice->SetDIBits(pDIBitmap, left, top))
    128       return;
    129   } else if (m_pDevice->SetBitMask(pDIBitmap, left, top, 0)) {
    130     return;
    131   }
    132 
    133   bool bGetBackGround = ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) ||
    134                         (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) &&
    135                          (m_pDevice->GetRenderCaps() & FXRC_GET_BITS));
    136   if (bGetBackGround) {
    137     if (pDIBitmap->IsAlphaMask())
    138       return;
    139 
    140     m_pDevice->SetDIBitsWithBlend(pDIBitmap, left, top, FXDIB_BLEND_NORMAL);
    141     return;
    142   }
    143   if (!pDIBitmap->HasAlpha() ||
    144       (m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE)) {
    145     return;
    146   }
    147 
    148   RetainPtr<CFX_DIBitmap> pCloneConvert = pDIBitmap->CloneConvert(FXDIB_Rgb);
    149   if (!pCloneConvert)
    150     return;
    151 
    152   CXFA_ImageRenderer imageRender(m_pDevice, pCloneConvert, &m_ImageMatrix);
    153   if (!imageRender.Start())
    154     return;
    155 
    156   while (imageRender.Continue())
    157     continue;
    158 }
    159