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_dibsource.h"
8
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12 #include <vector>
13
14 #include "core/fxcodec/fx_codec.h"
15 #include "core/fxge/cfx_cliprgn.h"
16 #include "core/fxge/dib/cfx_bitmapstorer.h"
17 #include "core/fxge/dib/cfx_dibitmap.h"
18 #include "core/fxge/dib/cfx_imagestretcher.h"
19 #include "core/fxge/dib/cfx_imagetransformer.h"
20 #include "third_party/base/logging.h"
21 #include "third_party/base/ptr_util.h"
22
23 namespace {
24
25 class CFX_Palette {
26 public:
27 explicit CFX_Palette(const RetainPtr<CFX_DIBSource>& pBitmap);
28 ~CFX_Palette();
29
GetPalette()30 const uint32_t* GetPalette() { return m_Palette.data(); }
GetLuts() const31 const std::pair<uint32_t, uint32_t>* GetLuts() const { return m_Luts.data(); }
GetLutCount() const32 int32_t GetLutCount() const { return m_lut; }
SetAmountLut(int row,uint32_t value)33 void SetAmountLut(int row, uint32_t value) { m_Luts[row].first = value; }
34
35 private:
36 std::vector<uint32_t> m_Palette;
37 // (Amount, Color) pairs
38 std::vector<std::pair<uint32_t, uint32_t>> m_Luts;
39 int m_lut;
40 };
41
ColorDecode(uint32_t pal_v,uint8_t * r,uint8_t * g,uint8_t * b)42 void ColorDecode(uint32_t pal_v, uint8_t* r, uint8_t* g, uint8_t* b) {
43 *r = static_cast<uint8_t>((pal_v & 0xf00) >> 4);
44 *g = static_cast<uint8_t>(pal_v & 0x0f0);
45 *b = static_cast<uint8_t>((pal_v & 0x00f) << 4);
46 }
47
Obtain_Pal(std::pair<uint32_t,uint32_t> * luts,uint32_t * dest_pal,uint32_t lut)48 void Obtain_Pal(std::pair<uint32_t, uint32_t>* luts,
49 uint32_t* dest_pal,
50 uint32_t lut) {
51 uint32_t lut_1 = lut - 1;
52 for (int row = 0; row < 256; ++row) {
53 int lut_offset = lut_1 - row;
54 if (lut_offset < 0)
55 lut_offset += 256;
56 uint32_t color = luts[lut_offset].second;
57 uint8_t r;
58 uint8_t g;
59 uint8_t b;
60 ColorDecode(color, &r, &g, &b);
61 dest_pal[row] = (static_cast<uint32_t>(r) << 16) |
62 (static_cast<uint32_t>(g) << 8) | b | 0xff000000;
63 luts[lut_offset].first = row;
64 }
65 }
66
CFX_Palette(const RetainPtr<CFX_DIBSource> & pBitmap)67 CFX_Palette::CFX_Palette(const RetainPtr<CFX_DIBSource>& pBitmap)
68 : m_Palette(256), m_Luts(4096), m_lut(0) {
69 int bpp = pBitmap->GetBPP() / 8;
70 int width = pBitmap->GetWidth();
71 int height = pBitmap->GetHeight();
72 for (int row = 0; row < height; ++row) {
73 const uint8_t* scan_line = pBitmap->GetScanline(row);
74 for (int col = 0; col < width; ++col) {
75 const uint8_t* src_port = scan_line + col * bpp;
76 uint32_t b = src_port[0] & 0xf0;
77 uint32_t g = src_port[1] & 0xf0;
78 uint32_t r = src_port[2] & 0xf0;
79 uint32_t index = (r << 4) + g + (b >> 4);
80 ++m_Luts[index].first;
81 }
82 }
83 // Move non-zeros to the front and count them
84 for (int row = 0; row < 4096; ++row) {
85 if (m_Luts[row].first != 0) {
86 m_Luts[m_lut].first = m_Luts[row].first;
87 m_Luts[m_lut].second = row;
88 ++m_lut;
89 }
90 }
91 std::sort(m_Luts.begin(), m_Luts.begin() + m_lut,
92 [](const std::pair<uint32_t, uint32_t>& arg1,
93 const std::pair<uint32_t, uint32_t>& arg2) {
94 return arg1.first < arg2.first;
95 });
96 Obtain_Pal(m_Luts.data(), m_Palette.data(), m_lut);
97 }
98
~CFX_Palette()99 CFX_Palette::~CFX_Palette() {}
100
ConvertBuffer_1bppMask2Gray(uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)101 void ConvertBuffer_1bppMask2Gray(uint8_t* dest_buf,
102 int dest_pitch,
103 int width,
104 int height,
105 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
106 int src_left,
107 int src_top) {
108 uint8_t set_gray, reset_gray;
109 set_gray = 0xff;
110 reset_gray = 0x00;
111 for (int row = 0; row < height; ++row) {
112 uint8_t* dest_scan = dest_buf + row * dest_pitch;
113 memset(dest_scan, reset_gray, width);
114 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
115 for (int col = src_left; col < src_left + width; ++col) {
116 if (src_scan[col / 8] & (1 << (7 - col % 8)))
117 *dest_scan = set_gray;
118 ++dest_scan;
119 }
120 }
121 }
122
ConvertBuffer_8bppMask2Gray(uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)123 void ConvertBuffer_8bppMask2Gray(uint8_t* dest_buf,
124 int dest_pitch,
125 int width,
126 int height,
127 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
128 int src_left,
129 int src_top) {
130 for (int row = 0; row < height; ++row) {
131 uint8_t* dest_scan = dest_buf + row * dest_pitch;
132 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left;
133 memcpy(dest_scan, src_scan, width);
134 }
135 }
136
ConvertBuffer_1bppPlt2Gray(uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)137 void ConvertBuffer_1bppPlt2Gray(uint8_t* dest_buf,
138 int dest_pitch,
139 int width,
140 int height,
141 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
142 int src_left,
143 int src_top) {
144 uint32_t* src_plt = pSrcBitmap->GetPalette();
145 uint8_t gray[2];
146 uint8_t reset_r;
147 uint8_t reset_g;
148 uint8_t reset_b;
149 uint8_t set_r;
150 uint8_t set_g;
151 uint8_t set_b;
152 if (pSrcBitmap->IsCmykImage()) {
153 std::tie(reset_r, reset_g, reset_b) = AdobeCMYK_to_sRGB1(
154 FXSYS_GetCValue(src_plt[0]), FXSYS_GetMValue(src_plt[0]),
155 FXSYS_GetYValue(src_plt[0]), FXSYS_GetKValue(src_plt[0]));
156 std::tie(set_r, set_g, set_b) = AdobeCMYK_to_sRGB1(
157 FXSYS_GetCValue(src_plt[1]), FXSYS_GetMValue(src_plt[1]),
158 FXSYS_GetYValue(src_plt[1]), FXSYS_GetKValue(src_plt[1]));
159 } else {
160 reset_r = FXARGB_R(src_plt[0]);
161 reset_g = FXARGB_G(src_plt[0]);
162 reset_b = FXARGB_B(src_plt[0]);
163 set_r = FXARGB_R(src_plt[1]);
164 set_g = FXARGB_G(src_plt[1]);
165 set_b = FXARGB_B(src_plt[1]);
166 }
167 gray[0] = FXRGB2GRAY(reset_r, reset_g, reset_b);
168 gray[1] = FXRGB2GRAY(set_r, set_g, set_b);
169
170 for (int row = 0; row < height; ++row) {
171 uint8_t* dest_scan = dest_buf + row * dest_pitch;
172 memset(dest_scan, gray[0], width);
173 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
174 for (int col = src_left; col < src_left + width; ++col) {
175 if (src_scan[col / 8] & (1 << (7 - col % 8)))
176 *dest_scan = gray[1];
177 ++dest_scan;
178 }
179 }
180 }
181
ConvertBuffer_8bppPlt2Gray(uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)182 void ConvertBuffer_8bppPlt2Gray(uint8_t* dest_buf,
183 int dest_pitch,
184 int width,
185 int height,
186 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
187 int src_left,
188 int src_top) {
189 uint32_t* src_plt = pSrcBitmap->GetPalette();
190 uint8_t gray[256];
191 if (pSrcBitmap->IsCmykImage()) {
192 uint8_t r;
193 uint8_t g;
194 uint8_t b;
195 for (size_t i = 0; i < FX_ArraySize(gray); ++i) {
196 std::tie(r, g, b) = AdobeCMYK_to_sRGB1(
197 FXSYS_GetCValue(src_plt[i]), FXSYS_GetMValue(src_plt[i]),
198 FXSYS_GetYValue(src_plt[i]), FXSYS_GetKValue(src_plt[i]));
199 gray[i] = FXRGB2GRAY(r, g, b);
200 }
201 } else {
202 for (size_t i = 0; i < FX_ArraySize(gray); ++i) {
203 gray[i] = FXRGB2GRAY(FXARGB_R(src_plt[i]), FXARGB_G(src_plt[i]),
204 FXARGB_B(src_plt[i]));
205 }
206 }
207
208 for (int row = 0; row < height; ++row) {
209 uint8_t* dest_scan = dest_buf + row * dest_pitch;
210 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left;
211 for (int col = 0; col < width; ++col)
212 *dest_scan++ = gray[*src_scan++];
213 }
214 }
215
ConvertBuffer_RgbOrCmyk2Gray(uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)216 void ConvertBuffer_RgbOrCmyk2Gray(uint8_t* dest_buf,
217 int dest_pitch,
218 int width,
219 int height,
220 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
221 int src_left,
222 int src_top) {
223 int Bpp = pSrcBitmap->GetBPP() / 8;
224 if (pSrcBitmap->IsCmykImage()) {
225 for (int row = 0; row < height; ++row) {
226 uint8_t* dest_scan = dest_buf + row * dest_pitch;
227 const uint8_t* src_scan =
228 pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
229 for (int col = 0; col < width; ++col) {
230 uint8_t r;
231 uint8_t g;
232 uint8_t b;
233 std::tie(r, g, b) = AdobeCMYK_to_sRGB1(
234 FXSYS_GetCValue(static_cast<uint32_t>(src_scan[0])),
235 FXSYS_GetMValue(static_cast<uint32_t>(src_scan[1])),
236 FXSYS_GetYValue(static_cast<uint32_t>(src_scan[2])),
237 FXSYS_GetKValue(static_cast<uint32_t>(src_scan[3])));
238 *dest_scan++ = FXRGB2GRAY(r, g, b);
239 src_scan += 4;
240 }
241 }
242 } else {
243 for (int row = 0; row < height; ++row) {
244 uint8_t* dest_scan = dest_buf + row * dest_pitch;
245 const uint8_t* src_scan =
246 pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp;
247 for (int col = 0; col < width; ++col) {
248 *dest_scan++ = FXRGB2GRAY(src_scan[2], src_scan[1], src_scan[0]);
249 src_scan += Bpp;
250 }
251 }
252 }
253 }
254
ConvertBuffer_IndexCopy(uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)255 void ConvertBuffer_IndexCopy(uint8_t* dest_buf,
256 int dest_pitch,
257 int width,
258 int height,
259 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
260 int src_left,
261 int src_top) {
262 if (pSrcBitmap->GetBPP() == 1) {
263 for (int row = 0; row < height; ++row) {
264 uint8_t* dest_scan = dest_buf + row * dest_pitch;
265 // Set all destination pixels to be white initially.
266 memset(dest_scan, 255, width);
267 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
268 for (int col = src_left; col < src_left + width; ++col) {
269 // If the source bit is set, then set the destination pixel to be black.
270 if (src_scan[col / 8] & (1 << (7 - col % 8)))
271 *dest_scan = 0;
272
273 ++dest_scan;
274 }
275 }
276 } else {
277 for (int row = 0; row < height; ++row) {
278 uint8_t* dest_scan = dest_buf + row * dest_pitch;
279 const uint8_t* src_scan =
280 pSrcBitmap->GetScanline(src_top + row) + src_left;
281 memcpy(dest_scan, src_scan, width);
282 }
283 }
284 }
285
ConvertBuffer_Plt2PltRgb8(uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top,uint32_t * dst_plt)286 void ConvertBuffer_Plt2PltRgb8(uint8_t* dest_buf,
287 int dest_pitch,
288 int width,
289 int height,
290 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
291 int src_left,
292 int src_top,
293 uint32_t* dst_plt) {
294 ConvertBuffer_IndexCopy(dest_buf, dest_pitch, width, height, pSrcBitmap,
295 src_left, src_top);
296 uint32_t* src_plt = pSrcBitmap->GetPalette();
297 int plt_size = pSrcBitmap->GetPaletteSize();
298 if (pSrcBitmap->IsCmykImage()) {
299 for (int i = 0; i < plt_size; ++i) {
300 uint8_t r;
301 uint8_t g;
302 uint8_t b;
303 std::tie(r, g, b) = AdobeCMYK_to_sRGB1(
304 FXSYS_GetCValue(src_plt[i]), FXSYS_GetMValue(src_plt[i]),
305 FXSYS_GetYValue(src_plt[i]), FXSYS_GetKValue(src_plt[i]));
306 dst_plt[i] = FXARGB_MAKE(0xff, r, g, b);
307 }
308 } else {
309 memcpy(dst_plt, src_plt, plt_size * 4);
310 }
311 }
312
ConvertBuffer_Rgb2PltRgb8(uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top,uint32_t * dst_plt)313 void ConvertBuffer_Rgb2PltRgb8(uint8_t* dest_buf,
314 int dest_pitch,
315 int width,
316 int height,
317 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
318 int src_left,
319 int src_top,
320 uint32_t* dst_plt) {
321 int bpp = pSrcBitmap->GetBPP() / 8;
322 CFX_Palette palette(pSrcBitmap);
323 const std::pair<uint32_t, uint32_t>* Luts = palette.GetLuts();
324 int lut = palette.GetLutCount();
325 const uint32_t* pal = palette.GetPalette();
326 if (lut > 256) {
327 int err;
328 int min_err;
329 int lut_256 = lut - 256;
330 for (int row = 0; row < lut_256; ++row) {
331 min_err = 1000000;
332 uint8_t r;
333 uint8_t g;
334 uint8_t b;
335 ColorDecode(Luts[row].second, &r, &g, &b);
336 uint32_t clrindex = 0;
337 for (int col = 0; col < 256; ++col) {
338 uint32_t p_color = pal[col];
339 int d_r = r - static_cast<uint8_t>(p_color >> 16);
340 int d_g = g - static_cast<uint8_t>(p_color >> 8);
341 int d_b = b - static_cast<uint8_t>(p_color);
342 err = d_r * d_r + d_g * d_g + d_b * d_b;
343 if (err < min_err) {
344 min_err = err;
345 clrindex = col;
346 }
347 }
348 palette.SetAmountLut(row, clrindex);
349 }
350 }
351 int32_t lut_1 = lut - 1;
352 for (int row = 0; row < height; ++row) {
353 uint8_t* src_scan =
354 const_cast<uint8_t*>(pSrcBitmap->GetScanline(src_top + row)) + src_left;
355 uint8_t* dest_scan = dest_buf + row * dest_pitch;
356 for (int col = 0; col < width; ++col) {
357 uint8_t* src_port = src_scan + col * bpp;
358 int r = src_port[2] & 0xf0;
359 int g = src_port[1] & 0xf0;
360 int b = src_port[0] & 0xf0;
361 uint32_t clrindex = (r << 4) + g + (b >> 4);
362 for (int i = lut_1; i >= 0; --i)
363 if (clrindex == Luts[i].second) {
364 *(dest_scan + col) = static_cast<uint8_t>(Luts[i].first);
365 break;
366 }
367 }
368 }
369 memcpy(dst_plt, pal, sizeof(uint32_t) * 256);
370 }
371
ConvertBuffer_1bppMask2Rgb(FXDIB_Format dst_format,uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)372 void ConvertBuffer_1bppMask2Rgb(FXDIB_Format dst_format,
373 uint8_t* dest_buf,
374 int dest_pitch,
375 int width,
376 int height,
377 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
378 int src_left,
379 int src_top) {
380 int comps = (dst_format & 0xff) / 8;
381 uint8_t set_gray, reset_gray;
382 set_gray = 0xff;
383 reset_gray = 0x00;
384 for (int row = 0; row < height; ++row) {
385 uint8_t* dest_scan = dest_buf + row * dest_pitch;
386 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
387 for (int col = src_left; col < src_left + width; ++col) {
388 if (src_scan[col / 8] & (1 << (7 - col % 8))) {
389 dest_scan[0] = set_gray;
390 dest_scan[1] = set_gray;
391 dest_scan[2] = set_gray;
392 } else {
393 dest_scan[0] = reset_gray;
394 dest_scan[1] = reset_gray;
395 dest_scan[2] = reset_gray;
396 }
397 dest_scan += comps;
398 }
399 }
400 }
401
ConvertBuffer_8bppMask2Rgb(FXDIB_Format dst_format,uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)402 void ConvertBuffer_8bppMask2Rgb(FXDIB_Format dst_format,
403 uint8_t* dest_buf,
404 int dest_pitch,
405 int width,
406 int height,
407 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
408 int src_left,
409 int src_top) {
410 int comps = (dst_format & 0xff) / 8;
411 for (int row = 0; row < height; ++row) {
412 uint8_t* dest_scan = dest_buf + row * dest_pitch;
413 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left;
414 uint8_t src_pixel;
415 for (int col = 0; col < width; ++col) {
416 src_pixel = *src_scan++;
417 *dest_scan++ = src_pixel;
418 *dest_scan++ = src_pixel;
419 *dest_scan = src_pixel;
420 dest_scan += comps - 2;
421 }
422 }
423 }
424
ConvertBuffer_1bppPlt2Rgb(FXDIB_Format dst_format,uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)425 void ConvertBuffer_1bppPlt2Rgb(FXDIB_Format dst_format,
426 uint8_t* dest_buf,
427 int dest_pitch,
428 int width,
429 int height,
430 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
431 int src_left,
432 int src_top) {
433 int comps = (dst_format & 0xff) / 8;
434 uint32_t* src_plt = pSrcBitmap->GetPalette();
435 uint32_t plt[2];
436 uint8_t* bgr_ptr = reinterpret_cast<uint8_t*>(plt);
437 if (pSrcBitmap->IsCmykImage()) {
438 plt[0] = FXCMYK_TODIB(src_plt[0]);
439 plt[1] = FXCMYK_TODIB(src_plt[1]);
440 } else {
441 bgr_ptr[0] = FXARGB_B(src_plt[0]);
442 bgr_ptr[1] = FXARGB_G(src_plt[0]);
443 bgr_ptr[2] = FXARGB_R(src_plt[0]);
444 bgr_ptr[3] = FXARGB_B(src_plt[1]);
445 bgr_ptr[4] = FXARGB_G(src_plt[1]);
446 bgr_ptr[5] = FXARGB_R(src_plt[1]);
447 }
448
449 if (pSrcBitmap->IsCmykImage()) {
450 std::tie(bgr_ptr[2], bgr_ptr[1], bgr_ptr[0]) = AdobeCMYK_to_sRGB1(
451 FXSYS_GetCValue(src_plt[0]), FXSYS_GetMValue(src_plt[0]),
452 FXSYS_GetYValue(src_plt[0]), FXSYS_GetKValue(src_plt[0]));
453 std::tie(bgr_ptr[5], bgr_ptr[4], bgr_ptr[3]) = AdobeCMYK_to_sRGB1(
454 FXSYS_GetCValue(src_plt[1]), FXSYS_GetMValue(src_plt[1]),
455 FXSYS_GetYValue(src_plt[1]), FXSYS_GetKValue(src_plt[1]));
456 }
457
458 for (int row = 0; row < height; ++row) {
459 uint8_t* dest_scan = dest_buf + row * dest_pitch;
460 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
461 for (int col = src_left; col < src_left + width; ++col) {
462 if (src_scan[col / 8] & (1 << (7 - col % 8))) {
463 *dest_scan++ = bgr_ptr[3];
464 *dest_scan++ = bgr_ptr[4];
465 *dest_scan = bgr_ptr[5];
466 } else {
467 *dest_scan++ = bgr_ptr[0];
468 *dest_scan++ = bgr_ptr[1];
469 *dest_scan = bgr_ptr[2];
470 }
471 dest_scan += comps - 2;
472 }
473 }
474 }
475
ConvertBuffer_8bppPlt2Rgb(FXDIB_Format dst_format,uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)476 void ConvertBuffer_8bppPlt2Rgb(FXDIB_Format dst_format,
477 uint8_t* dest_buf,
478 int dest_pitch,
479 int width,
480 int height,
481 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
482 int src_left,
483 int src_top) {
484 int comps = (dst_format & 0xff) / 8;
485 uint32_t* src_plt = pSrcBitmap->GetPalette();
486 uint32_t plt[256];
487 uint8_t* bgr_ptr = reinterpret_cast<uint8_t*>(plt);
488 if (!pSrcBitmap->IsCmykImage()) {
489 for (int i = 0; i < 256; ++i) {
490 *bgr_ptr++ = FXARGB_B(src_plt[i]);
491 *bgr_ptr++ = FXARGB_G(src_plt[i]);
492 *bgr_ptr++ = FXARGB_R(src_plt[i]);
493 }
494 bgr_ptr = reinterpret_cast<uint8_t*>(plt);
495 }
496
497 if (pSrcBitmap->IsCmykImage()) {
498 for (int i = 0; i < 256; ++i) {
499 std::tie(bgr_ptr[2], bgr_ptr[1], bgr_ptr[0]) = AdobeCMYK_to_sRGB1(
500 FXSYS_GetCValue(src_plt[i]), FXSYS_GetMValue(src_plt[i]),
501 FXSYS_GetYValue(src_plt[i]), FXSYS_GetKValue(src_plt[i]));
502 bgr_ptr += 3;
503 }
504 bgr_ptr = reinterpret_cast<uint8_t*>(plt);
505 }
506
507 for (int row = 0; row < height; ++row) {
508 uint8_t* dest_scan = dest_buf + row * dest_pitch;
509 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left;
510 for (int col = 0; col < width; ++col) {
511 uint8_t* src_pixel = bgr_ptr + 3 * (*src_scan++);
512 *dest_scan++ = *src_pixel++;
513 *dest_scan++ = *src_pixel++;
514 *dest_scan = *src_pixel++;
515 dest_scan += comps - 2;
516 }
517 }
518 }
519
ConvertBuffer_24bppRgb2Rgb24(uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)520 void ConvertBuffer_24bppRgb2Rgb24(uint8_t* dest_buf,
521 int dest_pitch,
522 int width,
523 int height,
524 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
525 int src_left,
526 int src_top) {
527 for (int row = 0; row < height; ++row) {
528 uint8_t* dest_scan = dest_buf + row * dest_pitch;
529 const uint8_t* src_scan =
530 pSrcBitmap->GetScanline(src_top + row) + src_left * 3;
531 memcpy(dest_scan, src_scan, width * 3);
532 }
533 }
534
ConvertBuffer_32bppRgb2Rgb24(uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)535 void ConvertBuffer_32bppRgb2Rgb24(uint8_t* dest_buf,
536 int dest_pitch,
537 int width,
538 int height,
539 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
540 int src_left,
541 int src_top) {
542 for (int row = 0; row < height; ++row) {
543 uint8_t* dest_scan = dest_buf + row * dest_pitch;
544 const uint8_t* src_scan =
545 pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
546 for (int col = 0; col < width; ++col) {
547 *dest_scan++ = *src_scan++;
548 *dest_scan++ = *src_scan++;
549 *dest_scan++ = *src_scan++;
550 ++src_scan;
551 }
552 }
553 }
554
ConvertBuffer_Rgb2Rgb32(uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)555 void ConvertBuffer_Rgb2Rgb32(uint8_t* dest_buf,
556 int dest_pitch,
557 int width,
558 int height,
559 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
560 int src_left,
561 int src_top) {
562 int comps = pSrcBitmap->GetBPP() / 8;
563 for (int row = 0; row < height; ++row) {
564 uint8_t* dest_scan = dest_buf + row * dest_pitch;
565 const uint8_t* src_scan =
566 pSrcBitmap->GetScanline(src_top + row) + src_left * comps;
567 for (int col = 0; col < width; ++col) {
568 *dest_scan++ = *src_scan++;
569 *dest_scan++ = *src_scan++;
570 *dest_scan++ = *src_scan++;
571 ++dest_scan;
572 src_scan += comps - 3;
573 }
574 }
575 }
576
ConvertBuffer_32bppCmyk2Rgb32(uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)577 void ConvertBuffer_32bppCmyk2Rgb32(uint8_t* dest_buf,
578 int dest_pitch,
579 int width,
580 int height,
581 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
582 int src_left,
583 int src_top) {
584 for (int row = 0; row < height; ++row) {
585 uint8_t* dest_scan = dest_buf + row * dest_pitch;
586 const uint8_t* src_scan =
587 pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
588 for (int col = 0; col < width; ++col) {
589 std::tie(dest_scan[2], dest_scan[1], dest_scan[0]) = AdobeCMYK_to_sRGB1(
590 src_scan[0], src_scan[1], src_scan[2], src_scan[3]);
591 dest_scan += 4;
592 src_scan += 4;
593 }
594 }
595 }
596
597 } // namespace
598
CFX_DIBSource()599 CFX_DIBSource::CFX_DIBSource()
600 : m_Width(0), m_Height(0), m_bpp(0), m_AlphaFlag(0), m_Pitch(0) {}
601
~CFX_DIBSource()602 CFX_DIBSource::~CFX_DIBSource() {}
603
GetBuffer() const604 uint8_t* CFX_DIBSource::GetBuffer() const {
605 return nullptr;
606 }
607
SkipToScanline(int line,IFX_PauseIndicator * pPause) const608 bool CFX_DIBSource::SkipToScanline(int line, IFX_PauseIndicator* pPause) const {
609 return false;
610 }
611
Clone(const FX_RECT * pClip) const612 RetainPtr<CFX_DIBitmap> CFX_DIBSource::Clone(const FX_RECT* pClip) const {
613 FX_RECT rect(0, 0, m_Width, m_Height);
614 if (pClip) {
615 rect.Intersect(*pClip);
616 if (rect.IsEmpty())
617 return nullptr;
618 }
619 auto pNewBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
620 if (!pNewBitmap->Create(rect.Width(), rect.Height(), GetFormat()))
621 return nullptr;
622
623 pNewBitmap->SetPalette(m_pPalette.get());
624 pNewBitmap->SetAlphaMask(m_pAlphaMask, pClip);
625 if (GetBPP() == 1 && rect.left % 8 != 0) {
626 int left_shift = rect.left % 32;
627 int right_shift = 32 - left_shift;
628 int dword_count = pNewBitmap->m_Pitch / 4;
629 for (int row = rect.top; row < rect.bottom; ++row) {
630 uint32_t* src_scan = (uint32_t*)GetScanline(row) + rect.left / 32;
631 uint32_t* dest_scan = (uint32_t*)pNewBitmap->GetScanline(row - rect.top);
632 for (int i = 0; i < dword_count; ++i) {
633 dest_scan[i] =
634 (src_scan[i] << left_shift) | (src_scan[i + 1] >> right_shift);
635 }
636 }
637 } else {
638 int copy_len = (pNewBitmap->GetWidth() * pNewBitmap->GetBPP() + 7) / 8;
639 if (m_Pitch < static_cast<uint32_t>(copy_len))
640 copy_len = m_Pitch;
641
642 for (int row = rect.top; row < rect.bottom; ++row) {
643 const uint8_t* src_scan = GetScanline(row) + rect.left * m_bpp / 8;
644 uint8_t* dest_scan = (uint8_t*)pNewBitmap->GetScanline(row - rect.top);
645 memcpy(dest_scan, src_scan, copy_len);
646 }
647 }
648 return pNewBitmap;
649 }
650
BuildPalette()651 void CFX_DIBSource::BuildPalette() {
652 if (m_pPalette)
653 return;
654
655 if (GetBPP() == 1) {
656 m_pPalette.reset(FX_Alloc(uint32_t, 2));
657 if (IsCmykImage()) {
658 m_pPalette.get()[0] = 0xff;
659 m_pPalette.get()[1] = 0;
660 } else {
661 m_pPalette.get()[0] = 0xff000000;
662 m_pPalette.get()[1] = 0xffffffff;
663 }
664 } else if (GetBPP() == 8) {
665 m_pPalette.reset(FX_Alloc(uint32_t, 256));
666 if (IsCmykImage()) {
667 for (int i = 0; i < 256; ++i)
668 m_pPalette.get()[i] = 0xff - i;
669 } else {
670 for (int i = 0; i < 256; ++i)
671 m_pPalette.get()[i] = 0xff000000 | (i * 0x10101);
672 }
673 }
674 }
675
BuildAlphaMask()676 bool CFX_DIBSource::BuildAlphaMask() {
677 if (m_pAlphaMask)
678 return true;
679
680 m_pAlphaMask = pdfium::MakeRetain<CFX_DIBitmap>();
681 if (!m_pAlphaMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
682 m_pAlphaMask = nullptr;
683 return false;
684 }
685 memset(m_pAlphaMask->GetBuffer(), 0xff,
686 m_pAlphaMask->GetHeight() * m_pAlphaMask->GetPitch());
687 return true;
688 }
689
GetPaletteArgb(int index) const690 uint32_t CFX_DIBSource::GetPaletteArgb(int index) const {
691 ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask());
692 if (m_pPalette)
693 return m_pPalette.get()[index];
694
695 if (IsCmykImage()) {
696 if (GetBPP() == 1)
697 return index ? 0 : 0xff;
698
699 return 0xff - index;
700 }
701 if (GetBPP() == 1)
702 return index ? 0xffffffff : 0xff000000;
703
704 return index * 0x10101 | 0xff000000;
705 }
706
SetPaletteArgb(int index,uint32_t color)707 void CFX_DIBSource::SetPaletteArgb(int index, uint32_t color) {
708 ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask());
709 if (!m_pPalette) {
710 BuildPalette();
711 }
712 m_pPalette.get()[index] = color;
713 }
714
FindPalette(uint32_t color) const715 int CFX_DIBSource::FindPalette(uint32_t color) const {
716 ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask());
717 if (!m_pPalette) {
718 if (IsCmykImage()) {
719 if (GetBPP() == 1)
720 return (static_cast<uint8_t>(color) == 0xff) ? 0 : 1;
721
722 return 0xff - static_cast<uint8_t>(color);
723 }
724 if (GetBPP() == 1)
725 return (static_cast<uint8_t>(color) == 0xff) ? 1 : 0;
726
727 return static_cast<uint8_t>(color);
728 }
729 int palsize = (1 << GetBPP());
730 for (int i = 0; i < palsize; ++i) {
731 if (m_pPalette.get()[i] == color)
732 return i;
733 }
734 return -1;
735 }
736
GetOverlapRect(int & dest_left,int & dest_top,int & width,int & height,int src_width,int src_height,int & src_left,int & src_top,const CFX_ClipRgn * pClipRgn)737 void CFX_DIBSource::GetOverlapRect(int& dest_left,
738 int& dest_top,
739 int& width,
740 int& height,
741 int src_width,
742 int src_height,
743 int& src_left,
744 int& src_top,
745 const CFX_ClipRgn* pClipRgn) {
746 if (width == 0 || height == 0)
747 return;
748
749 ASSERT(width > 0 && height > 0);
750 if (dest_left > m_Width || dest_top > m_Height) {
751 width = 0;
752 height = 0;
753 return;
754 }
755 int x_offset = dest_left - src_left;
756 int y_offset = dest_top - src_top;
757 FX_RECT src_rect(src_left, src_top, src_left + width, src_top + height);
758 FX_RECT src_bound(0, 0, src_width, src_height);
759 src_rect.Intersect(src_bound);
760 FX_RECT dest_rect(src_rect.left + x_offset, src_rect.top + y_offset,
761 src_rect.right + x_offset, src_rect.bottom + y_offset);
762 FX_RECT dest_bound(0, 0, m_Width, m_Height);
763 dest_rect.Intersect(dest_bound);
764 if (pClipRgn)
765 dest_rect.Intersect(pClipRgn->GetBox());
766 dest_left = dest_rect.left;
767 dest_top = dest_rect.top;
768 src_left = dest_left - x_offset;
769 src_top = dest_top - y_offset;
770 width = dest_rect.right - dest_rect.left;
771 height = dest_rect.bottom - dest_rect.top;
772 }
773
SetPalette(const uint32_t * pSrc)774 void CFX_DIBSource::SetPalette(const uint32_t* pSrc) {
775 static const uint32_t kPaletteSize = 256;
776 if (!pSrc || GetBPP() > 8) {
777 m_pPalette.reset();
778 return;
779 }
780 uint32_t pal_size = 1 << GetBPP();
781 if (!m_pPalette)
782 m_pPalette.reset(FX_Alloc(uint32_t, pal_size));
783 pal_size = std::min(pal_size, kPaletteSize);
784 memcpy(m_pPalette.get(), pSrc, pal_size * sizeof(uint32_t));
785 }
786
GetPalette(uint32_t * pal,int alpha) const787 void CFX_DIBSource::GetPalette(uint32_t* pal, int alpha) const {
788 ASSERT(GetBPP() <= 8 && !IsCmykImage());
789 if (GetBPP() == 1) {
790 pal[0] = ((m_pPalette ? m_pPalette.get()[0] : 0xff000000) & 0xffffff) |
791 (alpha << 24);
792 pal[1] = ((m_pPalette ? m_pPalette.get()[1] : 0xffffffff) & 0xffffff) |
793 (alpha << 24);
794 return;
795 }
796 if (m_pPalette) {
797 for (int i = 0; i < 256; ++i)
798 pal[i] = (m_pPalette.get()[i] & 0x00ffffff) | (alpha << 24);
799 } else {
800 for (int i = 0; i < 256; ++i)
801 pal[i] = (i * 0x10101) | (alpha << 24);
802 }
803 }
804
CloneAlphaMask() const805 RetainPtr<CFX_DIBitmap> CFX_DIBSource::CloneAlphaMask() const {
806 ASSERT(GetFormat() == FXDIB_Argb);
807 FX_RECT rect(0, 0, m_Width, m_Height);
808 auto pMask = pdfium::MakeRetain<CFX_DIBitmap>();
809 if (!pMask->Create(rect.Width(), rect.Height(), FXDIB_8bppMask))
810 return nullptr;
811
812 for (int row = rect.top; row < rect.bottom; ++row) {
813 const uint8_t* src_scan = GetScanline(row) + rect.left * 4 + 3;
814 uint8_t* dest_scan =
815 const_cast<uint8_t*>(pMask->GetScanline(row - rect.top));
816 for (int col = rect.left; col < rect.right; ++col) {
817 *dest_scan++ = *src_scan;
818 src_scan += 4;
819 }
820 }
821 return pMask;
822 }
823
SetAlphaMask(const RetainPtr<CFX_DIBSource> & pAlphaMask,const FX_RECT * pClip)824 bool CFX_DIBSource::SetAlphaMask(const RetainPtr<CFX_DIBSource>& pAlphaMask,
825 const FX_RECT* pClip) {
826 if (!HasAlpha() || GetFormat() == FXDIB_Argb)
827 return false;
828
829 if (!pAlphaMask) {
830 m_pAlphaMask->Clear(0xff000000);
831 return true;
832 }
833 FX_RECT rect(0, 0, pAlphaMask->m_Width, pAlphaMask->m_Height);
834 if (pClip) {
835 rect.Intersect(*pClip);
836 if (rect.IsEmpty() || rect.Width() != m_Width ||
837 rect.Height() != m_Height) {
838 return false;
839 }
840 } else {
841 if (pAlphaMask->m_Width != m_Width || pAlphaMask->m_Height != m_Height)
842 return false;
843 }
844 for (int row = 0; row < m_Height; ++row) {
845 memcpy(const_cast<uint8_t*>(m_pAlphaMask->GetScanline(row)),
846 pAlphaMask->GetScanline(row + rect.top) + rect.left,
847 m_pAlphaMask->m_Pitch);
848 }
849 return true;
850 }
851
FlipImage(bool bXFlip,bool bYFlip) const852 RetainPtr<CFX_DIBitmap> CFX_DIBSource::FlipImage(bool bXFlip,
853 bool bYFlip) const {
854 auto pFlipped = pdfium::MakeRetain<CFX_DIBitmap>();
855 if (!pFlipped->Create(m_Width, m_Height, GetFormat()))
856 return nullptr;
857
858 pFlipped->SetPalette(m_pPalette.get());
859 uint8_t* pDestBuffer = pFlipped->GetBuffer();
860 int Bpp = m_bpp / 8;
861 for (int row = 0; row < m_Height; ++row) {
862 const uint8_t* src_scan = GetScanline(row);
863 uint8_t* dest_scan =
864 pDestBuffer + m_Pitch * (bYFlip ? (m_Height - row - 1) : row);
865 if (!bXFlip) {
866 memcpy(dest_scan, src_scan, m_Pitch);
867 continue;
868 }
869 if (m_bpp == 1) {
870 memset(dest_scan, 0, m_Pitch);
871 for (int col = 0; col < m_Width; ++col)
872 if (src_scan[col / 8] & (1 << (7 - col % 8))) {
873 int dest_col = m_Width - col - 1;
874 dest_scan[dest_col / 8] |= (1 << (7 - dest_col % 8));
875 }
876 } else {
877 dest_scan += (m_Width - 1) * Bpp;
878 if (Bpp == 1) {
879 for (int col = 0; col < m_Width; ++col) {
880 *dest_scan = *src_scan;
881 --dest_scan;
882 ++src_scan;
883 }
884 } else if (Bpp == 3) {
885 for (int col = 0; col < m_Width; ++col) {
886 dest_scan[0] = src_scan[0];
887 dest_scan[1] = src_scan[1];
888 dest_scan[2] = src_scan[2];
889 dest_scan -= 3;
890 src_scan += 3;
891 }
892 } else {
893 ASSERT(Bpp == 4);
894 for (int col = 0; col < m_Width; ++col) {
895 *(uint32_t*)dest_scan = *(uint32_t*)src_scan;
896 dest_scan -= 4;
897 src_scan += 4;
898 }
899 }
900 }
901 }
902 if (m_pAlphaMask) {
903 pDestBuffer = pFlipped->m_pAlphaMask->GetBuffer();
904 uint32_t dest_pitch = pFlipped->m_pAlphaMask->GetPitch();
905 for (int row = 0; row < m_Height; ++row) {
906 const uint8_t* src_scan = m_pAlphaMask->GetScanline(row);
907 uint8_t* dest_scan =
908 pDestBuffer + dest_pitch * (bYFlip ? (m_Height - row - 1) : row);
909 if (!bXFlip) {
910 memcpy(dest_scan, src_scan, dest_pitch);
911 continue;
912 }
913 dest_scan += (m_Width - 1);
914 for (int col = 0; col < m_Width; ++col) {
915 *dest_scan = *src_scan;
916 --dest_scan;
917 ++src_scan;
918 }
919 }
920 }
921 return pFlipped;
922 }
923
CloneConvert(FXDIB_Format dest_format)924 RetainPtr<CFX_DIBitmap> CFX_DIBSource::CloneConvert(FXDIB_Format dest_format) {
925 if (dest_format == GetFormat())
926 return Clone(nullptr);
927
928 auto pClone = pdfium::MakeRetain<CFX_DIBitmap>();
929 if (!pClone->Create(m_Width, m_Height, dest_format))
930 return nullptr;
931
932 RetainPtr<CFX_DIBitmap> pSrcAlpha;
933 if (HasAlpha()) {
934 if (GetFormat() == FXDIB_Argb)
935 pSrcAlpha = CloneAlphaMask();
936 else
937 pSrcAlpha = m_pAlphaMask;
938
939 if (!pSrcAlpha)
940 return nullptr;
941 }
942 bool ret = true;
943 if (dest_format & 0x0200) {
944 if (dest_format == FXDIB_Argb) {
945 ret = pSrcAlpha ? pClone->LoadChannel(FXDIB_Alpha, pSrcAlpha, FXDIB_Alpha)
946 : pClone->LoadChannel(FXDIB_Alpha, 0xff);
947 } else {
948 ret = pClone->SetAlphaMask(pSrcAlpha, nullptr);
949 }
950 }
951 if (!ret)
952 return nullptr;
953
954 RetainPtr<CFX_DIBSource> holder(this);
955 std::unique_ptr<uint32_t, FxFreeDeleter> pal_8bpp;
956 if (!ConvertBuffer(dest_format, pClone->GetBuffer(), pClone->GetPitch(),
957 m_Width, m_Height, holder, 0, 0, &pal_8bpp)) {
958 return nullptr;
959 }
960 if (pal_8bpp)
961 pClone->SetPalette(pal_8bpp.get());
962
963 return pClone;
964 }
965
SwapXY(bool bXFlip,bool bYFlip) const966 RetainPtr<CFX_DIBitmap> CFX_DIBSource::SwapXY(bool bXFlip, bool bYFlip) const {
967 FX_RECT dest_clip(0, 0, m_Height, m_Width);
968 if (dest_clip.IsEmpty())
969 return nullptr;
970
971 auto pTransBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
972 int result_height = dest_clip.Height();
973 int result_width = dest_clip.Width();
974 if (!pTransBitmap->Create(result_width, result_height, GetFormat()))
975 return nullptr;
976
977 pTransBitmap->SetPalette(m_pPalette.get());
978 int dest_pitch = pTransBitmap->GetPitch();
979 uint8_t* dest_buf = pTransBitmap->GetBuffer();
980 int row_start = bXFlip ? m_Height - dest_clip.right : dest_clip.left;
981 int row_end = bXFlip ? m_Height - dest_clip.left : dest_clip.right;
982 int col_start = bYFlip ? m_Width - dest_clip.bottom : dest_clip.top;
983 int col_end = bYFlip ? m_Width - dest_clip.top : dest_clip.bottom;
984 if (GetBPP() == 1) {
985 memset(dest_buf, 0xff, dest_pitch * result_height);
986 for (int row = row_start; row < row_end; ++row) {
987 const uint8_t* src_scan = GetScanline(row);
988 int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) -
989 dest_clip.left;
990 uint8_t* dest_scan = dest_buf;
991 if (bYFlip)
992 dest_scan += (result_height - 1) * dest_pitch;
993 int dest_step = bYFlip ? -dest_pitch : dest_pitch;
994 for (int col = col_start; col < col_end; ++col) {
995 if (!(src_scan[col / 8] & (1 << (7 - col % 8))))
996 dest_scan[dest_col / 8] &= ~(1 << (7 - dest_col % 8));
997 dest_scan += dest_step;
998 }
999 }
1000 } else {
1001 int nBytes = GetBPP() / 8;
1002 int dest_step = bYFlip ? -dest_pitch : dest_pitch;
1003 if (nBytes == 3)
1004 dest_step -= 2;
1005 for (int row = row_start; row < row_end; ++row) {
1006 int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) -
1007 dest_clip.left;
1008 uint8_t* dest_scan = dest_buf + dest_col * nBytes;
1009 if (bYFlip)
1010 dest_scan += (result_height - 1) * dest_pitch;
1011 if (nBytes == 4) {
1012 uint32_t* src_scan = (uint32_t*)GetScanline(row) + col_start;
1013 for (int col = col_start; col < col_end; ++col) {
1014 *(uint32_t*)dest_scan = *src_scan++;
1015 dest_scan += dest_step;
1016 }
1017 } else {
1018 const uint8_t* src_scan = GetScanline(row) + col_start * nBytes;
1019 if (nBytes == 1) {
1020 for (int col = col_start; col < col_end; ++col) {
1021 *dest_scan = *src_scan++;
1022 dest_scan += dest_step;
1023 }
1024 } else {
1025 for (int col = col_start; col < col_end; ++col) {
1026 *dest_scan++ = *src_scan++;
1027 *dest_scan++ = *src_scan++;
1028 *dest_scan = *src_scan++;
1029 dest_scan += dest_step;
1030 }
1031 }
1032 }
1033 }
1034 }
1035 if (m_pAlphaMask) {
1036 dest_pitch = pTransBitmap->m_pAlphaMask->GetPitch();
1037 dest_buf = pTransBitmap->m_pAlphaMask->GetBuffer();
1038 int dest_step = bYFlip ? -dest_pitch : dest_pitch;
1039 for (int row = row_start; row < row_end; ++row) {
1040 int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) -
1041 dest_clip.left;
1042 uint8_t* dest_scan = dest_buf + dest_col;
1043 if (bYFlip)
1044 dest_scan += (result_height - 1) * dest_pitch;
1045 const uint8_t* src_scan = m_pAlphaMask->GetScanline(row) + col_start;
1046 for (int col = col_start; col < col_end; ++col) {
1047 *dest_scan = *src_scan++;
1048 dest_scan += dest_step;
1049 }
1050 }
1051 }
1052 return pTransBitmap;
1053 }
1054
TransformTo(const CFX_Matrix * pDestMatrix,int * result_left,int * result_top)1055 RetainPtr<CFX_DIBitmap> CFX_DIBSource::TransformTo(
1056 const CFX_Matrix* pDestMatrix,
1057 int* result_left,
1058 int* result_top) {
1059 RetainPtr<CFX_DIBSource> holder(this);
1060 CFX_ImageTransformer transformer(holder, pDestMatrix, 0, nullptr);
1061 transformer.Continue(nullptr);
1062 *result_left = transformer.result().left;
1063 *result_top = transformer.result().top;
1064 return transformer.DetachBitmap();
1065 }
1066
StretchTo(int dest_width,int dest_height,uint32_t flags,const FX_RECT * pClip)1067 RetainPtr<CFX_DIBitmap> CFX_DIBSource::StretchTo(int dest_width,
1068 int dest_height,
1069 uint32_t flags,
1070 const FX_RECT* pClip) {
1071 RetainPtr<CFX_DIBSource> holder(this);
1072 FX_RECT clip_rect(0, 0, abs(dest_width), abs(dest_height));
1073 if (pClip)
1074 clip_rect.Intersect(*pClip);
1075
1076 if (clip_rect.IsEmpty())
1077 return nullptr;
1078
1079 if (dest_width == m_Width && dest_height == m_Height)
1080 return Clone(&clip_rect);
1081
1082 CFX_BitmapStorer storer;
1083 CFX_ImageStretcher stretcher(&storer, holder, dest_width, dest_height,
1084 clip_rect, flags);
1085 if (stretcher.Start())
1086 stretcher.Continue(nullptr);
1087
1088 return storer.Detach();
1089 }
1090
1091 // static
ConvertBuffer(FXDIB_Format dest_format,uint8_t * dest_buf,int dest_pitch,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top,std::unique_ptr<uint32_t,FxFreeDeleter> * p_pal)1092 bool CFX_DIBSource::ConvertBuffer(
1093 FXDIB_Format dest_format,
1094 uint8_t* dest_buf,
1095 int dest_pitch,
1096 int width,
1097 int height,
1098 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
1099 int src_left,
1100 int src_top,
1101 std::unique_ptr<uint32_t, FxFreeDeleter>* p_pal) {
1102 FXDIB_Format src_format = pSrcBitmap->GetFormat();
1103 switch (dest_format) {
1104 case FXDIB_Invalid:
1105 case FXDIB_1bppCmyk:
1106 case FXDIB_1bppMask:
1107 case FXDIB_1bppRgb:
1108 NOTREACHED();
1109 return false;
1110 case FXDIB_8bppMask: {
1111 if ((src_format & 0xff) == 1) {
1112 if (pSrcBitmap->GetPalette()) {
1113 ConvertBuffer_1bppPlt2Gray(dest_buf, dest_pitch, width, height,
1114 pSrcBitmap, src_left, src_top);
1115 return true;
1116 }
1117 ConvertBuffer_1bppMask2Gray(dest_buf, dest_pitch, width, height,
1118 pSrcBitmap, src_left, src_top);
1119 return true;
1120 }
1121 if ((src_format & 0xff) == 8) {
1122 if (pSrcBitmap->GetPalette()) {
1123 ConvertBuffer_8bppPlt2Gray(dest_buf, dest_pitch, width, height,
1124 pSrcBitmap, src_left, src_top);
1125 return true;
1126 }
1127 ConvertBuffer_8bppMask2Gray(dest_buf, dest_pitch, width, height,
1128 pSrcBitmap, src_left, src_top);
1129 return true;
1130 }
1131 if ((src_format & 0xff) >= 24) {
1132 ConvertBuffer_RgbOrCmyk2Gray(dest_buf, dest_pitch, width, height,
1133 pSrcBitmap, src_left, src_top);
1134 return true;
1135 }
1136 return false;
1137 }
1138 case FXDIB_8bppRgb:
1139 case FXDIB_8bppRgba: {
1140 if ((src_format & 0xff) == 8 && !pSrcBitmap->GetPalette()) {
1141 return ConvertBuffer(FXDIB_8bppMask, dest_buf, dest_pitch, width,
1142 height, pSrcBitmap, src_left, src_top, p_pal);
1143 }
1144 p_pal->reset(FX_Alloc(uint32_t, 256));
1145 if (((src_format & 0xff) == 1 || (src_format & 0xff) == 8) &&
1146 pSrcBitmap->GetPalette()) {
1147 ConvertBuffer_Plt2PltRgb8(dest_buf, dest_pitch, width, height,
1148 pSrcBitmap, src_left, src_top, p_pal->get());
1149 return true;
1150 }
1151 if ((src_format & 0xff) >= 24) {
1152 ConvertBuffer_Rgb2PltRgb8(dest_buf, dest_pitch, width, height,
1153 pSrcBitmap, src_left, src_top, p_pal->get());
1154 return true;
1155 }
1156 return false;
1157 }
1158 case FXDIB_Rgb:
1159 case FXDIB_Rgba: {
1160 if ((src_format & 0xff) == 1) {
1161 if (pSrcBitmap->GetPalette()) {
1162 ConvertBuffer_1bppPlt2Rgb(dest_format, dest_buf, dest_pitch, width,
1163 height, pSrcBitmap, src_left, src_top);
1164 return true;
1165 }
1166 ConvertBuffer_1bppMask2Rgb(dest_format, dest_buf, dest_pitch, width,
1167 height, pSrcBitmap, src_left, src_top);
1168 return true;
1169 }
1170 if ((src_format & 0xff) == 8) {
1171 if (pSrcBitmap->GetPalette()) {
1172 ConvertBuffer_8bppPlt2Rgb(dest_format, dest_buf, dest_pitch, width,
1173 height, pSrcBitmap, src_left, src_top);
1174 return true;
1175 }
1176 ConvertBuffer_8bppMask2Rgb(dest_format, dest_buf, dest_pitch, width,
1177 height, pSrcBitmap, src_left, src_top);
1178 return true;
1179 }
1180 if ((src_format & 0xff) == 24) {
1181 ConvertBuffer_24bppRgb2Rgb24(dest_buf, dest_pitch, width, height,
1182 pSrcBitmap, src_left, src_top);
1183 return true;
1184 }
1185 if ((src_format & 0xff) == 32) {
1186 ConvertBuffer_32bppRgb2Rgb24(dest_buf, dest_pitch, width, height,
1187 pSrcBitmap, src_left, src_top);
1188 return true;
1189 }
1190 return false;
1191 }
1192 case FXDIB_Argb:
1193 case FXDIB_Rgb32: {
1194 if ((src_format & 0xff) == 1) {
1195 if (pSrcBitmap->GetPalette()) {
1196 ConvertBuffer_1bppPlt2Rgb(dest_format, dest_buf, dest_pitch, width,
1197 height, pSrcBitmap, src_left, src_top);
1198 return true;
1199 }
1200 ConvertBuffer_1bppMask2Rgb(dest_format, dest_buf, dest_pitch, width,
1201 height, pSrcBitmap, src_left, src_top);
1202 return true;
1203 }
1204 if ((src_format & 0xff) == 8) {
1205 if (pSrcBitmap->GetPalette()) {
1206 ConvertBuffer_8bppPlt2Rgb(dest_format, dest_buf, dest_pitch, width,
1207 height, pSrcBitmap, src_left, src_top);
1208 return true;
1209 }
1210 ConvertBuffer_8bppMask2Rgb(dest_format, dest_buf, dest_pitch, width,
1211 height, pSrcBitmap, src_left, src_top);
1212 return true;
1213 }
1214 if ((src_format & 0xff) >= 24) {
1215 if (src_format & 0x0400) {
1216 ConvertBuffer_32bppCmyk2Rgb32(dest_buf, dest_pitch, width, height,
1217 pSrcBitmap, src_left, src_top);
1218 return true;
1219 }
1220 ConvertBuffer_Rgb2Rgb32(dest_buf, dest_pitch, width, height, pSrcBitmap,
1221 src_left, src_top);
1222 return true;
1223 }
1224 return false;
1225 }
1226 default:
1227 return false;
1228 }
1229 }
1230