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_bitmapcomposer.h"
      8 
      9 #include "core/fxge/cfx_cliprgn.h"
     10 #include "core/fxge/dib/cfx_dibitmap.h"
     11 
     12 CFX_BitmapComposer::CFX_BitmapComposer()
     13     : m_bRgbByteOrder(false), m_BlendType(FXDIB_BLEND_NORMAL) {}
     14 
     15 CFX_BitmapComposer::~CFX_BitmapComposer() {}
     16 
     17 void CFX_BitmapComposer::Compose(const RetainPtr<CFX_DIBitmap>& pDest,
     18                                  const CFX_ClipRgn* pClipRgn,
     19                                  int bitmap_alpha,
     20                                  uint32_t mask_color,
     21                                  const FX_RECT& dest_rect,
     22                                  bool bVertical,
     23                                  bool bFlipX,
     24                                  bool bFlipY,
     25                                  bool bRgbByteOrder,
     26                                  int alpha_flag,
     27                                  int blend_type) {
     28   m_pBitmap = pDest;
     29   m_pClipRgn = pClipRgn;
     30   m_DestLeft = dest_rect.left;
     31   m_DestTop = dest_rect.top;
     32   m_DestWidth = dest_rect.Width();
     33   m_DestHeight = dest_rect.Height();
     34   m_BitmapAlpha = bitmap_alpha;
     35   m_MaskColor = mask_color;
     36   m_pClipMask = nullptr;
     37   if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI)
     38     m_pClipMask = pClipRgn->GetMask();
     39   m_bVertical = bVertical;
     40   m_bFlipX = bFlipX;
     41   m_bFlipY = bFlipY;
     42   m_AlphaFlag = alpha_flag;
     43   m_bRgbByteOrder = bRgbByteOrder;
     44   m_BlendType = blend_type;
     45 }
     46 
     47 bool CFX_BitmapComposer::SetInfo(int width,
     48                                  int height,
     49                                  FXDIB_Format src_format,
     50                                  uint32_t* pSrcPalette) {
     51   m_SrcFormat = src_format;
     52   if (!m_Compositor.Init(m_pBitmap->GetFormat(), src_format, width, pSrcPalette,
     53                          m_MaskColor, FXDIB_BLEND_NORMAL,
     54                          m_pClipMask != nullptr || (m_BitmapAlpha < 255),
     55                          m_bRgbByteOrder, m_AlphaFlag)) {
     56     return false;
     57   }
     58   if (m_bVertical) {
     59     m_pScanlineV.resize(m_pBitmap->GetBPP() / 8 * width + 4);
     60     m_pClipScanV.resize(m_pBitmap->GetHeight());
     61     if (m_pBitmap->m_pAlphaMask)
     62       m_pScanlineAlphaV.resize(width + 4);
     63   }
     64   if (m_BitmapAlpha < 255) {
     65     m_pAddClipScan.resize(m_bVertical ? m_pBitmap->GetHeight()
     66                                       : m_pBitmap->GetWidth());
     67   }
     68   return true;
     69 }
     70 
     71 void CFX_BitmapComposer::DoCompose(uint8_t* dest_scan,
     72                                    const uint8_t* src_scan,
     73                                    int dest_width,
     74                                    const uint8_t* clip_scan,
     75                                    const uint8_t* src_extra_alpha,
     76                                    uint8_t* dst_extra_alpha) {
     77   uint8_t* pAddClipScan = m_pAddClipScan.data();
     78   if (m_BitmapAlpha < 255) {
     79     if (clip_scan) {
     80       for (int i = 0; i < dest_width; ++i)
     81         pAddClipScan[i] = clip_scan[i] * m_BitmapAlpha / 255;
     82     } else {
     83       memset(pAddClipScan, m_BitmapAlpha, dest_width);
     84     }
     85     clip_scan = pAddClipScan;
     86   }
     87   if (m_SrcFormat == FXDIB_8bppMask) {
     88     m_Compositor.CompositeByteMaskLine(dest_scan, src_scan, dest_width,
     89                                        clip_scan, dst_extra_alpha);
     90   } else if ((m_SrcFormat & 0xff) == 8) {
     91     m_Compositor.CompositePalBitmapLine(dest_scan, src_scan, 0, dest_width,
     92                                         clip_scan, src_extra_alpha,
     93                                         dst_extra_alpha);
     94   } else {
     95     m_Compositor.CompositeRgbBitmapLine(dest_scan, src_scan, dest_width,
     96                                         clip_scan, src_extra_alpha,
     97                                         dst_extra_alpha);
     98   }
     99 }
    100 
    101 void CFX_BitmapComposer::ComposeScanline(int line,
    102                                          const uint8_t* scanline,
    103                                          const uint8_t* scan_extra_alpha) {
    104   if (m_bVertical) {
    105     ComposeScanlineV(line, scanline, scan_extra_alpha);
    106     return;
    107   }
    108   const uint8_t* clip_scan = nullptr;
    109   if (m_pClipMask) {
    110     clip_scan = m_pClipMask->GetBuffer() +
    111                 (m_DestTop + line - m_pClipRgn->GetBox().top) *
    112                     m_pClipMask->GetPitch() +
    113                 (m_DestLeft - m_pClipRgn->GetBox().left);
    114   }
    115   uint8_t* dest_scan =
    116       const_cast<uint8_t*>(m_pBitmap->GetScanline(line + m_DestTop)) +
    117       m_DestLeft * m_pBitmap->GetBPP() / 8;
    118   uint8_t* dest_alpha_scan =
    119       m_pBitmap->m_pAlphaMask
    120           ? const_cast<uint8_t*>(
    121                 m_pBitmap->m_pAlphaMask->GetScanline(line + m_DestTop)) +
    122                 m_DestLeft
    123           : nullptr;
    124   DoCompose(dest_scan, scanline, m_DestWidth, clip_scan, scan_extra_alpha,
    125             dest_alpha_scan);
    126 }
    127 
    128 void CFX_BitmapComposer::ComposeScanlineV(int line,
    129                                           const uint8_t* scanline,
    130                                           const uint8_t* scan_extra_alpha) {
    131   int Bpp = m_pBitmap->GetBPP() / 8;
    132   int dest_pitch = m_pBitmap->GetPitch();
    133   int dest_alpha_pitch =
    134       m_pBitmap->m_pAlphaMask ? m_pBitmap->m_pAlphaMask->GetPitch() : 0;
    135   int dest_x = m_DestLeft + (m_bFlipX ? (m_DestWidth - line - 1) : line);
    136   uint8_t* dest_buf =
    137       m_pBitmap->GetBuffer() + dest_x * Bpp + m_DestTop * dest_pitch;
    138   uint8_t* dest_alpha_buf = m_pBitmap->m_pAlphaMask
    139                                 ? m_pBitmap->m_pAlphaMask->GetBuffer() +
    140                                       dest_x + m_DestTop * dest_alpha_pitch
    141                                 : nullptr;
    142   if (m_bFlipY) {
    143     dest_buf += dest_pitch * (m_DestHeight - 1);
    144     dest_alpha_buf += dest_alpha_pitch * (m_DestHeight - 1);
    145   }
    146   int y_step = dest_pitch;
    147   int y_alpha_step = dest_alpha_pitch;
    148   if (m_bFlipY) {
    149     y_step = -y_step;
    150     y_alpha_step = -y_alpha_step;
    151   }
    152   uint8_t* src_scan = m_pScanlineV.data();
    153   uint8_t* dest_scan = dest_buf;
    154   for (int i = 0; i < m_DestHeight; ++i) {
    155     for (int j = 0; j < Bpp; ++j)
    156       *src_scan++ = dest_scan[j];
    157     dest_scan += y_step;
    158   }
    159   uint8_t* src_alpha_scan = m_pScanlineAlphaV.data();
    160   uint8_t* dest_alpha_scan = dest_alpha_buf;
    161   if (dest_alpha_scan) {
    162     for (int i = 0; i < m_DestHeight; ++i) {
    163       *src_alpha_scan++ = *dest_alpha_scan;
    164       dest_alpha_scan += y_alpha_step;
    165     }
    166   }
    167   uint8_t* clip_scan = nullptr;
    168   if (m_pClipMask) {
    169     clip_scan = m_pClipScanV.data();
    170     int clip_pitch = m_pClipMask->GetPitch();
    171     const uint8_t* src_clip =
    172         m_pClipMask->GetBuffer() +
    173         (m_DestTop - m_pClipRgn->GetBox().top) * clip_pitch +
    174         (dest_x - m_pClipRgn->GetBox().left);
    175     if (m_bFlipY) {
    176       src_clip += clip_pitch * (m_DestHeight - 1);
    177       clip_pitch = -clip_pitch;
    178     }
    179     for (int i = 0; i < m_DestHeight; ++i) {
    180       clip_scan[i] = *src_clip;
    181       src_clip += clip_pitch;
    182     }
    183   }
    184   DoCompose(m_pScanlineV.data(), scanline, m_DestHeight, clip_scan,
    185             scan_extra_alpha, m_pScanlineAlphaV.data());
    186   src_scan = m_pScanlineV.data();
    187   dest_scan = dest_buf;
    188   for (int i = 0; i < m_DestHeight; ++i) {
    189     for (int j = 0; j < Bpp; ++j)
    190       dest_scan[j] = *src_scan++;
    191     dest_scan += y_step;
    192   }
    193   src_alpha_scan = m_pScanlineAlphaV.data();
    194   dest_alpha_scan = dest_alpha_buf;
    195   if (!dest_alpha_scan)
    196     return;
    197   for (int i = 0; i < m_DestHeight; ++i) {
    198     *dest_alpha_scan = *src_alpha_scan++;
    199     dest_alpha_scan += y_alpha_step;
    200   }
    201 }
    202