kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 1 | // Copyright 2017 The PDFium Authors |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 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 | |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 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" |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 15 | #include "core/fxge/cfx_cliprgn.h" |
| 16 | #include "core/fxge/dib/cfx_dibitmap.h" |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 17 | #include "third_party/base/check_op.h" |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 18 | |
Haibo Huang | 49cc930 | 2020-04-27 16:14:24 -0700 | [diff] [blame] | 19 | CFX_BitmapComposer::CFX_BitmapComposer() = default; |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 20 | |
Haibo Huang | 49cc930 | 2020-04-27 16:14:24 -0700 | [diff] [blame] | 21 | CFX_BitmapComposer::~CFX_BitmapComposer() = default; |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 22 | |
| 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, |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 32 | BlendMode blend_mode) { |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 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; |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 42 | if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::kRectI) |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 43 | m_pClipMask = pClipRgn->GetMask(); |
| 44 | m_bVertical = bVertical; |
| 45 | m_bFlipX = bFlipX; |
| 46 | m_bFlipY = bFlipY; |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 47 | m_bRgbByteOrder = bRgbByteOrder; |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 48 | m_BlendMode = blend_mode; |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 49 | } |
| 50 | |
| 51 | bool CFX_BitmapComposer::SetInfo(int width, |
| 52 | int height, |
| 53 | FXDIB_Format src_format, |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 54 | pdfium::span<const uint32_t> src_palette) { |
| 55 | DCHECK_NE(src_format, FXDIB_Format::k1bppMask); |
| 56 | DCHECK_NE(src_format, FXDIB_Format::k1bppRgb); |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 57 | m_SrcFormat = src_format; |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 58 | if (!m_Compositor.Init(m_pBitmap->GetFormat(), src_format, src_palette, |
| 59 | m_MaskColor, m_BlendMode, |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 60 | m_pClipMask != nullptr || (m_BitmapAlpha < 255), |
Haibo Huang | 49cc930 | 2020-04-27 16:14:24 -0700 | [diff] [blame] | 61 | m_bRgbByteOrder)) { |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 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()); |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 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 | |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 75 | void CFX_BitmapComposer::DoCompose(pdfium::span<uint8_t> dest_scan, |
| 76 | pdfium::span<const uint8_t> src_scan, |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 77 | int dest_width, |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 78 | pdfium::span<const uint8_t> clip_scan) { |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 79 | if (m_BitmapAlpha < 255) { |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 80 | if (!clip_scan.empty()) { |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 81 | for (int i = 0; i < dest_width; ++i) |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 82 | m_pAddClipScan[i] = clip_scan[i] * m_BitmapAlpha / 255; |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 83 | } else { |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 84 | fxcrt::spanset(pdfium::make_span(m_pAddClipScan).first(dest_width), |
| 85 | m_BitmapAlpha); |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 86 | } |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 87 | clip_scan = m_pAddClipScan; |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 88 | } |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 89 | if (m_SrcFormat == FXDIB_Format::k8bppMask) { |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 90 | m_Compositor.CompositeByteMaskLine(dest_scan, src_scan, dest_width, |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 91 | clip_scan); |
| 92 | } else if (m_SrcFormat == FXDIB_Format::k8bppRgb) { |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 93 | m_Compositor.CompositePalBitmapLine(dest_scan, src_scan, 0, dest_width, |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 94 | clip_scan); |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 95 | } else { |
| 96 | m_Compositor.CompositeRgbBitmapLine(dest_scan, src_scan, dest_width, |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 97 | clip_scan); |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 98 | } |
| 99 | } |
| 100 | |
| 101 | void CFX_BitmapComposer::ComposeScanline(int line, |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 102 | pdfium::span<const uint8_t> scanline) { |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 103 | if (m_bVertical) { |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 104 | ComposeScanlineV(line, scanline); |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 105 | return; |
| 106 | } |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 107 | pdfium::span<const uint8_t> clip_scan; |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 108 | if (m_pClipMask) { |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 109 | clip_scan = |
| 110 | m_pClipMask |
| 111 | ->GetWritableScanline(m_DestTop + line - m_pClipRgn->GetBox().top) |
| 112 | .subspan(m_DestLeft - m_pClipRgn->GetBox().left); |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 113 | } |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 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); |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 126 | } |
| 127 | |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 128 | void CFX_BitmapComposer::ComposeScanlineV( |
| 129 | int line, |
| 130 | pdfium::span<const uint8_t> scanline) { |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 131 | int Bpp = m_pBitmap->GetBPP() / 8; |
| 132 | int dest_pitch = m_pBitmap->GetPitch(); |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 133 | int dest_x = m_DestLeft + (m_bFlipX ? (m_DestWidth - line - 1) : line); |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 134 | pdfium::span<uint8_t> dest_span = m_pBitmap->GetBuffer(); |
| 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 | } |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 144 | } |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 145 | uint8_t* dest_buf = dest_span.data(); |
| 146 | const int y_step = m_bFlipY ? -dest_pitch : dest_pitch; |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 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 | } |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 154 | pdfium::span<uint8_t> clip_scan; |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 155 | if (m_pClipMask) { |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 156 | clip_scan = m_pClipScanV; |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 157 | int clip_pitch = m_pClipMask->GetPitch(); |
| 158 | const uint8_t* src_clip = |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 159 | m_pClipMask->GetScanline(m_DestTop - m_pClipRgn->GetBox().top) |
| 160 | .subspan(dest_x - m_pClipRgn->GetBox().left) |
| 161 | .data(); |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 162 | if (m_bFlipY) { |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 163 | src_clip += Fx2DSizeOrDie(clip_pitch, m_DestHeight - 1); |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 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 | } |
kumarashishg | 826308d | 2023-06-23 13:21:22 +0000 | [diff] [blame] | 171 | DoCompose(m_pScanlineV, scanline, m_DestHeight, clip_scan); |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 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 | } |
Philip P. Moltmann | d904c1e | 2018-03-19 09:26:45 -0700 | [diff] [blame] | 179 | } |