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