Home | History | Annotate | Download | only in dib
      1 // Copyright 2017 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/fxge/dib/cfx_imagerenderer.h"
      8 
      9 #include <memory>
     10 
     11 #include "core/fxge/cfx_cliprgn.h"
     12 #include "core/fxge/dib/cfx_imagestretcher.h"
     13 #include "core/fxge/dib/cfx_imagetransformer.h"
     14 #include "third_party/base/ptr_util.h"
     15 
     16 CFX_ImageRenderer::CFX_ImageRenderer(const RetainPtr<CFX_DIBitmap>& pDevice,
     17                                      const CFX_ClipRgn* pClipRgn,
     18                                      const RetainPtr<CFX_DIBSource>& pSource,
     19                                      int bitmap_alpha,
     20                                      uint32_t mask_color,
     21                                      const CFX_Matrix* pMatrix,
     22                                      uint32_t dib_flags,
     23                                      bool bRgbByteOrder)
     24     : m_pDevice(pDevice),
     25       m_pClipRgn(pClipRgn),
     26       m_Matrix(*pMatrix),
     27       m_BitmapAlpha(bitmap_alpha),
     28       m_BlendType(FXDIB_BLEND_NORMAL),
     29       m_bRgbByteOrder(bRgbByteOrder),
     30       m_MaskColor(mask_color),
     31       m_Status(0),
     32       m_AlphaFlag(0) {
     33   FX_RECT image_rect = m_Matrix.GetUnitRect().GetOuterRect();
     34   m_ClipBox = pClipRgn ? pClipRgn->GetBox() : FX_RECT(0, 0, pDevice->GetWidth(),
     35                                                       pDevice->GetHeight());
     36   m_ClipBox.Intersect(image_rect);
     37   if (m_ClipBox.IsEmpty())
     38     return;
     39 
     40   if ((fabs(m_Matrix.b) >= 0.5f || m_Matrix.a == 0) ||
     41       (fabs(m_Matrix.c) >= 0.5f || m_Matrix.d == 0)) {
     42     if (fabs(m_Matrix.a) < fabs(m_Matrix.b) / 20 &&
     43         fabs(m_Matrix.d) < fabs(m_Matrix.c) / 20 && fabs(m_Matrix.a) < 0.5f &&
     44         fabs(m_Matrix.d) < 0.5f) {
     45       int dest_width = image_rect.Width();
     46       int dest_height = image_rect.Height();
     47       FX_RECT bitmap_clip = m_ClipBox;
     48       bitmap_clip.Offset(-image_rect.left, -image_rect.top);
     49       bitmap_clip = FXDIB_SwapClipBox(bitmap_clip, dest_width, dest_height,
     50                                       m_Matrix.c > 0, m_Matrix.b < 0);
     51       m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox,
     52                          true, m_Matrix.c > 0, m_Matrix.b < 0, m_bRgbByteOrder,
     53                          0, m_BlendType);
     54       m_Stretcher = pdfium::MakeUnique<CFX_ImageStretcher>(
     55           &m_Composer, pSource, dest_height, dest_width, bitmap_clip,
     56           dib_flags);
     57       if (m_Stretcher->Start())
     58         m_Status = 1;
     59       return;
     60     }
     61     m_Status = 2;
     62     m_pTransformer = pdfium::MakeUnique<CFX_ImageTransformer>(
     63         pSource, &m_Matrix, dib_flags, &m_ClipBox);
     64     return;
     65   }
     66 
     67   int dest_width = image_rect.Width();
     68   if (m_Matrix.a < 0)
     69     dest_width = -dest_width;
     70 
     71   int dest_height = image_rect.Height();
     72   if (m_Matrix.d > 0)
     73     dest_height = -dest_height;
     74 
     75   if (dest_width == 0 || dest_height == 0)
     76     return;
     77 
     78   FX_RECT bitmap_clip = m_ClipBox;
     79   bitmap_clip.Offset(-image_rect.left, -image_rect.top);
     80   m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox,
     81                      false, false, false, m_bRgbByteOrder, 0, m_BlendType);
     82   m_Status = 1;
     83   m_Stretcher = pdfium::MakeUnique<CFX_ImageStretcher>(
     84       &m_Composer, pSource, dest_width, dest_height, bitmap_clip, dib_flags);
     85   m_Stretcher->Start();
     86 }
     87 
     88 CFX_ImageRenderer::~CFX_ImageRenderer() {}
     89 
     90 bool CFX_ImageRenderer::Continue(IFX_PauseIndicator* pPause) {
     91   if (m_Status == 1)
     92     return m_Stretcher->Continue(pPause);
     93   if (m_Status != 2)
     94     return false;
     95   if (m_pTransformer->Continue(pPause))
     96     return true;
     97 
     98   RetainPtr<CFX_DIBitmap> pBitmap = m_pTransformer->DetachBitmap();
     99   if (!pBitmap || !pBitmap->GetBuffer())
    100     return false;
    101 
    102   if (pBitmap->IsAlphaMask()) {
    103     if (m_BitmapAlpha != 255) {
    104       if (m_AlphaFlag >> 8) {
    105         m_AlphaFlag = (((uint8_t)((m_AlphaFlag & 0xff) * m_BitmapAlpha / 255)) |
    106                        ((m_AlphaFlag >> 8) << 8));
    107       } else {
    108         m_MaskColor = FXARGB_MUL_ALPHA(m_MaskColor, m_BitmapAlpha);
    109       }
    110     }
    111     m_pDevice->CompositeMask(
    112         m_pTransformer->result().left, m_pTransformer->result().top,
    113         pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap, m_MaskColor, 0, 0,
    114         m_BlendType, m_pClipRgn.Get(), m_bRgbByteOrder, m_AlphaFlag);
    115   } else {
    116     if (m_BitmapAlpha != 255)
    117       pBitmap->MultiplyAlpha(m_BitmapAlpha);
    118     m_pDevice->CompositeBitmap(
    119         m_pTransformer->result().left, m_pTransformer->result().top,
    120         pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap, 0, 0, m_BlendType,
    121         m_pClipRgn.Get(), m_bRgbByteOrder);
    122   }
    123   return false;
    124 }
    125