blob: 009a618893a645a93eb00f9bb12a1dc9b6251fb8 [file] [log] [blame]
kumarashishg826308d2023-06-23 13:21:22 +00001// Copyright 2017 The PDFium Authors
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -07002// 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
kumarashishg826308d2023-06-23 13:21:22 +00009#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. Moltmannd904c1e2018-03-19 09:26:45 -070015#include "core/fxge/cfx_cliprgn.h"
16#include "core/fxge/dib/cfx_dibitmap.h"
kumarashishg826308d2023-06-23 13:21:22 +000017#include "third_party/base/check_op.h"
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070018
Haibo Huang49cc9302020-04-27 16:14:24 -070019CFX_BitmapComposer::CFX_BitmapComposer() = default;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070020
Haibo Huang49cc9302020-04-27 16:14:24 -070021CFX_BitmapComposer::~CFX_BitmapComposer() = default;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070022
23void 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,
kumarashishg826308d2023-06-23 13:21:22 +000032 BlendMode blend_mode) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070033 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;
kumarashishg826308d2023-06-23 13:21:22 +000042 if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::kRectI)
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070043 m_pClipMask = pClipRgn->GetMask();
44 m_bVertical = bVertical;
45 m_bFlipX = bFlipX;
46 m_bFlipY = bFlipY;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070047 m_bRgbByteOrder = bRgbByteOrder;
kumarashishg826308d2023-06-23 13:21:22 +000048 m_BlendMode = blend_mode;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070049}
50
51bool CFX_BitmapComposer::SetInfo(int width,
52 int height,
53 FXDIB_Format src_format,
kumarashishg826308d2023-06-23 13:21:22 +000054 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. Moltmannd904c1e2018-03-19 09:26:45 -070057 m_SrcFormat = src_format;
kumarashishg826308d2023-06-23 13:21:22 +000058 if (!m_Compositor.Init(m_pBitmap->GetFormat(), src_format, src_palette,
59 m_MaskColor, m_BlendMode,
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070060 m_pClipMask != nullptr || (m_BitmapAlpha < 255),
Haibo Huang49cc9302020-04-27 16:14:24 -070061 m_bRgbByteOrder)) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070062 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. Moltmannd904c1e2018-03-19 09:26:45 -070067 }
68 if (m_BitmapAlpha < 255) {
69 m_pAddClipScan.resize(m_bVertical ? m_pBitmap->GetHeight()
70 : m_pBitmap->GetWidth());
71 }
72 return true;
73}
74
kumarashishg826308d2023-06-23 13:21:22 +000075void CFX_BitmapComposer::DoCompose(pdfium::span<uint8_t> dest_scan,
76 pdfium::span<const uint8_t> src_scan,
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070077 int dest_width,
kumarashishg826308d2023-06-23 13:21:22 +000078 pdfium::span<const uint8_t> clip_scan) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070079 if (m_BitmapAlpha < 255) {
kumarashishg826308d2023-06-23 13:21:22 +000080 if (!clip_scan.empty()) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070081 for (int i = 0; i < dest_width; ++i)
kumarashishg826308d2023-06-23 13:21:22 +000082 m_pAddClipScan[i] = clip_scan[i] * m_BitmapAlpha / 255;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070083 } else {
kumarashishg826308d2023-06-23 13:21:22 +000084 fxcrt::spanset(pdfium::make_span(m_pAddClipScan).first(dest_width),
85 m_BitmapAlpha);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070086 }
kumarashishg826308d2023-06-23 13:21:22 +000087 clip_scan = m_pAddClipScan;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070088 }
kumarashishg826308d2023-06-23 13:21:22 +000089 if (m_SrcFormat == FXDIB_Format::k8bppMask) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070090 m_Compositor.CompositeByteMaskLine(dest_scan, src_scan, dest_width,
kumarashishg826308d2023-06-23 13:21:22 +000091 clip_scan);
92 } else if (m_SrcFormat == FXDIB_Format::k8bppRgb) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070093 m_Compositor.CompositePalBitmapLine(dest_scan, src_scan, 0, dest_width,
kumarashishg826308d2023-06-23 13:21:22 +000094 clip_scan);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070095 } else {
96 m_Compositor.CompositeRgbBitmapLine(dest_scan, src_scan, dest_width,
kumarashishg826308d2023-06-23 13:21:22 +000097 clip_scan);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070098 }
99}
100
101void CFX_BitmapComposer::ComposeScanline(int line,
kumarashishg826308d2023-06-23 13:21:22 +0000102 pdfium::span<const uint8_t> scanline) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700103 if (m_bVertical) {
kumarashishg826308d2023-06-23 13:21:22 +0000104 ComposeScanlineV(line, scanline);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700105 return;
106 }
kumarashishg826308d2023-06-23 13:21:22 +0000107 pdfium::span<const uint8_t> clip_scan;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700108 if (m_pClipMask) {
kumarashishg826308d2023-06-23 13:21:22 +0000109 clip_scan =
110 m_pClipMask
111 ->GetWritableScanline(m_DestTop + line - m_pClipRgn->GetBox().top)
112 .subspan(m_DestLeft - m_pClipRgn->GetBox().left);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700113 }
kumarashishg826308d2023-06-23 13:21:22 +0000114 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. Moltmannd904c1e2018-03-19 09:26:45 -0700126}
127
kumarashishg826308d2023-06-23 13:21:22 +0000128void CFX_BitmapComposer::ComposeScanlineV(
129 int line,
130 pdfium::span<const uint8_t> scanline) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700131 int Bpp = m_pBitmap->GetBPP() / 8;
132 int dest_pitch = m_pBitmap->GetPitch();
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700133 int dest_x = m_DestLeft + (m_bFlipX ? (m_DestWidth - line - 1) : line);
kumarashishg826308d2023-06-23 13:21:22 +0000134 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. Moltmannd904c1e2018-03-19 09:26:45 -0700144 }
kumarashishg826308d2023-06-23 13:21:22 +0000145 uint8_t* dest_buf = dest_span.data();
146 const int y_step = m_bFlipY ? -dest_pitch : dest_pitch;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700147 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 }
kumarashishg826308d2023-06-23 13:21:22 +0000154 pdfium::span<uint8_t> clip_scan;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700155 if (m_pClipMask) {
kumarashishg826308d2023-06-23 13:21:22 +0000156 clip_scan = m_pClipScanV;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700157 int clip_pitch = m_pClipMask->GetPitch();
158 const uint8_t* src_clip =
kumarashishg826308d2023-06-23 13:21:22 +0000159 m_pClipMask->GetScanline(m_DestTop - m_pClipRgn->GetBox().top)
160 .subspan(dest_x - m_pClipRgn->GetBox().left)
161 .data();
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700162 if (m_bFlipY) {
kumarashishg826308d2023-06-23 13:21:22 +0000163 src_clip += Fx2DSizeOrDie(clip_pitch, m_DestHeight - 1);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700164 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 }
kumarashishg826308d2023-06-23 13:21:22 +0000171 DoCompose(m_pScanlineV, scanline, m_DestHeight, clip_scan);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700172 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. Moltmannd904c1e2018-03-19 09:26:45 -0700179}