• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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