xref: /aosp_15_r20/external/pdfium/core/fxcodec/progressive_decoder.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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     }
637   }
638 }
639 
BmpDetectImageTypeInBuffer(CFX_DIBAttribute * pAttribute)640 bool ProgressiveDecoder::BmpDetectImageTypeInBuffer(
641     CFX_DIBAttribute* pAttribute) {
642   std::unique_ptr<ProgressiveDecoderIface::Context> pBmpContext =
643       BmpDecoder::StartDecode(this);
644   BmpDecoder::Input(pBmpContext.get(), m_pCodecMemory);
645 
646   const std::vector<uint32_t>* palette;
647   BmpDecoder::Status read_result = BmpDecoder::ReadHeader(
648       pBmpContext.get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom,
649       &m_SrcComponents, &m_SrcPaletteNumber, &palette, pAttribute);
650   while (read_result == BmpDecoder::Status::kContinue) {
651     FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
652     if (!BmpReadMoreData(pBmpContext.get(), &error_status)) {
653       m_status = error_status;
654       return false;
655     }
656     read_result = BmpDecoder::ReadHeader(
657         pBmpContext.get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom,
658         &m_SrcComponents, &m_SrcPaletteNumber, &palette, pAttribute);
659   }
660 
661   if (read_result != BmpDecoder::Status::kSuccess) {
662     m_status = FXCODEC_STATUS::kError;
663     return false;
664   }
665 
666   FXDIB_Format format = FXDIB_Format::kInvalid;
667   switch (m_SrcComponents) {
668     case 1:
669       m_SrcFormat = FXCodec_8bppRgb;
670       format = FXDIB_Format::k8bppRgb;
671       break;
672     case 3:
673       m_SrcFormat = FXCodec_Rgb;
674       format = FXDIB_Format::kRgb;
675       break;
676     case 4:
677       m_SrcFormat = FXCodec_Rgb32;
678       format = FXDIB_Format::kRgb32;
679       break;
680     default:
681       m_status = FXCODEC_STATUS::kError;
682       return false;
683   }
684 
685   // Set to 0 to make CalculatePitchAndSize() calculate it.
686   constexpr uint32_t kNoPitch = 0;
687   absl::optional<CFX_DIBitmap::PitchAndSize> needed_data =
688       CFX_DIBitmap::CalculatePitchAndSize(m_SrcWidth, m_SrcHeight, format,
689                                           kNoPitch);
690   if (!needed_data.has_value()) {
691     m_status = FXCODEC_STATUS::kError;
692     return false;
693   }
694 
695   uint32_t available_data = pdfium::base::checked_cast<uint32_t>(
696       m_pFile->GetSize() - m_offSet +
697       BmpDecoder::GetAvailInput(pBmpContext.get()));
698   if (needed_data.value().size > available_data) {
699     m_status = FXCODEC_STATUS::kError;
700     return false;
701   }
702 
703   m_SrcBPC = 8;
704   m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
705   m_pBmpContext = std::move(pBmpContext);
706   if (m_SrcPaletteNumber) {
707     m_SrcPalette.resize(m_SrcPaletteNumber);
708     memcpy(m_SrcPalette.data(), palette->data(),
709            m_SrcPaletteNumber * sizeof(FX_ARGB));
710   } else {
711     m_SrcPalette.clear();
712   }
713   return true;
714 }
715 
BmpReadMoreData(ProgressiveDecoderIface::Context * pContext,FXCODEC_STATUS * err_status)716 bool ProgressiveDecoder::BmpReadMoreData(
717     ProgressiveDecoderIface::Context* pContext,
718     FXCODEC_STATUS* err_status) {
719   return ReadMoreData(BmpProgressiveDecoder::GetInstance(), pContext,
720                       err_status);
721 }
722 
BmpStartDecode()723 FXCODEC_STATUS ProgressiveDecoder::BmpStartDecode() {
724   GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
725   m_ScanlineSize = FxAlignToBoundary<4>(m_SrcWidth * m_SrcComponents);
726   m_DecodeBuf.resize(m_ScanlineSize);
727   FXDIB_ResampleOptions options;
728   options.bInterpolateBilinear = true;
729   m_WeightHorz.CalculateWeights(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0,
730                                 m_clipBox.Width(), options);
731   m_WeightVert.CalculateWeights(m_sizeY, m_clipBox.Height());
732   m_status = FXCODEC_STATUS::kDecodeToBeContinued;
733   return m_status;
734 }
735 
BmpContinueDecode()736 FXCODEC_STATUS ProgressiveDecoder::BmpContinueDecode() {
737   BmpDecoder::Status read_res = BmpDecoder::LoadImage(m_pBmpContext.get());
738   while (read_res == BmpDecoder::Status::kContinue) {
739     FXCODEC_STATUS error_status = FXCODEC_STATUS::kDecodeFinished;
740     if (!BmpReadMoreData(m_pBmpContext.get(), &error_status)) {
741       m_pDeviceBitmap = nullptr;
742       m_pFile = nullptr;
743       m_status = error_status;
744       return m_status;
745     }
746     read_res = BmpDecoder::LoadImage(m_pBmpContext.get());
747   }
748 
749   m_pDeviceBitmap = nullptr;
750   m_pFile = nullptr;
751   m_status = read_res == BmpDecoder::Status::kSuccess
752                  ? FXCODEC_STATUS::kDecodeFinished
753                  : FXCODEC_STATUS::kError;
754   return m_status;
755 }
756 #endif  // PDF_ENABLE_XFA_BMP
757 
758 #ifdef PDF_ENABLE_XFA_GIF
GifReadMoreData(FXCODEC_STATUS * err_status)759 bool ProgressiveDecoder::GifReadMoreData(FXCODEC_STATUS* err_status) {
760   return ReadMoreData(GifProgressiveDecoder::GetInstance(), m_pGifContext.get(),
761                       err_status);
762 }
763 
GifDetectImageTypeInBuffer()764 bool ProgressiveDecoder::GifDetectImageTypeInBuffer() {
765   m_pGifContext = GifDecoder::StartDecode(this);
766   GifDecoder::Input(m_pGifContext.get(), m_pCodecMemory);
767   m_SrcComponents = 1;
768   GifDecoder::Status readResult =
769       GifDecoder::ReadHeader(m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight,
770                              &m_GifPltNumber, &m_pGifPalette, &m_GifBgIndex);
771   while (readResult == GifDecoder::Status::kUnfinished) {
772     FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
773     if (!GifReadMoreData(&error_status)) {
774       m_pGifContext = nullptr;
775       m_status = error_status;
776       return false;
777     }
778     readResult =
779         GifDecoder::ReadHeader(m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight,
780                                &m_GifPltNumber, &m_pGifPalette, &m_GifBgIndex);
781   }
782   if (readResult == GifDecoder::Status::kSuccess) {
783     m_SrcBPC = 8;
784     m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
785     return true;
786   }
787   m_pGifContext = nullptr;
788   m_status = FXCODEC_STATUS::kError;
789   return false;
790 }
791 
GifStartDecode()792 FXCODEC_STATUS ProgressiveDecoder::GifStartDecode() {
793   m_SrcFormat = FXCodec_8bppRgb;
794   GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
795   int scanline_size = FxAlignToBoundary<4>(m_SrcWidth);
796   m_DecodeBuf.resize(scanline_size);
797   FXDIB_ResampleOptions options;
798   options.bInterpolateBilinear = true;
799   m_WeightHorz.CalculateWeights(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0,
800                                 m_clipBox.Width(), options);
801   m_WeightVert.CalculateWeights(m_sizeY, m_clipBox.Height());
802   m_FrameCur = 0;
803   m_status = FXCODEC_STATUS::kDecodeToBeContinued;
804   return m_status;
805 }
806 
GifContinueDecode()807 FXCODEC_STATUS ProgressiveDecoder::GifContinueDecode() {
808   GifDecoder::Status readRes =
809       GifDecoder::LoadFrame(m_pGifContext.get(), m_FrameCur);
810   while (readRes == GifDecoder::Status::kUnfinished) {
811     FXCODEC_STATUS error_status = FXCODEC_STATUS::kDecodeFinished;
812     if (!GifReadMoreData(&error_status)) {
813       m_pDeviceBitmap = nullptr;
814       m_pFile = nullptr;
815       m_status = error_status;
816       return m_status;
817     }
818     readRes = GifDecoder::LoadFrame(m_pGifContext.get(), m_FrameCur);
819   }
820 
821   if (readRes == GifDecoder::Status::kSuccess) {
822     m_pDeviceBitmap = nullptr;
823     m_pFile = nullptr;
824     m_status = FXCODEC_STATUS::kDecodeFinished;
825     return m_status;
826   }
827 
828   m_pDeviceBitmap = nullptr;
829   m_pFile = nullptr;
830   m_status = FXCODEC_STATUS::kError;
831   return m_status;
832 }
833 
GifDoubleLineResampleVert(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,double scale_y,int dest_row)834 void ProgressiveDecoder::GifDoubleLineResampleVert(
835     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
836     double scale_y,
837     int dest_row) {
838   int dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
839   uint32_t dest_ScanOffset = m_startX * dest_Bpp;
840   int dest_top = m_startY;
841   pdfium::base::CheckedNumeric<double> scale_y2 = scale_y;
842   scale_y2 *= 2;
843   FX_SAFE_INT32 check_dest_row_1 = dest_row;
844   check_dest_row_1 -= scale_y2.ValueOrDie();
845   int dest_row_1 = check_dest_row_1.ValueOrDie();
846   dest_row_1 = std::max(dest_row_1, dest_top);
847   for (; dest_row_1 < dest_row; dest_row_1++) {
848     uint8_t* scan_des = pDeviceBitmap->GetWritableScanline(dest_row_1)
849                             .subspan(dest_ScanOffset)
850                             .data();
851     PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top);
852     const uint8_t* scan_src1 =
853         pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top)
854             .subspan(dest_ScanOffset)
855             .data();
856     const uint8_t* scan_src2 =
857         pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top)
858             .subspan(dest_ScanOffset)
859             .data();
860     switch (pDeviceBitmap->GetFormat()) {
861       case FXDIB_Format::kInvalid:
862       case FXDIB_Format::k1bppMask:
863       case FXDIB_Format::k1bppRgb:
864         return;
865       case FXDIB_Format::k8bppMask:
866       case FXDIB_Format::k8bppRgb:
867         if (pDeviceBitmap->HasPalette())
868           return;
869         for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
870           uint32_t dest_g = 0;
871           dest_g += pWeight->m_Weights[0] * (*scan_src1++);
872           dest_g += pWeight->m_Weights[1] * (*scan_src2++);
873           *scan_des++ = CStretchEngine::PixelFromFixed(dest_g);
874         }
875         break;
876       case FXDIB_Format::kRgb:
877       case FXDIB_Format::kRgb32:
878         for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
879           uint32_t dest_b = pWeight->m_Weights[0] * (*scan_src1++);
880           uint32_t dest_g = pWeight->m_Weights[0] * (*scan_src1++);
881           uint32_t dest_r = pWeight->m_Weights[0] * (*scan_src1++);
882           scan_src1 += dest_Bpp - 3;
883           dest_b += pWeight->m_Weights[1] * (*scan_src2++);
884           dest_g += pWeight->m_Weights[1] * (*scan_src2++);
885           dest_r += pWeight->m_Weights[1] * (*scan_src2++);
886           scan_src2 += dest_Bpp - 3;
887           *scan_des++ = CStretchEngine::PixelFromFixed(dest_b);
888           *scan_des++ = CStretchEngine::PixelFromFixed(dest_g);
889           *scan_des++ = CStretchEngine::PixelFromFixed(dest_r);
890           scan_des += dest_Bpp - 3;
891         }
892         break;
893       case FXDIB_Format::kArgb:
894         for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
895           uint32_t dest_b = pWeight->m_Weights[0] * (*scan_src1++);
896           uint32_t dest_g = pWeight->m_Weights[0] * (*scan_src1++);
897           uint32_t dest_r = pWeight->m_Weights[0] * (*scan_src1++);
898           uint32_t dest_a = pWeight->m_Weights[0] * (*scan_src1++);
899           dest_b += pWeight->m_Weights[1] * (*scan_src2++);
900           dest_g += pWeight->m_Weights[1] * (*scan_src2++);
901           dest_r += pWeight->m_Weights[1] * (*scan_src2++);
902           dest_a += pWeight->m_Weights[1] * (*scan_src2++);
903           *scan_des++ = CStretchEngine::PixelFromFixed(dest_b);
904           *scan_des++ = CStretchEngine::PixelFromFixed(dest_g);
905           *scan_des++ = CStretchEngine::PixelFromFixed(dest_r);
906           *scan_des++ = CStretchEngine::PixelFromFixed(dest_a);
907         }
908         break;
909     }
910   }
911   int dest_bottom = dest_top + m_sizeY - 1;
912   if (dest_row + (int)(2 * scale_y) >= dest_bottom &&
913       dest_row + (int)scale_y < dest_bottom) {
914     GifDoubleLineResampleVert(pDeviceBitmap, scale_y, dest_row + (int)scale_y);
915   }
916 }
917 #endif  // PDF_ENABLE_XFA_GIF
918 
JpegReadMoreData(FXCODEC_STATUS * err_status)919 bool ProgressiveDecoder::JpegReadMoreData(FXCODEC_STATUS* err_status) {
920   return ReadMoreData(JpegProgressiveDecoder::GetInstance(),
921                       m_pJpegContext.get(), err_status);
922 }
923 
JpegDetectImageTypeInBuffer(CFX_DIBAttribute * pAttribute)924 bool ProgressiveDecoder::JpegDetectImageTypeInBuffer(
925     CFX_DIBAttribute* pAttribute) {
926   m_pJpegContext = JpegProgressiveDecoder::Start();
927   if (!m_pJpegContext) {
928     m_status = FXCODEC_STATUS::kError;
929     return false;
930   }
931   JpegProgressiveDecoder::GetInstance()->Input(m_pJpegContext.get(),
932                                                m_pCodecMemory);
933 
934   // Setting jump marker before calling ReadHeader, since a longjmp to
935   // the marker indicates a fatal error.
936   if (setjmp(JpegProgressiveDecoder::GetJumpMark(m_pJpegContext.get())) == -1) {
937     m_pJpegContext.reset();
938     m_status = FXCODEC_STATUS::kError;
939     return false;
940   }
941 
942   int32_t readResult = JpegProgressiveDecoder::ReadHeader(
943       m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight, &m_SrcComponents,
944       pAttribute);
945   while (readResult == 2) {
946     FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
947     if (!JpegReadMoreData(&error_status)) {
948       m_status = error_status;
949       return false;
950     }
951     readResult = JpegProgressiveDecoder::ReadHeader(
952         m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight, &m_SrcComponents,
953         pAttribute);
954   }
955   if (!readResult) {
956     m_SrcBPC = 8;
957     m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
958     return true;
959   }
960   m_pJpegContext.reset();
961   m_status = FXCODEC_STATUS::kError;
962   return false;
963 }
964 
JpegStartDecode(FXDIB_Format format)965 FXCODEC_STATUS ProgressiveDecoder::JpegStartDecode(FXDIB_Format format) {
966   int down_scale = GetDownScale();
967   // Setting jump marker before calling StartScanLine, since a longjmp to
968   // the marker indicates a fatal error.
969   if (setjmp(JpegProgressiveDecoder::GetJumpMark(m_pJpegContext.get())) == -1) {
970     m_pJpegContext.reset();
971     m_status = FXCODEC_STATUS::kError;
972     return FXCODEC_STATUS::kError;
973   }
974 
975   bool startStatus =
976       JpegProgressiveDecoder::StartScanline(m_pJpegContext.get(), down_scale);
977   while (!startStatus) {
978     FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
979     if (!JpegReadMoreData(&error_status)) {
980       m_pDeviceBitmap = nullptr;
981       m_pFile = nullptr;
982       m_status = error_status;
983       return m_status;
984     }
985 
986     startStatus =
987         JpegProgressiveDecoder::StartScanline(m_pJpegContext.get(), down_scale);
988   }
989   int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale;
990   scanline_size = FxAlignToBoundary<4>(scanline_size * m_SrcComponents);
991   m_DecodeBuf.resize(scanline_size);
992   FXDIB_ResampleOptions options;
993   options.bInterpolateBilinear = true;
994   m_WeightHorz.CalculateWeights(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0,
995                                 m_clipBox.Width(), options);
996   m_WeightVert.CalculateWeights(m_sizeY, m_clipBox.Height());
997   switch (m_SrcComponents) {
998     case 1:
999       m_SrcFormat = FXCodec_8bppGray;
1000       break;
1001     case 3:
1002       m_SrcFormat = FXCodec_Rgb;
1003       break;
1004     case 4:
1005       m_SrcFormat = FXCodec_Cmyk;
1006       break;
1007   }
1008   GetTransMethod(format, m_SrcFormat);
1009   m_status = FXCODEC_STATUS::kDecodeToBeContinued;
1010   return m_status;
1011 }
1012 
JpegContinueDecode()1013 FXCODEC_STATUS ProgressiveDecoder::JpegContinueDecode() {
1014   // JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
1015   // Setting jump marker before calling ReadScanLine, since a longjmp to
1016   // the marker indicates a fatal error.
1017   if (setjmp(JpegProgressiveDecoder::GetJumpMark(m_pJpegContext.get())) == -1) {
1018     m_pJpegContext.reset();
1019     m_status = FXCODEC_STATUS::kError;
1020     return FXCODEC_STATUS::kError;
1021   }
1022 
1023   while (true) {
1024     bool readRes = JpegProgressiveDecoder::ReadScanline(m_pJpegContext.get(),
1025                                                         m_DecodeBuf.data());
1026     while (!readRes) {
1027       FXCODEC_STATUS error_status = FXCODEC_STATUS::kDecodeFinished;
1028       if (!JpegReadMoreData(&error_status)) {
1029         m_pDeviceBitmap = nullptr;
1030         m_pFile = nullptr;
1031         m_status = error_status;
1032         return m_status;
1033       }
1034       readRes = JpegProgressiveDecoder::ReadScanline(m_pJpegContext.get(),
1035                                                      m_DecodeBuf.data());
1036     }
1037     if (m_SrcFormat == FXCodec_Rgb) {
1038       int src_Bpp = (m_SrcFormat & 0xff) >> 3;
1039       RGB2BGR(m_DecodeBuf.data() + m_clipBox.left * src_Bpp, m_clipBox.Width());
1040     }
1041     if (m_SrcRow >= m_clipBox.bottom) {
1042       m_pDeviceBitmap = nullptr;
1043       m_pFile = nullptr;
1044       m_status = FXCODEC_STATUS::kDecodeFinished;
1045       return m_status;
1046     }
1047     Resample(m_pDeviceBitmap, m_SrcRow, m_DecodeBuf.data(), m_SrcFormat);
1048     m_SrcRow++;
1049   }
1050 }
1051 
1052 #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)1053 void ProgressiveDecoder::PngOneOneMapResampleHorz(
1054     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1055     int32_t dest_line,
1056     pdfium::span<uint8_t> src_span,
1057     FXCodec_Format src_format) {
1058   int32_t src_Bpp = (m_SrcFormat & 0xff) >> 3;
1059   int32_t dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
1060   int32_t src_left = m_clipBox.left;
1061   int32_t dest_left = m_startX;
1062   uint8_t* src_scan = src_span.subspan(src_left * src_Bpp).data();
1063   uint8_t* dest_scan = pDeviceBitmap->GetWritableScanline(dest_line)
1064                            .subspan(dest_left * dest_Bpp)
1065                            .data();
1066   switch (pDeviceBitmap->GetFormat()) {
1067     case FXDIB_Format::k1bppMask:
1068     case FXDIB_Format::k1bppRgb:
1069       NOTREACHED_NORETURN();
1070     case FXDIB_Format::k8bppMask:
1071     case FXDIB_Format::k8bppRgb:
1072       if (pDeviceBitmap->HasPalette())
1073         return;
1074       for (int32_t dest_col = 0; dest_col < m_sizeX; dest_col++) {
1075         PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(dest_col);
1076         uint32_t dest_g =
1077             pPixelWeights->m_Weights[0] * src_scan[pPixelWeights->m_SrcStart];
1078         dest_g +=
1079             pPixelWeights->m_Weights[1] * src_scan[pPixelWeights->m_SrcEnd];
1080         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1081       }
1082       break;
1083     case FXDIB_Format::kRgb:
1084     case FXDIB_Format::kRgb32:
1085       for (int32_t dest_col = 0; dest_col < m_sizeX; dest_col++) {
1086         PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(dest_col);
1087         const uint8_t* p = src_scan + pPixelWeights->m_SrcStart * src_Bpp;
1088         uint32_t dest_b = pPixelWeights->m_Weights[0] * (*p++);
1089         uint32_t dest_g = pPixelWeights->m_Weights[0] * (*p++);
1090         uint32_t dest_r = pPixelWeights->m_Weights[0] * (*p);
1091         p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp;
1092         dest_b += pPixelWeights->m_Weights[1] * (*p++);
1093         dest_g += pPixelWeights->m_Weights[1] * (*p++);
1094         dest_r += pPixelWeights->m_Weights[1] * (*p);
1095         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1096         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1097         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1098         dest_scan += dest_Bpp - 3;
1099       }
1100       break;
1101     case FXDIB_Format::kArgb:
1102       for (int32_t dest_col = 0; dest_col < m_sizeX; dest_col++) {
1103         PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(dest_col);
1104         const uint8_t* p = src_scan + pPixelWeights->m_SrcStart * src_Bpp;
1105         uint32_t dest_b = pPixelWeights->m_Weights[0] * (*p++);
1106         uint32_t dest_g = pPixelWeights->m_Weights[0] * (*p++);
1107         uint32_t dest_r = pPixelWeights->m_Weights[0] * (*p++);
1108         uint32_t dest_a = pPixelWeights->m_Weights[0] * (*p);
1109         p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp;
1110         dest_b += pPixelWeights->m_Weights[1] * (*p++);
1111         dest_g += pPixelWeights->m_Weights[1] * (*p++);
1112         dest_r += pPixelWeights->m_Weights[1] * (*p++);
1113         dest_a += pPixelWeights->m_Weights[1] * (*p);
1114         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1115         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1116         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1117         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_a);
1118       }
1119       break;
1120     default:
1121       return;
1122   }
1123 }
1124 
PngDetectImageTypeInBuffer(CFX_DIBAttribute * pAttribute)1125 bool ProgressiveDecoder::PngDetectImageTypeInBuffer(
1126     CFX_DIBAttribute* pAttribute) {
1127   m_pPngContext = PngDecoder::StartDecode(this);
1128   if (!m_pPngContext) {
1129     m_status = FXCODEC_STATUS::kError;
1130     return false;
1131   }
1132   while (PngDecoder::ContinueDecode(m_pPngContext.get(), m_pCodecMemory,
1133                                     pAttribute)) {
1134     uint32_t remain_size = static_cast<uint32_t>(m_pFile->GetSize()) - m_offSet;
1135     uint32_t input_size = std::min<uint32_t>(remain_size, kBlockSize);
1136     if (input_size == 0) {
1137       m_pPngContext.reset();
1138       m_status = FXCODEC_STATUS::kError;
1139       return false;
1140     }
1141     if (m_pCodecMemory && input_size > m_pCodecMemory->GetSize())
1142       m_pCodecMemory = pdfium::MakeRetain<CFX_CodecMemory>(input_size);
1143 
1144     if (!m_pFile->ReadBlockAtOffset(
1145             m_pCodecMemory->GetBufferSpan().first(input_size), m_offSet)) {
1146       m_status = FXCODEC_STATUS::kError;
1147       return false;
1148     }
1149     m_offSet += input_size;
1150   }
1151   m_pPngContext.reset();
1152   if (m_SrcPassNumber == 0) {
1153     m_status = FXCODEC_STATUS::kError;
1154     return false;
1155   }
1156   return true;
1157 }
1158 
PngStartDecode()1159 FXCODEC_STATUS ProgressiveDecoder::PngStartDecode() {
1160   m_pPngContext = PngDecoder::StartDecode(this);
1161   if (!m_pPngContext) {
1162     m_pDeviceBitmap = nullptr;
1163     m_pFile = nullptr;
1164     m_status = FXCODEC_STATUS::kError;
1165     return m_status;
1166   }
1167   m_offSet = 0;
1168   switch (m_pDeviceBitmap->GetFormat()) {
1169     case FXDIB_Format::k8bppMask:
1170     case FXDIB_Format::k8bppRgb:
1171       m_SrcComponents = 1;
1172       m_SrcFormat = FXCodec_8bppGray;
1173       break;
1174     case FXDIB_Format::kRgb:
1175       m_SrcComponents = 3;
1176       m_SrcFormat = FXCodec_Rgb;
1177       break;
1178     case FXDIB_Format::kRgb32:
1179     case FXDIB_Format::kArgb:
1180       m_SrcComponents = 4;
1181       m_SrcFormat = FXCodec_Argb;
1182       break;
1183     default: {
1184       m_pDeviceBitmap = nullptr;
1185       m_pFile = nullptr;
1186       m_status = FXCODEC_STATUS::kError;
1187       return m_status;
1188     }
1189   }
1190   GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
1191   int scanline_size = FxAlignToBoundary<4>(m_SrcWidth * m_SrcComponents);
1192   m_DecodeBuf.resize(scanline_size);
1193   m_WeightHorzOO.CalculateWeights(m_sizeX, m_clipBox.Width());
1194   m_WeightVert.CalculateWeights(m_sizeY, m_clipBox.Height());
1195   m_status = FXCODEC_STATUS::kDecodeToBeContinued;
1196   return m_status;
1197 }
1198 
PngContinueDecode()1199 FXCODEC_STATUS ProgressiveDecoder::PngContinueDecode() {
1200   while (true) {
1201     uint32_t remain_size = (uint32_t)m_pFile->GetSize() - m_offSet;
1202     uint32_t input_size = std::min<uint32_t>(remain_size, kBlockSize);
1203     if (input_size == 0) {
1204       m_pPngContext.reset();
1205       m_pDeviceBitmap = nullptr;
1206       m_pFile = nullptr;
1207       m_status = FXCODEC_STATUS::kDecodeFinished;
1208       return m_status;
1209     }
1210     if (m_pCodecMemory && input_size > m_pCodecMemory->GetSize())
1211       m_pCodecMemory = pdfium::MakeRetain<CFX_CodecMemory>(input_size);
1212 
1213     bool bResult = m_pFile->ReadBlockAtOffset(
1214         m_pCodecMemory->GetBufferSpan().first(input_size), m_offSet);
1215     if (!bResult) {
1216       m_pDeviceBitmap = nullptr;
1217       m_pFile = nullptr;
1218       m_status = FXCODEC_STATUS::kError;
1219       return m_status;
1220     }
1221     m_offSet += input_size;
1222     bResult = PngDecoder::ContinueDecode(m_pPngContext.get(), m_pCodecMemory,
1223                                          nullptr);
1224     if (!bResult) {
1225       m_pDeviceBitmap = nullptr;
1226       m_pFile = nullptr;
1227       m_status = FXCODEC_STATUS::kError;
1228       return m_status;
1229     }
1230   }
1231 }
1232 #endif  // PDF_ENABLE_XFA_PNG
1233 
1234 #ifdef PDF_ENABLE_XFA_TIFF
TiffDetectImageTypeFromFile(CFX_DIBAttribute * pAttribute)1235 bool ProgressiveDecoder::TiffDetectImageTypeFromFile(
1236     CFX_DIBAttribute* pAttribute) {
1237   m_pTiffContext = TiffDecoder::CreateDecoder(m_pFile);
1238   if (!m_pTiffContext) {
1239     m_status = FXCODEC_STATUS::kError;
1240     return false;
1241   }
1242   int32_t dummy_bpc;
1243   bool ret = TiffDecoder::LoadFrameInfo(m_pTiffContext.get(), 0, &m_SrcWidth,
1244                                         &m_SrcHeight, &m_SrcComponents,
1245                                         &dummy_bpc, pAttribute);
1246   m_SrcComponents = 4;
1247   m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
1248   if (!ret) {
1249     m_pTiffContext.reset();
1250     m_status = FXCODEC_STATUS::kError;
1251     return false;
1252   }
1253   return true;
1254 }
1255 
TiffContinueDecode()1256 FXCODEC_STATUS ProgressiveDecoder::TiffContinueDecode() {
1257   bool ret = false;
1258   if (m_pDeviceBitmap->GetBPP() == 32 &&
1259       m_pDeviceBitmap->GetWidth() == m_SrcWidth && m_SrcWidth == m_sizeX &&
1260       m_pDeviceBitmap->GetHeight() == m_SrcHeight && m_SrcHeight == m_sizeY &&
1261       m_startX == 0 && m_startY == 0 && m_clipBox.left == 0 &&
1262       m_clipBox.top == 0 && m_clipBox.right == m_SrcWidth &&
1263       m_clipBox.bottom == m_SrcHeight) {
1264     ret = TiffDecoder::Decode(m_pTiffContext.get(), m_pDeviceBitmap);
1265     m_pDeviceBitmap = nullptr;
1266     m_pFile = nullptr;
1267     if (!ret) {
1268       m_status = FXCODEC_STATUS::kError;
1269       return m_status;
1270     }
1271     m_status = FXCODEC_STATUS::kDecodeFinished;
1272     return m_status;
1273   }
1274 
1275   auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1276   pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Format::kArgb);
1277   if (pDIBitmap->GetBuffer().empty()) {
1278     m_pDeviceBitmap = nullptr;
1279     m_pFile = nullptr;
1280     m_status = FXCODEC_STATUS::kError;
1281     return m_status;
1282   }
1283   ret = TiffDecoder::Decode(m_pTiffContext.get(), pDIBitmap);
1284   if (!ret) {
1285     m_pDeviceBitmap = nullptr;
1286     m_pFile = nullptr;
1287     m_status = FXCODEC_STATUS::kError;
1288     return m_status;
1289   }
1290   RetainPtr<CFX_DIBitmap> pClipBitmap =
1291       (m_clipBox.left == 0 && m_clipBox.top == 0 &&
1292        m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight)
1293           ? pDIBitmap
1294           : pDIBitmap->ClipTo(m_clipBox);
1295   if (!pClipBitmap) {
1296     m_pDeviceBitmap = nullptr;
1297     m_pFile = nullptr;
1298     m_status = FXCODEC_STATUS::kError;
1299     return m_status;
1300   }
1301   RetainPtr<CFX_DIBitmap> pFormatBitmap;
1302   switch (m_pDeviceBitmap->GetFormat()) {
1303     case FXDIB_Format::k8bppRgb:
1304       pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1305       pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1306                             FXDIB_Format::k8bppRgb);
1307       break;
1308     case FXDIB_Format::k8bppMask:
1309       pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1310       pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1311                             FXDIB_Format::k8bppMask);
1312       break;
1313     case FXDIB_Format::kRgb:
1314       pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1315       pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1316                             FXDIB_Format::kRgb);
1317       break;
1318     case FXDIB_Format::kRgb32:
1319       pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1320       pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1321                             FXDIB_Format::kRgb32);
1322       break;
1323     case FXDIB_Format::kArgb:
1324       pFormatBitmap = pClipBitmap;
1325       break;
1326     default:
1327       break;
1328   }
1329   switch (m_pDeviceBitmap->GetFormat()) {
1330     case FXDIB_Format::k8bppRgb:
1331     case FXDIB_Format::k8bppMask: {
1332       for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) {
1333         const uint8_t* src_line = pClipBitmap->GetScanline(row).data();
1334         uint8_t* dest_line = pFormatBitmap->GetWritableScanline(row).data();
1335         for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) {
1336           uint8_t _a = 255 - src_line[3];
1337           uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
1338           uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
1339           uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255;
1340           *dest_line++ = FXRGB2GRAY(r, g, b);
1341           src_line += 4;
1342         }
1343       }
1344     } break;
1345     case FXDIB_Format::kRgb:
1346     case FXDIB_Format::kRgb32: {
1347       int32_t desBpp =
1348           (m_pDeviceBitmap->GetFormat() == FXDIB_Format::kRgb) ? 3 : 4;
1349       for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) {
1350         const uint8_t* src_line = pClipBitmap->GetScanline(row).data();
1351         uint8_t* dest_line = pFormatBitmap->GetWritableScanline(row).data();
1352         for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) {
1353           uint8_t _a = 255 - src_line[3];
1354           uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
1355           uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
1356           uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255;
1357           *dest_line++ = b;
1358           *dest_line++ = g;
1359           *dest_line++ = r;
1360           dest_line += desBpp - 3;
1361           src_line += 4;
1362         }
1363       }
1364     } break;
1365     default:
1366       break;
1367   }
1368   if (!pFormatBitmap) {
1369     m_pDeviceBitmap = nullptr;
1370     m_pFile = nullptr;
1371     m_status = FXCODEC_STATUS::kError;
1372     return m_status;
1373   }
1374 
1375   FXDIB_ResampleOptions options;
1376   options.bInterpolateBilinear = true;
1377   RetainPtr<CFX_DIBitmap> pStrechBitmap =
1378       pFormatBitmap->StretchTo(m_sizeX, m_sizeY, options, nullptr);
1379   pFormatBitmap = nullptr;
1380   if (!pStrechBitmap) {
1381     m_pDeviceBitmap = nullptr;
1382     m_pFile = nullptr;
1383     m_status = FXCODEC_STATUS::kError;
1384     return m_status;
1385   }
1386   m_pDeviceBitmap->TransferBitmap(m_startX, m_startY, m_sizeX, m_sizeY,
1387                                   pStrechBitmap, 0, 0);
1388   m_pDeviceBitmap = nullptr;
1389   m_pFile = nullptr;
1390   m_status = FXCODEC_STATUS::kDecodeFinished;
1391   return m_status;
1392 }
1393 #endif  // PDF_ENABLE_XFA_TIFF
1394 
DetectImageType(FXCODEC_IMAGE_TYPE imageType,CFX_DIBAttribute * pAttribute)1395 bool ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType,
1396                                          CFX_DIBAttribute* pAttribute) {
1397 #ifdef PDF_ENABLE_XFA_TIFF
1398   if (imageType == FXCODEC_IMAGE_TIFF)
1399     return TiffDetectImageTypeFromFile(pAttribute);
1400 #endif  // PDF_ENABLE_XFA_TIFF
1401 
1402   size_t size = pdfium::base::checked_cast<size_t>(
1403       std::min<FX_FILESIZE>(m_pFile->GetSize(), kBlockSize));
1404   m_pCodecMemory = pdfium::MakeRetain<CFX_CodecMemory>(size);
1405   m_offSet = 0;
1406   if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBufferSpan().first(size),
1407                                   m_offSet)) {
1408     m_status = FXCODEC_STATUS::kError;
1409     return false;
1410   }
1411   m_offSet += size;
1412 
1413   if (imageType == FXCODEC_IMAGE_JPG)
1414     return JpegDetectImageTypeInBuffer(pAttribute);
1415 
1416 #ifdef PDF_ENABLE_XFA_BMP
1417   if (imageType == FXCODEC_IMAGE_BMP)
1418     return BmpDetectImageTypeInBuffer(pAttribute);
1419 #endif  // PDF_ENABLE_XFA_BMP
1420 
1421 #ifdef PDF_ENABLE_XFA_GIF
1422   if (imageType == FXCODEC_IMAGE_GIF)
1423     return GifDetectImageTypeInBuffer();
1424 #endif  // PDF_ENABLE_XFA_GIF
1425 
1426 #ifdef PDF_ENABLE_XFA_PNG
1427   if (imageType == FXCODEC_IMAGE_PNG)
1428     return PngDetectImageTypeInBuffer(pAttribute);
1429 #endif  // PDF_ENABLE_XFA_PNG
1430 
1431   m_status = FXCODEC_STATUS::kError;
1432   return false;
1433 }
1434 
ReadMoreData(ProgressiveDecoderIface * pModule,ProgressiveDecoderIface::Context * pContext,FXCODEC_STATUS * err_status)1435 bool ProgressiveDecoder::ReadMoreData(
1436     ProgressiveDecoderIface* pModule,
1437     ProgressiveDecoderIface::Context* pContext,
1438     FXCODEC_STATUS* err_status) {
1439   // Check for EOF.
1440   if (m_offSet >= static_cast<uint32_t>(m_pFile->GetSize()))
1441     return false;
1442 
1443   // Try to get whatever remains.
1444   uint32_t dwBytesToFetchFromFile =
1445       pdfium::base::checked_cast<uint32_t>(m_pFile->GetSize() - m_offSet);
1446 
1447   // Figure out if the codec stopped processing midway through the buffer.
1448   size_t dwUnconsumed;
1449   FX_SAFE_SIZE_T avail_input = pModule->GetAvailInput(pContext);
1450   if (!avail_input.AssignIfValid(&dwUnconsumed))
1451     return false;
1452 
1453   if (dwUnconsumed == m_pCodecMemory->GetSize()) {
1454     // Codec couldn't make any progress against the bytes in the buffer.
1455     // Increase the buffer size so that there might be enough contiguous
1456     // bytes to allow whatever operation is having difficulty to succeed.
1457     dwBytesToFetchFromFile =
1458         std::min<uint32_t>(dwBytesToFetchFromFile, kBlockSize);
1459     size_t dwNewSize = m_pCodecMemory->GetSize() + dwBytesToFetchFromFile;
1460     if (!m_pCodecMemory->TryResize(dwNewSize)) {
1461       *err_status = FXCODEC_STATUS::kError;
1462       return false;
1463     }
1464   } else {
1465     // TODO(crbug.com/pdfium/1904): Simplify the `CFX_CodecMemory` API so we
1466     // don't need to do this awkward dance to free up exactly enough buffer
1467     // space for the next read.
1468     size_t dwConsumable = m_pCodecMemory->GetSize() - dwUnconsumed;
1469     dwBytesToFetchFromFile = pdfium::base::checked_cast<uint32_t>(
1470         std::min<size_t>(dwBytesToFetchFromFile, dwConsumable));
1471     m_pCodecMemory->Consume(dwBytesToFetchFromFile);
1472     m_pCodecMemory->Seek(dwConsumable - dwBytesToFetchFromFile);
1473     dwUnconsumed += m_pCodecMemory->GetPosition();
1474   }
1475 
1476   // Append new data past the bytes not yet processed by the codec.
1477   if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBufferSpan().subspan(
1478                                       dwUnconsumed, dwBytesToFetchFromFile),
1479                                   m_offSet)) {
1480     *err_status = FXCODEC_STATUS::kError;
1481     return false;
1482   }
1483   m_offSet += dwBytesToFetchFromFile;
1484   return pModule->Input(pContext, m_pCodecMemory);
1485 }
1486 
LoadImageInfo(RetainPtr<IFX_SeekableReadStream> pFile,FXCODEC_IMAGE_TYPE imageType,CFX_DIBAttribute * pAttribute,bool bSkipImageTypeCheck)1487 FXCODEC_STATUS ProgressiveDecoder::LoadImageInfo(
1488     RetainPtr<IFX_SeekableReadStream> pFile,
1489     FXCODEC_IMAGE_TYPE imageType,
1490     CFX_DIBAttribute* pAttribute,
1491     bool bSkipImageTypeCheck) {
1492   DCHECK(pAttribute);
1493 
1494   switch (m_status) {
1495     case FXCODEC_STATUS::kFrameReady:
1496     case FXCODEC_STATUS::kFrameToBeContinued:
1497     case FXCODEC_STATUS::kDecodeReady:
1498     case FXCODEC_STATUS::kDecodeToBeContinued:
1499       return FXCODEC_STATUS::kError;
1500     default:
1501       break;
1502   }
1503   m_pFile = std::move(pFile);
1504   if (!m_pFile) {
1505     m_status = FXCODEC_STATUS::kError;
1506     return m_status;
1507   }
1508   m_offSet = 0;
1509   m_SrcWidth = m_SrcHeight = 0;
1510   m_SrcComponents = m_SrcBPC = 0;
1511   m_clipBox = FX_RECT();
1512   m_startX = m_startY = 0;
1513   m_sizeX = m_sizeY = 0;
1514   m_SrcPassNumber = 0;
1515   if (imageType != FXCODEC_IMAGE_UNKNOWN &&
1516       DetectImageType(imageType, pAttribute)) {
1517     m_imageType = imageType;
1518     m_status = FXCODEC_STATUS::kFrameReady;
1519     return m_status;
1520   }
1521   // If we got here then the image data does not match the requested decoder.
1522   // If we're skipping the type check then bail out at this point and return
1523   // the failed status.
1524   if (bSkipImageTypeCheck)
1525     return m_status;
1526 
1527   for (int type = FXCODEC_IMAGE_UNKNOWN + 1; type < FXCODEC_IMAGE_MAX; type++) {
1528     if (DetectImageType(static_cast<FXCODEC_IMAGE_TYPE>(type), pAttribute)) {
1529       m_imageType = static_cast<FXCODEC_IMAGE_TYPE>(type);
1530       m_status = FXCODEC_STATUS::kFrameReady;
1531       return m_status;
1532     }
1533   }
1534   m_status = FXCODEC_STATUS::kError;
1535   m_pFile = nullptr;
1536   return m_status;
1537 }
1538 
SetClipBox(FX_RECT * clip)1539 void ProgressiveDecoder::SetClipBox(FX_RECT* clip) {
1540   if (m_status != FXCODEC_STATUS::kFrameReady)
1541     return;
1542 
1543   if (clip->IsEmpty()) {
1544     m_clipBox = FX_RECT();
1545     return;
1546   }
1547   clip->left = std::max(clip->left, 0);
1548   clip->right = std::min(clip->right, m_SrcWidth);
1549   clip->top = std::max(clip->top, 0);
1550   clip->bottom = std::min(clip->bottom, m_SrcHeight);
1551   if (clip->IsEmpty()) {
1552     m_clipBox = FX_RECT();
1553     return;
1554   }
1555   m_clipBox = *clip;
1556 }
1557 
GetDownScale()1558 int ProgressiveDecoder::GetDownScale() {
1559   int down_scale = 1;
1560   int ratio_w = m_clipBox.Width() / m_sizeX;
1561   int ratio_h = m_clipBox.Height() / m_sizeY;
1562   int ratio = std::min(ratio_w, ratio_h);
1563   if (ratio >= 8)
1564     down_scale = 8;
1565   else if (ratio >= 4)
1566     down_scale = 4;
1567   else if (ratio >= 2)
1568     down_scale = 2;
1569 
1570   m_clipBox.left /= down_scale;
1571   m_clipBox.right /= down_scale;
1572   m_clipBox.top /= down_scale;
1573   m_clipBox.bottom /= down_scale;
1574   if (m_clipBox.right == m_clipBox.left)
1575     m_clipBox.right = m_clipBox.left + 1;
1576   if (m_clipBox.bottom == m_clipBox.top)
1577     m_clipBox.bottom = m_clipBox.top + 1;
1578   return down_scale;
1579 }
1580 
GetTransMethod(FXDIB_Format dest_format,FXCodec_Format src_format)1581 void ProgressiveDecoder::GetTransMethod(FXDIB_Format dest_format,
1582                                         FXCodec_Format src_format) {
1583   switch (dest_format) {
1584     case FXDIB_Format::k1bppMask:
1585     case FXDIB_Format::k1bppRgb: {
1586       switch (src_format) {
1587         case FXCodec_1bppGray:
1588           m_TransMethod = 0;
1589           break;
1590         default:
1591           m_TransMethod = -1;
1592       }
1593     } break;
1594     case FXDIB_Format::k8bppMask:
1595     case FXDIB_Format::k8bppRgb: {
1596       switch (src_format) {
1597         case FXCodec_1bppGray:
1598           m_TransMethod = 1;
1599           break;
1600         case FXCodec_8bppGray:
1601           m_TransMethod = 2;
1602           break;
1603         case FXCodec_1bppRgb:
1604         case FXCodec_8bppRgb:
1605           m_TransMethod = 3;
1606           break;
1607         case FXCodec_Rgb:
1608         case FXCodec_Rgb32:
1609         case FXCodec_Argb:
1610           m_TransMethod = 4;
1611           break;
1612         case FXCodec_Cmyk:
1613           m_TransMethod = 5;
1614           break;
1615         default:
1616           m_TransMethod = -1;
1617       }
1618     } break;
1619     case FXDIB_Format::kRgb: {
1620       switch (src_format) {
1621         case FXCodec_1bppGray:
1622           m_TransMethod = 6;
1623           break;
1624         case FXCodec_8bppGray:
1625           m_TransMethod = 7;
1626           break;
1627         case FXCodec_1bppRgb:
1628         case FXCodec_8bppRgb:
1629           m_TransMethod = 8;
1630           break;
1631         case FXCodec_Rgb:
1632         case FXCodec_Rgb32:
1633         case FXCodec_Argb:
1634           m_TransMethod = 9;
1635           break;
1636         case FXCodec_Cmyk:
1637           m_TransMethod = 10;
1638           break;
1639         default:
1640           m_TransMethod = -1;
1641       }
1642     } break;
1643     case FXDIB_Format::kRgb32:
1644     case FXDIB_Format::kArgb: {
1645       switch (src_format) {
1646         case FXCodec_1bppGray:
1647           m_TransMethod = 6;
1648           break;
1649         case FXCodec_8bppGray:
1650           m_TransMethod = 7;
1651           break;
1652         case FXCodec_1bppRgb:
1653         case FXCodec_8bppRgb:
1654           if (dest_format == FXDIB_Format::kArgb) {
1655             m_TransMethod = 12;
1656           } else {
1657             m_TransMethod = 8;
1658           }
1659           break;
1660         case FXCodec_Rgb:
1661         case FXCodec_Rgb32:
1662           m_TransMethod = 9;
1663           break;
1664         case FXCodec_Cmyk:
1665           m_TransMethod = 10;
1666           break;
1667         case FXCodec_Argb:
1668           m_TransMethod = 11;
1669           break;
1670         default:
1671           m_TransMethod = -1;
1672       }
1673     } break;
1674     default:
1675       m_TransMethod = -1;
1676   }
1677 }
1678 
ResampleScanline(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,int dest_line,pdfium::span<uint8_t> src_span,FXCodec_Format src_format)1679 void ProgressiveDecoder::ResampleScanline(
1680     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1681     int dest_line,
1682     pdfium::span<uint8_t> src_span,
1683     FXCodec_Format src_format) {
1684   uint8_t* src_scan = src_span.data();
1685   int src_left = m_clipBox.left;
1686   int dest_left = m_startX;
1687   uint8_t* dest_scan = pDeviceBitmap->GetWritableScanline(dest_line).data();
1688   int src_bytes_per_pixel = (src_format & 0xff) / 8;
1689   int dest_bytes_per_pixel = pDeviceBitmap->GetBPP() / 8;
1690   src_scan += src_left * src_bytes_per_pixel;
1691   dest_scan += dest_left * dest_bytes_per_pixel;
1692   for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1693     PixelWeight* pPixelWeights = m_WeightHorz.GetPixelWeight(dest_col);
1694     switch (m_TransMethod) {
1695       case -1:
1696         return;
1697       case 0:
1698         return;
1699       case 1:
1700         return;
1701       case 2: {
1702         uint32_t dest_g = 0;
1703         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1704              j++) {
1705           uint32_t pixel_weight =
1706               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1707           dest_g += pixel_weight * src_scan[j];
1708         }
1709         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1710       } break;
1711       case 3: {
1712         uint32_t dest_r = 0;
1713         uint32_t dest_g = 0;
1714         uint32_t dest_b = 0;
1715         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1716              j++) {
1717           uint32_t pixel_weight =
1718               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1719           uint32_t argb = m_SrcPalette[src_scan[j]];
1720           dest_r += pixel_weight * FXARGB_R(argb);
1721           dest_g += pixel_weight * FXARGB_G(argb);
1722           dest_b += pixel_weight * FXARGB_B(argb);
1723         }
1724         *dest_scan++ = static_cast<uint8_t>(
1725             FXRGB2GRAY(CStretchEngine::PixelFromFixed(dest_r),
1726                        CStretchEngine::PixelFromFixed(dest_g),
1727                        CStretchEngine::PixelFromFixed(dest_b)));
1728       } break;
1729       case 4: {
1730         uint32_t dest_b = 0;
1731         uint32_t dest_g = 0;
1732         uint32_t dest_r = 0;
1733         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1734              j++) {
1735           uint32_t pixel_weight =
1736               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1737           const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1738           dest_b += pixel_weight * (*src_pixel++);
1739           dest_g += pixel_weight * (*src_pixel++);
1740           dest_r += pixel_weight * (*src_pixel);
1741         }
1742         *dest_scan++ = static_cast<uint8_t>(
1743             FXRGB2GRAY(CStretchEngine::PixelFromFixed(dest_r),
1744                        CStretchEngine::PixelFromFixed(dest_g),
1745                        CStretchEngine::PixelFromFixed(dest_b)));
1746       } break;
1747       case 5: {
1748         uint32_t dest_b = 0;
1749         uint32_t dest_g = 0;
1750         uint32_t dest_r = 0;
1751         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1752              j++) {
1753           uint32_t pixel_weight =
1754               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1755           const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1756           uint8_t src_b = 0;
1757           uint8_t src_g = 0;
1758           uint8_t src_r = 0;
1759           std::tie(src_r, src_g, src_b) =
1760               AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1],
1761                                  255 - src_pixel[2], 255 - src_pixel[3]);
1762           dest_b += pixel_weight * src_b;
1763           dest_g += pixel_weight * src_g;
1764           dest_r += pixel_weight * src_r;
1765         }
1766         *dest_scan++ = static_cast<uint8_t>(
1767             FXRGB2GRAY(CStretchEngine::PixelFromFixed(dest_r),
1768                        CStretchEngine::PixelFromFixed(dest_g),
1769                        CStretchEngine::PixelFromFixed(dest_b)));
1770       } break;
1771       case 6:
1772         return;
1773       case 7: {
1774         uint32_t dest_g = 0;
1775         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1776              j++) {
1777           uint32_t pixel_weight =
1778               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1779           dest_g += pixel_weight * src_scan[j];
1780         }
1781         memset(dest_scan, CStretchEngine::PixelFromFixed(dest_g), 3);
1782         dest_scan += dest_bytes_per_pixel;
1783       } break;
1784       case 8: {
1785         uint32_t dest_r = 0;
1786         uint32_t dest_g = 0;
1787         uint32_t dest_b = 0;
1788         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1789              j++) {
1790           uint32_t pixel_weight =
1791               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1792           uint32_t argb = m_SrcPalette[src_scan[j]];
1793           dest_r += pixel_weight * FXARGB_R(argb);
1794           dest_g += pixel_weight * FXARGB_G(argb);
1795           dest_b += pixel_weight * FXARGB_B(argb);
1796         }
1797         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1798         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1799         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1800         dest_scan += dest_bytes_per_pixel - 3;
1801       } break;
1802       case 12: {
1803 #ifdef PDF_ENABLE_XFA_BMP
1804         if (m_pBmpContext) {
1805           uint32_t dest_r = 0;
1806           uint32_t dest_g = 0;
1807           uint32_t dest_b = 0;
1808           for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1809                j++) {
1810             uint32_t pixel_weight =
1811                 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1812             uint32_t argb = m_SrcPalette[src_scan[j]];
1813             dest_r += pixel_weight * FXARGB_R(argb);
1814             dest_g += pixel_weight * FXARGB_G(argb);
1815             dest_b += pixel_weight * FXARGB_B(argb);
1816           }
1817           *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1818           *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1819           *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1820           *dest_scan++ = 0xFF;
1821           break;
1822         }
1823 #endif  // PDF_ENABLE_XFA_BMP
1824         uint32_t dest_a = 0;
1825         uint32_t dest_r = 0;
1826         uint32_t dest_g = 0;
1827         uint32_t dest_b = 0;
1828         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1829              j++) {
1830           uint32_t pixel_weight =
1831               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1832           unsigned long argb = m_SrcPalette[src_scan[j]];
1833           dest_a += pixel_weight * FXARGB_A(argb);
1834           dest_r += pixel_weight * FXARGB_R(argb);
1835           dest_g += pixel_weight * FXARGB_G(argb);
1836           dest_b += pixel_weight * FXARGB_B(argb);
1837         }
1838         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1839         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1840         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1841         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_a);
1842       } break;
1843       case 9: {
1844         uint32_t dest_b = 0;
1845         uint32_t dest_g = 0;
1846         uint32_t dest_r = 0;
1847         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1848              j++) {
1849           uint32_t pixel_weight =
1850               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1851           const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1852           dest_b += pixel_weight * (*src_pixel++);
1853           dest_g += pixel_weight * (*src_pixel++);
1854           dest_r += pixel_weight * (*src_pixel);
1855         }
1856         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1857         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1858         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1859         dest_scan += dest_bytes_per_pixel - 3;
1860       } break;
1861       case 10: {
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           uint32_t 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++ = CStretchEngine::PixelFromFixed(dest_b);
1881         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1882         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1883         dest_scan += dest_bytes_per_pixel - 3;
1884       } break;
1885       case 11: {
1886         uint32_t dest_alpha = 0;
1887         uint32_t dest_r = 0;
1888         uint32_t dest_g = 0;
1889         uint32_t dest_b = 0;
1890         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1891              j++) {
1892           uint32_t pixel_weight =
1893               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1894           const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1895           pixel_weight = pixel_weight * src_pixel[3] / 255;
1896           dest_b += pixel_weight * (*src_pixel++);
1897           dest_g += pixel_weight * (*src_pixel++);
1898           dest_r += pixel_weight * (*src_pixel);
1899           dest_alpha += pixel_weight;
1900         }
1901         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1902         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1903         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1904         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_alpha * 255);
1905       } break;
1906       default:
1907         return;
1908     }
1909   }
1910 }
1911 
ResampleVert(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,double scale_y,int dest_row)1912 void ProgressiveDecoder::ResampleVert(
1913     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1914     double scale_y,
1915     int dest_row) {
1916   int dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
1917   uint32_t dest_ScanOffset = m_startX * dest_Bpp;
1918   int dest_top = m_startY;
1919   FX_SAFE_INT32 check_dest_row_1 = dest_row;
1920   check_dest_row_1 -= pdfium::base::checked_cast<int>(scale_y);
1921   int dest_row_1 = check_dest_row_1.ValueOrDie();
1922   if (dest_row_1 < dest_top) {
1923     int dest_bottom = dest_top + m_sizeY;
1924     if (dest_row + (int)scale_y >= dest_bottom - 1) {
1925       pdfium::span<const uint8_t> scan_src =
1926           pDeviceBitmap->GetScanline(dest_row).subspan(dest_ScanOffset,
1927                                                        m_sizeX * dest_Bpp);
1928       while (++dest_row < dest_bottom) {
1929         fxcrt::spanmove(pDeviceBitmap->GetWritableScanline(dest_row).subspan(
1930                             dest_ScanOffset),
1931                         scan_src);
1932       }
1933     }
1934     return;
1935   }
1936   for (; dest_row_1 < dest_row; dest_row_1++) {
1937     uint8_t* scan_des = pDeviceBitmap->GetWritableScanline(dest_row_1)
1938                             .subspan(dest_ScanOffset)
1939                             .data();
1940     PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top);
1941     const uint8_t* scan_src1 =
1942         pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top)
1943             .subspan(dest_ScanOffset)
1944             .data();
1945     const uint8_t* scan_src2 =
1946         pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top)
1947             .subspan(dest_ScanOffset)
1948             .data();
1949     switch (pDeviceBitmap->GetFormat()) {
1950       case FXDIB_Format::kInvalid:
1951       case FXDIB_Format::k1bppMask:
1952       case FXDIB_Format::k1bppRgb:
1953         return;
1954       case FXDIB_Format::k8bppMask:
1955       case FXDIB_Format::k8bppRgb:
1956         if (pDeviceBitmap->HasPalette())
1957           return;
1958         for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1959           uint32_t dest_g = 0;
1960           dest_g += pWeight->m_Weights[0] * (*scan_src1++);
1961           dest_g += pWeight->m_Weights[1] * (*scan_src2++);
1962           *scan_des++ = CStretchEngine::PixelFromFixed(dest_g);
1963         }
1964         break;
1965       case FXDIB_Format::kRgb:
1966       case FXDIB_Format::kRgb32:
1967         for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1968           uint32_t dest_b = pWeight->m_Weights[0] * (*scan_src1++);
1969           uint32_t dest_g = pWeight->m_Weights[0] * (*scan_src1++);
1970           uint32_t dest_r = pWeight->m_Weights[0] * (*scan_src1++);
1971           scan_src1 += dest_Bpp - 3;
1972           dest_b += pWeight->m_Weights[1] * (*scan_src2++);
1973           dest_g += pWeight->m_Weights[1] * (*scan_src2++);
1974           dest_r += pWeight->m_Weights[1] * (*scan_src2++);
1975           scan_src2 += dest_Bpp - 3;
1976           *scan_des++ = CStretchEngine::PixelFromFixed(dest_b);
1977           *scan_des++ = CStretchEngine::PixelFromFixed(dest_g);
1978           *scan_des++ = CStretchEngine::PixelFromFixed(dest_r);
1979           scan_des += dest_Bpp - 3;
1980         }
1981         break;
1982       case FXDIB_Format::kArgb:
1983         for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1984           uint32_t dest_b = pWeight->m_Weights[0] * (*scan_src1++);
1985           uint32_t dest_g = pWeight->m_Weights[0] * (*scan_src1++);
1986           uint32_t dest_r = pWeight->m_Weights[0] * (*scan_src1++);
1987           uint32_t dest_a = pWeight->m_Weights[0] * (*scan_src1++);
1988           dest_b += pWeight->m_Weights[1] * (*scan_src2++);
1989           dest_g += pWeight->m_Weights[1] * (*scan_src2++);
1990           dest_r += pWeight->m_Weights[1] * (*scan_src2++);
1991           dest_a += pWeight->m_Weights[1] * (*scan_src2++);
1992           *scan_des++ = CStretchEngine::PixelFromFixed(dest_b);
1993           *scan_des++ = CStretchEngine::PixelFromFixed(dest_g);
1994           *scan_des++ = CStretchEngine::PixelFromFixed(dest_r);
1995           *scan_des++ = CStretchEngine::PixelFromFixed(dest_a);
1996         }
1997         break;
1998     }
1999   }
2000   int dest_bottom = dest_top + m_sizeY;
2001   if (dest_row + (int)scale_y >= dest_bottom - 1) {
2002     pdfium::span<const uint8_t> scan_src =
2003         pDeviceBitmap->GetScanline(dest_row).subspan(dest_ScanOffset,
2004                                                      m_sizeX * dest_Bpp);
2005     while (++dest_row < dest_bottom) {
2006       fxcrt::spanmove(
2007           pDeviceBitmap->GetWritableScanline(dest_row).subspan(dest_ScanOffset),
2008           scan_src);
2009     }
2010   }
2011 }
2012 
Resample(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,int32_t src_line,uint8_t * src_scan,FXCodec_Format src_format)2013 void ProgressiveDecoder::Resample(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
2014                                   int32_t src_line,
2015                                   uint8_t* src_scan,
2016                                   FXCodec_Format src_format) {
2017   int src_top = m_clipBox.top;
2018   int dest_top = m_startY;
2019   int src_height = m_clipBox.Height();
2020   int dest_height = m_sizeY;
2021   if (src_line >= src_top) {
2022     double scale_y = static_cast<double>(dest_height) / src_height;
2023     int src_row = src_line - src_top;
2024     int dest_row = (int)(src_row * scale_y) + dest_top;
2025     if (dest_row >= dest_top + dest_height)
2026       return;
2027 
2028     ResampleScanline(pDeviceBitmap, dest_row, m_DecodeBuf, src_format);
2029     if (scale_y > 1.0)
2030       ResampleVert(pDeviceBitmap, scale_y, dest_row);
2031   }
2032 }
2033 
GetFrames()2034 std::pair<FXCODEC_STATUS, size_t> ProgressiveDecoder::GetFrames() {
2035   if (!(m_status == FXCODEC_STATUS::kFrameReady ||
2036         m_status == FXCODEC_STATUS::kFrameToBeContinued)) {
2037     return {FXCODEC_STATUS::kError, 0};
2038   }
2039 
2040   switch (m_imageType) {
2041 #ifdef PDF_ENABLE_XFA_BMP
2042     case FXCODEC_IMAGE_BMP:
2043 #endif  // PDF_ENABLE_XFA_BMP
2044     case FXCODEC_IMAGE_JPG:
2045 #ifdef PDF_ENABLE_XFA_PNG
2046     case FXCODEC_IMAGE_PNG:
2047 #endif  // PDF_ENABLE_XFA_PNG
2048 #ifdef PDF_ENABLE_XFA_TIFF
2049     case FXCODEC_IMAGE_TIFF:
2050 #endif  // PDF_ENABLE_XFA_TIFF
2051       m_FrameNumber = 1;
2052       m_status = FXCODEC_STATUS::kDecodeReady;
2053       return {m_status, 1};
2054 #ifdef PDF_ENABLE_XFA_GIF
2055     case FXCODEC_IMAGE_GIF: {
2056       while (true) {
2057         GifDecoder::Status readResult;
2058         std::tie(readResult, m_FrameNumber) =
2059             GifDecoder::LoadFrameInfo(m_pGifContext.get());
2060         while (readResult == GifDecoder::Status::kUnfinished) {
2061           FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
2062           if (!GifReadMoreData(&error_status))
2063             return {error_status, 0};
2064 
2065           std::tie(readResult, m_FrameNumber) =
2066               GifDecoder::LoadFrameInfo(m_pGifContext.get());
2067         }
2068         if (readResult == GifDecoder::Status::kSuccess) {
2069           m_status = FXCODEC_STATUS::kDecodeReady;
2070           return {m_status, m_FrameNumber};
2071         }
2072         m_pGifContext = nullptr;
2073         m_status = FXCODEC_STATUS::kError;
2074         return {m_status, 0};
2075       }
2076     }
2077 #endif  // PDF_ENABLE_XFA_GIF
2078     default:
2079       return {FXCODEC_STATUS::kError, 0};
2080   }
2081 }
2082 
StartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap,int start_x,int start_y,int size_x,int size_y)2083 FXCODEC_STATUS ProgressiveDecoder::StartDecode(
2084     const RetainPtr<CFX_DIBitmap>& pDIBitmap,
2085     int start_x,
2086     int start_y,
2087     int size_x,
2088     int size_y) {
2089   if (m_status != FXCODEC_STATUS::kDecodeReady)
2090     return FXCODEC_STATUS::kError;
2091 
2092   if (!pDIBitmap || pDIBitmap->GetBPP() < 8 || m_FrameNumber == 0)
2093     return FXCODEC_STATUS::kError;
2094 
2095   m_pDeviceBitmap = pDIBitmap;
2096   if (m_clipBox.IsEmpty())
2097     return FXCODEC_STATUS::kError;
2098   if (size_x <= 0 || size_x > 65535 || size_y <= 0 || size_y > 65535)
2099     return FXCODEC_STATUS::kError;
2100 
2101   FX_RECT device_rc =
2102       FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y);
2103   int32_t out_range_x = device_rc.right - pDIBitmap->GetWidth();
2104   int32_t out_range_y = device_rc.bottom - pDIBitmap->GetHeight();
2105   device_rc.Intersect(
2106       FX_RECT(0, 0, pDIBitmap->GetWidth(), pDIBitmap->GetHeight()));
2107   if (device_rc.IsEmpty())
2108     return FXCODEC_STATUS::kError;
2109 
2110   m_startX = device_rc.left;
2111   m_startY = device_rc.top;
2112   m_sizeX = device_rc.Width();
2113   m_sizeY = device_rc.Height();
2114   m_FrameCur = 0;
2115   if (start_x < 0 || out_range_x > 0) {
2116     float scaleX = (float)m_clipBox.Width() / (float)size_x;
2117     if (start_x < 0) {
2118       m_clipBox.left -= static_cast<int32_t>(ceil((float)start_x * scaleX));
2119     }
2120     if (out_range_x > 0) {
2121       m_clipBox.right -=
2122           static_cast<int32_t>(floor((float)out_range_x * scaleX));
2123     }
2124   }
2125   if (start_y < 0 || out_range_y > 0) {
2126     float scaleY = (float)m_clipBox.Height() / (float)size_y;
2127     if (start_y < 0) {
2128       m_clipBox.top -= static_cast<int32_t>(ceil((float)start_y * scaleY));
2129     }
2130     if (out_range_y > 0) {
2131       m_clipBox.bottom -=
2132           static_cast<int32_t>(floor((float)out_range_y * scaleY));
2133     }
2134   }
2135   if (m_clipBox.IsEmpty()) {
2136     return FXCODEC_STATUS::kError;
2137   }
2138   switch (m_imageType) {
2139 #ifdef PDF_ENABLE_XFA_BMP
2140     case FXCODEC_IMAGE_BMP:
2141       return BmpStartDecode();
2142 #endif  // PDF_ENABLE_XFA_BMP
2143 #ifdef PDF_ENABLE_XFA_GIF
2144     case FXCODEC_IMAGE_GIF:
2145       return GifStartDecode();
2146 #endif  // PDF_ENABLE_XFA_GIF
2147     case FXCODEC_IMAGE_JPG:
2148       return JpegStartDecode(pDIBitmap->GetFormat());
2149 #ifdef PDF_ENABLE_XFA_PNG
2150     case FXCODEC_IMAGE_PNG:
2151       return PngStartDecode();
2152 #endif  // PDF_ENABLE_XFA_PNG
2153 #ifdef PDF_ENABLE_XFA_TIFF
2154     case FXCODEC_IMAGE_TIFF:
2155       m_status = FXCODEC_STATUS::kDecodeToBeContinued;
2156       return m_status;
2157 #endif  // PDF_ENABLE_XFA_TIFF
2158     default:
2159       return FXCODEC_STATUS::kError;
2160   }
2161 }
2162 
ContinueDecode()2163 FXCODEC_STATUS ProgressiveDecoder::ContinueDecode() {
2164   if (m_status != FXCODEC_STATUS::kDecodeToBeContinued)
2165     return FXCODEC_STATUS::kError;
2166 
2167   switch (m_imageType) {
2168     case FXCODEC_IMAGE_JPG:
2169       return JpegContinueDecode();
2170 #ifdef PDF_ENABLE_XFA_BMP
2171     case FXCODEC_IMAGE_BMP:
2172       return BmpContinueDecode();
2173 #endif  // PDF_ENABLE_XFA_BMP
2174 #ifdef PDF_ENABLE_XFA_GIF
2175     case FXCODEC_IMAGE_GIF:
2176       return GifContinueDecode();
2177 #endif  // PDF_ENABLE_XFA_GIF
2178 #ifdef PDF_ENABLE_XFA_PNG
2179     case FXCODEC_IMAGE_PNG:
2180       return PngContinueDecode();
2181 #endif  // PDF_ENABLE_XFA_PNG
2182 #ifdef PDF_ENABLE_XFA_TIFF
2183     case FXCODEC_IMAGE_TIFF:
2184       return TiffContinueDecode();
2185 #endif  // PDF_ENABLE_XFA_TIFF
2186     default:
2187       return FXCODEC_STATUS::kError;
2188   }
2189 }
2190 
2191 }  // namespace fxcodec
2192