• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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/fxcodec/progressivedecoder.h"
8 
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12 #include <vector>
13 
14 #include "build/build_config.h"
15 #include "core/fxcodec/cfx_codec_memory.h"
16 #include "core/fxcodec/fx_codec.h"
17 #include "core/fxcrt/fx_safe_types.h"
18 #include "core/fxcrt/fx_stream.h"
19 #include "core/fxge/dib/cfx_cmyk_to_srgb.h"
20 #include "core/fxge/dib/cfx_dibitmap.h"
21 #include "core/fxge/fx_dib.h"
22 #include "third_party/base/logging.h"
23 #include "third_party/base/numerics/safe_math.h"
24 #include "third_party/base/ptr_util.h"
25 
26 namespace fxcodec {
27 
28 namespace {
29 
30 constexpr size_t kBlockSize = 4096;
31 
32 #ifdef PDF_ENABLE_XFA_PNG
33 #if defined(OS_MACOSX)
34 const double kPngGamma = 1.7;
35 #else
36 const double kPngGamma = 2.2;
37 #endif  // defined(OS_MACOSX)
38 #endif  // PDF_ENABLE_XFA_PNG
39 
RGB2BGR(uint8_t * buffer,int width=1)40 void RGB2BGR(uint8_t* buffer, int width = 1) {
41   if (buffer && width > 0) {
42     uint8_t temp;
43     int i = 0;
44     int j = 0;
45     for (; i < width; i++, j += 3) {
46       temp = buffer[j];
47       buffer[j] = buffer[j + 2];
48       buffer[j + 2] = temp;
49     }
50   }
51 }
52 
53 }  // namespace
54 
55 ProgressiveDecoder::CFXCODEC_WeightTable::CFXCODEC_WeightTable() = default;
56 
57 ProgressiveDecoder::CFXCODEC_WeightTable::~CFXCODEC_WeightTable() = default;
58 
Calc(int dest_len,int src_len)59 void ProgressiveDecoder::CFXCODEC_WeightTable::Calc(int dest_len, int src_len) {
60   double scale = static_cast<double>(src_len) / dest_len;
61   double base = dest_len < 0 ? src_len : 0.0;
62   m_ItemSize = (int)(sizeof(int) * 2 + sizeof(int) * (ceil(fabs(scale)) + 1));
63   m_DestMin = 0;
64   m_pWeightTables.resize(dest_len * m_ItemSize + 4);
65   if (fabs(scale) < 1.0) {
66     for (int dest_pixel = 0; dest_pixel < dest_len; dest_pixel++) {
67       PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel);
68       double src_pos = dest_pixel * scale + scale / 2 + base;
69       pixel_weights.m_SrcStart = (int)floor((float)src_pos - 1.0f / 2);
70       pixel_weights.m_SrcEnd = (int)floor((float)src_pos + 1.0f / 2);
71       pixel_weights.m_SrcStart = std::max(pixel_weights.m_SrcStart, 0);
72       pixel_weights.m_SrcEnd = std::min(pixel_weights.m_SrcEnd, src_len - 1);
73       if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) {
74         pixel_weights.m_Weights[0] = 65536;
75       } else {
76         pixel_weights.m_Weights[1] = FXSYS_roundf(
77             (float)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * 65536);
78         pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights[1];
79       }
80     }
81     return;
82   }
83   for (int dest_pixel = 0; dest_pixel < dest_len; dest_pixel++) {
84     PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel);
85     double src_start = dest_pixel * scale + base;
86     double src_end = src_start + scale;
87     int start_i;
88     int end_i;
89     if (src_start < src_end) {
90       start_i = (int)floor((float)src_start);
91       end_i = (int)ceil((float)src_end);
92     } else {
93       start_i = (int)floor((float)src_end);
94       end_i = (int)ceil((float)src_start);
95     }
96     start_i = std::max(start_i, 0);
97     end_i = std::min(end_i, src_len - 1);
98     if (start_i > end_i) {
99       pixel_weights.m_SrcStart = start_i;
100       pixel_weights.m_SrcEnd = start_i;
101       continue;
102     }
103     pixel_weights.m_SrcStart = start_i;
104     pixel_weights.m_SrcEnd = end_i;
105     for (int j = start_i; j <= end_i; j++) {
106       double dest_start = ((float)j - base) / scale;
107       double dest_end = ((float)(j + 1) - base) / scale;
108       if (dest_start > dest_end) {
109         double temp = dest_start;
110         dest_start = dest_end;
111         dest_end = temp;
112       }
113       double area_start =
114           dest_start > (float)(dest_pixel) ? dest_start : (float)(dest_pixel);
115       double area_end = dest_end > (float)(dest_pixel + 1)
116                             ? (float)(dest_pixel + 1)
117                             : dest_end;
118       double weight = area_start >= area_end ? 0.0 : area_end - area_start;
119       if (weight == 0 && j == end_i) {
120         pixel_weights.m_SrcEnd--;
121         break;
122       }
123       pixel_weights.m_Weights[j - start_i] =
124           FXSYS_roundf((float)(weight * 65536));
125     }
126   }
127 }
128 
129 ProgressiveDecoder::CFXCODEC_HorzTable::CFXCODEC_HorzTable() = default;
130 
131 ProgressiveDecoder::CFXCODEC_HorzTable::~CFXCODEC_HorzTable() = default;
132 
Calc(int dest_len,int src_len)133 void ProgressiveDecoder::CFXCODEC_HorzTable::Calc(int dest_len, int src_len) {
134   double scale = (double)dest_len / (double)src_len;
135   m_ItemSize = sizeof(int) * 4;
136   int size = dest_len * m_ItemSize + 4;
137   m_pWeightTables.resize(size, 0);
138   if (scale > 1) {
139     int pre_dest_col = 0;
140     for (int src_col = 0; src_col < src_len; src_col++) {
141       double dest_col_f = src_col * scale;
142       int dest_col = FXSYS_roundf((float)dest_col_f);
143       PixelWeight* pWeight = GetPixelWeight(dest_col);
144       pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col;
145       pWeight->m_Weights[0] = 65536;
146       pWeight->m_Weights[1] = 0;
147       if (src_col == src_len - 1 && dest_col < dest_len - 1) {
148         for (int dest_col_index = pre_dest_col + 1; dest_col_index < dest_len;
149              dest_col_index++) {
150           pWeight = GetPixelWeight(dest_col_index);
151           pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col;
152           pWeight->m_Weights[0] = 65536;
153           pWeight->m_Weights[1] = 0;
154         }
155         return;
156       }
157       int dest_col_len = dest_col - pre_dest_col;
158       for (int dest_col_index = pre_dest_col + 1; dest_col_index < dest_col;
159            dest_col_index++) {
160         pWeight = GetPixelWeight(dest_col_index);
161         pWeight->m_SrcStart = src_col - 1;
162         pWeight->m_SrcEnd = src_col;
163         pWeight->m_Weights[0] =
164             FXSYS_roundf((float)(((float)dest_col - (float)dest_col_index) /
165                                  (float)dest_col_len * 65536));
166         pWeight->m_Weights[1] = 65536 - pWeight->m_Weights[0];
167       }
168       pre_dest_col = dest_col;
169     }
170     return;
171   }
172   for (int dest_col = 0; dest_col < dest_len; dest_col++) {
173     double src_col_f = dest_col / scale;
174     int src_col = FXSYS_roundf((float)src_col_f);
175     PixelWeight* pWeight = GetPixelWeight(dest_col);
176     pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col;
177     pWeight->m_Weights[0] = 65536;
178     pWeight->m_Weights[1] = 0;
179   }
180 }
181 
182 ProgressiveDecoder::CFXCODEC_VertTable::CFXCODEC_VertTable() = default;
183 
184 ProgressiveDecoder::CFXCODEC_VertTable::~CFXCODEC_VertTable() = default;
185 
Calc(int dest_len,int src_len)186 void ProgressiveDecoder::CFXCODEC_VertTable::Calc(int dest_len, int src_len) {
187   double scale = (double)dest_len / (double)src_len;
188   m_ItemSize = sizeof(int) * 4;
189   int size = dest_len * m_ItemSize + 4;
190   m_pWeightTables.resize(size, 0);
191   if (scale <= 1) {
192     for (int dest_row = 0; dest_row < dest_len; dest_row++) {
193       PixelWeight* pWeight = GetPixelWeight(dest_row);
194       pWeight->m_SrcStart = dest_row;
195       pWeight->m_SrcEnd = dest_row;
196       pWeight->m_Weights[0] = 65536;
197       pWeight->m_Weights[1] = 0;
198     }
199     return;
200   }
201 
202   double step = 0.0;
203   int src_row = 0;
204   while (step < (double)dest_len) {
205     int start_step = (int)step;
206     step = scale * (++src_row);
207     int end_step = (int)step;
208     if (end_step >= dest_len) {
209       end_step = dest_len;
210       for (int dest_row = start_step; dest_row < end_step; dest_row++) {
211         PixelWeight* pWeight = GetPixelWeight(dest_row);
212         pWeight->m_SrcStart = start_step;
213         pWeight->m_SrcEnd = start_step;
214         pWeight->m_Weights[0] = 65536;
215         pWeight->m_Weights[1] = 0;
216       }
217       return;
218     }
219     int length = end_step - start_step;
220     {
221       PixelWeight* pWeight = GetPixelWeight(start_step);
222       pWeight->m_SrcStart = start_step;
223       pWeight->m_SrcEnd = start_step;
224       pWeight->m_Weights[0] = 65536;
225       pWeight->m_Weights[1] = 0;
226     }
227     for (int dest_row = start_step + 1; dest_row < end_step; dest_row++) {
228       PixelWeight* pWeight = GetPixelWeight(dest_row);
229       pWeight->m_SrcStart = start_step;
230       pWeight->m_SrcEnd = end_step;
231       pWeight->m_Weights[0] =
232           FXSYS_roundf((float)(end_step - dest_row) / (float)length * 65536);
233       pWeight->m_Weights[1] = 65536 - pWeight->m_Weights[0];
234     }
235   }
236 }
237 
ProgressiveDecoder(ModuleMgr * pCodecMgr)238 ProgressiveDecoder::ProgressiveDecoder(ModuleMgr* pCodecMgr)
239     : m_pCodecMgr(pCodecMgr) {}
240 
241 ProgressiveDecoder::~ProgressiveDecoder() = default;
242 
243 #ifdef PDF_ENABLE_XFA_PNG
PngReadHeader(int width,int height,int bpc,int pass,int * color_type,double * gamma)244 bool ProgressiveDecoder::PngReadHeader(int width,
245                                        int height,
246                                        int bpc,
247                                        int pass,
248                                        int* color_type,
249                                        double* gamma) {
250   if (!m_pDeviceBitmap) {
251     m_SrcWidth = width;
252     m_SrcHeight = height;
253     m_SrcBPC = bpc;
254     m_SrcPassNumber = pass;
255     switch (*color_type) {
256       case 0:
257         m_SrcComponents = 1;
258         break;
259       case 4:
260         m_SrcComponents = 2;
261         break;
262       case 2:
263         m_SrcComponents = 3;
264         break;
265       case 3:
266       case 6:
267         m_SrcComponents = 4;
268         break;
269       default:
270         m_SrcComponents = 0;
271         break;
272     }
273     m_clipBox = FX_RECT(0, 0, width, height);
274     return false;
275   }
276   FXDIB_Format format = m_pDeviceBitmap->GetFormat();
277   switch (format) {
278     case FXDIB_1bppMask:
279     case FXDIB_1bppRgb:
280       NOTREACHED();
281       return false;
282     case FXDIB_8bppMask:
283     case FXDIB_8bppRgb:
284       *color_type = 0;
285       break;
286     case FXDIB_Rgb:
287       *color_type = 2;
288       break;
289     case FXDIB_Rgb32:
290     case FXDIB_Argb:
291       *color_type = 6;
292       break;
293     default:
294       NOTREACHED();
295       return false;
296   }
297   *gamma = kPngGamma;
298   return true;
299 }
300 
PngAskScanlineBuf(int line,uint8_t ** pSrcBuf)301 bool ProgressiveDecoder::PngAskScanlineBuf(int line, uint8_t** pSrcBuf) {
302   RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap;
303   if (!pDIBitmap) {
304     NOTREACHED();
305     return false;
306   }
307   if (line >= m_clipBox.top && line < m_clipBox.bottom) {
308     double scale_y = static_cast<double>(m_sizeY) / m_clipBox.Height();
309     int32_t row = (int32_t)((line - m_clipBox.top) * scale_y) + m_startY;
310     const uint8_t* src_scan = pDIBitmap->GetScanline(row);
311     uint8_t* dest_scan = m_pDecodeBuf.get();
312     *pSrcBuf = m_pDecodeBuf.get();
313     int32_t src_Bpp = pDIBitmap->GetBPP() >> 3;
314     int32_t dest_Bpp = (m_SrcFormat & 0xff) >> 3;
315     int32_t src_left = m_startX;
316     int32_t dest_left = m_clipBox.left;
317     src_scan += src_left * src_Bpp;
318     dest_scan += dest_left * dest_Bpp;
319     for (int32_t src_col = 0; src_col < m_sizeX; src_col++) {
320       PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(src_col);
321       if (pPixelWeights->m_SrcStart != pPixelWeights->m_SrcEnd) {
322         continue;
323       }
324       switch (pDIBitmap->GetFormat()) {
325         case FXDIB_1bppMask:
326         case FXDIB_1bppRgb:
327           NOTREACHED();
328           return false;
329         case FXDIB_8bppMask:
330         case FXDIB_8bppRgb: {
331           if (pDIBitmap->GetPalette()) {
332             return false;
333           }
334           uint32_t dest_g = 0;
335           dest_g += pPixelWeights->m_Weights[0] * src_scan[src_col];
336           dest_scan[pPixelWeights->m_SrcStart] = (uint8_t)(dest_g >> 16);
337         } break;
338         case FXDIB_Rgb:
339         case FXDIB_Rgb32: {
340           uint32_t dest_b = 0;
341           uint32_t dest_g = 0;
342           uint32_t dest_r = 0;
343           const uint8_t* p = src_scan + src_col * src_Bpp;
344           dest_b += pPixelWeights->m_Weights[0] * (*p++);
345           dest_g += pPixelWeights->m_Weights[0] * (*p++);
346           dest_r += pPixelWeights->m_Weights[0] * (*p);
347           uint8_t* pDes = &dest_scan[pPixelWeights->m_SrcStart * dest_Bpp];
348           *pDes++ = (uint8_t)((dest_b) >> 16);
349           *pDes++ = (uint8_t)((dest_g) >> 16);
350           *pDes = (uint8_t)((dest_r) >> 16);
351         } break;
352         case FXDIB_Argb: {
353           uint32_t dest_r = 0;
354           uint32_t dest_g = 0;
355           uint32_t dest_b = 0;
356           const uint8_t* p = src_scan + src_col * src_Bpp;
357           dest_b += pPixelWeights->m_Weights[0] * (*p++);
358           dest_g += pPixelWeights->m_Weights[0] * (*p++);
359           dest_r += pPixelWeights->m_Weights[0] * (*p++);
360           uint8_t* pDes = &dest_scan[pPixelWeights->m_SrcStart * dest_Bpp];
361           *pDes++ = (uint8_t)((dest_b) >> 16);
362           *pDes++ = (uint8_t)((dest_g) >> 16);
363           *pDes++ = (uint8_t)((dest_r) >> 16);
364           *pDes = *p;
365         } break;
366         default:
367           return false;
368       }
369     }
370   }
371   return true;
372 }
373 
PngFillScanlineBufCompleted(int pass,int line)374 void ProgressiveDecoder::PngFillScanlineBufCompleted(int pass, int line) {
375   RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap;
376   ASSERT(pDIBitmap);
377   int src_top = m_clipBox.top;
378   int src_bottom = m_clipBox.bottom;
379   int dest_top = m_startY;
380   int src_height = m_clipBox.Height();
381   int dest_height = m_sizeY;
382   if (line >= src_top && line < src_bottom) {
383     double scale_y = static_cast<double>(dest_height) / src_height;
384     int src_row = line - src_top;
385     int dest_row = (int)(src_row * scale_y) + dest_top;
386     if (dest_row >= dest_top + dest_height) {
387       return;
388     }
389     PngOneOneMapResampleHorz(pDIBitmap, dest_row, m_pDecodeBuf.get(),
390                              m_SrcFormat);
391     if (m_SrcPassNumber == 1 && scale_y > 1.0) {
392       ResampleVert(pDIBitmap, scale_y, dest_row);
393       return;
394     }
395     if (pass == 6 && scale_y > 1.0) {
396       ResampleVert(pDIBitmap, scale_y, dest_row);
397     }
398   }
399 }
400 #endif  // PDF_ENABLE_XFA_PNG
401 
402 #ifdef PDF_ENABLE_XFA_GIF
GifRecordCurrentPosition(uint32_t & cur_pos)403 void ProgressiveDecoder::GifRecordCurrentPosition(uint32_t& cur_pos) {
404   uint32_t remain_size =
405       m_pCodecMgr->GetGifModule()->GetAvailInput(m_pGifContext.get());
406   cur_pos = m_offSet - remain_size;
407 }
408 
GifInputRecordPositionBuf(uint32_t rcd_pos,const FX_RECT & img_rc,int32_t pal_num,CFX_GifPalette * pal_ptr,int32_t delay_time,bool user_input,int32_t trans_index,int32_t disposal_method,bool interlace)409 bool ProgressiveDecoder::GifInputRecordPositionBuf(uint32_t rcd_pos,
410                                                    const FX_RECT& img_rc,
411                                                    int32_t pal_num,
412                                                    CFX_GifPalette* pal_ptr,
413                                                    int32_t delay_time,
414                                                    bool user_input,
415                                                    int32_t trans_index,
416                                                    int32_t disposal_method,
417                                                    bool interlace) {
418   m_offSet = rcd_pos;
419   m_InvalidateGifBuffer = true;
420 
421   FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR;
422   if (!GifReadMoreData(m_pCodecMgr->GetGifModule(), error_status)) {
423     return false;
424   }
425   CFX_GifPalette* pPalette = nullptr;
426   if (pal_num != 0 && pal_ptr) {
427     pPalette = pal_ptr;
428   } else {
429     if (!m_pGifPalette)
430       return false;
431     pal_num = m_GifPltNumber;
432     pPalette = m_pGifPalette;
433   }
434   if (!m_pSrcPalette)
435     m_pSrcPalette.reset(FX_Alloc(FX_ARGB, pal_num));
436   else if (pal_num > m_SrcPaletteNumber)
437     m_pSrcPalette.reset(FX_Realloc(FX_ARGB, m_pSrcPalette.release(), pal_num));
438   if (!m_pSrcPalette)
439     return false;
440 
441   m_SrcPaletteNumber = pal_num;
442   for (int i = 0; i < pal_num; i++) {
443     m_pSrcPalette.get()[i] =
444         ArgbEncode(0xff, pPalette[i].r, pPalette[i].g, pPalette[i].b);
445   }
446   m_GifTransIndex = trans_index;
447   m_GifFrameRect = img_rc;
448   m_SrcPassNumber = interlace ? 4 : 1;
449   int32_t pal_index = m_GifBgIndex;
450   RetainPtr<CFX_DIBitmap> pDevice = m_pDeviceBitmap;
451   if (trans_index >= pal_num)
452     trans_index = -1;
453   if (trans_index != -1) {
454     m_pSrcPalette.get()[trans_index] &= 0x00ffffff;
455     if (pDevice->HasAlpha())
456       pal_index = trans_index;
457   }
458   if (pal_index >= pal_num)
459     return false;
460 
461   int startX = m_startX;
462   int startY = m_startY;
463   int sizeX = m_sizeX;
464   int sizeY = m_sizeY;
465   int Bpp = pDevice->GetBPP() / 8;
466   FX_ARGB argb = m_pSrcPalette.get()[pal_index];
467   for (int row = 0; row < sizeY; row++) {
468     uint8_t* pScanline =
469         pDevice->GetWritableScanline(row + startY) + startX * Bpp;
470     switch (m_TransMethod) {
471       case 3: {
472         uint8_t gray =
473             FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb));
474         memset(pScanline, gray, sizeX);
475         break;
476       }
477       case 8: {
478         for (int col = 0; col < sizeX; col++) {
479           *pScanline++ = FXARGB_B(argb);
480           *pScanline++ = FXARGB_G(argb);
481           *pScanline++ = FXARGB_R(argb);
482           pScanline += Bpp - 3;
483         }
484         break;
485       }
486       case 12: {
487         for (int col = 0; col < sizeX; col++) {
488           FXARGB_SETDIB(pScanline, argb);
489           pScanline += 4;
490         }
491         break;
492       }
493     }
494   }
495   return true;
496 }
497 
GifReadScanline(int32_t row_num,uint8_t * row_buf)498 void ProgressiveDecoder::GifReadScanline(int32_t row_num, uint8_t* row_buf) {
499   RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap;
500   ASSERT(pDIBitmap);
501   int32_t img_width = m_GifFrameRect.Width();
502   if (!pDIBitmap->HasAlpha()) {
503     uint8_t* byte_ptr = row_buf;
504     for (int i = 0; i < img_width; i++) {
505       if (*byte_ptr == m_GifTransIndex) {
506         *byte_ptr = m_GifBgIndex;
507       }
508       byte_ptr++;
509     }
510   }
511   int32_t pal_index = m_GifBgIndex;
512   if (m_GifTransIndex != -1 && m_pDeviceBitmap->HasAlpha()) {
513     pal_index = m_GifTransIndex;
514   }
515   memset(m_pDecodeBuf.get(), pal_index, m_SrcWidth);
516   bool bLastPass = (row_num % 2) == 1;
517   int32_t line = row_num + m_GifFrameRect.top;
518   int32_t left = m_GifFrameRect.left;
519   memcpy(m_pDecodeBuf.get() + left, row_buf, img_width);
520   int src_top = m_clipBox.top;
521   int src_bottom = m_clipBox.bottom;
522   int dest_top = m_startY;
523   int src_height = m_clipBox.Height();
524   int dest_height = m_sizeY;
525   if (line < src_top || line >= src_bottom)
526     return;
527 
528   double scale_y = static_cast<double>(dest_height) / src_height;
529   int src_row = line - src_top;
530   int dest_row = (int)(src_row * scale_y) + dest_top;
531   if (dest_row >= dest_top + dest_height)
532     return;
533 
534   ReSampleScanline(pDIBitmap, dest_row, m_pDecodeBuf.get(), m_SrcFormat);
535   if (scale_y > 1.0 && m_SrcPassNumber == 1) {
536     ResampleVert(pDIBitmap, scale_y, dest_row);
537     return;
538   }
539   if (scale_y <= 1.0)
540     return;
541 
542   int dest_bottom = dest_top + m_sizeY;
543   int dest_Bpp = pDIBitmap->GetBPP() >> 3;
544   uint32_t dest_ScanOffet = m_startX * dest_Bpp;
545   if (dest_row + (int)scale_y >= dest_bottom - 1) {
546     const uint8_t* scan_src = pDIBitmap->GetScanline(dest_row) + dest_ScanOffet;
547     int cur_row = dest_row;
548     while (++cur_row < dest_bottom) {
549       uint8_t* scan_des =
550           pDIBitmap->GetWritableScanline(cur_row) + dest_ScanOffet;
551       uint32_t size = m_sizeX * dest_Bpp;
552       memmove(scan_des, scan_src, size);
553     }
554   }
555   if (bLastPass)
556     GifDoubleLineResampleVert(pDIBitmap, scale_y, dest_row);
557 }
558 #endif  // PDF_ENABLE_XFA_GIF
559 
560 #ifdef PDF_ENABLE_XFA_BMP
BmpInputImagePositionBuf(uint32_t rcd_pos)561 bool ProgressiveDecoder::BmpInputImagePositionBuf(uint32_t rcd_pos) {
562   m_offSet = rcd_pos;
563   FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR;
564   return BmpReadMoreData(m_pCodecMgr->GetBmpModule(), m_pBmpContext.get(),
565                          error_status);
566 }
567 
BmpReadScanline(uint32_t row_num,pdfium::span<const uint8_t> row_buf)568 void ProgressiveDecoder::BmpReadScanline(uint32_t row_num,
569                                          pdfium::span<const uint8_t> row_buf) {
570   RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap;
571   ASSERT(pDIBitmap);
572 
573   pdfium::span<const uint8_t> src_span = row_buf.first(m_ScanlineSize);
574   std::copy(std::begin(src_span), std::end(src_span), m_pDecodeBuf.get());
575 
576   int src_top = m_clipBox.top;
577   int src_bottom = m_clipBox.bottom;
578   int dest_top = m_startY;
579   int src_height = m_clipBox.Height();
580   int dest_height = m_sizeY;
581   if ((src_top >= 0 && row_num < static_cast<uint32_t>(src_top)) ||
582       src_bottom < 0 || row_num >= static_cast<uint32_t>(src_bottom)) {
583     return;
584   }
585 
586   double scale_y = static_cast<double>(dest_height) / src_height;
587   int src_row = row_num - src_top;
588   int dest_row = (int)(src_row * scale_y) + dest_top;
589   if (dest_row >= dest_top + dest_height)
590     return;
591 
592   ReSampleScanline(pDIBitmap, dest_row, m_pDecodeBuf.get(), m_SrcFormat);
593   if (scale_y <= 1.0)
594     return;
595 
596   if (m_BmpIsTopBottom) {
597     ResampleVert(pDIBitmap, scale_y, dest_row);
598     return;
599   }
600   ResampleVertBT(pDIBitmap, scale_y, dest_row);
601 }
602 
ResampleVertBT(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,double scale_y,int dest_row)603 void ProgressiveDecoder::ResampleVertBT(
604     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
605     double scale_y,
606     int dest_row) {
607   int dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
608   uint32_t dest_ScanOffet = m_startX * dest_Bpp;
609   int dest_top = m_startY;
610   int dest_bottom = m_startY + m_sizeY;
611   pdfium::base::CheckedNumeric<int> check_dest_row_1 = dest_row;
612   check_dest_row_1 += pdfium::base::checked_cast<int>(scale_y);
613   int dest_row_1 = check_dest_row_1.ValueOrDie();
614   if (dest_row_1 >= dest_bottom - 1) {
615     const uint8_t* scan_src =
616         pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet;
617     while (++dest_row < dest_bottom) {
618       uint8_t* scan_des =
619           pDeviceBitmap->GetWritableScanline(dest_row) + dest_ScanOffet;
620       uint32_t size = m_sizeX * dest_Bpp;
621       memmove(scan_des, scan_src, size);
622     }
623     return;
624   }
625   for (; dest_row_1 > dest_row; dest_row_1--) {
626     uint8_t* scan_des =
627         pDeviceBitmap->GetWritableScanline(dest_row_1) + dest_ScanOffet;
628     PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top);
629     const uint8_t* scan_src1 =
630         pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top) +
631         dest_ScanOffet;
632     const uint8_t* scan_src2 =
633         pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top) +
634         dest_ScanOffet;
635     for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
636       switch (pDeviceBitmap->GetFormat()) {
637         case FXDIB_Invalid:
638         case FXDIB_1bppMask:
639         case FXDIB_1bppRgb:
640           return;
641         case FXDIB_8bppMask:
642         case FXDIB_8bppRgb: {
643           if (pDeviceBitmap->GetPalette()) {
644             return;
645           }
646           int dest_g = 0;
647           dest_g += pWeight->m_Weights[0] * (*scan_src1++);
648           dest_g += pWeight->m_Weights[1] * (*scan_src2++);
649           *scan_des++ = (uint8_t)(dest_g >> 16);
650         } break;
651         case FXDIB_Rgb:
652         case FXDIB_Rgb32: {
653           uint32_t dest_b = 0;
654           uint32_t dest_g = 0;
655           uint32_t dest_r = 0;
656           dest_b += pWeight->m_Weights[0] * (*scan_src1++);
657           dest_g += pWeight->m_Weights[0] * (*scan_src1++);
658           dest_r += pWeight->m_Weights[0] * (*scan_src1++);
659           scan_src1 += dest_Bpp - 3;
660           dest_b += pWeight->m_Weights[1] * (*scan_src2++);
661           dest_g += pWeight->m_Weights[1] * (*scan_src2++);
662           dest_r += pWeight->m_Weights[1] * (*scan_src2++);
663           scan_src2 += dest_Bpp - 3;
664           *scan_des++ = (uint8_t)((dest_b) >> 16);
665           *scan_des++ = (uint8_t)((dest_g) >> 16);
666           *scan_des++ = (uint8_t)((dest_r) >> 16);
667           scan_des += dest_Bpp - 3;
668         } break;
669         case FXDIB_Argb: {
670           uint32_t dest_a = 0;
671           uint32_t dest_b = 0;
672           uint32_t dest_g = 0;
673           uint32_t dest_r = 0;
674           dest_b += pWeight->m_Weights[0] * (*scan_src1++);
675           dest_g += pWeight->m_Weights[0] * (*scan_src1++);
676           dest_r += pWeight->m_Weights[0] * (*scan_src1++);
677           dest_a += pWeight->m_Weights[0] * (*scan_src1++);
678           dest_b += pWeight->m_Weights[1] * (*scan_src2++);
679           dest_g += pWeight->m_Weights[1] * (*scan_src2++);
680           dest_r += pWeight->m_Weights[1] * (*scan_src2++);
681           dest_a += pWeight->m_Weights[1] * (*scan_src2++);
682           *scan_des++ = (uint8_t)((dest_b) >> 16);
683           *scan_des++ = (uint8_t)((dest_g) >> 16);
684           *scan_des++ = (uint8_t)((dest_r) >> 16);
685           *scan_des++ = (uint8_t)((dest_a) >> 16);
686         } break;
687         default:
688           return;
689       }
690     }
691   }
692 }
693 
BmpDetectImageTypeInBuffer(CFX_DIBAttribute * pAttribute)694 bool ProgressiveDecoder::BmpDetectImageTypeInBuffer(
695     CFX_DIBAttribute* pAttribute) {
696   BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule();
697   if (!pBmpModule) {
698     m_status = FXCODEC_STATUS_ERR_MEMORY;
699     return false;
700   }
701 
702   std::unique_ptr<ModuleIface::Context> pBmpContext = pBmpModule->Start(this);
703   pBmpModule->Input(pBmpContext.get(), m_pCodecMemory, nullptr);
704 
705   const std::vector<uint32_t>* palette;
706   BmpModule::Status read_result = pBmpModule->ReadHeader(
707       pBmpContext.get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom,
708       &m_SrcComponents, &m_SrcPaletteNumber, &palette, pAttribute);
709   while (read_result == BmpModule::Status::kContinue) {
710     FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT;
711     if (!BmpReadMoreData(pBmpModule, pBmpContext.get(), error_status)) {
712       m_status = error_status;
713       return false;
714     }
715     read_result = pBmpModule->ReadHeader(
716         pBmpContext.get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom,
717         &m_SrcComponents, &m_SrcPaletteNumber, &palette, pAttribute);
718   }
719 
720   if (read_result != BmpModule::Status::kSuccess) {
721     m_status = FXCODEC_STATUS_ERR_FORMAT;
722     return false;
723   }
724 
725   FXDIB_Format format = FXDIB_Invalid;
726   switch (m_SrcComponents) {
727     case 1:
728       m_SrcFormat = FXCodec_8bppRgb;
729       format = FXDIB_8bppRgb;
730       break;
731     case 3:
732       m_SrcFormat = FXCodec_Rgb;
733       format = FXDIB_Rgb;
734       break;
735     case 4:
736       m_SrcFormat = FXCodec_Rgb32;
737       format = FXDIB_Rgb32;
738       break;
739     default:
740       m_status = FXCODEC_STATUS_ERR_FORMAT;
741       return false;
742   }
743 
744   uint32_t pitch = 0;
745   uint32_t neededData = 0;
746   if (!CFX_DIBitmap::CalculatePitchAndSize(m_SrcWidth, m_SrcHeight, format,
747                                            &pitch, &neededData)) {
748     m_status = FXCODEC_STATUS_ERR_FORMAT;
749     return false;
750   }
751 
752   uint32_t availableData = m_pFile->GetSize() - m_offSet +
753                            pBmpModule->GetAvailInput(pBmpContext.get());
754   if (neededData > availableData) {
755     m_status = FXCODEC_STATUS_ERR_FORMAT;
756     return false;
757   }
758 
759   m_SrcBPC = 8;
760   m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
761   m_pBmpContext = std::move(pBmpContext);
762   if (m_SrcPaletteNumber) {
763     m_pSrcPalette.reset(FX_Alloc(FX_ARGB, m_SrcPaletteNumber));
764     memcpy(m_pSrcPalette.get(), palette->data(),
765            m_SrcPaletteNumber * sizeof(FX_ARGB));
766   } else {
767     m_pSrcPalette.reset();
768   }
769   return true;
770 }
771 
BmpReadMoreData(BmpModule * pBmpModule,ModuleIface::Context * pContext,FXCODEC_STATUS & err_status)772 bool ProgressiveDecoder::BmpReadMoreData(BmpModule* pBmpModule,
773                                          ModuleIface::Context* pContext,
774                                          FXCODEC_STATUS& err_status) {
775   return ReadMoreData(pBmpModule, pContext, false, err_status);
776 }
777 
BmpStartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap)778 FXCODEC_STATUS ProgressiveDecoder::BmpStartDecode(
779     const RetainPtr<CFX_DIBitmap>& pDIBitmap) {
780   BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule();
781   if (!pBmpModule) {
782     m_pDeviceBitmap = nullptr;
783     m_pFile = nullptr;
784     m_status = FXCODEC_STATUS_ERR_MEMORY;
785     return m_status;
786   }
787   GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
788   m_ScanlineSize = FxAlignToBoundary<4>(m_SrcWidth * m_SrcComponents);
789   m_pDecodeBuf.reset(FX_Alloc(uint8_t, m_ScanlineSize));
790   m_WeightHorz.Calc(m_sizeX, m_clipBox.Width());
791   m_WeightVert.Calc(m_sizeY, m_clipBox.Height());
792   m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
793   return m_status;
794 }
795 
BmpContinueDecode()796 FXCODEC_STATUS ProgressiveDecoder::BmpContinueDecode() {
797   BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule();
798   if (!pBmpModule) {
799     m_status = FXCODEC_STATUS_ERR_MEMORY;
800     return m_status;
801   }
802 
803   BmpModule::Status read_res = pBmpModule->LoadImage(m_pBmpContext.get());
804   while (read_res == BmpModule::Status::kContinue) {
805     FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
806     if (!BmpReadMoreData(pBmpModule, m_pBmpContext.get(), error_status)) {
807       m_pDeviceBitmap = nullptr;
808       m_pFile = nullptr;
809       m_status = error_status;
810       return m_status;
811     }
812     read_res = pBmpModule->LoadImage(m_pBmpContext.get());
813   }
814 
815   m_pDeviceBitmap = nullptr;
816   m_pFile = nullptr;
817   m_status = read_res == BmpModule::Status::kSuccess
818                  ? FXCODEC_STATUS_DECODE_FINISH
819                  : FXCODEC_STATUS_ERROR;
820   return m_status;
821 }
822 #endif  // PDF_ENABLE_XFA_BMP
823 
824 #ifdef PDF_ENABLE_XFA_GIF
GifReadMoreData(GifModule * pGifModule,FXCODEC_STATUS & err_status)825 bool ProgressiveDecoder::GifReadMoreData(GifModule* pGifModule,
826                                          FXCODEC_STATUS& err_status) {
827   if (!ReadMoreData(pGifModule, m_pGifContext.get(), m_InvalidateGifBuffer,
828                     err_status)) {
829     return false;
830   }
831   m_InvalidateGifBuffer = false;
832   return true;
833 }
834 
GifDetectImageTypeInBuffer()835 bool ProgressiveDecoder::GifDetectImageTypeInBuffer() {
836   GifModule* pGifModule = m_pCodecMgr->GetGifModule();
837   if (!pGifModule) {
838     m_status = FXCODEC_STATUS_ERR_MEMORY;
839     return false;
840   }
841   m_pGifContext = pGifModule->Start(this);
842   pGifModule->Input(m_pGifContext.get(), m_pCodecMemory, nullptr);
843   m_SrcComponents = 1;
844   CFX_GifDecodeStatus readResult =
845       pGifModule->ReadHeader(m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight,
846                              &m_GifPltNumber, &m_pGifPalette, &m_GifBgIndex);
847   while (readResult == CFX_GifDecodeStatus::Unfinished) {
848     FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT;
849     if (!GifReadMoreData(pGifModule, error_status)) {
850       m_pGifContext = nullptr;
851       m_status = error_status;
852       return false;
853     }
854     readResult =
855         pGifModule->ReadHeader(m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight,
856                                &m_GifPltNumber, &m_pGifPalette, &m_GifBgIndex);
857   }
858   if (readResult == CFX_GifDecodeStatus::Success) {
859     m_SrcBPC = 8;
860     m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
861     return true;
862   }
863   m_pGifContext = nullptr;
864   m_status = FXCODEC_STATUS_ERR_FORMAT;
865   return false;
866 }
867 
GifStartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap)868 FXCODEC_STATUS ProgressiveDecoder::GifStartDecode(
869     const RetainPtr<CFX_DIBitmap>& pDIBitmap) {
870   GifModule* pGifModule = m_pCodecMgr->GetGifModule();
871   if (!pGifModule) {
872     m_pDeviceBitmap = nullptr;
873     m_pFile = nullptr;
874     m_status = FXCODEC_STATUS_ERR_MEMORY;
875     return m_status;
876   }
877   m_SrcFormat = FXCodec_8bppRgb;
878   GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
879   int scanline_size = FxAlignToBoundary<4>(m_SrcWidth);
880   m_pDecodeBuf.reset(FX_Alloc(uint8_t, scanline_size));
881   m_WeightHorz.Calc(m_sizeX, m_clipBox.Width());
882   m_WeightVert.Calc(m_sizeY, m_clipBox.Height());
883   m_FrameCur = 0;
884   m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
885   return m_status;
886 }
887 
GifContinueDecode()888 FXCODEC_STATUS ProgressiveDecoder::GifContinueDecode() {
889   GifModule* pGifModule = m_pCodecMgr->GetGifModule();
890   if (!pGifModule) {
891     m_pDeviceBitmap = nullptr;
892     m_pFile = nullptr;
893     m_status = FXCODEC_STATUS_ERR_MEMORY;
894     return m_status;
895   }
896 
897   CFX_GifDecodeStatus readRes =
898       pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur);
899   while (readRes == CFX_GifDecodeStatus::Unfinished) {
900     FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
901     if (!GifReadMoreData(pGifModule, error_status)) {
902       m_pDeviceBitmap = nullptr;
903       m_pFile = nullptr;
904       m_status = error_status;
905       return m_status;
906     }
907     readRes = pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur);
908   }
909 
910   if (readRes == CFX_GifDecodeStatus::Success) {
911     m_pDeviceBitmap = nullptr;
912     m_pFile = nullptr;
913     m_status = FXCODEC_STATUS_DECODE_FINISH;
914     return m_status;
915   }
916 
917   m_pDeviceBitmap = nullptr;
918   m_pFile = nullptr;
919   m_status = FXCODEC_STATUS_ERROR;
920   return m_status;
921 }
922 
GifDoubleLineResampleVert(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,double scale_y,int dest_row)923 void ProgressiveDecoder::GifDoubleLineResampleVert(
924     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
925     double scale_y,
926     int dest_row) {
927   int dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
928   uint32_t dest_ScanOffet = m_startX * dest_Bpp;
929   int dest_top = m_startY;
930   pdfium::base::CheckedNumeric<double> scale_y2 = scale_y;
931   scale_y2 *= 2;
932   pdfium::base::CheckedNumeric<int> check_dest_row_1 = dest_row;
933   check_dest_row_1 -= scale_y2.ValueOrDie();
934   int dest_row_1 = check_dest_row_1.ValueOrDie();
935   dest_row_1 = std::max(dest_row_1, dest_top);
936   for (; dest_row_1 < dest_row; dest_row_1++) {
937     uint8_t* scan_des =
938         pDeviceBitmap->GetWritableScanline(dest_row_1) + dest_ScanOffet;
939     PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top);
940     const uint8_t* scan_src1 =
941         pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top) +
942         dest_ScanOffet;
943     const uint8_t* scan_src2 =
944         pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top) +
945         dest_ScanOffet;
946     for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
947       switch (pDeviceBitmap->GetFormat()) {
948         case FXDIB_Invalid:
949         case FXDIB_1bppMask:
950         case FXDIB_1bppRgb:
951           return;
952         case FXDIB_8bppMask:
953         case FXDIB_8bppRgb: {
954           if (pDeviceBitmap->GetPalette()) {
955             return;
956           }
957           int dest_g = 0;
958           dest_g += pWeight->m_Weights[0] * (*scan_src1++);
959           dest_g += pWeight->m_Weights[1] * (*scan_src2++);
960           *scan_des++ = (uint8_t)(dest_g >> 16);
961         } break;
962         case FXDIB_Rgb:
963         case FXDIB_Rgb32: {
964           uint32_t dest_b = 0;
965           uint32_t dest_g = 0;
966           uint32_t dest_r = 0;
967           dest_b += pWeight->m_Weights[0] * (*scan_src1++);
968           dest_g += pWeight->m_Weights[0] * (*scan_src1++);
969           dest_r += pWeight->m_Weights[0] * (*scan_src1++);
970           scan_src1 += dest_Bpp - 3;
971           dest_b += pWeight->m_Weights[1] * (*scan_src2++);
972           dest_g += pWeight->m_Weights[1] * (*scan_src2++);
973           dest_r += pWeight->m_Weights[1] * (*scan_src2++);
974           scan_src2 += dest_Bpp - 3;
975           *scan_des++ = (uint8_t)((dest_b) >> 16);
976           *scan_des++ = (uint8_t)((dest_g) >> 16);
977           *scan_des++ = (uint8_t)((dest_r) >> 16);
978           scan_des += dest_Bpp - 3;
979         } break;
980         case FXDIB_Argb: {
981           uint32_t dest_a = 0;
982           uint32_t dest_b = 0;
983           uint32_t dest_g = 0;
984           uint32_t dest_r = 0;
985           dest_b += pWeight->m_Weights[0] * (*scan_src1++);
986           dest_g += pWeight->m_Weights[0] * (*scan_src1++);
987           dest_r += pWeight->m_Weights[0] * (*scan_src1++);
988           dest_a += pWeight->m_Weights[0] * (*scan_src1++);
989           dest_b += pWeight->m_Weights[1] * (*scan_src2++);
990           dest_g += pWeight->m_Weights[1] * (*scan_src2++);
991           dest_r += pWeight->m_Weights[1] * (*scan_src2++);
992           dest_a += pWeight->m_Weights[1] * (*scan_src2++);
993           *scan_des++ = (uint8_t)((dest_b) >> 16);
994           *scan_des++ = (uint8_t)((dest_g) >> 16);
995           *scan_des++ = (uint8_t)((dest_r) >> 16);
996           *scan_des++ = (uint8_t)((dest_a) >> 16);
997         } break;
998         default:
999           return;
1000       }
1001     }
1002   }
1003   int dest_bottom = dest_top + m_sizeY - 1;
1004   if (dest_row + (int)(2 * scale_y) >= dest_bottom &&
1005       dest_row + (int)scale_y < dest_bottom) {
1006     GifDoubleLineResampleVert(pDeviceBitmap, scale_y, dest_row + (int)scale_y);
1007   }
1008 }
1009 #endif  // PDF_ENABLE_XFA_GIF
1010 
JpegReadMoreData(JpegModule * pJpegModule,FXCODEC_STATUS & err_status)1011 bool ProgressiveDecoder::JpegReadMoreData(JpegModule* pJpegModule,
1012                                           FXCODEC_STATUS& err_status) {
1013   return ReadMoreData(pJpegModule, m_pJpegContext.get(), false, err_status);
1014 }
1015 
JpegDetectImageTypeInBuffer(CFX_DIBAttribute * pAttribute)1016 bool ProgressiveDecoder::JpegDetectImageTypeInBuffer(
1017     CFX_DIBAttribute* pAttribute) {
1018   JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
1019   m_pJpegContext = pJpegModule->Start();
1020   if (!m_pJpegContext) {
1021     m_status = FXCODEC_STATUS_ERR_MEMORY;
1022     return false;
1023   }
1024   pJpegModule->Input(m_pJpegContext.get(), m_pCodecMemory, nullptr);
1025 
1026   // Setting jump marker before calling ReadHeader, since a longjmp to
1027   // the marker indicates a fatal error.
1028   if (setjmp(pJpegModule->GetJumpMark(m_pJpegContext.get())) == -1) {
1029     m_pJpegContext.reset();
1030     m_status = FXCODEC_STATUS_ERR_FORMAT;
1031     return false;
1032   }
1033 
1034   int32_t readResult =
1035       pJpegModule->ReadHeader(m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight,
1036                               &m_SrcComponents, pAttribute);
1037   while (readResult == 2) {
1038     FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT;
1039     if (!JpegReadMoreData(pJpegModule, error_status)) {
1040       m_status = error_status;
1041       return false;
1042     }
1043     readResult =
1044         pJpegModule->ReadHeader(m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight,
1045                                 &m_SrcComponents, pAttribute);
1046   }
1047   if (!readResult) {
1048     m_SrcBPC = 8;
1049     m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
1050     return true;
1051   }
1052   m_pJpegContext.reset();
1053   m_status = FXCODEC_STATUS_ERR_FORMAT;
1054   return false;
1055 }
1056 
JpegStartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap)1057 FXCODEC_STATUS ProgressiveDecoder::JpegStartDecode(
1058     const RetainPtr<CFX_DIBitmap>& pDIBitmap) {
1059   JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
1060   int down_scale = 1;
1061   GetDownScale(down_scale);
1062   // Setting jump marker before calling StartScanLine, since a longjmp to
1063   // the marker indicates a fatal error.
1064   if (setjmp(pJpegModule->GetJumpMark(m_pJpegContext.get())) == -1) {
1065     m_pJpegContext.reset();
1066     m_status = FXCODEC_STATUS_ERROR;
1067     return FXCODEC_STATUS_ERROR;
1068   }
1069 
1070   bool startStatus =
1071       pJpegModule->StartScanline(m_pJpegContext.get(), down_scale);
1072   while (!startStatus) {
1073     FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR;
1074     if (!JpegReadMoreData(pJpegModule, error_status)) {
1075       m_pDeviceBitmap = nullptr;
1076       m_pFile = nullptr;
1077       m_status = error_status;
1078       return m_status;
1079     }
1080 
1081     startStatus = pJpegModule->StartScanline(m_pJpegContext.get(), down_scale);
1082   }
1083   int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale;
1084   scanline_size = FxAlignToBoundary<4>(scanline_size * m_SrcComponents);
1085   m_pDecodeBuf.reset(FX_Alloc(uint8_t, scanline_size));
1086   m_WeightHorz.Calc(m_sizeX, m_clipBox.Width());
1087   m_WeightVert.Calc(m_sizeY, m_clipBox.Height());
1088   switch (m_SrcComponents) {
1089     case 1:
1090       m_SrcFormat = FXCodec_8bppGray;
1091       break;
1092     case 3:
1093       m_SrcFormat = FXCodec_Rgb;
1094       break;
1095     case 4:
1096       m_SrcFormat = FXCodec_Cmyk;
1097       break;
1098   }
1099   GetTransMethod(pDIBitmap->GetFormat(), m_SrcFormat);
1100   m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
1101   return m_status;
1102 }
1103 
JpegContinueDecode()1104 FXCODEC_STATUS ProgressiveDecoder::JpegContinueDecode() {
1105   JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
1106   // Setting jump marker before calling ReadScanLine, since a longjmp to
1107   // the marker indicates a fatal error.
1108   if (setjmp(pJpegModule->GetJumpMark(m_pJpegContext.get())) == -1) {
1109     m_pJpegContext.reset();
1110     m_status = FXCODEC_STATUS_ERROR;
1111     return FXCODEC_STATUS_ERROR;
1112   }
1113 
1114   while (true) {
1115     bool readRes =
1116         pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf.get());
1117     while (!readRes) {
1118       FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
1119       if (!JpegReadMoreData(pJpegModule, error_status)) {
1120         m_pDeviceBitmap = nullptr;
1121         m_pFile = nullptr;
1122         m_status = error_status;
1123         return m_status;
1124       }
1125       readRes =
1126           pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf.get());
1127     }
1128     if (m_SrcFormat == FXCodec_Rgb) {
1129       int src_Bpp = (m_SrcFormat & 0xff) >> 3;
1130       RGB2BGR(m_pDecodeBuf.get() + m_clipBox.left * src_Bpp, m_clipBox.Width());
1131     }
1132     if (m_SrcRow >= m_clipBox.bottom) {
1133       m_pDeviceBitmap = nullptr;
1134       m_pFile = nullptr;
1135       m_status = FXCODEC_STATUS_DECODE_FINISH;
1136       return m_status;
1137     }
1138     Resample(m_pDeviceBitmap, m_SrcRow, m_pDecodeBuf.get(), m_SrcFormat);
1139     m_SrcRow++;
1140   }
1141 }
1142 
1143 #ifdef PDF_ENABLE_XFA_PNG
PngOneOneMapResampleHorz(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,int32_t dest_line,uint8_t * src_scan,FXCodec_Format src_format)1144 void ProgressiveDecoder::PngOneOneMapResampleHorz(
1145     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1146     int32_t dest_line,
1147     uint8_t* src_scan,
1148     FXCodec_Format src_format) {
1149   uint8_t* dest_scan = pDeviceBitmap->GetWritableScanline(dest_line);
1150   int32_t src_Bpp = (m_SrcFormat & 0xff) >> 3;
1151   int32_t dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
1152   int32_t src_left = m_clipBox.left;
1153   int32_t dest_left = m_startX;
1154   src_scan += src_left * src_Bpp;
1155   dest_scan += dest_left * dest_Bpp;
1156   for (int32_t dest_col = 0; dest_col < m_sizeX; dest_col++) {
1157     PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(dest_col);
1158     switch (pDeviceBitmap->GetFormat()) {
1159       case FXDIB_1bppMask:
1160       case FXDIB_1bppRgb:
1161         NOTREACHED();
1162         return;
1163       case FXDIB_8bppMask:
1164       case FXDIB_8bppRgb: {
1165         if (pDeviceBitmap->GetPalette()) {
1166           return;
1167         }
1168         uint32_t dest_g = 0;
1169         dest_g +=
1170             pPixelWeights->m_Weights[0] * src_scan[pPixelWeights->m_SrcStart];
1171         dest_g +=
1172             pPixelWeights->m_Weights[1] * src_scan[pPixelWeights->m_SrcEnd];
1173         *dest_scan++ = (uint8_t)(dest_g >> 16);
1174       } break;
1175       case FXDIB_Rgb:
1176       case FXDIB_Rgb32: {
1177         uint32_t dest_b = 0;
1178         uint32_t dest_g = 0;
1179         uint32_t dest_r = 0;
1180         const uint8_t* p = src_scan;
1181         p = src_scan + pPixelWeights->m_SrcStart * src_Bpp;
1182         dest_b += pPixelWeights->m_Weights[0] * (*p++);
1183         dest_g += pPixelWeights->m_Weights[0] * (*p++);
1184         dest_r += pPixelWeights->m_Weights[0] * (*p);
1185         p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp;
1186         dest_b += pPixelWeights->m_Weights[1] * (*p++);
1187         dest_g += pPixelWeights->m_Weights[1] * (*p++);
1188         dest_r += pPixelWeights->m_Weights[1] * (*p);
1189         *dest_scan++ = (uint8_t)((dest_b) >> 16);
1190         *dest_scan++ = (uint8_t)((dest_g) >> 16);
1191         *dest_scan++ = (uint8_t)((dest_r) >> 16);
1192         dest_scan += dest_Bpp - 3;
1193       } break;
1194       case FXDIB_Argb: {
1195         uint32_t dest_a = 0;
1196         uint32_t dest_b = 0;
1197         uint32_t dest_g = 0;
1198         uint32_t dest_r = 0;
1199         const uint8_t* p = src_scan;
1200         p = src_scan + pPixelWeights->m_SrcStart * src_Bpp;
1201         dest_b += pPixelWeights->m_Weights[0] * (*p++);
1202         dest_g += pPixelWeights->m_Weights[0] * (*p++);
1203         dest_r += pPixelWeights->m_Weights[0] * (*p++);
1204         dest_a += pPixelWeights->m_Weights[0] * (*p);
1205         p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp;
1206         dest_b += pPixelWeights->m_Weights[1] * (*p++);
1207         dest_g += pPixelWeights->m_Weights[1] * (*p++);
1208         dest_r += pPixelWeights->m_Weights[1] * (*p++);
1209         dest_a += pPixelWeights->m_Weights[1] * (*p);
1210         *dest_scan++ = (uint8_t)((dest_b) >> 16);
1211         *dest_scan++ = (uint8_t)((dest_g) >> 16);
1212         *dest_scan++ = (uint8_t)((dest_r) >> 16);
1213         *dest_scan++ = (uint8_t)((dest_a) >> 16);
1214       } break;
1215       default:
1216         return;
1217     }
1218   }
1219 }
1220 
PngDetectImageTypeInBuffer(CFX_DIBAttribute * pAttribute)1221 bool ProgressiveDecoder::PngDetectImageTypeInBuffer(
1222     CFX_DIBAttribute* pAttribute) {
1223   PngModule* pPngModule = m_pCodecMgr->GetPngModule();
1224   if (!pPngModule) {
1225     m_status = FXCODEC_STATUS_ERR_MEMORY;
1226     return false;
1227   }
1228   m_pPngContext = pPngModule->Start(this);
1229   if (!m_pPngContext) {
1230     m_status = FXCODEC_STATUS_ERR_MEMORY;
1231     return false;
1232   }
1233   while (pPngModule->Input(m_pPngContext.get(), m_pCodecMemory, pAttribute)) {
1234     uint32_t remain_size = static_cast<uint32_t>(m_pFile->GetSize()) - m_offSet;
1235     uint32_t input_size = std::min<uint32_t>(remain_size, kBlockSize);
1236     if (input_size == 0) {
1237       m_pPngContext.reset();
1238       m_status = FXCODEC_STATUS_ERR_FORMAT;
1239       return false;
1240     }
1241     if (m_pCodecMemory && input_size > m_pCodecMemory->GetSize())
1242       m_pCodecMemory = pdfium::MakeRetain<CFX_CodecMemory>(input_size);
1243 
1244     if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBuffer(), m_offSet,
1245                                     input_size)) {
1246       m_status = FXCODEC_STATUS_ERR_READ;
1247       return false;
1248     }
1249     m_offSet += input_size;
1250   }
1251   m_pPngContext.reset();
1252   if (m_SrcPassNumber == 0) {
1253     m_status = FXCODEC_STATUS_ERR_FORMAT;
1254     return false;
1255   }
1256   return true;
1257 }
1258 
PngStartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap)1259 FXCODEC_STATUS ProgressiveDecoder::PngStartDecode(
1260     const RetainPtr<CFX_DIBitmap>& pDIBitmap) {
1261   PngModule* pPngModule = m_pCodecMgr->GetPngModule();
1262   if (!pPngModule) {
1263     m_pDeviceBitmap = nullptr;
1264     m_pFile = nullptr;
1265     m_status = FXCODEC_STATUS_ERR_MEMORY;
1266     return m_status;
1267   }
1268   m_pPngContext = pPngModule->Start(this);
1269   if (!m_pPngContext) {
1270     m_pDeviceBitmap = nullptr;
1271     m_pFile = nullptr;
1272     m_status = FXCODEC_STATUS_ERR_MEMORY;
1273     return m_status;
1274   }
1275   m_offSet = 0;
1276   switch (m_pDeviceBitmap->GetFormat()) {
1277     case FXDIB_8bppMask:
1278     case FXDIB_8bppRgb:
1279       m_SrcComponents = 1;
1280       m_SrcFormat = FXCodec_8bppGray;
1281       break;
1282     case FXDIB_Rgb:
1283       m_SrcComponents = 3;
1284       m_SrcFormat = FXCodec_Rgb;
1285       break;
1286     case FXDIB_Rgb32:
1287     case FXDIB_Argb:
1288       m_SrcComponents = 4;
1289       m_SrcFormat = FXCodec_Argb;
1290       break;
1291     default: {
1292       m_pDeviceBitmap = nullptr;
1293       m_pFile = nullptr;
1294       m_status = FXCODEC_STATUS_ERR_PARAMS;
1295       return m_status;
1296     }
1297   }
1298   GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
1299   int scanline_size = FxAlignToBoundary<4>(m_SrcWidth * m_SrcComponents);
1300   m_pDecodeBuf.reset(FX_Alloc(uint8_t, scanline_size));
1301   m_WeightHorzOO.Calc(m_sizeX, m_clipBox.Width());
1302   m_WeightVert.Calc(m_sizeY, m_clipBox.Height());
1303   m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
1304   return m_status;
1305 }
1306 
PngContinueDecode()1307 FXCODEC_STATUS ProgressiveDecoder::PngContinueDecode() {
1308   PngModule* pPngModule = m_pCodecMgr->GetPngModule();
1309   if (!pPngModule) {
1310     m_status = FXCODEC_STATUS_ERR_MEMORY;
1311     return m_status;
1312   }
1313   while (true) {
1314     uint32_t remain_size = (uint32_t)m_pFile->GetSize() - m_offSet;
1315     uint32_t input_size = std::min<uint32_t>(remain_size, kBlockSize);
1316     if (input_size == 0) {
1317       m_pPngContext.reset();
1318       m_pDeviceBitmap = nullptr;
1319       m_pFile = nullptr;
1320       m_status = FXCODEC_STATUS_DECODE_FINISH;
1321       return m_status;
1322     }
1323     if (m_pCodecMemory && input_size > m_pCodecMemory->GetSize())
1324       m_pCodecMemory = pdfium::MakeRetain<CFX_CodecMemory>(input_size);
1325 
1326     bool bResult = m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBuffer(),
1327                                               m_offSet, input_size);
1328     if (!bResult) {
1329       m_pDeviceBitmap = nullptr;
1330       m_pFile = nullptr;
1331       m_status = FXCODEC_STATUS_ERR_READ;
1332       return m_status;
1333     }
1334     m_offSet += input_size;
1335     bResult = pPngModule->Input(m_pPngContext.get(), m_pCodecMemory, nullptr);
1336     if (!bResult) {
1337       m_pDeviceBitmap = nullptr;
1338       m_pFile = nullptr;
1339       m_status = FXCODEC_STATUS_ERROR;
1340       return m_status;
1341     }
1342   }
1343 }
1344 #endif  // PDF_ENABLE_XFA_PNG
1345 
1346 #ifdef PDF_ENABLE_XFA_TIFF
TiffDetectImageTypeFromFile(CFX_DIBAttribute * pAttribute)1347 bool ProgressiveDecoder::TiffDetectImageTypeFromFile(
1348     CFX_DIBAttribute* pAttribute) {
1349   TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule();
1350   if (!pTiffModule) {
1351     m_status = FXCODEC_STATUS_ERR_FORMAT;
1352     return false;
1353   }
1354   m_pTiffContext = pTiffModule->CreateDecoder(m_pFile);
1355   if (!m_pTiffContext) {
1356     m_status = FXCODEC_STATUS_ERR_FORMAT;
1357     return false;
1358   }
1359   int32_t dummy_bpc;
1360   bool ret = pTiffModule->LoadFrameInfo(m_pTiffContext.get(), 0, &m_SrcWidth,
1361                                         &m_SrcHeight, &m_SrcComponents,
1362                                         &dummy_bpc, pAttribute);
1363   m_SrcComponents = 4;
1364   m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
1365   if (!ret) {
1366     m_pTiffContext.reset();
1367     m_status = FXCODEC_STATUS_ERR_FORMAT;
1368     return false;
1369   }
1370   return true;
1371 }
1372 
TiffContinueDecode()1373 FXCODEC_STATUS ProgressiveDecoder::TiffContinueDecode() {
1374   TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule();
1375   if (!pTiffModule) {
1376     m_status = FXCODEC_STATUS_ERR_MEMORY;
1377     return m_status;
1378   }
1379   bool ret = false;
1380   if (m_pDeviceBitmap->GetBPP() == 32 &&
1381       m_pDeviceBitmap->GetWidth() == m_SrcWidth && m_SrcWidth == m_sizeX &&
1382       m_pDeviceBitmap->GetHeight() == m_SrcHeight && m_SrcHeight == m_sizeY &&
1383       m_startX == 0 && m_startY == 0 && m_clipBox.left == 0 &&
1384       m_clipBox.top == 0 && m_clipBox.right == m_SrcWidth &&
1385       m_clipBox.bottom == m_SrcHeight) {
1386     ret = pTiffModule->Decode(m_pTiffContext.get(), m_pDeviceBitmap);
1387     m_pDeviceBitmap = nullptr;
1388     m_pFile = nullptr;
1389     if (!ret) {
1390       m_status = FXCODEC_STATUS_ERROR;
1391       return m_status;
1392     }
1393     m_status = FXCODEC_STATUS_DECODE_FINISH;
1394     return m_status;
1395   }
1396 
1397   auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1398   pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Argb);
1399   if (!pDIBitmap->GetBuffer()) {
1400     m_pDeviceBitmap = nullptr;
1401     m_pFile = nullptr;
1402     m_status = FXCODEC_STATUS_ERR_MEMORY;
1403     return m_status;
1404   }
1405   ret = pTiffModule->Decode(m_pTiffContext.get(), pDIBitmap);
1406   if (!ret) {
1407     m_pDeviceBitmap = nullptr;
1408     m_pFile = nullptr;
1409     m_status = FXCODEC_STATUS_ERROR;
1410     return m_status;
1411   }
1412   RetainPtr<CFX_DIBitmap> pClipBitmap =
1413       (m_clipBox.left == 0 && m_clipBox.top == 0 &&
1414        m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight)
1415           ? pDIBitmap
1416           : pDIBitmap->Clone(&m_clipBox);
1417   if (!pClipBitmap) {
1418     m_pDeviceBitmap = nullptr;
1419     m_pFile = nullptr;
1420     m_status = FXCODEC_STATUS_ERR_MEMORY;
1421     return m_status;
1422   }
1423   RetainPtr<CFX_DIBitmap> pFormatBitmap;
1424   switch (m_pDeviceBitmap->GetFormat()) {
1425     case FXDIB_8bppRgb:
1426       pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1427       pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1428                             FXDIB_8bppRgb);
1429       break;
1430     case FXDIB_8bppMask:
1431       pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1432       pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1433                             FXDIB_8bppMask);
1434       break;
1435     case FXDIB_Rgb:
1436       pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1437       pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1438                             FXDIB_Rgb);
1439       break;
1440     case FXDIB_Rgb32:
1441       pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1442       pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1443                             FXDIB_Rgb32);
1444       break;
1445     case FXDIB_Argb:
1446       pFormatBitmap = pClipBitmap;
1447       break;
1448     default:
1449       break;
1450   }
1451   switch (m_pDeviceBitmap->GetFormat()) {
1452     case FXDIB_8bppRgb:
1453     case FXDIB_8bppMask: {
1454       for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) {
1455         const uint8_t* src_line = pClipBitmap->GetScanline(row);
1456         uint8_t* dest_line = pFormatBitmap->GetWritableScanline(row);
1457         for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) {
1458           uint8_t _a = 255 - src_line[3];
1459           uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
1460           uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
1461           uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255;
1462           *dest_line++ = FXRGB2GRAY(r, g, b);
1463           src_line += 4;
1464         }
1465       }
1466     } break;
1467     case FXDIB_Rgb:
1468     case FXDIB_Rgb32: {
1469       int32_t desBpp = (m_pDeviceBitmap->GetFormat() == FXDIB_Rgb) ? 3 : 4;
1470       for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) {
1471         const uint8_t* src_line = pClipBitmap->GetScanline(row);
1472         uint8_t* dest_line = pFormatBitmap->GetWritableScanline(row);
1473         for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) {
1474           uint8_t _a = 255 - src_line[3];
1475           uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
1476           uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
1477           uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255;
1478           *dest_line++ = b;
1479           *dest_line++ = g;
1480           *dest_line++ = r;
1481           dest_line += desBpp - 3;
1482           src_line += 4;
1483         }
1484       }
1485     } break;
1486     default:
1487       break;
1488   }
1489   if (!pFormatBitmap) {
1490     m_pDeviceBitmap = nullptr;
1491     m_pFile = nullptr;
1492     m_status = FXCODEC_STATUS_ERR_MEMORY;
1493     return m_status;
1494   }
1495 
1496   FXDIB_ResampleOptions options;
1497   options.bInterpolateBilinear = true;
1498   RetainPtr<CFX_DIBitmap> pStrechBitmap =
1499       pFormatBitmap->StretchTo(m_sizeX, m_sizeY, options, nullptr);
1500   pFormatBitmap = nullptr;
1501   if (!pStrechBitmap) {
1502     m_pDeviceBitmap = nullptr;
1503     m_pFile = nullptr;
1504     m_status = FXCODEC_STATUS_ERR_MEMORY;
1505     return m_status;
1506   }
1507   m_pDeviceBitmap->TransferBitmap(m_startX, m_startY, m_sizeX, m_sizeY,
1508                                   pStrechBitmap, 0, 0);
1509   m_pDeviceBitmap = nullptr;
1510   m_pFile = nullptr;
1511   m_status = FXCODEC_STATUS_DECODE_FINISH;
1512   return m_status;
1513 }
1514 #endif  // PDF_ENABLE_XFA_TIFF
1515 
DetectImageType(FXCODEC_IMAGE_TYPE imageType,CFX_DIBAttribute * pAttribute)1516 bool ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType,
1517                                          CFX_DIBAttribute* pAttribute) {
1518 #ifdef PDF_ENABLE_XFA_TIFF
1519   if (imageType == FXCODEC_IMAGE_TIFF)
1520     return TiffDetectImageTypeFromFile(pAttribute);
1521 #endif  // PDF_ENABLE_XFA_TIFF
1522 
1523   size_t size = std::min<size_t>(m_pFile->GetSize(), kBlockSize);
1524   m_pCodecMemory = pdfium::MakeRetain<CFX_CodecMemory>(size);
1525   m_offSet = 0;
1526   if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBuffer(), m_offSet,
1527                                   size)) {
1528     m_status = FXCODEC_STATUS_ERR_READ;
1529     return false;
1530   }
1531   m_offSet += size;
1532 
1533   if (imageType == FXCODEC_IMAGE_JPG)
1534     return JpegDetectImageTypeInBuffer(pAttribute);
1535 
1536 #ifdef PDF_ENABLE_XFA_BMP
1537   if (imageType == FXCODEC_IMAGE_BMP)
1538     return BmpDetectImageTypeInBuffer(pAttribute);
1539 #endif  // PDF_ENABLE_XFA_BMP
1540 
1541 #ifdef PDF_ENABLE_XFA_GIF
1542   if (imageType == FXCODEC_IMAGE_GIF)
1543     return GifDetectImageTypeInBuffer();
1544 #endif  // PDF_ENABLE_XFA_GIF
1545 
1546 #ifdef PDF_ENABLE_XFA_PNG
1547   if (imageType == FXCODEC_IMAGE_PNG)
1548     return PngDetectImageTypeInBuffer(pAttribute);
1549 #endif  // PDF_ENABLE_XFA_PNG
1550 
1551   m_status = FXCODEC_STATUS_ERR_FORMAT;
1552   return false;
1553 }
1554 
ReadMoreData(ModuleIface * pModule,ModuleIface::Context * pContext,bool invalidate_buffer,FXCODEC_STATUS & err_status)1555 bool ProgressiveDecoder::ReadMoreData(ModuleIface* pModule,
1556                                       ModuleIface::Context* pContext,
1557                                       bool invalidate_buffer,
1558                                       FXCODEC_STATUS& err_status) {
1559   // Check for EOF.
1560   if (m_offSet >= static_cast<uint32_t>(m_pFile->GetSize()))
1561     return false;
1562 
1563   // Try to get whatever remains.
1564   uint32_t dwBytesToFetchFromFile = m_pFile->GetSize() - m_offSet;
1565 
1566   // Figure out if the codec stopped processing midway through the buffer.
1567   size_t dwUnconsumed = 0;
1568   if (!invalidate_buffer) {
1569     FX_SAFE_SIZE_T avail_input = pModule->GetAvailInput(pContext);
1570     if (!avail_input.IsValid())
1571       return false;
1572     dwUnconsumed = avail_input.ValueOrDie();
1573   }
1574 
1575   if (dwUnconsumed == m_pCodecMemory->GetSize()) {
1576     // Codec couldn't make any progress against the bytes in the buffer.
1577     // Increase the buffer size so that there might be enough contiguous
1578     // bytes to allow whatever operation is having difficulty to succeed.
1579     dwBytesToFetchFromFile =
1580         std::min<uint32_t>(dwBytesToFetchFromFile, kBlockSize);
1581     size_t dwNewSize = m_pCodecMemory->GetSize() + dwBytesToFetchFromFile;
1582     if (!m_pCodecMemory->TryResize(dwNewSize)) {
1583       err_status = FXCODEC_STATUS_ERR_MEMORY;
1584       return false;
1585     }
1586   } else {
1587     size_t dwConsumed = m_pCodecMemory->GetSize() - dwUnconsumed;
1588     m_pCodecMemory->Consume(dwConsumed);
1589     dwBytesToFetchFromFile =
1590         std::min<uint32_t>(dwBytesToFetchFromFile, dwConsumed);
1591   }
1592 
1593   // Append new data past the bytes not yet processed by the codec.
1594   if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBuffer() + dwUnconsumed,
1595                                   m_offSet, dwBytesToFetchFromFile)) {
1596     err_status = FXCODEC_STATUS_ERR_READ;
1597     return false;
1598   }
1599   m_offSet += dwBytesToFetchFromFile;
1600   return pModule->Input(pContext, m_pCodecMemory, nullptr);
1601 }
1602 
LoadImageInfo(const RetainPtr<IFX_SeekableReadStream> & pFile,FXCODEC_IMAGE_TYPE imageType,CFX_DIBAttribute * pAttribute,bool bSkipImageTypeCheck)1603 FXCODEC_STATUS ProgressiveDecoder::LoadImageInfo(
1604     const RetainPtr<IFX_SeekableReadStream>& pFile,
1605     FXCODEC_IMAGE_TYPE imageType,
1606     CFX_DIBAttribute* pAttribute,
1607     bool bSkipImageTypeCheck) {
1608   ASSERT(pAttribute);
1609 
1610   switch (m_status) {
1611     case FXCODEC_STATUS_FRAME_READY:
1612     case FXCODEC_STATUS_FRAME_TOBECONTINUE:
1613     case FXCODEC_STATUS_DECODE_READY:
1614     case FXCODEC_STATUS_DECODE_TOBECONTINUE:
1615       return FXCODEC_STATUS_ERROR;
1616     default:
1617       break;
1618   }
1619   if (!pFile) {
1620     m_status = FXCODEC_STATUS_ERR_PARAMS;
1621     m_pFile = nullptr;
1622     return m_status;
1623   }
1624   m_pFile = pFile;
1625   m_offSet = 0;
1626   m_SrcWidth = m_SrcHeight = 0;
1627   m_SrcComponents = m_SrcBPC = 0;
1628   m_clipBox = FX_RECT();
1629   m_startX = m_startY = 0;
1630   m_sizeX = m_sizeY = 0;
1631   m_SrcPassNumber = 0;
1632   if (imageType != FXCODEC_IMAGE_UNKNOWN &&
1633       DetectImageType(imageType, pAttribute)) {
1634     m_imageType = imageType;
1635     m_status = FXCODEC_STATUS_FRAME_READY;
1636     return m_status;
1637   }
1638   // If we got here then the image data does not match the requested decoder.
1639   // If we're skipping the type check then bail out at this point and return
1640   // the failed status.
1641   if (bSkipImageTypeCheck)
1642     return m_status;
1643 
1644   for (int type = FXCODEC_IMAGE_UNKNOWN + 1; type < FXCODEC_IMAGE_MAX; type++) {
1645     if (DetectImageType(static_cast<FXCODEC_IMAGE_TYPE>(type), pAttribute)) {
1646       m_imageType = static_cast<FXCODEC_IMAGE_TYPE>(type);
1647       m_status = FXCODEC_STATUS_FRAME_READY;
1648       return m_status;
1649     }
1650   }
1651   m_status = FXCODEC_STATUS_ERR_FORMAT;
1652   m_pFile = nullptr;
1653   return m_status;
1654 }
1655 
SetClipBox(FX_RECT * clip)1656 void ProgressiveDecoder::SetClipBox(FX_RECT* clip) {
1657   if (m_status != FXCODEC_STATUS_FRAME_READY)
1658     return;
1659 
1660   if (clip->IsEmpty()) {
1661     m_clipBox = FX_RECT();
1662     return;
1663   }
1664   clip->left = std::max(clip->left, 0);
1665   clip->right = std::min(clip->right, m_SrcWidth);
1666   clip->top = std::max(clip->top, 0);
1667   clip->bottom = std::min(clip->bottom, m_SrcHeight);
1668   if (clip->IsEmpty()) {
1669     m_clipBox = FX_RECT();
1670     return;
1671   }
1672   m_clipBox = *clip;
1673 }
1674 
GetDownScale(int & down_scale)1675 void ProgressiveDecoder::GetDownScale(int& down_scale) {
1676   down_scale = 1;
1677   int ratio_w = m_clipBox.Width() / m_sizeX;
1678   int ratio_h = m_clipBox.Height() / m_sizeY;
1679   int ratio = (ratio_w > ratio_h) ? ratio_h : ratio_w;
1680   if (ratio >= 8) {
1681     down_scale = 8;
1682   } else if (ratio >= 4) {
1683     down_scale = 4;
1684   } else if (ratio >= 2) {
1685     down_scale = 2;
1686   }
1687   m_clipBox.left /= down_scale;
1688   m_clipBox.right /= down_scale;
1689   m_clipBox.top /= down_scale;
1690   m_clipBox.bottom /= down_scale;
1691   if (m_clipBox.right == m_clipBox.left) {
1692     m_clipBox.right = m_clipBox.left + 1;
1693   }
1694   if (m_clipBox.bottom == m_clipBox.top) {
1695     m_clipBox.bottom = m_clipBox.top + 1;
1696   }
1697 }
1698 
GetTransMethod(FXDIB_Format dest_format,FXCodec_Format src_format)1699 void ProgressiveDecoder::GetTransMethod(FXDIB_Format dest_format,
1700                                         FXCodec_Format src_format) {
1701   switch (dest_format) {
1702     case FXDIB_1bppMask:
1703     case FXDIB_1bppRgb: {
1704       switch (src_format) {
1705         case FXCodec_1bppGray:
1706           m_TransMethod = 0;
1707           break;
1708         default:
1709           m_TransMethod = -1;
1710       }
1711     } break;
1712     case FXDIB_8bppMask:
1713     case FXDIB_8bppRgb: {
1714       switch (src_format) {
1715         case FXCodec_1bppGray:
1716           m_TransMethod = 1;
1717           break;
1718         case FXCodec_8bppGray:
1719           m_TransMethod = 2;
1720           break;
1721         case FXCodec_1bppRgb:
1722         case FXCodec_8bppRgb:
1723           m_TransMethod = 3;
1724           break;
1725         case FXCodec_Rgb:
1726         case FXCodec_Rgb32:
1727         case FXCodec_Argb:
1728           m_TransMethod = 4;
1729           break;
1730         case FXCodec_Cmyk:
1731           m_TransMethod = 5;
1732           break;
1733         default:
1734           m_TransMethod = -1;
1735       }
1736     } break;
1737     case FXDIB_Rgb: {
1738       switch (src_format) {
1739         case FXCodec_1bppGray:
1740           m_TransMethod = 6;
1741           break;
1742         case FXCodec_8bppGray:
1743           m_TransMethod = 7;
1744           break;
1745         case FXCodec_1bppRgb:
1746         case FXCodec_8bppRgb:
1747           m_TransMethod = 8;
1748           break;
1749         case FXCodec_Rgb:
1750         case FXCodec_Rgb32:
1751         case FXCodec_Argb:
1752           m_TransMethod = 9;
1753           break;
1754         case FXCodec_Cmyk:
1755           m_TransMethod = 10;
1756           break;
1757         default:
1758           m_TransMethod = -1;
1759       }
1760     } break;
1761     case FXDIB_Rgb32:
1762     case FXDIB_Argb: {
1763       switch (src_format) {
1764         case FXCodec_1bppGray:
1765           m_TransMethod = 6;
1766           break;
1767         case FXCodec_8bppGray:
1768           m_TransMethod = 7;
1769           break;
1770         case FXCodec_1bppRgb:
1771         case FXCodec_8bppRgb:
1772           if (dest_format == FXDIB_Argb) {
1773             m_TransMethod = 12;
1774           } else {
1775             m_TransMethod = 8;
1776           }
1777           break;
1778         case FXCodec_Rgb:
1779         case FXCodec_Rgb32:
1780           m_TransMethod = 9;
1781           break;
1782         case FXCodec_Cmyk:
1783           m_TransMethod = 10;
1784           break;
1785         case FXCodec_Argb:
1786           m_TransMethod = 11;
1787           break;
1788         default:
1789           m_TransMethod = -1;
1790       }
1791     } break;
1792     default:
1793       m_TransMethod = -1;
1794   }
1795 }
1796 
ReSampleScanline(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,int dest_line,uint8_t * src_scan,FXCodec_Format src_format)1797 void ProgressiveDecoder::ReSampleScanline(
1798     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1799     int dest_line,
1800     uint8_t* src_scan,
1801     FXCodec_Format src_format) {
1802   int src_left = m_clipBox.left;
1803   int dest_left = m_startX;
1804   uint8_t* dest_scan =
1805       pDeviceBitmap->GetBuffer() + dest_line * pDeviceBitmap->GetPitch();
1806   int src_bytes_per_pixel = (src_format & 0xff) / 8;
1807   int dest_bytes_per_pixel = pDeviceBitmap->GetBPP() / 8;
1808   src_scan += src_left * src_bytes_per_pixel;
1809   dest_scan += dest_left * dest_bytes_per_pixel;
1810   for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1811     PixelWeight* pPixelWeights = m_WeightHorz.GetPixelWeight(dest_col);
1812     switch (m_TransMethod) {
1813       case -1:
1814         return;
1815       case 0:
1816         return;
1817       case 1:
1818         return;
1819       case 2: {
1820         uint32_t dest_g = 0;
1821         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1822              j++) {
1823           int pixel_weight =
1824               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1825           dest_g += pixel_weight * src_scan[j];
1826         }
1827         *dest_scan++ = (uint8_t)(dest_g >> 16);
1828       } break;
1829       case 3: {
1830         int dest_r = 0;
1831         int dest_g = 0;
1832         int dest_b = 0;
1833         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1834              j++) {
1835           int pixel_weight =
1836               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1837           unsigned long argb = m_pSrcPalette.get()[src_scan[j]];
1838           dest_r += pixel_weight * FXARGB_R(argb);
1839           dest_g += pixel_weight * FXARGB_G(argb);
1840           dest_b += pixel_weight * FXARGB_B(argb);
1841         }
1842         *dest_scan++ =
1843             (uint8_t)FXRGB2GRAY((dest_r >> 16), (dest_g >> 16), (dest_b >> 16));
1844       } break;
1845       case 4: {
1846         uint32_t dest_b = 0;
1847         uint32_t dest_g = 0;
1848         uint32_t dest_r = 0;
1849         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1850              j++) {
1851           int pixel_weight =
1852               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1853           const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1854           dest_b += pixel_weight * (*src_pixel++);
1855           dest_g += pixel_weight * (*src_pixel++);
1856           dest_r += pixel_weight * (*src_pixel);
1857         }
1858         *dest_scan++ =
1859             (uint8_t)FXRGB2GRAY((dest_r >> 16), (dest_g >> 16), (dest_b >> 16));
1860       } break;
1861       case 5: {
1862         uint32_t dest_b = 0;
1863         uint32_t dest_g = 0;
1864         uint32_t dest_r = 0;
1865         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1866              j++) {
1867           int pixel_weight =
1868               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1869           const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1870           uint8_t src_b = 0;
1871           uint8_t src_g = 0;
1872           uint8_t src_r = 0;
1873           std::tie(src_r, src_g, src_b) =
1874               AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1],
1875                                  255 - src_pixel[2], 255 - src_pixel[3]);
1876           dest_b += pixel_weight * src_b;
1877           dest_g += pixel_weight * src_g;
1878           dest_r += pixel_weight * src_r;
1879         }
1880         *dest_scan++ =
1881             (uint8_t)FXRGB2GRAY((dest_r >> 16), (dest_g >> 16), (dest_b >> 16));
1882       } break;
1883       case 6:
1884         return;
1885       case 7: {
1886         uint32_t dest_g = 0;
1887         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1888              j++) {
1889           int pixel_weight =
1890               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1891           dest_g += pixel_weight * src_scan[j];
1892         }
1893         memset(dest_scan, (uint8_t)(dest_g >> 16), 3);
1894         dest_scan += dest_bytes_per_pixel;
1895       } break;
1896       case 8: {
1897         int dest_r = 0;
1898         int dest_g = 0;
1899         int dest_b = 0;
1900         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1901              j++) {
1902           int pixel_weight =
1903               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1904           unsigned long argb = m_pSrcPalette.get()[src_scan[j]];
1905           dest_r += pixel_weight * FXARGB_R(argb);
1906           dest_g += pixel_weight * FXARGB_G(argb);
1907           dest_b += pixel_weight * FXARGB_B(argb);
1908         }
1909         *dest_scan++ = (uint8_t)((dest_b) >> 16);
1910         *dest_scan++ = (uint8_t)((dest_g) >> 16);
1911         *dest_scan++ = (uint8_t)((dest_r) >> 16);
1912         dest_scan += dest_bytes_per_pixel - 3;
1913       } break;
1914       case 12: {
1915 #ifdef PDF_ENABLE_XFA_BMP
1916         if (m_pBmpContext) {
1917           int dest_r = 0;
1918           int dest_g = 0;
1919           int dest_b = 0;
1920           for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1921                j++) {
1922             int pixel_weight =
1923                 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1924             unsigned long argb = m_pSrcPalette.get()[src_scan[j]];
1925             dest_r += pixel_weight * FXARGB_R(argb);
1926             dest_g += pixel_weight * FXARGB_G(argb);
1927             dest_b += pixel_weight * FXARGB_B(argb);
1928           }
1929           *dest_scan++ = (uint8_t)((dest_b) >> 16);
1930           *dest_scan++ = (uint8_t)((dest_g) >> 16);
1931           *dest_scan++ = (uint8_t)((dest_r) >> 16);
1932           *dest_scan++ = 0xFF;
1933           break;
1934         }
1935 #endif  // PDF_ENABLE_XFA_BMP
1936         int dest_a = 0;
1937         int dest_r = 0;
1938         int dest_g = 0;
1939         int dest_b = 0;
1940         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1941              j++) {
1942           int pixel_weight =
1943               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1944           unsigned long argb = m_pSrcPalette.get()[src_scan[j]];
1945           dest_a += pixel_weight * FXARGB_A(argb);
1946           dest_r += pixel_weight * FXARGB_R(argb);
1947           dest_g += pixel_weight * FXARGB_G(argb);
1948           dest_b += pixel_weight * FXARGB_B(argb);
1949         }
1950         *dest_scan++ = (uint8_t)((dest_b) >> 16);
1951         *dest_scan++ = (uint8_t)((dest_g) >> 16);
1952         *dest_scan++ = (uint8_t)((dest_r) >> 16);
1953         *dest_scan++ = (uint8_t)((dest_a) >> 16);
1954       } break;
1955       case 9: {
1956         uint32_t dest_b = 0;
1957         uint32_t dest_g = 0;
1958         uint32_t dest_r = 0;
1959         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1960              j++) {
1961           int pixel_weight =
1962               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1963           const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1964           dest_b += pixel_weight * (*src_pixel++);
1965           dest_g += pixel_weight * (*src_pixel++);
1966           dest_r += pixel_weight * (*src_pixel);
1967         }
1968         *dest_scan++ = (uint8_t)((dest_b) >> 16);
1969         *dest_scan++ = (uint8_t)((dest_g) >> 16);
1970         *dest_scan++ = (uint8_t)((dest_r) >> 16);
1971         dest_scan += dest_bytes_per_pixel - 3;
1972       } break;
1973       case 10: {
1974         uint32_t dest_b = 0;
1975         uint32_t dest_g = 0;
1976         uint32_t dest_r = 0;
1977         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1978              j++) {
1979           int pixel_weight =
1980               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1981           const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1982           uint8_t src_b = 0;
1983           uint8_t src_g = 0;
1984           uint8_t src_r = 0;
1985           std::tie(src_r, src_g, src_b) =
1986               AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1],
1987                                  255 - src_pixel[2], 255 - src_pixel[3]);
1988           dest_b += pixel_weight * src_b;
1989           dest_g += pixel_weight * src_g;
1990           dest_r += pixel_weight * src_r;
1991         }
1992         *dest_scan++ = (uint8_t)((dest_b) >> 16);
1993         *dest_scan++ = (uint8_t)((dest_g) >> 16);
1994         *dest_scan++ = (uint8_t)((dest_r) >> 16);
1995         dest_scan += dest_bytes_per_pixel - 3;
1996       } break;
1997       case 11: {
1998         uint32_t dest_alpha = 0;
1999         uint32_t dest_r = 0;
2000         uint32_t dest_g = 0;
2001         uint32_t dest_b = 0;
2002         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
2003              j++) {
2004           int pixel_weight =
2005               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
2006           const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
2007           pixel_weight = pixel_weight * src_pixel[3] / 255;
2008           dest_b += pixel_weight * (*src_pixel++);
2009           dest_g += pixel_weight * (*src_pixel++);
2010           dest_r += pixel_weight * (*src_pixel);
2011           dest_alpha += pixel_weight;
2012         }
2013         *dest_scan++ = (uint8_t)((dest_b) >> 16);
2014         *dest_scan++ = (uint8_t)((dest_g) >> 16);
2015         *dest_scan++ = (uint8_t)((dest_r) >> 16);
2016         *dest_scan++ = (uint8_t)((dest_alpha * 255) >> 16);
2017       } break;
2018       default:
2019         return;
2020     }
2021   }
2022 }
2023 
ResampleVert(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,double scale_y,int dest_row)2024 void ProgressiveDecoder::ResampleVert(
2025     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
2026     double scale_y,
2027     int dest_row) {
2028   int dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
2029   uint32_t dest_ScanOffet = m_startX * dest_Bpp;
2030   int dest_top = m_startY;
2031   pdfium::base::CheckedNumeric<int> check_dest_row_1 = dest_row;
2032   check_dest_row_1 -= pdfium::base::checked_cast<int>(scale_y);
2033   int dest_row_1 = check_dest_row_1.ValueOrDie();
2034   if (dest_row_1 < dest_top) {
2035     int dest_bottom = dest_top + m_sizeY;
2036     if (dest_row + (int)scale_y >= dest_bottom - 1) {
2037       const uint8_t* scan_src =
2038           pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet;
2039       while (++dest_row < dest_bottom) {
2040         uint8_t* scan_des =
2041             pDeviceBitmap->GetWritableScanline(dest_row) + dest_ScanOffet;
2042         uint32_t size = m_sizeX * dest_Bpp;
2043         memmove(scan_des, scan_src, size);
2044       }
2045     }
2046     return;
2047   }
2048   for (; dest_row_1 < dest_row; dest_row_1++) {
2049     uint8_t* scan_des =
2050         pDeviceBitmap->GetWritableScanline(dest_row_1) + dest_ScanOffet;
2051     PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top);
2052     const uint8_t* scan_src1 =
2053         pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top) +
2054         dest_ScanOffet;
2055     const uint8_t* scan_src2 =
2056         pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top) +
2057         dest_ScanOffet;
2058     for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
2059       switch (pDeviceBitmap->GetFormat()) {
2060         case FXDIB_Invalid:
2061         case FXDIB_1bppMask:
2062         case FXDIB_1bppRgb:
2063           return;
2064         case FXDIB_8bppMask:
2065         case FXDIB_8bppRgb: {
2066           if (pDeviceBitmap->GetPalette()) {
2067             return;
2068           }
2069           int dest_g = 0;
2070           dest_g += pWeight->m_Weights[0] * (*scan_src1++);
2071           dest_g += pWeight->m_Weights[1] * (*scan_src2++);
2072           *scan_des++ = (uint8_t)(dest_g >> 16);
2073         } break;
2074         case FXDIB_Rgb:
2075         case FXDIB_Rgb32: {
2076           uint32_t dest_b = 0;
2077           uint32_t dest_g = 0;
2078           uint32_t dest_r = 0;
2079           dest_b += pWeight->m_Weights[0] * (*scan_src1++);
2080           dest_g += pWeight->m_Weights[0] * (*scan_src1++);
2081           dest_r += pWeight->m_Weights[0] * (*scan_src1++);
2082           scan_src1 += dest_Bpp - 3;
2083           dest_b += pWeight->m_Weights[1] * (*scan_src2++);
2084           dest_g += pWeight->m_Weights[1] * (*scan_src2++);
2085           dest_r += pWeight->m_Weights[1] * (*scan_src2++);
2086           scan_src2 += dest_Bpp - 3;
2087           *scan_des++ = (uint8_t)((dest_b) >> 16);
2088           *scan_des++ = (uint8_t)((dest_g) >> 16);
2089           *scan_des++ = (uint8_t)((dest_r) >> 16);
2090           scan_des += dest_Bpp - 3;
2091         } break;
2092         case FXDIB_Argb: {
2093           uint32_t dest_a = 0;
2094           uint32_t dest_b = 0;
2095           uint32_t dest_g = 0;
2096           uint32_t dest_r = 0;
2097           dest_b += pWeight->m_Weights[0] * (*scan_src1++);
2098           dest_g += pWeight->m_Weights[0] * (*scan_src1++);
2099           dest_r += pWeight->m_Weights[0] * (*scan_src1++);
2100           dest_a += pWeight->m_Weights[0] * (*scan_src1++);
2101           dest_b += pWeight->m_Weights[1] * (*scan_src2++);
2102           dest_g += pWeight->m_Weights[1] * (*scan_src2++);
2103           dest_r += pWeight->m_Weights[1] * (*scan_src2++);
2104           dest_a += pWeight->m_Weights[1] * (*scan_src2++);
2105           *scan_des++ = (uint8_t)((dest_b) >> 16);
2106           *scan_des++ = (uint8_t)((dest_g) >> 16);
2107           *scan_des++ = (uint8_t)((dest_r) >> 16);
2108           *scan_des++ = (uint8_t)((dest_a) >> 16);
2109         } break;
2110         default:
2111           return;
2112       }
2113     }
2114   }
2115   int dest_bottom = dest_top + m_sizeY;
2116   if (dest_row + (int)scale_y >= dest_bottom - 1) {
2117     const uint8_t* scan_src =
2118         pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet;
2119     while (++dest_row < dest_bottom) {
2120       uint8_t* scan_des =
2121           pDeviceBitmap->GetWritableScanline(dest_row) + dest_ScanOffet;
2122       uint32_t size = m_sizeX * dest_Bpp;
2123       memmove(scan_des, scan_src, size);
2124     }
2125   }
2126 }
2127 
Resample(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,int32_t src_line,uint8_t * src_scan,FXCodec_Format src_format)2128 void ProgressiveDecoder::Resample(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
2129                                   int32_t src_line,
2130                                   uint8_t* src_scan,
2131                                   FXCodec_Format src_format) {
2132   int src_top = m_clipBox.top;
2133   int dest_top = m_startY;
2134   int src_height = m_clipBox.Height();
2135   int dest_height = m_sizeY;
2136   if (src_line >= src_top) {
2137     double scale_y = static_cast<double>(dest_height) / src_height;
2138     int src_row = src_line - src_top;
2139     int dest_row = (int)(src_row * scale_y) + dest_top;
2140     if (dest_row >= dest_top + dest_height)
2141       return;
2142 
2143     ReSampleScanline(pDeviceBitmap, dest_row, m_pDecodeBuf.get(), src_format);
2144     if (scale_y > 1.0)
2145       ResampleVert(pDeviceBitmap, scale_y, dest_row);
2146   }
2147 }
2148 
GetFrames()2149 std::pair<FXCODEC_STATUS, size_t> ProgressiveDecoder::GetFrames() {
2150   if (!(m_status == FXCODEC_STATUS_FRAME_READY ||
2151         m_status == FXCODEC_STATUS_FRAME_TOBECONTINUE)) {
2152     return {FXCODEC_STATUS_ERROR, 0};
2153   }
2154 
2155   switch (m_imageType) {
2156 #ifdef PDF_ENABLE_XFA_BMP
2157     case FXCODEC_IMAGE_BMP:
2158 #endif  // PDF_ENABLE_XFA_BMP
2159     case FXCODEC_IMAGE_JPG:
2160 #ifdef PDF_ENABLE_XFA_PNG
2161     case FXCODEC_IMAGE_PNG:
2162 #endif  // PDF_ENABLE_XFA_PNG
2163 #ifdef PDF_ENABLE_XFA_TIFF
2164     case FXCODEC_IMAGE_TIFF:
2165 #endif  // PDF_ENABLE_XFA_TIFF
2166       m_FrameNumber = 1;
2167       m_status = FXCODEC_STATUS_DECODE_READY;
2168       return {m_status, 1};
2169 #ifdef PDF_ENABLE_XFA_GIF
2170     case FXCODEC_IMAGE_GIF: {
2171       GifModule* pGifModule = m_pCodecMgr->GetGifModule();
2172       if (!pGifModule) {
2173         m_status = FXCODEC_STATUS_ERR_MEMORY;
2174         return {m_status, 0};
2175       }
2176       while (true) {
2177         CFX_GifDecodeStatus readResult;
2178         std::tie(readResult, m_FrameNumber) =
2179             pGifModule->LoadFrameInfo(m_pGifContext.get());
2180         while (readResult == CFX_GifDecodeStatus::Unfinished) {
2181           FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_READ;
2182           if (!GifReadMoreData(pGifModule, error_status))
2183             return {error_status, 0};
2184 
2185           std::tie(readResult, m_FrameNumber) =
2186               pGifModule->LoadFrameInfo(m_pGifContext.get());
2187         }
2188         if (readResult == CFX_GifDecodeStatus::Success) {
2189           m_status = FXCODEC_STATUS_DECODE_READY;
2190           return {m_status, m_FrameNumber};
2191         }
2192         m_pGifContext = nullptr;
2193         m_status = FXCODEC_STATUS_ERROR;
2194         return {m_status, 0};
2195       }
2196     }
2197 #endif  // PDF_ENABLE_XFA_GIF
2198     default:
2199       return {FXCODEC_STATUS_ERROR, 0};
2200   }
2201 }
2202 
StartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap,int start_x,int start_y,int size_x,int size_y)2203 FXCODEC_STATUS ProgressiveDecoder::StartDecode(
2204     const RetainPtr<CFX_DIBitmap>& pDIBitmap,
2205     int start_x,
2206     int start_y,
2207     int size_x,
2208     int size_y) {
2209   if (m_status != FXCODEC_STATUS_DECODE_READY)
2210     return FXCODEC_STATUS_ERROR;
2211 
2212   if (!pDIBitmap || pDIBitmap->GetBPP() < 8 || m_FrameNumber == 0)
2213     return FXCODEC_STATUS_ERR_PARAMS;
2214 
2215   m_pDeviceBitmap = pDIBitmap;
2216   if (m_clipBox.IsEmpty())
2217     return FXCODEC_STATUS_ERR_PARAMS;
2218   if (size_x <= 0 || size_x > 65535 || size_y <= 0 || size_y > 65535)
2219     return FXCODEC_STATUS_ERR_PARAMS;
2220 
2221   FX_RECT device_rc =
2222       FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y);
2223   int32_t out_range_x = device_rc.right - pDIBitmap->GetWidth();
2224   int32_t out_range_y = device_rc.bottom - pDIBitmap->GetHeight();
2225   device_rc.Intersect(
2226       FX_RECT(0, 0, pDIBitmap->GetWidth(), pDIBitmap->GetHeight()));
2227   if (device_rc.IsEmpty())
2228     return FXCODEC_STATUS_ERR_PARAMS;
2229 
2230   m_startX = device_rc.left;
2231   m_startY = device_rc.top;
2232   m_sizeX = device_rc.Width();
2233   m_sizeY = device_rc.Height();
2234   m_FrameCur = 0;
2235   if (start_x < 0 || out_range_x > 0) {
2236     float scaleX = (float)m_clipBox.Width() / (float)size_x;
2237     if (start_x < 0) {
2238       m_clipBox.left -= (int32_t)ceil((float)start_x * scaleX);
2239     }
2240     if (out_range_x > 0) {
2241       m_clipBox.right -= (int32_t)floor((float)out_range_x * scaleX);
2242     }
2243   }
2244   if (start_y < 0 || out_range_y > 0) {
2245     float scaleY = (float)m_clipBox.Height() / (float)size_y;
2246     if (start_y < 0) {
2247       m_clipBox.top -= (int32_t)ceil((float)start_y * scaleY);
2248     }
2249     if (out_range_y > 0) {
2250       m_clipBox.bottom -= (int32_t)floor((float)out_range_y * scaleY);
2251     }
2252   }
2253   if (m_clipBox.IsEmpty()) {
2254     return FXCODEC_STATUS_ERR_PARAMS;
2255   }
2256   switch (m_imageType) {
2257 #ifdef PDF_ENABLE_XFA_BMP
2258     case FXCODEC_IMAGE_BMP:
2259       return BmpStartDecode(pDIBitmap);
2260 #endif  // PDF_ENABLE_XFA_BMP
2261 #ifdef PDF_ENABLE_XFA_GIF
2262     case FXCODEC_IMAGE_GIF:
2263       return GifStartDecode(pDIBitmap);
2264 #endif  // PDF_ENABLE_XFA_GIF
2265     case FXCODEC_IMAGE_JPG:
2266       return JpegStartDecode(pDIBitmap);
2267 #ifdef PDF_ENABLE_XFA_PNG
2268     case FXCODEC_IMAGE_PNG:
2269       return PngStartDecode(pDIBitmap);
2270 #endif  // PDF_ENABLE_XFA_PNG
2271 #ifdef PDF_ENABLE_XFA_TIFF
2272     case FXCODEC_IMAGE_TIFF:
2273       m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
2274       return m_status;
2275 #endif  // PDF_ENABLE_XFA_TIFF
2276     default:
2277       return FXCODEC_STATUS_ERROR;
2278   }
2279 }
2280 
ContinueDecode()2281 FXCODEC_STATUS ProgressiveDecoder::ContinueDecode() {
2282   if (m_status != FXCODEC_STATUS_DECODE_TOBECONTINUE)
2283     return FXCODEC_STATUS_ERROR;
2284 
2285   switch (m_imageType) {
2286     case FXCODEC_IMAGE_JPG:
2287       return JpegContinueDecode();
2288 #ifdef PDF_ENABLE_XFA_BMP
2289     case FXCODEC_IMAGE_BMP:
2290       return BmpContinueDecode();
2291 #endif  // PDF_ENABLE_XFA_BMP
2292 #ifdef PDF_ENABLE_XFA_GIF
2293     case FXCODEC_IMAGE_GIF:
2294       return GifContinueDecode();
2295 #endif  // PDF_ENABLE_XFA_GIF
2296 #ifdef PDF_ENABLE_XFA_PNG
2297     case FXCODEC_IMAGE_PNG:
2298       return PngContinueDecode();
2299 #endif  // PDF_ENABLE_XFA_PNG
2300 #ifdef PDF_ENABLE_XFA_TIFF
2301     case FXCODEC_IMAGE_TIFF:
2302       return TiffContinueDecode();
2303 #endif  // PDF_ENABLE_XFA_TIFF
2304     default:
2305       return FXCODEC_STATUS_ERROR;
2306   }
2307 }
2308 
CreateProgressiveDecoder()2309 std::unique_ptr<ProgressiveDecoder> ModuleMgr::CreateProgressiveDecoder() {
2310   return pdfium::MakeUnique<ProgressiveDecoder>(this);
2311 }
2312 
2313 }  // namespace fxcodec
2314