blob: 07c7b744db0df1fa0922a8a310ef0837f241a1dd [file] [log] [blame]
kumarashishg826308d2023-06-23 13:21:22 +00001// Copyright 2017 The PDFium Authors
Haibo Huang49cc9302020-04-27 16:14:24 -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_dibbase.h"
8
kumarashishg826308d2023-06-23 13:21:22 +00009#include <stdint.h>
10#include <string.h>
11
Haibo Huang49cc9302020-04-27 16:14:24 -070012#include <algorithm>
Haibo Huang49cc9302020-04-27 16:14:24 -070013#include <utility>
14#include <vector>
15
kumarashishg826308d2023-06-23 13:21:22 +000016#include "core/fxcrt/data_vector.h"
17#include "core/fxcrt/fx_2d_size.h"
18#include "core/fxcrt/fx_coordinates.h"
19#include "core/fxcrt/fx_memory.h"
20#include "core/fxcrt/fx_safe_types.h"
21#include "core/fxcrt/span_util.h"
Haibo Huang49cc9302020-04-27 16:14:24 -070022#include "core/fxge/cfx_cliprgn.h"
23#include "core/fxge/dib/cfx_bitmapstorer.h"
Haibo Huang49cc9302020-04-27 16:14:24 -070024#include "core/fxge/dib/cfx_dibitmap.h"
25#include "core/fxge/dib/cfx_imagestretcher.h"
26#include "core/fxge/dib/cfx_imagetransformer.h"
kumarashishg826308d2023-06-23 13:21:22 +000027#include "third_party/base/check.h"
28#include "third_party/base/check_op.h"
29#include "third_party/base/notreached.h"
30#include "third_party/base/span.h"
Haibo Huang49cc9302020-04-27 16:14:24 -070031
32namespace {
33
34void ColorDecode(uint32_t pal_v, uint8_t* r, uint8_t* g, uint8_t* b) {
35 *r = static_cast<uint8_t>((pal_v & 0xf00) >> 4);
36 *g = static_cast<uint8_t>(pal_v & 0x0f0);
37 *b = static_cast<uint8_t>((pal_v & 0x00f) << 4);
38}
39
40void Obtain_Pal(std::pair<uint32_t, uint32_t>* luts,
41 uint32_t* dest_pal,
42 uint32_t lut) {
43 uint32_t lut_1 = lut - 1;
44 for (int row = 0; row < 256; ++row) {
45 int lut_offset = lut_1 - row;
46 if (lut_offset < 0)
47 lut_offset += 256;
48 uint32_t color = luts[lut_offset].second;
49 uint8_t r;
50 uint8_t g;
51 uint8_t b;
52 ColorDecode(color, &r, &g, &b);
53 dest_pal[row] = (static_cast<uint32_t>(r) << 16) |
54 (static_cast<uint32_t>(g) << 8) | b | 0xff000000;
55 luts[lut_offset].first = row;
56 }
57}
58
59class CFX_Palette {
60 public:
kumarashishg826308d2023-06-23 13:21:22 +000061 explicit CFX_Palette(const RetainPtr<const CFX_DIBBase>& pBitmap);
Haibo Huang49cc9302020-04-27 16:14:24 -070062 ~CFX_Palette();
63
64 const uint32_t* GetPalette() { return m_Palette.data(); }
65 const std::pair<uint32_t, uint32_t>* GetLuts() const { return m_Luts.data(); }
66 int32_t GetLutCount() const { return m_lut; }
67 void SetAmountLut(int row, uint32_t value) { m_Luts[row].first = value; }
68
69 private:
70 std::vector<uint32_t> m_Palette;
71 // (Amount, Color) pairs
72 std::vector<std::pair<uint32_t, uint32_t>> m_Luts;
kumarashishg826308d2023-06-23 13:21:22 +000073 int m_lut = 0;
Haibo Huang49cc9302020-04-27 16:14:24 -070074};
75
kumarashishg826308d2023-06-23 13:21:22 +000076CFX_Palette::CFX_Palette(const RetainPtr<const CFX_DIBBase>& pBitmap)
77 : m_Palette(256), m_Luts(4096) {
Haibo Huang49cc9302020-04-27 16:14:24 -070078 int bpp = pBitmap->GetBPP() / 8;
79 int width = pBitmap->GetWidth();
80 int height = pBitmap->GetHeight();
81 for (int row = 0; row < height; ++row) {
kumarashishg826308d2023-06-23 13:21:22 +000082 pdfium::span<const uint8_t> scan_line = pBitmap->GetScanline(row);
Haibo Huang49cc9302020-04-27 16:14:24 -070083 for (int col = 0; col < width; ++col) {
kumarashishg826308d2023-06-23 13:21:22 +000084 const uint8_t* src_port =
85 scan_line.subspan(Fx2DSizeOrDie(col, bpp)).data();
Haibo Huang49cc9302020-04-27 16:14:24 -070086 uint32_t b = src_port[0] & 0xf0;
87 uint32_t g = src_port[1] & 0xf0;
88 uint32_t r = src_port[2] & 0xf0;
89 uint32_t index = (r << 4) + g + (b >> 4);
90 ++m_Luts[index].first;
91 }
92 }
93 // Move non-zeros to the front and count them
94 for (int row = 0; row < 4096; ++row) {
95 if (m_Luts[row].first != 0) {
96 m_Luts[m_lut].first = m_Luts[row].first;
97 m_Luts[m_lut].second = row;
98 ++m_lut;
99 }
100 }
101 std::sort(m_Luts.begin(), m_Luts.begin() + m_lut,
102 [](const std::pair<uint32_t, uint32_t>& arg1,
103 const std::pair<uint32_t, uint32_t>& arg2) {
104 return arg1.first < arg2.first;
105 });
106 Obtain_Pal(m_Luts.data(), m_Palette.data(), m_lut);
107}
108
kumarashishg826308d2023-06-23 13:21:22 +0000109CFX_Palette::~CFX_Palette() = default;
Haibo Huang49cc9302020-04-27 16:14:24 -0700110
kumarashishg826308d2023-06-23 13:21:22 +0000111void ConvertBuffer_1bppMask2Gray(pdfium::span<uint8_t> dest_buf,
Haibo Huang49cc9302020-04-27 16:14:24 -0700112 int dest_pitch,
113 int width,
114 int height,
kumarashishg826308d2023-06-23 13:21:22 +0000115 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
Haibo Huang49cc9302020-04-27 16:14:24 -0700116 int src_left,
117 int src_top) {
118 static constexpr uint8_t kSetGray = 0xff;
119 static constexpr uint8_t kResetGray = 0x00;
120 for (int row = 0; row < height; ++row) {
kumarashishg826308d2023-06-23 13:21:22 +0000121 pdfium::span<uint8_t> dest_span =
122 dest_buf.subspan(Fx2DSizeOrDie(row, dest_pitch));
123 pdfium::span<const uint8_t> src_span =
124 pSrcBitmap->GetScanline(src_top + row);
125 fxcrt::spanset(dest_span.first(width), kResetGray);
126 uint8_t* dest_scan = dest_span.data();
127 const uint8_t* src_scan = src_span.data();
Haibo Huang49cc9302020-04-27 16:14:24 -0700128 for (int col = src_left; col < src_left + width; ++col) {
129 if (src_scan[col / 8] & (1 << (7 - col % 8)))
130 *dest_scan = kSetGray;
131 ++dest_scan;
132 }
133 }
134}
135
kumarashishg826308d2023-06-23 13:21:22 +0000136void ConvertBuffer_8bppMask2Gray(pdfium::span<uint8_t> dest_buf,
Haibo Huang49cc9302020-04-27 16:14:24 -0700137 int dest_pitch,
138 int width,
139 int height,
kumarashishg826308d2023-06-23 13:21:22 +0000140 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
Haibo Huang49cc9302020-04-27 16:14:24 -0700141 int src_left,
142 int src_top) {
143 for (int row = 0; row < height; ++row) {
kumarashishg826308d2023-06-23 13:21:22 +0000144 fxcrt::spancpy(
145 dest_buf.subspan(Fx2DSizeOrDie(row, dest_pitch)),
146 pSrcBitmap->GetScanline(src_top + row).subspan(src_left, width));
Haibo Huang49cc9302020-04-27 16:14:24 -0700147 }
148}
149
kumarashishg826308d2023-06-23 13:21:22 +0000150void ConvertBuffer_1bppPlt2Gray(pdfium::span<uint8_t> dest_buf,
Haibo Huang49cc9302020-04-27 16:14:24 -0700151 int dest_pitch,
152 int width,
153 int height,
kumarashishg826308d2023-06-23 13:21:22 +0000154 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
Haibo Huang49cc9302020-04-27 16:14:24 -0700155 int src_left,
156 int src_top) {
kumarashishg826308d2023-06-23 13:21:22 +0000157 pdfium::span<const uint32_t> src_palette = pSrcBitmap->GetPaletteSpan();
158 const uint8_t reset_r = FXARGB_R(src_palette[0]);
159 const uint8_t reset_g = FXARGB_G(src_palette[0]);
160 const uint8_t reset_b = FXARGB_B(src_palette[0]);
161 const uint8_t set_r = FXARGB_R(src_palette[1]);
162 const uint8_t set_g = FXARGB_G(src_palette[1]);
163 const uint8_t set_b = FXARGB_B(src_palette[1]);
164 const uint8_t gray0 = FXRGB2GRAY(reset_r, reset_g, reset_b);
165 const uint8_t gray1 = FXRGB2GRAY(set_r, set_g, set_b);
Haibo Huang49cc9302020-04-27 16:14:24 -0700166
167 for (int row = 0; row < height; ++row) {
kumarashishg826308d2023-06-23 13:21:22 +0000168 pdfium::span<uint8_t> dest_span =
169 dest_buf.subspan(Fx2DSizeOrDie(row, dest_pitch));
170 fxcrt::spanset(dest_span.first(width), gray0);
171 uint8_t* dest_scan = dest_span.data();
172 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row).data();
Haibo Huang49cc9302020-04-27 16:14:24 -0700173 for (int col = src_left; col < src_left + width; ++col) {
174 if (src_scan[col / 8] & (1 << (7 - col % 8)))
kumarashishg826308d2023-06-23 13:21:22 +0000175 *dest_scan = gray1;
Haibo Huang49cc9302020-04-27 16:14:24 -0700176 ++dest_scan;
177 }
178 }
179}
180
kumarashishg826308d2023-06-23 13:21:22 +0000181void ConvertBuffer_8bppPlt2Gray(pdfium::span<uint8_t> dest_buf,
Haibo Huang49cc9302020-04-27 16:14:24 -0700182 int dest_pitch,
183 int width,
184 int height,
kumarashishg826308d2023-06-23 13:21:22 +0000185 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
Haibo Huang49cc9302020-04-27 16:14:24 -0700186 int src_left,
187 int src_top) {
kumarashishg826308d2023-06-23 13:21:22 +0000188 pdfium::span<const uint32_t> src_palette = pSrcBitmap->GetPaletteSpan();
Haibo Huang49cc9302020-04-27 16:14:24 -0700189 uint8_t gray[256];
kumarashishg826308d2023-06-23 13:21:22 +0000190 for (size_t i = 0; i < std::size(gray); ++i) {
191 gray[i] = FXRGB2GRAY(FXARGB_R(src_palette[i]), FXARGB_G(src_palette[i]),
192 FXARGB_B(src_palette[i]));
Haibo Huang49cc9302020-04-27 16:14:24 -0700193 }
194
195 for (int row = 0; row < height; ++row) {
kumarashishg826308d2023-06-23 13:21:22 +0000196 uint8_t* dest_scan =
197 dest_buf.subspan(Fx2DSizeOrDie(row, dest_pitch)).data();
198 const uint8_t* src_scan =
199 pSrcBitmap->GetScanline(src_top + row).subspan(src_left).data();
Haibo Huang49cc9302020-04-27 16:14:24 -0700200 for (int col = 0; col < width; ++col)
201 *dest_scan++ = gray[*src_scan++];
202 }
203}
204
kumarashishg826308d2023-06-23 13:21:22 +0000205void ConvertBuffer_Rgb2Gray(pdfium::span<uint8_t> dest_buf,
206 int dest_pitch,
207 int width,
208 int height,
209 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
210 int src_left,
211 int src_top) {
212 const int Bpp = pSrcBitmap->GetBPP() / 8;
213 const size_t x_offset = Fx2DSizeOrDie(src_left, Bpp);
214 for (int row = 0; row < height; ++row) {
215 uint8_t* dest_scan =
216 dest_buf.subspan(Fx2DSizeOrDie(row, dest_pitch)).data();
217 const uint8_t* src_scan =
218 pSrcBitmap->GetScanline(src_top + row).subspan(x_offset).data();
219 for (int col = 0; col < width; ++col) {
220 *dest_scan++ = FXRGB2GRAY(src_scan[2], src_scan[1], src_scan[0]);
221 src_scan += Bpp;
Haibo Huang49cc9302020-04-27 16:14:24 -0700222 }
223 }
224}
225
kumarashishg826308d2023-06-23 13:21:22 +0000226void ConvertBuffer_IndexCopy(pdfium::span<uint8_t> dest_buf,
Haibo Huang49cc9302020-04-27 16:14:24 -0700227 int dest_pitch,
228 int width,
229 int height,
kumarashishg826308d2023-06-23 13:21:22 +0000230 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
Haibo Huang49cc9302020-04-27 16:14:24 -0700231 int src_left,
232 int src_top) {
233 if (pSrcBitmap->GetBPP() == 1) {
234 for (int row = 0; row < height; ++row) {
kumarashishg826308d2023-06-23 13:21:22 +0000235 pdfium::span<uint8_t> dest_span =
236 dest_buf.subspan(Fx2DSizeOrDie(row, dest_pitch));
Haibo Huang49cc9302020-04-27 16:14:24 -0700237 // Set all destination pixels to be white initially.
kumarashishg826308d2023-06-23 13:21:22 +0000238 fxcrt::spanset(dest_span.first(width), 255);
239 uint8_t* dest_scan = dest_span.data();
240 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row).data();
Haibo Huang49cc9302020-04-27 16:14:24 -0700241 for (int col = src_left; col < src_left + width; ++col) {
242 // If the source bit is set, then set the destination pixel to be black.
243 if (src_scan[col / 8] & (1 << (7 - col % 8)))
244 *dest_scan = 0;
245
246 ++dest_scan;
247 }
248 }
249 } else {
250 for (int row = 0; row < height; ++row) {
kumarashishg826308d2023-06-23 13:21:22 +0000251 fxcrt::spancpy(
252 dest_buf.subspan(Fx2DSizeOrDie(row, dest_pitch)),
253 pSrcBitmap->GetScanline(src_top + row).subspan(src_left, width));
Haibo Huang49cc9302020-04-27 16:14:24 -0700254 }
255 }
256}
257
kumarashishg826308d2023-06-23 13:21:22 +0000258void ConvertBuffer_Plt2PltRgb8(pdfium::span<uint8_t> dest_buf,
Haibo Huang49cc9302020-04-27 16:14:24 -0700259 int dest_pitch,
260 int width,
261 int height,
kumarashishg826308d2023-06-23 13:21:22 +0000262 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
Haibo Huang49cc9302020-04-27 16:14:24 -0700263 int src_left,
264 int src_top,
kumarashishg826308d2023-06-23 13:21:22 +0000265 pdfium::span<uint32_t> dst_plt) {
Haibo Huang49cc9302020-04-27 16:14:24 -0700266 ConvertBuffer_IndexCopy(dest_buf, dest_pitch, width, height, pSrcBitmap,
267 src_left, src_top);
kumarashishg826308d2023-06-23 13:21:22 +0000268 const size_t plt_size = pSrcBitmap->GetRequiredPaletteSize();
269 pdfium::span<const uint32_t> src_span = pSrcBitmap->GetPaletteSpan();
270 CHECK_LE(plt_size, src_span.size());
271
272 const uint32_t* src_plt = src_span.data();
273 for (size_t i = 0; i < plt_size; ++i)
274 dst_plt[i] = src_plt[i];
Haibo Huang49cc9302020-04-27 16:14:24 -0700275}
276
kumarashishg826308d2023-06-23 13:21:22 +0000277void ConvertBuffer_Rgb2PltRgb8(pdfium::span<uint8_t> dest_buf,
Haibo Huang49cc9302020-04-27 16:14:24 -0700278 int dest_pitch,
279 int width,
280 int height,
kumarashishg826308d2023-06-23 13:21:22 +0000281 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
Haibo Huang49cc9302020-04-27 16:14:24 -0700282 int src_left,
283 int src_top,
kumarashishg826308d2023-06-23 13:21:22 +0000284 pdfium::span<uint32_t> dst_plt) {
Haibo Huang49cc9302020-04-27 16:14:24 -0700285 int bpp = pSrcBitmap->GetBPP() / 8;
286 CFX_Palette palette(pSrcBitmap);
287 const std::pair<uint32_t, uint32_t>* Luts = palette.GetLuts();
288 int lut = palette.GetLutCount();
289 const uint32_t* pal = palette.GetPalette();
290 if (lut > 256) {
291 int err;
292 int min_err;
293 int lut_256 = lut - 256;
294 for (int row = 0; row < lut_256; ++row) {
295 min_err = 1000000;
296 uint8_t r;
297 uint8_t g;
298 uint8_t b;
299 ColorDecode(Luts[row].second, &r, &g, &b);
300 uint32_t clrindex = 0;
301 for (int col = 0; col < 256; ++col) {
302 uint32_t p_color = pal[col];
303 int d_r = r - static_cast<uint8_t>(p_color >> 16);
304 int d_g = g - static_cast<uint8_t>(p_color >> 8);
305 int d_b = b - static_cast<uint8_t>(p_color);
306 err = d_r * d_r + d_g * d_g + d_b * d_b;
307 if (err < min_err) {
308 min_err = err;
309 clrindex = col;
310 }
311 }
312 palette.SetAmountLut(row, clrindex);
313 }
314 }
315 int32_t lut_1 = lut - 1;
316 for (int row = 0; row < height; ++row) {
kumarashishg826308d2023-06-23 13:21:22 +0000317 pdfium::span<const uint8_t> src_span =
318 pSrcBitmap->GetScanline(src_top + row).subspan(src_left);
319 uint8_t* dest_scan =
320 dest_buf.subspan(Fx2DSizeOrDie(row, dest_pitch)).data();
Haibo Huang49cc9302020-04-27 16:14:24 -0700321 for (int col = 0; col < width; ++col) {
kumarashishg826308d2023-06-23 13:21:22 +0000322 const uint8_t* src_port =
323 src_span.subspan(Fx2DSizeOrDie(col, bpp)).data();
Haibo Huang49cc9302020-04-27 16:14:24 -0700324 int r = src_port[2] & 0xf0;
325 int g = src_port[1] & 0xf0;
326 int b = src_port[0] & 0xf0;
327 uint32_t clrindex = (r << 4) + g + (b >> 4);
328 for (int i = lut_1; i >= 0; --i)
329 if (clrindex == Luts[i].second) {
330 *(dest_scan + col) = static_cast<uint8_t>(Luts[i].first);
331 break;
332 }
333 }
334 }
kumarashishg826308d2023-06-23 13:21:22 +0000335 for (size_t i = 0; i < 256; ++i)
336 dst_plt[i] = pal[i];
Haibo Huang49cc9302020-04-27 16:14:24 -0700337}
338
339void ConvertBuffer_1bppMask2Rgb(FXDIB_Format dest_format,
kumarashishg826308d2023-06-23 13:21:22 +0000340 pdfium::span<uint8_t> dest_buf,
Haibo Huang49cc9302020-04-27 16:14:24 -0700341 int dest_pitch,
342 int width,
343 int height,
kumarashishg826308d2023-06-23 13:21:22 +0000344 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
Haibo Huang49cc9302020-04-27 16:14:24 -0700345 int src_left,
346 int src_top) {
347 int comps = GetCompsFromFormat(dest_format);
348 static constexpr uint8_t kSetGray = 0xff;
349 static constexpr uint8_t kResetGray = 0x00;
350 for (int row = 0; row < height; ++row) {
kumarashishg826308d2023-06-23 13:21:22 +0000351 uint8_t* dest_scan =
352 dest_buf.subspan(Fx2DSizeOrDie(row, dest_pitch)).data();
353 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row).data();
Haibo Huang49cc9302020-04-27 16:14:24 -0700354 for (int col = src_left; col < src_left + width; ++col) {
kumarashishg826308d2023-06-23 13:21:22 +0000355 uint8_t value =
356 (src_scan[col / 8] & (1 << (7 - col % 8))) ? kSetGray : kResetGray;
357 memset(dest_scan, value, 3);
Haibo Huang49cc9302020-04-27 16:14:24 -0700358 dest_scan += comps;
359 }
360 }
361}
362
363void ConvertBuffer_8bppMask2Rgb(FXDIB_Format dest_format,
kumarashishg826308d2023-06-23 13:21:22 +0000364 pdfium::span<uint8_t> dest_buf,
Haibo Huang49cc9302020-04-27 16:14:24 -0700365 int dest_pitch,
366 int width,
367 int height,
kumarashishg826308d2023-06-23 13:21:22 +0000368 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
Haibo Huang49cc9302020-04-27 16:14:24 -0700369 int src_left,
370 int src_top) {
371 int comps = GetCompsFromFormat(dest_format);
372 for (int row = 0; row < height; ++row) {
kumarashishg826308d2023-06-23 13:21:22 +0000373 uint8_t* dest_scan =
374 dest_buf.subspan(Fx2DSizeOrDie(row, dest_pitch)).data();
Haibo Huang49cc9302020-04-27 16:14:24 -0700375 const uint8_t* src_scan =
kumarashishg826308d2023-06-23 13:21:22 +0000376 pSrcBitmap->GetScanline(src_top + row).subspan(src_left).data();
Haibo Huang49cc9302020-04-27 16:14:24 -0700377 for (int col = 0; col < width; ++col) {
kumarashishg826308d2023-06-23 13:21:22 +0000378 memset(dest_scan, *src_scan, 3);
379 dest_scan += comps;
Haibo Huang49cc9302020-04-27 16:14:24 -0700380 ++src_scan;
381 }
382 }
383}
384
kumarashishg826308d2023-06-23 13:21:22 +0000385void ConvertBuffer_1bppPlt2Rgb(FXDIB_Format dest_format,
386 pdfium::span<uint8_t> dest_buf,
387 int dest_pitch,
388 int width,
389 int height,
390 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
391 int src_left,
392 int src_top) {
393 pdfium::span<const uint32_t> src_palette = pSrcBitmap->GetPaletteSpan();
394 const uint8_t dst_palette[6] = {
395 FXARGB_B(src_palette[0]), FXARGB_G(src_palette[0]),
396 FXARGB_R(src_palette[0]), FXARGB_B(src_palette[1]),
397 FXARGB_G(src_palette[1]), FXARGB_R(src_palette[1])};
398 int comps = GetCompsFromFormat(dest_format);
Haibo Huang49cc9302020-04-27 16:14:24 -0700399 for (int row = 0; row < height; ++row) {
kumarashishg826308d2023-06-23 13:21:22 +0000400 uint8_t* dest_scan =
401 dest_buf.subspan(Fx2DSizeOrDie(row, dest_pitch)).data();
402 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row).data();
403 for (int col = src_left; col < src_left + width; ++col) {
404 size_t offset = (src_scan[col / 8] & (1 << (7 - col % 8))) ? 3 : 0;
405 memcpy(dest_scan, dst_palette + offset, 3);
406 dest_scan += comps;
Haibo Huang49cc9302020-04-27 16:14:24 -0700407 }
408 }
409}
410
kumarashishg826308d2023-06-23 13:21:22 +0000411void ConvertBuffer_8bppPlt2Rgb(FXDIB_Format dest_format,
412 pdfium::span<uint8_t> dest_buf,
413 int dest_pitch,
414 int width,
415 int height,
416 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
417 int src_left,
418 int src_top) {
419 pdfium::span<const uint32_t> src_palette = pSrcBitmap->GetPaletteSpan();
420 uint8_t dst_palette[768];
421 for (int i = 0; i < 256; ++i) {
422 dst_palette[3 * i] = FXARGB_B(src_palette[i]);
423 dst_palette[3 * i + 1] = FXARGB_G(src_palette[i]);
424 dst_palette[3 * i + 2] = FXARGB_R(src_palette[i]);
425 }
426 int comps = GetCompsFromFormat(dest_format);
Haibo Huang49cc9302020-04-27 16:14:24 -0700427 for (int row = 0; row < height; ++row) {
kumarashishg826308d2023-06-23 13:21:22 +0000428 uint8_t* dest_scan =
429 dest_buf.subspan(Fx2DSizeOrDie(row, dest_pitch)).data();
Haibo Huang49cc9302020-04-27 16:14:24 -0700430 const uint8_t* src_scan =
kumarashishg826308d2023-06-23 13:21:22 +0000431 pSrcBitmap->GetScanline(src_top + row).subspan(src_left).data();
Haibo Huang49cc9302020-04-27 16:14:24 -0700432 for (int col = 0; col < width; ++col) {
kumarashishg826308d2023-06-23 13:21:22 +0000433 uint8_t* src_pixel = dst_palette + 3 * (*src_scan++);
434 memcpy(dest_scan, src_pixel, 3);
435 dest_scan += comps;
436 }
437 }
438}
439
440void ConvertBuffer_24bppRgb2Rgb24(
441 pdfium::span<uint8_t> dest_buf,
442 int dest_pitch,
443 int width,
444 int height,
445 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
446 int src_left,
447 int src_top) {
448 const size_t x_offset = Fx2DSizeOrDie(src_left, 3);
449 const size_t byte_count = Fx2DSizeOrDie(width, 3);
450 for (int row = 0; row < height; ++row) {
451 fxcrt::spancpy(
452 dest_buf.subspan(Fx2DSizeOrDie(row, dest_pitch)),
453 pSrcBitmap->GetScanline(src_top + row).subspan(x_offset, byte_count));
454 }
455}
456
457void ConvertBuffer_32bppRgb2Rgb24(
458 pdfium::span<uint8_t> dest_buf,
459 int dest_pitch,
460 int width,
461 int height,
462 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
463 int src_left,
464 int src_top) {
465 const size_t x_offset = Fx2DSizeOrDie(src_left, 4);
466 for (int row = 0; row < height; ++row) {
467 uint8_t* dest_scan =
468 dest_buf.subspan(Fx2DSizeOrDie(row, dest_pitch)).data();
469 const uint8_t* src_scan =
470 pSrcBitmap->GetScanline(src_top + row).subspan(x_offset).data();
471 for (int col = 0; col < width; ++col) {
472 memcpy(dest_scan, src_scan, 3);
473 dest_scan += 3;
Haibo Huang49cc9302020-04-27 16:14:24 -0700474 src_scan += 4;
475 }
476 }
477}
478
kumarashishg826308d2023-06-23 13:21:22 +0000479void ConvertBuffer_Rgb2Rgb32(pdfium::span<uint8_t> dest_buf,
480 int dest_pitch,
481 int width,
482 int height,
483 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
484 int src_left,
485 int src_top) {
486 const int comps = pSrcBitmap->GetBPP() / 8;
487 const size_t x_offset = Fx2DSizeOrDie(src_left, comps);
488 for (int row = 0; row < height; ++row) {
489 uint8_t* dest_scan =
490 dest_buf.subspan(Fx2DSizeOrDie(row, dest_pitch)).data();
491 const uint8_t* src_scan =
492 pSrcBitmap->GetScanline(src_top + row).subspan(x_offset).data();
493 for (int col = 0; col < width; ++col) {
494 memcpy(dest_scan, src_scan, 3);
495 dest_scan += 4;
496 src_scan += comps;
497 }
498 }
499}
500
Haibo Huang49cc9302020-04-27 16:14:24 -0700501bool ConvertBuffer_8bppMask(int bpp,
kumarashishg826308d2023-06-23 13:21:22 +0000502 pdfium::span<uint8_t> dest_buf,
Haibo Huang49cc9302020-04-27 16:14:24 -0700503 int dest_pitch,
504 int width,
505 int height,
kumarashishg826308d2023-06-23 13:21:22 +0000506 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
Haibo Huang49cc9302020-04-27 16:14:24 -0700507 int src_left,
508 int src_top) {
509 switch (bpp) {
510 case 1:
kumarashishg826308d2023-06-23 13:21:22 +0000511 if (pSrcBitmap->HasPalette()) {
Haibo Huang49cc9302020-04-27 16:14:24 -0700512 ConvertBuffer_1bppPlt2Gray(dest_buf, dest_pitch, width, height,
513 pSrcBitmap, src_left, src_top);
514 } else {
515 ConvertBuffer_1bppMask2Gray(dest_buf, dest_pitch, width, height,
516 pSrcBitmap, src_left, src_top);
517 }
518 return true;
519 case 8:
kumarashishg826308d2023-06-23 13:21:22 +0000520 if (pSrcBitmap->HasPalette()) {
Haibo Huang49cc9302020-04-27 16:14:24 -0700521 ConvertBuffer_8bppPlt2Gray(dest_buf, dest_pitch, width, height,
522 pSrcBitmap, src_left, src_top);
523 } else {
524 ConvertBuffer_8bppMask2Gray(dest_buf, dest_pitch, width, height,
525 pSrcBitmap, src_left, src_top);
526 }
527 return true;
528 case 24:
529 case 32:
kumarashishg826308d2023-06-23 13:21:22 +0000530 ConvertBuffer_Rgb2Gray(dest_buf, dest_pitch, width, height, pSrcBitmap,
531 src_left, src_top);
Haibo Huang49cc9302020-04-27 16:14:24 -0700532 return true;
533 default:
534 return false;
535 }
536}
537
538bool ConvertBuffer_Rgb(int bpp,
539 FXDIB_Format dest_format,
kumarashishg826308d2023-06-23 13:21:22 +0000540 pdfium::span<uint8_t> dest_buf,
Haibo Huang49cc9302020-04-27 16:14:24 -0700541 int dest_pitch,
542 int width,
543 int height,
kumarashishg826308d2023-06-23 13:21:22 +0000544 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
Haibo Huang49cc9302020-04-27 16:14:24 -0700545 int src_left,
546 int src_top) {
547 switch (bpp) {
548 case 1:
kumarashishg826308d2023-06-23 13:21:22 +0000549 if (pSrcBitmap->HasPalette()) {
Haibo Huang49cc9302020-04-27 16:14:24 -0700550 ConvertBuffer_1bppPlt2Rgb(dest_format, dest_buf, dest_pitch, width,
551 height, pSrcBitmap, src_left, src_top);
552 } else {
553 ConvertBuffer_1bppMask2Rgb(dest_format, dest_buf, dest_pitch, width,
554 height, pSrcBitmap, src_left, src_top);
555 }
556 return true;
557 case 8:
kumarashishg826308d2023-06-23 13:21:22 +0000558 if (pSrcBitmap->HasPalette()) {
Haibo Huang49cc9302020-04-27 16:14:24 -0700559 ConvertBuffer_8bppPlt2Rgb(dest_format, dest_buf, dest_pitch, width,
560 height, pSrcBitmap, src_left, src_top);
561 } else {
562 ConvertBuffer_8bppMask2Rgb(dest_format, dest_buf, dest_pitch, width,
563 height, pSrcBitmap, src_left, src_top);
564 }
565 return true;
566 case 24:
567 ConvertBuffer_24bppRgb2Rgb24(dest_buf, dest_pitch, width, height,
568 pSrcBitmap, src_left, src_top);
569 return true;
570 case 32:
571 ConvertBuffer_32bppRgb2Rgb24(dest_buf, dest_pitch, width, height,
572 pSrcBitmap, src_left, src_top);
573 return true;
574 default:
575 return false;
576 }
577}
578
579bool ConvertBuffer_Argb(int bpp,
Haibo Huang49cc9302020-04-27 16:14:24 -0700580 FXDIB_Format dest_format,
kumarashishg826308d2023-06-23 13:21:22 +0000581 pdfium::span<uint8_t> dest_buf,
Haibo Huang49cc9302020-04-27 16:14:24 -0700582 int dest_pitch,
583 int width,
584 int height,
kumarashishg826308d2023-06-23 13:21:22 +0000585 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
Haibo Huang49cc9302020-04-27 16:14:24 -0700586 int src_left,
587 int src_top) {
588 switch (bpp) {
589 case 1:
kumarashishg826308d2023-06-23 13:21:22 +0000590 if (pSrcBitmap->HasPalette()) {
Haibo Huang49cc9302020-04-27 16:14:24 -0700591 ConvertBuffer_1bppPlt2Rgb(dest_format, dest_buf, dest_pitch, width,
592 height, pSrcBitmap, src_left, src_top);
593 } else {
594 ConvertBuffer_1bppMask2Rgb(dest_format, dest_buf, dest_pitch, width,
595 height, pSrcBitmap, src_left, src_top);
596 }
597 return true;
598 case 8:
kumarashishg826308d2023-06-23 13:21:22 +0000599 if (pSrcBitmap->HasPalette()) {
Haibo Huang49cc9302020-04-27 16:14:24 -0700600 ConvertBuffer_8bppPlt2Rgb(dest_format, dest_buf, dest_pitch, width,
601 height, pSrcBitmap, src_left, src_top);
602 } else {
603 ConvertBuffer_8bppMask2Rgb(dest_format, dest_buf, dest_pitch, width,
604 height, pSrcBitmap, src_left, src_top);
605 }
606 return true;
607 case 24:
608 case 32:
kumarashishg826308d2023-06-23 13:21:22 +0000609 ConvertBuffer_Rgb2Rgb32(dest_buf, dest_pitch, width, height, pSrcBitmap,
610 src_left, src_top);
Haibo Huang49cc9302020-04-27 16:14:24 -0700611 return true;
612 default:
613 return false;
614 }
615}
616
617} // namespace
618
kumarashishg826308d2023-06-23 13:21:22 +0000619CFX_DIBBase::CFX_DIBBase() = default;
Haibo Huang49cc9302020-04-27 16:14:24 -0700620
kumarashishg826308d2023-06-23 13:21:22 +0000621CFX_DIBBase::~CFX_DIBBase() = default;
Haibo Huang49cc9302020-04-27 16:14:24 -0700622
kumarashishg826308d2023-06-23 13:21:22 +0000623pdfium::span<uint8_t> CFX_DIBBase::GetBuffer() const {
624 return pdfium::span<uint8_t>();
Haibo Huang49cc9302020-04-27 16:14:24 -0700625}
626
627bool CFX_DIBBase::SkipToScanline(int line, PauseIndicatorIface* pPause) const {
628 return false;
629}
630
kumarashishg826308d2023-06-23 13:21:22 +0000631size_t CFX_DIBBase::GetEstimatedImageMemoryBurden() const {
632 return GetRequiredPaletteSize() * sizeof(uint32_t);
633}
634
635RetainPtr<CFX_DIBitmap> CFX_DIBBase::Realize() const {
636 return ClipToInternal(nullptr);
637}
638
639RetainPtr<CFX_DIBitmap> CFX_DIBBase::ClipTo(const FX_RECT& rect) const {
640 return ClipToInternal(&rect);
641}
642
643RetainPtr<CFX_DIBitmap> CFX_DIBBase::ClipToInternal(
644 const FX_RECT* pClip) const {
Haibo Huang49cc9302020-04-27 16:14:24 -0700645 FX_RECT rect(0, 0, m_Width, m_Height);
646 if (pClip) {
647 rect.Intersect(*pClip);
648 if (rect.IsEmpty())
649 return nullptr;
650 }
651 auto pNewBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
652 if (!pNewBitmap->Create(rect.Width(), rect.Height(), GetFormat()))
653 return nullptr;
654
kumarashishg826308d2023-06-23 13:21:22 +0000655 pNewBitmap->SetPalette(GetPaletteSpan());
Haibo Huang49cc9302020-04-27 16:14:24 -0700656 if (GetBPP() == 1 && rect.left % 8 != 0) {
657 int left_shift = rect.left % 32;
658 int right_shift = 32 - left_shift;
659 int dword_count = pNewBitmap->m_Pitch / 4;
660 for (int row = rect.top; row < rect.bottom; ++row) {
661 const uint32_t* src_scan =
kumarashishg826308d2023-06-23 13:21:22 +0000662 reinterpret_cast<const uint32_t*>(GetScanline(row).data()) +
663 rect.left / 32;
Haibo Huang49cc9302020-04-27 16:14:24 -0700664 uint32_t* dest_scan = reinterpret_cast<uint32_t*>(
kumarashishg826308d2023-06-23 13:21:22 +0000665 pNewBitmap->GetWritableScanline(row - rect.top).data());
Haibo Huang49cc9302020-04-27 16:14:24 -0700666 for (int i = 0; i < dword_count; ++i) {
667 dest_scan[i] =
668 (src_scan[i] << left_shift) | (src_scan[i + 1] >> right_shift);
669 }
670 }
671 } else {
kumarashishg826308d2023-06-23 13:21:22 +0000672 FX_SAFE_UINT32 copy_len = pNewBitmap->GetWidth();
673 copy_len *= pNewBitmap->GetBPP();
674 copy_len += 7;
675 copy_len /= 8;
676 if (!copy_len.IsValid())
677 return nullptr;
678
679 copy_len = std::min<uint32_t>(m_Pitch, copy_len.ValueOrDie());
680
681 FX_SAFE_UINT32 offset = rect.left;
682 offset *= GetBppFromFormat(m_Format);
683 offset /= 8;
684 if (!offset.IsValid())
685 return nullptr;
Haibo Huang49cc9302020-04-27 16:14:24 -0700686
687 for (int row = rect.top; row < rect.bottom; ++row) {
kumarashishg826308d2023-06-23 13:21:22 +0000688 const uint8_t* src_scan =
689 GetScanline(row).subspan(offset.ValueOrDie()).data();
690 uint8_t* dest_scan =
691 pNewBitmap->GetWritableScanline(row - rect.top).data();
692 memcpy(dest_scan, src_scan, copy_len.ValueOrDie());
Haibo Huang49cc9302020-04-27 16:14:24 -0700693 }
694 }
695 return pNewBitmap;
696}
697
698void CFX_DIBBase::BuildPalette() {
kumarashishg826308d2023-06-23 13:21:22 +0000699 if (HasPalette())
Haibo Huang49cc9302020-04-27 16:14:24 -0700700 return;
701
702 if (GetBPP() == 1) {
kumarashishg826308d2023-06-23 13:21:22 +0000703 m_palette = {0xff000000, 0xffffffff};
Haibo Huang49cc9302020-04-27 16:14:24 -0700704 } else if (GetBPP() == 8) {
kumarashishg826308d2023-06-23 13:21:22 +0000705 m_palette.resize(256);
706 for (int i = 0; i < 256; ++i)
707 m_palette[i] = ArgbEncode(0xff, i, i, i);
Haibo Huang49cc9302020-04-27 16:14:24 -0700708 }
709}
710
kumarashishg826308d2023-06-23 13:21:22 +0000711size_t CFX_DIBBase::GetRequiredPaletteSize() const {
712 if (IsMaskFormat())
Haibo Huang49cc9302020-04-27 16:14:24 -0700713 return 0;
714
kumarashishg826308d2023-06-23 13:21:22 +0000715 switch (GetBppFromFormat(m_Format)) {
Haibo Huang49cc9302020-04-27 16:14:24 -0700716 case 1:
717 return 2;
718 case 8:
719 return 256;
720 default:
721 return 0;
722 }
723}
724
725uint32_t CFX_DIBBase::GetPaletteArgb(int index) const {
kumarashishg826308d2023-06-23 13:21:22 +0000726 DCHECK((GetBPP() == 1 || GetBPP() == 8) && !IsMaskFormat());
727 if (HasPalette())
728 return GetPaletteSpan()[index];
Haibo Huang49cc9302020-04-27 16:14:24 -0700729
Haibo Huang49cc9302020-04-27 16:14:24 -0700730 if (GetBPP() == 1)
731 return index ? 0xffffffff : 0xff000000;
732
kumarashishg826308d2023-06-23 13:21:22 +0000733 return ArgbEncode(0xff, index, index, index);
Haibo Huang49cc9302020-04-27 16:14:24 -0700734}
735
736void CFX_DIBBase::SetPaletteArgb(int index, uint32_t color) {
kumarashishg826308d2023-06-23 13:21:22 +0000737 DCHECK((GetBPP() == 1 || GetBPP() == 8) && !IsMaskFormat());
738 BuildPalette();
739 m_palette[index] = color;
Haibo Huang49cc9302020-04-27 16:14:24 -0700740}
741
742int CFX_DIBBase::FindPalette(uint32_t color) const {
kumarashishg826308d2023-06-23 13:21:22 +0000743 DCHECK((GetBPP() == 1 || GetBPP() == 8) && !IsMaskFormat());
744 if (HasPalette()) {
745 int palsize = (1 << GetBPP());
746 pdfium::span<const uint32_t> palette = GetPaletteSpan();
747 for (int i = 0; i < palsize; ++i) {
748 if (palette[i] == color)
749 return i;
Haibo Huang49cc9302020-04-27 16:14:24 -0700750 }
kumarashishg826308d2023-06-23 13:21:22 +0000751 return -1;
752 }
Haibo Huang49cc9302020-04-27 16:14:24 -0700753
kumarashishg826308d2023-06-23 13:21:22 +0000754 if (GetBPP() == 1)
755 return (static_cast<uint8_t>(color) == 0xff) ? 1 : 0;
756 return static_cast<uint8_t>(color);
Haibo Huang49cc9302020-04-27 16:14:24 -0700757}
758
759bool CFX_DIBBase::GetOverlapRect(int& dest_left,
760 int& dest_top,
761 int& width,
762 int& height,
763 int src_width,
764 int src_height,
765 int& src_left,
766 int& src_top,
kumarashishg826308d2023-06-23 13:21:22 +0000767 const CFX_ClipRgn* pClipRgn) const {
Haibo Huang49cc9302020-04-27 16:14:24 -0700768 if (width == 0 || height == 0)
769 return false;
770
kumarashishg826308d2023-06-23 13:21:22 +0000771 DCHECK_GT(width, 0);
772 DCHECK_GT(height, 0);
Haibo Huang49cc9302020-04-27 16:14:24 -0700773
kumarashishg826308d2023-06-23 13:21:22 +0000774 if (dest_left > m_Width || dest_top > m_Height)
Haibo Huang49cc9302020-04-27 16:14:24 -0700775 return false;
kumarashishg826308d2023-06-23 13:21:22 +0000776
777 FX_SAFE_INT32 safe_src_width = src_left;
778 safe_src_width += width;
779 if (!safe_src_width.IsValid())
780 return false;
781
782 FX_SAFE_INT32 safe_src_height = src_top;
783 safe_src_height += height;
784 if (!safe_src_height.IsValid())
785 return false;
786
787 FX_RECT src_rect(src_left, src_top, safe_src_width.ValueOrDie(),
788 safe_src_height.ValueOrDie());
Haibo Huang49cc9302020-04-27 16:14:24 -0700789 FX_RECT src_bound(0, 0, src_width, src_height);
790 src_rect.Intersect(src_bound);
kumarashishg826308d2023-06-23 13:21:22 +0000791
792 FX_SAFE_INT32 safe_x_offset = dest_left;
793 safe_x_offset -= src_left;
794 if (!safe_x_offset.IsValid())
795 return false;
796
797 FX_SAFE_INT32 safe_y_offset = dest_top;
798 safe_y_offset -= src_top;
799 if (!safe_y_offset.IsValid())
800 return false;
801
802 FX_SAFE_INT32 safe_dest_left = safe_x_offset;
803 safe_dest_left += src_rect.left;
804 if (!safe_dest_left.IsValid())
805 return false;
806
807 FX_SAFE_INT32 safe_dest_top = safe_y_offset;
808 safe_dest_top += src_rect.top;
809 if (!safe_dest_top.IsValid())
810 return false;
811
812 FX_SAFE_INT32 safe_dest_right = safe_x_offset;
813 safe_dest_right += src_rect.right;
814 if (!safe_dest_right.IsValid())
815 return false;
816
817 FX_SAFE_INT32 safe_dest_bottom = safe_y_offset;
818 safe_dest_bottom += src_rect.bottom;
819 if (!safe_dest_bottom.IsValid())
820 return false;
821
822 FX_RECT dest_rect(safe_dest_left.ValueOrDie(), safe_dest_top.ValueOrDie(),
823 safe_dest_right.ValueOrDie(),
824 safe_dest_bottom.ValueOrDie());
Haibo Huang49cc9302020-04-27 16:14:24 -0700825 FX_RECT dest_bound(0, 0, m_Width, m_Height);
826 dest_rect.Intersect(dest_bound);
kumarashishg826308d2023-06-23 13:21:22 +0000827
Haibo Huang49cc9302020-04-27 16:14:24 -0700828 if (pClipRgn)
829 dest_rect.Intersect(pClipRgn->GetBox());
830 dest_left = dest_rect.left;
831 dest_top = dest_rect.top;
832
kumarashishg826308d2023-06-23 13:21:22 +0000833 FX_SAFE_INT32 safe_new_src_left = dest_left;
834 safe_new_src_left -= safe_x_offset;
835 if (!safe_new_src_left.IsValid())
Haibo Huang49cc9302020-04-27 16:14:24 -0700836 return false;
kumarashishg826308d2023-06-23 13:21:22 +0000837 src_left = safe_new_src_left.ValueOrDie();
Haibo Huang49cc9302020-04-27 16:14:24 -0700838
kumarashishg826308d2023-06-23 13:21:22 +0000839 FX_SAFE_INT32 safe_new_src_top = dest_top;
840 safe_new_src_top -= safe_y_offset;
841 if (!safe_new_src_top.IsValid())
Haibo Huang49cc9302020-04-27 16:14:24 -0700842 return false;
kumarashishg826308d2023-06-23 13:21:22 +0000843 src_top = safe_new_src_top.ValueOrDie();
Haibo Huang49cc9302020-04-27 16:14:24 -0700844
kumarashishg826308d2023-06-23 13:21:22 +0000845 if (dest_rect.IsEmpty())
846 return false;
847
848 width = dest_rect.Width();
849 height = dest_rect.Height();
850 return true;
Haibo Huang49cc9302020-04-27 16:14:24 -0700851}
852
kumarashishg826308d2023-06-23 13:21:22 +0000853void CFX_DIBBase::SetPalette(pdfium::span<const uint32_t> src_palette) {
854 if (src_palette.empty() || GetBPP() > 8) {
855 m_palette.clear();
Haibo Huang49cc9302020-04-27 16:14:24 -0700856 return;
857 }
858 uint32_t pal_size = 1 << GetBPP();
kumarashishg826308d2023-06-23 13:21:22 +0000859 if (m_palette.empty())
860 m_palette.resize(pal_size);
Haibo Huang49cc9302020-04-27 16:14:24 -0700861 pal_size = std::min(pal_size, kPaletteSize);
kumarashishg826308d2023-06-23 13:21:22 +0000862 for (size_t i = 0; i < pal_size; ++i)
863 m_palette[i] = src_palette[i];
Haibo Huang49cc9302020-04-27 16:14:24 -0700864}
865
866RetainPtr<CFX_DIBitmap> CFX_DIBBase::CloneAlphaMask() const {
kumarashishg826308d2023-06-23 13:21:22 +0000867 DCHECK_EQ(GetFormat(), FXDIB_Format::kArgb);
Haibo Huang49cc9302020-04-27 16:14:24 -0700868 auto pMask = pdfium::MakeRetain<CFX_DIBitmap>();
kumarashishg826308d2023-06-23 13:21:22 +0000869 if (!pMask->Create(m_Width, m_Height, FXDIB_Format::k8bppMask))
Haibo Huang49cc9302020-04-27 16:14:24 -0700870 return nullptr;
871
kumarashishg826308d2023-06-23 13:21:22 +0000872 for (int row = 0; row < m_Height; ++row) {
873 const uint8_t* src_scan = GetScanline(row).subspan(3).data();
874 uint8_t* dest_scan = pMask->GetWritableScanline(row).data();
875 for (int col = 0; col < m_Width; ++col) {
Haibo Huang49cc9302020-04-27 16:14:24 -0700876 *dest_scan++ = *src_scan;
877 src_scan += 4;
878 }
879 }
880 return pMask;
881}
882
Haibo Huang49cc9302020-04-27 16:14:24 -0700883RetainPtr<CFX_DIBitmap> CFX_DIBBase::FlipImage(bool bXFlip, bool bYFlip) const {
884 auto pFlipped = pdfium::MakeRetain<CFX_DIBitmap>();
885 if (!pFlipped->Create(m_Width, m_Height, GetFormat()))
886 return nullptr;
887
kumarashishg826308d2023-06-23 13:21:22 +0000888 pFlipped->SetPalette(GetPaletteSpan());
889 int Bpp = GetBppFromFormat(m_Format) / 8;
Haibo Huang49cc9302020-04-27 16:14:24 -0700890 for (int row = 0; row < m_Height; ++row) {
kumarashishg826308d2023-06-23 13:21:22 +0000891 const uint8_t* src_scan = GetScanline(row).data();
Haibo Huang49cc9302020-04-27 16:14:24 -0700892 uint8_t* dest_scan =
kumarashishg826308d2023-06-23 13:21:22 +0000893 pFlipped->GetWritableScanline(bYFlip ? m_Height - row - 1 : row).data();
Haibo Huang49cc9302020-04-27 16:14:24 -0700894 if (!bXFlip) {
895 memcpy(dest_scan, src_scan, m_Pitch);
896 continue;
897 }
kumarashishg826308d2023-06-23 13:21:22 +0000898 if (GetBppFromFormat(m_Format) == 1) {
Haibo Huang49cc9302020-04-27 16:14:24 -0700899 memset(dest_scan, 0, m_Pitch);
900 for (int col = 0; col < m_Width; ++col) {
901 if (src_scan[col / 8] & (1 << (7 - col % 8))) {
902 int dest_col = m_Width - col - 1;
903 dest_scan[dest_col / 8] |= (1 << (7 - dest_col % 8));
904 }
905 }
906 continue;
907 }
908
909 dest_scan += (m_Width - 1) * Bpp;
910 if (Bpp == 1) {
911 for (int col = 0; col < m_Width; ++col) {
912 *dest_scan = *src_scan;
913 --dest_scan;
914 ++src_scan;
915 }
916 } else if (Bpp == 3) {
917 for (int col = 0; col < m_Width; ++col) {
kumarashishg826308d2023-06-23 13:21:22 +0000918 memcpy(dest_scan, src_scan, 3);
Haibo Huang49cc9302020-04-27 16:14:24 -0700919 dest_scan -= 3;
920 src_scan += 3;
921 }
922 } else {
kumarashishg826308d2023-06-23 13:21:22 +0000923 DCHECK_EQ(Bpp, 4);
Haibo Huang49cc9302020-04-27 16:14:24 -0700924 for (int col = 0; col < m_Width; ++col) {
925 const auto* src_scan32 = reinterpret_cast<const uint32_t*>(src_scan);
926 uint32_t* dest_scan32 = reinterpret_cast<uint32_t*>(dest_scan);
927 *dest_scan32 = *src_scan32;
928 dest_scan -= 4;
929 src_scan += 4;
930 }
931 }
932 }
Haibo Huang49cc9302020-04-27 16:14:24 -0700933 return pFlipped;
934}
935
kumarashishg826308d2023-06-23 13:21:22 +0000936RetainPtr<CFX_DIBitmap> CFX_DIBBase::ConvertTo(FXDIB_Format dest_format) const {
Haibo Huang49cc9302020-04-27 16:14:24 -0700937 if (dest_format == GetFormat())
kumarashishg826308d2023-06-23 13:21:22 +0000938 return Realize();
Haibo Huang49cc9302020-04-27 16:14:24 -0700939
940 auto pClone = pdfium::MakeRetain<CFX_DIBitmap>();
941 if (!pClone->Create(m_Width, m_Height, dest_format))
942 return nullptr;
943
944 RetainPtr<CFX_DIBitmap> pSrcAlpha;
kumarashishg826308d2023-06-23 13:21:22 +0000945 if (IsAlphaFormat()) {
946 pSrcAlpha = CloneAlphaMask();
Haibo Huang49cc9302020-04-27 16:14:24 -0700947 if (!pSrcAlpha)
948 return nullptr;
949 }
kumarashishg826308d2023-06-23 13:21:22 +0000950 if (dest_format == FXDIB_Format::kArgb) {
951 bool ret = pSrcAlpha ? pClone->SetAlphaFromBitmap(pSrcAlpha)
952 : pClone->SetUniformOpaqueAlpha();
Haibo Huang49cc9302020-04-27 16:14:24 -0700953 if (!ret)
954 return nullptr;
955 }
956
kumarashishg826308d2023-06-23 13:21:22 +0000957 RetainPtr<const CFX_DIBBase> holder(this);
958 DataVector<uint32_t> pal_8bpp;
Haibo Huang49cc9302020-04-27 16:14:24 -0700959 if (!ConvertBuffer(dest_format, pClone->GetBuffer(), pClone->GetPitch(),
960 m_Width, m_Height, holder, 0, 0, &pal_8bpp)) {
961 return nullptr;
962 }
kumarashishg826308d2023-06-23 13:21:22 +0000963 if (!pal_8bpp.empty())
964 pClone->SetPalette(pal_8bpp);
Haibo Huang49cc9302020-04-27 16:14:24 -0700965
966 return pClone;
967}
968
969RetainPtr<CFX_DIBitmap> CFX_DIBBase::SwapXY(bool bXFlip, bool bYFlip) const {
970 FX_RECT dest_clip(0, 0, m_Height, m_Width);
971 if (dest_clip.IsEmpty())
972 return nullptr;
973
974 auto pTransBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
kumarashishg826308d2023-06-23 13:21:22 +0000975 const int result_height = dest_clip.Height();
976 const int result_width = dest_clip.Width();
Haibo Huang49cc9302020-04-27 16:14:24 -0700977 if (!pTransBitmap->Create(result_width, result_height, GetFormat()))
978 return nullptr;
979
kumarashishg826308d2023-06-23 13:21:22 +0000980 pTransBitmap->SetPalette(GetPaletteSpan());
981 const int dest_pitch = pTransBitmap->GetPitch();
982 pdfium::span<uint8_t> dest_span =
983 pTransBitmap->GetBuffer().first(Fx2DSizeOrDie(dest_pitch, result_height));
984 const size_t dest_last_row_offset =
985 Fx2DSizeOrDie(dest_pitch, result_height - 1);
986 const int row_start = bXFlip ? m_Height - dest_clip.right : dest_clip.left;
987 const int row_end = bXFlip ? m_Height - dest_clip.left : dest_clip.right;
988 const int col_start = bYFlip ? m_Width - dest_clip.bottom : dest_clip.top;
989 const int col_end = bYFlip ? m_Width - dest_clip.top : dest_clip.bottom;
Haibo Huang49cc9302020-04-27 16:14:24 -0700990 if (GetBPP() == 1) {
kumarashishg826308d2023-06-23 13:21:22 +0000991 fxcrt::spanset(dest_span, 0xff);
992 if (bYFlip)
993 dest_span = dest_span.subspan(dest_last_row_offset);
994 const int dest_step = bYFlip ? -dest_pitch : dest_pitch;
Haibo Huang49cc9302020-04-27 16:14:24 -0700995 for (int row = row_start; row < row_end; ++row) {
kumarashishg826308d2023-06-23 13:21:22 +0000996 const uint8_t* src_scan = GetScanline(row).data();
Haibo Huang49cc9302020-04-27 16:14:24 -0700997 int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) -
998 dest_clip.left;
kumarashishg826308d2023-06-23 13:21:22 +0000999 uint8_t* dest_scan = dest_span.data();
Haibo Huang49cc9302020-04-27 16:14:24 -07001000 for (int col = col_start; col < col_end; ++col) {
1001 if (!(src_scan[col / 8] & (1 << (7 - col % 8))))
1002 dest_scan[dest_col / 8] &= ~(1 << (7 - dest_col % 8));
1003 dest_scan += dest_step;
1004 }
1005 }
1006 } else {
1007 int nBytes = GetBPP() / 8;
1008 int dest_step = bYFlip ? -dest_pitch : dest_pitch;
1009 if (nBytes == 3)
1010 dest_step -= 2;
kumarashishg826308d2023-06-23 13:21:22 +00001011 if (bYFlip)
1012 dest_span = dest_span.subspan(dest_last_row_offset);
Haibo Huang49cc9302020-04-27 16:14:24 -07001013 for (int row = row_start; row < row_end; ++row) {
1014 int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) -
1015 dest_clip.left;
kumarashishg826308d2023-06-23 13:21:22 +00001016 size_t dest_offset = Fx2DSizeOrDie(dest_col, nBytes);
1017 uint8_t* dest_scan = dest_span.subspan(dest_offset).data();
Haibo Huang49cc9302020-04-27 16:14:24 -07001018 if (nBytes == 4) {
1019 const uint32_t* src_scan =
kumarashishg826308d2023-06-23 13:21:22 +00001020 reinterpret_cast<const uint32_t*>(GetScanline(row).data()) +
1021 col_start;
Haibo Huang49cc9302020-04-27 16:14:24 -07001022 for (int col = col_start; col < col_end; ++col) {
1023 uint32_t* dest_scan32 = reinterpret_cast<uint32_t*>(dest_scan);
1024 *dest_scan32 = *src_scan++;
1025 dest_scan += dest_step;
1026 }
1027 } else {
kumarashishg826308d2023-06-23 13:21:22 +00001028 const uint8_t* src_scan =
1029 GetScanline(row).subspan(col_start * nBytes).data();
Haibo Huang49cc9302020-04-27 16:14:24 -07001030 if (nBytes == 1) {
1031 for (int col = col_start; col < col_end; ++col) {
1032 *dest_scan = *src_scan++;
1033 dest_scan += dest_step;
1034 }
1035 } else {
1036 for (int col = col_start; col < col_end; ++col) {
kumarashishg826308d2023-06-23 13:21:22 +00001037 memcpy(dest_scan, src_scan, 3);
1038 dest_scan += 2 + dest_step;
1039 src_scan += 3;
Haibo Huang49cc9302020-04-27 16:14:24 -07001040 }
1041 }
1042 }
1043 }
1044 }
Haibo Huang49cc9302020-04-27 16:14:24 -07001045 return pTransBitmap;
1046}
1047
1048RetainPtr<CFX_DIBitmap> CFX_DIBBase::TransformTo(const CFX_Matrix& mtDest,
1049 int* result_left,
kumarashishg826308d2023-06-23 13:21:22 +00001050 int* result_top) const {
1051 RetainPtr<const CFX_DIBBase> holder(this);
Haibo Huang49cc9302020-04-27 16:14:24 -07001052 CFX_ImageTransformer transformer(holder, mtDest, FXDIB_ResampleOptions(),
1053 nullptr);
1054 transformer.Continue(nullptr);
1055 *result_left = transformer.result().left;
1056 *result_top = transformer.result().top;
1057 return transformer.DetachBitmap();
1058}
1059
1060RetainPtr<CFX_DIBitmap> CFX_DIBBase::StretchTo(
1061 int dest_width,
1062 int dest_height,
1063 const FXDIB_ResampleOptions& options,
kumarashishg826308d2023-06-23 13:21:22 +00001064 const FX_RECT* pClip) const {
1065 RetainPtr<const CFX_DIBBase> holder(this);
Haibo Huang49cc9302020-04-27 16:14:24 -07001066 FX_RECT clip_rect(0, 0, abs(dest_width), abs(dest_height));
1067 if (pClip)
1068 clip_rect.Intersect(*pClip);
1069
1070 if (clip_rect.IsEmpty())
1071 return nullptr;
1072
1073 if (dest_width == m_Width && dest_height == m_Height)
kumarashishg826308d2023-06-23 13:21:22 +00001074 return ClipTo(clip_rect);
Haibo Huang49cc9302020-04-27 16:14:24 -07001075
1076 CFX_BitmapStorer storer;
1077 CFX_ImageStretcher stretcher(&storer, holder, dest_width, dest_height,
1078 clip_rect, options);
1079 if (stretcher.Start())
1080 stretcher.Continue(nullptr);
1081
1082 return storer.Detach();
1083}
1084
1085// static
kumarashishg826308d2023-06-23 13:21:22 +00001086bool CFX_DIBBase::ConvertBuffer(FXDIB_Format dest_format,
1087 pdfium::span<uint8_t> dest_buf,
1088 int dest_pitch,
1089 int width,
1090 int height,
1091 const RetainPtr<const CFX_DIBBase>& pSrcBitmap,
1092 int src_left,
1093 int src_top,
1094 DataVector<uint32_t>* pal) {
Haibo Huang49cc9302020-04-27 16:14:24 -07001095 FXDIB_Format src_format = pSrcBitmap->GetFormat();
1096 const int bpp = GetBppFromFormat(src_format);
1097 switch (dest_format) {
kumarashishg826308d2023-06-23 13:21:22 +00001098 case FXDIB_Format::k8bppMask: {
Haibo Huang49cc9302020-04-27 16:14:24 -07001099 return ConvertBuffer_8bppMask(bpp, dest_buf, dest_pitch, width, height,
1100 pSrcBitmap, src_left, src_top);
1101 }
kumarashishg826308d2023-06-23 13:21:22 +00001102 case FXDIB_Format::k8bppRgb: {
Haibo Huang49cc9302020-04-27 16:14:24 -07001103 const bool bpp_1_or_8 = (bpp == 1 || bpp == 8);
kumarashishg826308d2023-06-23 13:21:22 +00001104 if (bpp_1_or_8 && !pSrcBitmap->HasPalette()) {
1105 return ConvertBuffer(FXDIB_Format::k8bppMask, dest_buf, dest_pitch,
1106 width, height, pSrcBitmap, src_left, src_top, pal);
Haibo Huang49cc9302020-04-27 16:14:24 -07001107 }
kumarashishg826308d2023-06-23 13:21:22 +00001108 pal->resize(256);
1109 if (bpp_1_or_8 && pSrcBitmap->HasPalette()) {
Haibo Huang49cc9302020-04-27 16:14:24 -07001110 ConvertBuffer_Plt2PltRgb8(dest_buf, dest_pitch, width, height,
kumarashishg826308d2023-06-23 13:21:22 +00001111 pSrcBitmap, src_left, src_top, *pal);
Haibo Huang49cc9302020-04-27 16:14:24 -07001112 return true;
1113 }
1114 if (bpp >= 24) {
1115 ConvertBuffer_Rgb2PltRgb8(dest_buf, dest_pitch, width, height,
kumarashishg826308d2023-06-23 13:21:22 +00001116 pSrcBitmap, src_left, src_top, *pal);
Haibo Huang49cc9302020-04-27 16:14:24 -07001117 return true;
1118 }
1119 return false;
1120 }
kumarashishg826308d2023-06-23 13:21:22 +00001121 case FXDIB_Format::kRgb: {
Haibo Huang49cc9302020-04-27 16:14:24 -07001122 return ConvertBuffer_Rgb(bpp, dest_format, dest_buf, dest_pitch, width,
1123 height, pSrcBitmap, src_left, src_top);
1124 }
kumarashishg826308d2023-06-23 13:21:22 +00001125 case FXDIB_Format::kArgb:
1126 case FXDIB_Format::kRgb32: {
1127 return ConvertBuffer_Argb(bpp, dest_format, dest_buf, dest_pitch, width,
Haibo Huang49cc9302020-04-27 16:14:24 -07001128 height, pSrcBitmap, src_left, src_top);
1129 }
1130 default:
1131 NOTREACHED();
1132 return false;
1133 }
1134}