xref: /aosp_15_r20/external/pdfium/core/fxge/dib/cfx_bitmapcomposer.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2017 The PDFium Authors
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 <string.h>
10 
11 #include "core/fxcrt/fx_2d_size.h"
12 #include "core/fxcrt/fx_coordinates.h"
13 #include "core/fxcrt/fx_safe_types.h"
14 #include "core/fxcrt/span_util.h"
15 #include "core/fxge/cfx_cliprgn.h"
16 #include "core/fxge/dib/cfx_dibitmap.h"
17 #include "third_party/base/check_op.h"
18 
19 CFX_BitmapComposer::CFX_BitmapComposer() = default;
20 
21 CFX_BitmapComposer::~CFX_BitmapComposer() = default;
22 
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)23 void CFX_BitmapComposer::Compose(const RetainPtr<CFX_DIBitmap>& pDest,
24                                  const CFX_ClipRgn* pClipRgn,
25                                  int bitmap_alpha,
26                                  uint32_t mask_color,
27                                  const FX_RECT& dest_rect,
28                                  bool bVertical,
29                                  bool bFlipX,
30                                  bool bFlipY,
31                                  bool bRgbByteOrder,
32                                  BlendMode blend_mode) {
33   m_pBitmap = pDest;
34   m_pClipRgn = pClipRgn;
35   m_DestLeft = dest_rect.left;
36   m_DestTop = dest_rect.top;
37   m_DestWidth = dest_rect.Width();
38   m_DestHeight = dest_rect.Height();
39   m_BitmapAlpha = bitmap_alpha;
40   m_MaskColor = mask_color;
41   m_pClipMask = nullptr;
42   if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::kRectI)
43     m_pClipMask = pClipRgn->GetMask();
44   m_bVertical = bVertical;
45   m_bFlipX = bFlipX;
46   m_bFlipY = bFlipY;
47   m_bRgbByteOrder = bRgbByteOrder;
48   m_BlendMode = blend_mode;
49 }
50 
SetInfo(int width,int height,FXDIB_Format src_format,pdfium::span<const uint32_t> src_palette)51 bool CFX_BitmapComposer::SetInfo(int width,
52                                  int height,
53                                  FXDIB_Format src_format,
54                                  pdfium::span<const uint32_t> src_palette) {
55   DCHECK_NE(src_format, FXDIB_Format::k1bppMask);
56   DCHECK_NE(src_format, FXDIB_Format::k1bppRgb);
57   m_SrcFormat = src_format;
58   if (!m_Compositor.Init(m_pBitmap->GetFormat(), src_format, src_palette,
59                          m_MaskColor, m_BlendMode,
60                          m_pClipMask != nullptr || (m_BitmapAlpha < 255),
61                          m_bRgbByteOrder)) {
62     return false;
63   }
64   if (m_bVertical) {
65     m_pScanlineV.resize(m_pBitmap->GetBPP() / 8 * width + 4);
66     m_pClipScanV.resize(m_pBitmap->GetHeight());
67   }
68   if (m_BitmapAlpha < 255) {
69     m_pAddClipScan.resize(m_bVertical ? m_pBitmap->GetHeight()
70                                       : m_pBitmap->GetWidth());
71   }
72   return true;
73 }
74 
DoCompose(pdfium::span<uint8_t> dest_scan,pdfium::span<const uint8_t> src_scan,int dest_width,pdfium::span<const uint8_t> clip_scan)75 void CFX_BitmapComposer::DoCompose(pdfium::span<uint8_t> dest_scan,
76                                    pdfium::span<const uint8_t> src_scan,
77                                    int dest_width,
78                                    pdfium::span<const uint8_t> clip_scan) {
79   if (m_BitmapAlpha < 255) {
80     if (!clip_scan.empty()) {
81       for (int i = 0; i < dest_width; ++i)
82         m_pAddClipScan[i] = clip_scan[i] * m_BitmapAlpha / 255;
83     } else {
84       fxcrt::spanset(pdfium::make_span(m_pAddClipScan).first(dest_width),
85                      m_BitmapAlpha);
86     }
87     clip_scan = m_pAddClipScan;
88   }
89   if (m_SrcFormat == FXDIB_Format::k8bppMask) {
90     m_Compositor.CompositeByteMaskLine(dest_scan, src_scan, dest_width,
91                                        clip_scan);
92   } else if (m_SrcFormat == FXDIB_Format::k8bppRgb) {
93     m_Compositor.CompositePalBitmapLine(dest_scan, src_scan, 0, dest_width,
94                                         clip_scan);
95   } else {
96     m_Compositor.CompositeRgbBitmapLine(dest_scan, src_scan, dest_width,
97                                         clip_scan);
98   }
99 }
100 
ComposeScanline(int line,pdfium::span<const uint8_t> scanline)101 void CFX_BitmapComposer::ComposeScanline(int line,
102                                          pdfium::span<const uint8_t> scanline) {
103   if (m_bVertical) {
104     ComposeScanlineV(line, scanline);
105     return;
106   }
107   pdfium::span<const uint8_t> clip_scan;
108   if (m_pClipMask) {
109     clip_scan =
110         m_pClipMask
111             ->GetWritableScanline(m_DestTop + line - m_pClipRgn->GetBox().top)
112             .subspan(m_DestLeft - m_pClipRgn->GetBox().left);
113   }
114   pdfium::span<uint8_t> dest_scan =
115       m_pBitmap->GetWritableScanline(line + m_DestTop);
116   if (!dest_scan.empty()) {
117     FX_SAFE_UINT32 offset = m_DestLeft;
118     offset *= m_pBitmap->GetBPP();
119     offset /= 8;
120     if (!offset.IsValid())
121       return;
122 
123     dest_scan = dest_scan.subspan(offset.ValueOrDie());
124   }
125   DoCompose(dest_scan, scanline, m_DestWidth, clip_scan);
126 }
127 
ComposeScanlineV(int line,pdfium::span<const uint8_t> scanline)128 void CFX_BitmapComposer::ComposeScanlineV(
129     int line,
130     pdfium::span<const uint8_t> scanline) {
131   int Bpp = m_pBitmap->GetBPP() / 8;
132   int dest_pitch = m_pBitmap->GetPitch();
133   int dest_x = m_DestLeft + (m_bFlipX ? (m_DestWidth - line - 1) : line);
134   pdfium::span<uint8_t> dest_span = m_pBitmap->GetWritableBuffer();
135   if (!dest_span.empty()) {
136     const size_t dest_x_offset = Fx2DSizeOrDie(dest_x, Bpp);
137     const size_t dest_y_offset = Fx2DSizeOrDie(m_DestTop, dest_pitch);
138     dest_span = dest_span.subspan(dest_y_offset).subspan(dest_x_offset);
139     if (m_bFlipY) {
140       const size_t dest_flip_offset =
141           Fx2DSizeOrDie(dest_pitch, m_DestHeight - 1);
142       dest_span = dest_span.subspan(dest_flip_offset);
143     }
144   }
145   uint8_t* dest_buf = dest_span.data();
146   const int y_step = m_bFlipY ? -dest_pitch : dest_pitch;
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   pdfium::span<uint8_t> clip_scan;
155   if (m_pClipMask) {
156     clip_scan = m_pClipScanV;
157     int clip_pitch = m_pClipMask->GetPitch();
158     const uint8_t* src_clip =
159         m_pClipMask->GetScanline(m_DestTop - m_pClipRgn->GetBox().top)
160             .subspan(dest_x - m_pClipRgn->GetBox().left)
161             .data();
162     if (m_bFlipY) {
163       src_clip += Fx2DSizeOrDie(clip_pitch, m_DestHeight - 1);
164       clip_pitch = -clip_pitch;
165     }
166     for (int i = 0; i < m_DestHeight; ++i) {
167       clip_scan[i] = *src_clip;
168       src_clip += clip_pitch;
169     }
170   }
171   DoCompose(m_pScanlineV, scanline, m_DestHeight, clip_scan);
172   src_scan = m_pScanlineV.data();
173   dest_scan = dest_buf;
174   for (int i = 0; i < m_DestHeight; ++i) {
175     for (int j = 0; j < Bpp; ++j)
176       dest_scan[j] = *src_scan++;
177     dest_scan += y_step;
178   }
179 }
180