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