// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "core/fxge/dib/cfx_bitmapcomposer.h" #include "core/fxcodec/fx_codec.h" #include "core/fxge/cfx_gemodule.h" #include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/ge/cfx_cliprgn.h" CFX_BitmapComposer::CFX_BitmapComposer() { m_pScanlineV = nullptr; m_pScanlineAlphaV = nullptr; m_pClipScanV = nullptr; m_pAddClipScan = nullptr; m_bRgbByteOrder = false; m_BlendType = FXDIB_BLEND_NORMAL; } CFX_BitmapComposer::~CFX_BitmapComposer() { FX_Free(m_pScanlineV); FX_Free(m_pScanlineAlphaV); FX_Free(m_pClipScanV); FX_Free(m_pAddClipScan); } void CFX_BitmapComposer::Compose(const CFX_RetainPtr& pDest, const CFX_ClipRgn* pClipRgn, int bitmap_alpha, uint32_t mask_color, FX_RECT& dest_rect, bool bVertical, bool bFlipX, bool bFlipY, bool bRgbByteOrder, int alpha_flag, void* pIccTransform, int blend_type) { m_pBitmap = pDest; m_pClipRgn = pClipRgn; m_DestLeft = dest_rect.left; m_DestTop = dest_rect.top; m_DestWidth = dest_rect.Width(); m_DestHeight = dest_rect.Height(); m_BitmapAlpha = bitmap_alpha; m_MaskColor = mask_color; m_pClipMask = nullptr; if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) m_pClipMask = pClipRgn->GetMask(); m_bVertical = bVertical; m_bFlipX = bFlipX; m_bFlipY = bFlipY; m_AlphaFlag = alpha_flag; m_pIccTransform = pIccTransform; m_bRgbByteOrder = bRgbByteOrder; m_BlendType = blend_type; } bool CFX_BitmapComposer::SetInfo(int width, int height, FXDIB_Format src_format, uint32_t* pSrcPalette) { m_SrcFormat = src_format; if (!m_Compositor.Init(m_pBitmap->GetFormat(), src_format, width, pSrcPalette, m_MaskColor, FXDIB_BLEND_NORMAL, m_pClipMask != nullptr || (m_BitmapAlpha < 255), m_bRgbByteOrder, m_AlphaFlag, m_pIccTransform)) { return false; } if (m_bVertical) { m_pScanlineV = FX_Alloc(uint8_t, m_pBitmap->GetBPP() / 8 * width + 4); m_pClipScanV = FX_Alloc(uint8_t, m_pBitmap->GetHeight()); if (m_pBitmap->m_pAlphaMask) { m_pScanlineAlphaV = FX_Alloc(uint8_t, width + 4); } } if (m_BitmapAlpha < 255) { m_pAddClipScan = FX_Alloc( uint8_t, m_bVertical ? m_pBitmap->GetHeight() : m_pBitmap->GetWidth()); } return true; } void CFX_BitmapComposer::DoCompose(uint8_t* dest_scan, const uint8_t* src_scan, int dest_width, const uint8_t* clip_scan, const uint8_t* src_extra_alpha, uint8_t* dst_extra_alpha) { if (m_BitmapAlpha < 255) { if (clip_scan) { for (int i = 0; i < dest_width; i++) { m_pAddClipScan[i] = clip_scan[i] * m_BitmapAlpha / 255; } } else { memset(m_pAddClipScan, m_BitmapAlpha, dest_width); } clip_scan = m_pAddClipScan; } if (m_SrcFormat == FXDIB_8bppMask) { m_Compositor.CompositeByteMaskLine(dest_scan, src_scan, dest_width, clip_scan, dst_extra_alpha); } else if ((m_SrcFormat & 0xff) == 8) { m_Compositor.CompositePalBitmapLine(dest_scan, src_scan, 0, dest_width, clip_scan, src_extra_alpha, dst_extra_alpha); } else { m_Compositor.CompositeRgbBitmapLine(dest_scan, src_scan, dest_width, clip_scan, src_extra_alpha, dst_extra_alpha); } } void CFX_BitmapComposer::ComposeScanline(int line, const uint8_t* scanline, const uint8_t* scan_extra_alpha) { if (m_bVertical) { ComposeScanlineV(line, scanline, scan_extra_alpha); return; } const uint8_t* clip_scan = nullptr; if (m_pClipMask) clip_scan = m_pClipMask->GetBuffer() + (m_DestTop + line - m_pClipRgn->GetBox().top) * m_pClipMask->GetPitch() + (m_DestLeft - m_pClipRgn->GetBox().left); uint8_t* dest_scan = (uint8_t*)m_pBitmap->GetScanline(line + m_DestTop) + m_DestLeft * m_pBitmap->GetBPP() / 8; uint8_t* dest_alpha_scan = m_pBitmap->m_pAlphaMask ? (uint8_t*)m_pBitmap->m_pAlphaMask->GetScanline(line + m_DestTop) + m_DestLeft : nullptr; DoCompose(dest_scan, scanline, m_DestWidth, clip_scan, scan_extra_alpha, dest_alpha_scan); } void CFX_BitmapComposer::ComposeScanlineV(int line, const uint8_t* scanline, const uint8_t* scan_extra_alpha) { int i; int Bpp = m_pBitmap->GetBPP() / 8; int dest_pitch = m_pBitmap->GetPitch(); int dest_alpha_pitch = m_pBitmap->m_pAlphaMask ? m_pBitmap->m_pAlphaMask->GetPitch() : 0; int dest_x = m_DestLeft + (m_bFlipX ? (m_DestWidth - line - 1) : line); uint8_t* dest_buf = m_pBitmap->GetBuffer() + dest_x * Bpp + m_DestTop * dest_pitch; uint8_t* dest_alpha_buf = m_pBitmap->m_pAlphaMask ? m_pBitmap->m_pAlphaMask->GetBuffer() + dest_x + m_DestTop * dest_alpha_pitch : nullptr; if (m_bFlipY) { dest_buf += dest_pitch * (m_DestHeight - 1); dest_alpha_buf += dest_alpha_pitch * (m_DestHeight - 1); } int y_step = dest_pitch; int y_alpha_step = dest_alpha_pitch; if (m_bFlipY) { y_step = -y_step; y_alpha_step = -y_alpha_step; } uint8_t* src_scan = m_pScanlineV; uint8_t* dest_scan = dest_buf; for (i = 0; i < m_DestHeight; i++) { for (int j = 0; j < Bpp; j++) { *src_scan++ = dest_scan[j]; } dest_scan += y_step; } uint8_t* src_alpha_scan = m_pScanlineAlphaV; uint8_t* dest_alpha_scan = dest_alpha_buf; if (dest_alpha_scan) { for (i = 0; i < m_DestHeight; i++) { *src_alpha_scan++ = *dest_alpha_scan; dest_alpha_scan += y_alpha_step; } } uint8_t* clip_scan = nullptr; if (m_pClipMask) { clip_scan = m_pClipScanV; int clip_pitch = m_pClipMask->GetPitch(); const uint8_t* src_clip = m_pClipMask->GetBuffer() + (m_DestTop - m_pClipRgn->GetBox().top) * clip_pitch + (dest_x - m_pClipRgn->GetBox().left); if (m_bFlipY) { src_clip += clip_pitch * (m_DestHeight - 1); clip_pitch = -clip_pitch; } for (i = 0; i < m_DestHeight; i++) { clip_scan[i] = *src_clip; src_clip += clip_pitch; } } DoCompose(m_pScanlineV, scanline, m_DestHeight, clip_scan, scan_extra_alpha, m_pScanlineAlphaV); src_scan = m_pScanlineV; dest_scan = dest_buf; for (i = 0; i < m_DestHeight; i++) { for (int j = 0; j < Bpp; j++) { dest_scan[j] = *src_scan++; } dest_scan += y_step; } src_alpha_scan = m_pScanlineAlphaV; dest_alpha_scan = dest_alpha_buf; if (dest_alpha_scan) { for (i = 0; i < m_DestHeight; i++) { *dest_alpha_scan = *src_alpha_scan++; dest_alpha_scan += y_alpha_step; } } }