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