Various changes to JBig2 cache:
[pdfium.git] / core / src / fpdfapi / fpdf_render / fpdf_render_loadimage.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include <vector>
8
9 #include "../../../../third_party/base/nonstd_unique_ptr.h"
10 #include "../../../include/fpdfapi/fpdf_module.h"
11 #include "../../../include/fpdfapi/fpdf_pageobj.h"
12 #include "../../../include/fpdfapi/fpdf_render.h"
13 #include "../../../include/fxcodec/fx_codec.h"
14 #include "../../../include/fxcrt/fx_safe_types.h"
15 #include "../../../include/fxge/fx_ge.h"
16 #include "../fpdf_page/pageint.h"
17 #include "render_int.h"
18
19 namespace {
20
21 unsigned int _GetBits8(const uint8_t* pData, int bitpos, int nbits) {
22   unsigned int byte = pData[bitpos / 8];
23   if (nbits == 8) {
24     return byte;
25   }
26   if (nbits == 4) {
27     return (bitpos % 8) ? (byte & 0x0f) : (byte >> 4);
28   }
29   if (nbits == 2) {
30     return (byte >> (6 - bitpos % 8)) & 0x03;
31   }
32   if (nbits == 1) {
33     return (byte >> (7 - bitpos % 8)) & 0x01;
34   }
35   if (nbits == 16) {
36     return byte * 256 + pData[bitpos / 8 + 1];
37   }
38   return 0;
39 }
40
41 FX_SAFE_DWORD CalculatePitch8(FX_DWORD bpc,
42                               FX_DWORD components,
43                               int width,
44                               int height) {
45   FX_SAFE_DWORD pitch = bpc;
46   pitch *= components;
47   pitch *= width;
48   pitch += 7;
49   pitch /= 8;
50   pitch *= height;
51   return pitch;
52 }
53
54 FX_SAFE_DWORD CalculatePitch32(int bpp, int width) {
55   FX_SAFE_DWORD pitch = bpp;
56   pitch *= width;
57   pitch += 31;
58   pitch /= 8;
59   return pitch;
60 }
61
62 // Wrapper class to use with nonstd::unique_ptr for CJPX_Decoder.
63 class JpxBitMapContext {
64  public:
65   explicit JpxBitMapContext(ICodec_JpxModule* jpx_module)
66       : jpx_module_(jpx_module), decoder_(nullptr) {}
67
68   ~JpxBitMapContext() {
69     jpx_module_->DestroyDecoder(decoder_);
70   }
71
72   // Takes ownership of |decoder|.
73   void set_decoder(CJPX_Decoder* decoder) { decoder_ = decoder; }
74
75   CJPX_Decoder* decoder() { return decoder_; }
76
77  private:
78   ICodec_JpxModule* const jpx_module_;  // Weak pointer.
79   CJPX_Decoder* decoder_;               // Decoder, owned.
80
81   // Disallow evil constructors
82   JpxBitMapContext(const JpxBitMapContext&);
83   void operator=(const JpxBitMapContext&);
84 };
85
86 const int kMaxImageDimension = 0x01FFFF;
87
88 }  // namespace
89
90 CFX_DIBSource* CPDF_Image::LoadDIBSource(CFX_DIBSource** ppMask,
91                                          FX_DWORD* pMatteColor,
92                                          FX_BOOL bStdCS,
93                                          FX_DWORD GroupFamily,
94                                          FX_BOOL bLoadMask) const {
95   CPDF_DIBSource* pSource = new CPDF_DIBSource;
96   if (pSource->Load(m_pDocument, m_pStream, (CPDF_DIBSource**)ppMask,
97                     pMatteColor, NULL, NULL, bStdCS, GroupFamily, bLoadMask)) {
98     return pSource;
99   }
100   delete pSource;
101   return NULL;
102 }
103 CFX_DIBSource* CPDF_Image::DetachBitmap() {
104   CFX_DIBSource* pBitmap = m_pDIBSource;
105   m_pDIBSource = NULL;
106   return pBitmap;
107 }
108 CFX_DIBSource* CPDF_Image::DetachMask() {
109   CFX_DIBSource* pBitmap = m_pMask;
110   m_pMask = NULL;
111   return pBitmap;
112 }
113 FX_BOOL CPDF_Image::StartLoadDIBSource(CPDF_Dictionary* pFormResource,
114                                        CPDF_Dictionary* pPageResource,
115                                        FX_BOOL bStdCS,
116                                        FX_DWORD GroupFamily,
117                                        FX_BOOL bLoadMask) {
118   m_pDIBSource = new CPDF_DIBSource;
119   int ret =
120       ((CPDF_DIBSource*)m_pDIBSource)
121           ->StartLoadDIBSource(m_pDocument, m_pStream, TRUE, pFormResource,
122                                pPageResource, bStdCS, GroupFamily, bLoadMask);
123   if (ret == 2) {
124     return TRUE;
125   }
126   if (!ret) {
127     delete m_pDIBSource;
128     m_pDIBSource = NULL;
129     return FALSE;
130   }
131   m_pMask = ((CPDF_DIBSource*)m_pDIBSource)->DetachMask();
132   m_MatteColor = ((CPDF_DIBSource*)m_pDIBSource)->m_MatteColor;
133   return FALSE;
134 }
135 FX_BOOL CPDF_Image::Continue(IFX_Pause* pPause) {
136   int ret = ((CPDF_DIBSource*)m_pDIBSource)->ContinueLoadDIBSource(pPause);
137   if (ret == 2) {
138     return TRUE;
139   }
140   if (!ret) {
141     delete m_pDIBSource;
142     m_pDIBSource = NULL;
143     return FALSE;
144   }
145   m_pMask = ((CPDF_DIBSource*)m_pDIBSource)->DetachMask();
146   m_MatteColor = ((CPDF_DIBSource*)m_pDIBSource)->m_MatteColor;
147   return FALSE;
148 }
149 CPDF_DIBSource::CPDF_DIBSource() {
150   m_pDocument = NULL;
151   m_pStreamAcc = NULL;
152   m_pDict = NULL;
153   m_bpp = 0;
154   m_Width = m_Height = 0;
155   m_pColorSpace = NULL;
156   m_bDefaultDecode = TRUE;
157   m_bImageMask = FALSE;
158   m_bDoBpcCheck = TRUE;
159   m_pPalette = NULL;
160   m_pCompData = NULL;
161   m_bColorKey = FALSE;
162   m_pMaskedLine = m_pLineBuf = NULL;
163   m_pDecoder = NULL;
164   m_nComponents = 0;
165   m_bpc = 0;
166   m_bLoadMask = FALSE;
167   m_Family = 0;
168   m_pMask = NULL;
169   m_MatteColor = 0;
170   m_pJbig2Context = NULL;
171   m_pGlobalStream = NULL;
172   m_bStdCS = FALSE;
173   m_pMaskStream = NULL;
174   m_Status = 0;
175   m_bHasMask = FALSE;
176 }
177 CPDF_DIBSource::~CPDF_DIBSource() {
178   delete m_pStreamAcc;
179   FX_Free(m_pMaskedLine);
180   FX_Free(m_pLineBuf);
181   m_pCachedBitmap.reset();
182   delete m_pDecoder;
183   FX_Free(m_pCompData);
184   CPDF_ColorSpace* pCS = m_pColorSpace;
185   if (pCS && m_pDocument) {
186     m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
187   }
188   if (m_pJbig2Context) {
189     ICodec_Jbig2Module* pJbig2Module = CPDF_ModuleMgr::Get()->GetJbig2Module();
190     pJbig2Module->DestroyJbig2Context(m_pJbig2Context);
191   }
192   delete m_pGlobalStream;
193 }
194 CFX_DIBitmap* CPDF_DIBSource::GetBitmap() const {
195   return m_pCachedBitmap ? m_pCachedBitmap.get() : Clone();
196 }
197 void CPDF_DIBSource::ReleaseBitmap(CFX_DIBitmap* pBitmap) const {
198   if (pBitmap && pBitmap != m_pCachedBitmap) {
199     delete pBitmap;
200   }
201 }
202 FX_BOOL CPDF_DIBSource::Load(CPDF_Document* pDoc,
203                              const CPDF_Stream* pStream,
204                              CPDF_DIBSource** ppMask,
205                              FX_DWORD* pMatteColor,
206                              CPDF_Dictionary* pFormResources,
207                              CPDF_Dictionary* pPageResources,
208                              FX_BOOL bStdCS,
209                              FX_DWORD GroupFamily,
210                              FX_BOOL bLoadMask) {
211   if (pStream == NULL) {
212     return FALSE;
213   }
214   m_pDocument = pDoc;
215   m_pDict = pStream->GetDict();
216   if (m_pDict == NULL) {
217     return FALSE;
218   }
219   m_pStream = pStream;
220   m_Width = m_pDict->GetInteger(FX_BSTRC("Width"));
221   m_Height = m_pDict->GetInteger(FX_BSTRC("Height"));
222   if (m_Width <= 0 || m_Height <= 0 || m_Width > kMaxImageDimension ||
223       m_Height > kMaxImageDimension) {
224     return FALSE;
225   }
226   m_GroupFamily = GroupFamily;
227   m_bLoadMask = bLoadMask;
228   if (!LoadColorInfo(m_pStream->GetObjNum() != 0 ? NULL : pFormResources,
229                      pPageResources)) {
230     return FALSE;
231   }
232   if (m_bDoBpcCheck && (m_bpc == 0 || m_nComponents == 0)) {
233     return FALSE;
234   }
235   FX_SAFE_DWORD src_pitch =
236       CalculatePitch8(m_bpc, m_nComponents, m_Width, m_Height);
237   if (!src_pitch.IsValid()) {
238     return FALSE;
239   }
240   m_pStreamAcc = new CPDF_StreamAcc;
241   m_pStreamAcc->LoadAllData(pStream, FALSE, src_pitch.ValueOrDie(), TRUE);
242   if (m_pStreamAcc->GetSize() == 0 || m_pStreamAcc->GetData() == NULL) {
243     return FALSE;
244   }
245   if (!CreateDecoder()) {
246     return FALSE;
247   }
248   if (m_bImageMask) {
249     m_bpp = 1;
250     m_bpc = 1;
251     m_nComponents = 1;
252     m_AlphaFlag = 1;
253   } else if (m_bpc * m_nComponents == 1) {
254     m_bpp = 1;
255   } else if (m_bpc * m_nComponents <= 8) {
256     m_bpp = 8;
257   } else {
258     m_bpp = 24;
259   }
260   FX_SAFE_DWORD pitch = CalculatePitch32(m_bpp, m_Width);
261   if (!pitch.IsValid()) {
262     return FALSE;
263   }
264   m_pLineBuf = FX_Alloc(uint8_t, pitch.ValueOrDie());
265   if (m_pColorSpace && bStdCS) {
266     m_pColorSpace->EnableStdConversion(TRUE);
267   }
268   LoadPalette();
269   if (m_bColorKey) {
270     m_bpp = 32;
271     m_AlphaFlag = 2;
272     pitch = CalculatePitch32(m_bpp, m_Width);
273     if (!pitch.IsValid()) {
274       return FALSE;
275     }
276     m_pMaskedLine = FX_Alloc(uint8_t, pitch.ValueOrDie());
277   }
278   m_Pitch = pitch.ValueOrDie();
279   if (ppMask) {
280     *ppMask = LoadMask(*pMatteColor);
281   }
282   if (m_pColorSpace && bStdCS) {
283     m_pColorSpace->EnableStdConversion(FALSE);
284   }
285   return TRUE;
286 }
287 int CPDF_DIBSource::ContinueToLoadMask() {
288   if (m_bImageMask) {
289     m_bpp = 1;
290     m_bpc = 1;
291     m_nComponents = 1;
292     m_AlphaFlag = 1;
293   } else if (m_bpc * m_nComponents == 1) {
294     m_bpp = 1;
295   } else if (m_bpc * m_nComponents <= 8) {
296     m_bpp = 8;
297   } else {
298     m_bpp = 24;
299   }
300   if (!m_bpc || !m_nComponents) {
301     return 0;
302   }
303   FX_SAFE_DWORD pitch = CalculatePitch32(m_bpp, m_Width);
304   if (!pitch.IsValid()) {
305     return 0;
306   }
307   m_pLineBuf = FX_Alloc(uint8_t, pitch.ValueOrDie());
308   if (m_pColorSpace && m_bStdCS) {
309     m_pColorSpace->EnableStdConversion(TRUE);
310   }
311   LoadPalette();
312   if (m_bColorKey) {
313     m_bpp = 32;
314     m_AlphaFlag = 2;
315     pitch = CalculatePitch32(m_bpp, m_Width);
316     if (!pitch.IsValid()) {
317       return 0;
318     }
319     m_pMaskedLine = FX_Alloc(uint8_t, pitch.ValueOrDie());
320   }
321   m_Pitch = pitch.ValueOrDie();
322   return 1;
323 }
324 int CPDF_DIBSource::StartLoadDIBSource(CPDF_Document* pDoc,
325                                        const CPDF_Stream* pStream,
326                                        FX_BOOL bHasMask,
327                                        CPDF_Dictionary* pFormResources,
328                                        CPDF_Dictionary* pPageResources,
329                                        FX_BOOL bStdCS,
330                                        FX_DWORD GroupFamily,
331                                        FX_BOOL bLoadMask) {
332   if (pStream == NULL) {
333     return 0;
334   }
335   m_pDocument = pDoc;
336   m_pDict = pStream->GetDict();
337   m_pStream = pStream;
338   m_bStdCS = bStdCS;
339   m_bHasMask = bHasMask;
340   m_Width = m_pDict->GetInteger(FX_BSTRC("Width"));
341   m_Height = m_pDict->GetInteger(FX_BSTRC("Height"));
342   if (m_Width <= 0 || m_Height <= 0 || m_Width > kMaxImageDimension ||
343       m_Height > kMaxImageDimension) {
344     return 0;
345   }
346   m_GroupFamily = GroupFamily;
347   m_bLoadMask = bLoadMask;
348   if (!LoadColorInfo(m_pStream->GetObjNum() != 0 ? NULL : pFormResources,
349                      pPageResources)) {
350     return 0;
351   }
352   if (m_bDoBpcCheck && (m_bpc == 0 || m_nComponents == 0)) {
353     return 0;
354   }
355   FX_SAFE_DWORD src_pitch =
356       CalculatePitch8(m_bpc, m_nComponents, m_Width, m_Height);
357   if (!src_pitch.IsValid()) {
358     return 0;
359   }
360   m_pStreamAcc = new CPDF_StreamAcc;
361   m_pStreamAcc->LoadAllData(pStream, FALSE, src_pitch.ValueOrDie(), TRUE);
362   if (m_pStreamAcc->GetSize() == 0 || m_pStreamAcc->GetData() == NULL) {
363     return 0;
364   }
365   int ret = CreateDecoder();
366   if (ret != 1) {
367     if (!ret) {
368       return ret;
369     }
370     if (!ContinueToLoadMask()) {
371       return 0;
372     }
373     if (m_bHasMask) {
374       StratLoadMask();
375     }
376     return ret;
377   }
378   if (!ContinueToLoadMask()) {
379     return 0;
380   }
381   if (m_bHasMask) {
382     ret = StratLoadMask();
383   }
384   if (ret == 2) {
385     return ret;
386   }
387   if (m_pColorSpace && m_bStdCS) {
388     m_pColorSpace->EnableStdConversion(FALSE);
389   }
390   return ret;
391 }
392 int CPDF_DIBSource::ContinueLoadDIBSource(IFX_Pause* pPause) {
393   FXCODEC_STATUS ret;
394   if (m_Status == 1) {
395     const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder();
396     if (decoder == FX_BSTRC("JPXDecode")) {
397       return 0;
398     }
399     ICodec_Jbig2Module* pJbig2Module = CPDF_ModuleMgr::Get()->GetJbig2Module();
400     if (m_pJbig2Context == NULL) {
401       m_pJbig2Context = pJbig2Module->CreateJbig2Context();
402       if (m_pStreamAcc->GetImageParam()) {
403         CPDF_Stream* pGlobals =
404             m_pStreamAcc->GetImageParam()->GetStream(FX_BSTRC("JBIG2Globals"));
405         if (pGlobals) {
406           m_pGlobalStream = new CPDF_StreamAcc;
407           m_pGlobalStream->LoadAllData(pGlobals, FALSE);
408         }
409       }
410       ret = pJbig2Module->StartDecode(m_pJbig2Context, m_pDocument, m_Width,
411                                       m_Height, m_pStreamAcc, m_pGlobalStream,
412                                       m_pCachedBitmap->GetBuffer(),
413                                       m_pCachedBitmap->GetPitch(), pPause);
414       if (ret < 0) {
415         m_pCachedBitmap.reset();
416         delete m_pGlobalStream;
417         m_pGlobalStream = NULL;
418         pJbig2Module->DestroyJbig2Context(m_pJbig2Context);
419         m_pJbig2Context = NULL;
420         return 0;
421       }
422       if (ret == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
423         return 2;
424       }
425       int ret1 = 1;
426       if (m_bHasMask) {
427         ret1 = ContinueLoadMaskDIB(pPause);
428         m_Status = 2;
429       }
430       if (ret1 == 2) {
431         return ret1;
432       }
433       if (m_pColorSpace && m_bStdCS) {
434         m_pColorSpace->EnableStdConversion(FALSE);
435       }
436       return ret1;
437     }
438     FXCODEC_STATUS ret = pJbig2Module->ContinueDecode(m_pJbig2Context, pPause);
439     if (ret < 0) {
440       m_pCachedBitmap.reset();
441       delete m_pGlobalStream;
442       m_pGlobalStream = NULL;
443       pJbig2Module->DestroyJbig2Context(m_pJbig2Context);
444       m_pJbig2Context = NULL;
445       return 0;
446     }
447     if (ret == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
448       return 2;
449     }
450     int ret1 = 1;
451     if (m_bHasMask) {
452       ret1 = ContinueLoadMaskDIB(pPause);
453       m_Status = 2;
454     }
455     if (ret1 == 2) {
456       return ret1;
457     }
458     if (m_pColorSpace && m_bStdCS) {
459       m_pColorSpace->EnableStdConversion(FALSE);
460     }
461     return ret1;
462   }
463   if (m_Status == 2) {
464     return ContinueLoadMaskDIB(pPause);
465   }
466   return 0;
467 }
468 FX_BOOL CPDF_DIBSource::LoadColorInfo(CPDF_Dictionary* pFormResources,
469                                       CPDF_Dictionary* pPageResources) {
470   m_bpc_orig = m_pDict->GetInteger(FX_BSTRC("BitsPerComponent"));
471   if (m_pDict->GetInteger("ImageMask")) {
472     m_bImageMask = TRUE;
473   }
474   if (m_bImageMask || !m_pDict->KeyExist(FX_BSTRC("ColorSpace"))) {
475     if (!m_bImageMask) {
476       CPDF_Object* pFilter = m_pDict->GetElementValue(FX_BSTRC("Filter"));
477       if (pFilter) {
478         CFX_ByteString filter;
479         if (pFilter->GetType() == PDFOBJ_NAME) {
480           filter = pFilter->GetString();
481           if (filter == FX_BSTRC("JPXDecode")) {
482             m_bDoBpcCheck = FALSE;
483             return TRUE;
484           }
485         } else if (pFilter->GetType() == PDFOBJ_ARRAY) {
486           CPDF_Array* pArray = (CPDF_Array*)pFilter;
487           if (pArray->GetString(pArray->GetCount() - 1) ==
488               FX_BSTRC("JPXDecode")) {
489             m_bDoBpcCheck = FALSE;
490             return TRUE;
491           }
492         }
493       }
494     }
495     m_bImageMask = TRUE;
496     m_bpc = m_nComponents = 1;
497     CPDF_Array* pDecode = m_pDict->GetArray(FX_BSTRC("Decode"));
498     m_bDefaultDecode = pDecode == NULL || pDecode->GetInteger(0) == 0;
499     return TRUE;
500   }
501   CPDF_Object* pCSObj = m_pDict->GetElementValue(FX_BSTRC("ColorSpace"));
502   if (pCSObj == NULL) {
503     return FALSE;
504   }
505   CPDF_DocPageData* pDocPageData = m_pDocument->GetPageData();
506   if (pFormResources) {
507     m_pColorSpace = pDocPageData->GetColorSpace(pCSObj, pFormResources);
508   }
509   if (m_pColorSpace == NULL) {
510     m_pColorSpace = pDocPageData->GetColorSpace(pCSObj, pPageResources);
511   }
512   if (m_pColorSpace == NULL) {
513     return FALSE;
514   }
515   m_Family = m_pColorSpace->GetFamily();
516   m_nComponents = m_pColorSpace->CountComponents();
517   if (m_Family == PDFCS_ICCBASED && pCSObj->GetType() == PDFOBJ_NAME) {
518     CFX_ByteString cs = pCSObj->GetString();
519     if (cs == FX_BSTRC("DeviceGray")) {
520       m_nComponents = 1;
521     } else if (cs == FX_BSTRC("DeviceRGB")) {
522       m_nComponents = 3;
523     } else if (cs == FX_BSTRC("DeviceCMYK")) {
524       m_nComponents = 4;
525     }
526   }
527   ValidateDictParam();
528   m_pCompData = GetDecodeAndMaskArray(m_bDefaultDecode, m_bColorKey);
529   if (m_pCompData == NULL) {
530     return FALSE;
531   }
532   return TRUE;
533 }
534 DIB_COMP_DATA* CPDF_DIBSource::GetDecodeAndMaskArray(FX_BOOL& bDefaultDecode,
535                                                      FX_BOOL& bColorKey) {
536   if (m_pColorSpace == NULL) {
537     return NULL;
538   }
539   DIB_COMP_DATA* pCompData = FX_Alloc(DIB_COMP_DATA, m_nComponents);
540   int max_data = (1 << m_bpc) - 1;
541   CPDF_Array* pDecode = m_pDict->GetArray(FX_BSTRC("Decode"));
542   if (pDecode) {
543     for (FX_DWORD i = 0; i < m_nComponents; i++) {
544       pCompData[i].m_DecodeMin = pDecode->GetNumber(i * 2);
545       FX_FLOAT max = pDecode->GetNumber(i * 2 + 1);
546       pCompData[i].m_DecodeStep = (max - pCompData[i].m_DecodeMin) / max_data;
547       FX_FLOAT def_value, def_min, def_max;
548       m_pColorSpace->GetDefaultValue(i, def_value, def_min, def_max);
549       if (m_Family == PDFCS_INDEXED) {
550         def_max = (FX_FLOAT)max_data;
551       }
552       if (def_min != pCompData[i].m_DecodeMin || def_max != max) {
553         bDefaultDecode = FALSE;
554       }
555     }
556   } else {
557     for (FX_DWORD i = 0; i < m_nComponents; i++) {
558       FX_FLOAT def_value;
559       m_pColorSpace->GetDefaultValue(i, def_value, pCompData[i].m_DecodeMin,
560                                      pCompData[i].m_DecodeStep);
561       if (m_Family == PDFCS_INDEXED) {
562         pCompData[i].m_DecodeStep = (FX_FLOAT)max_data;
563       }
564       pCompData[i].m_DecodeStep =
565           (pCompData[i].m_DecodeStep - pCompData[i].m_DecodeMin) / max_data;
566     }
567   }
568   if (!m_pDict->KeyExist(FX_BSTRC("SMask"))) {
569     CPDF_Object* pMask = m_pDict->GetElementValue(FX_BSTRC("Mask"));
570     if (pMask == NULL) {
571       return pCompData;
572     }
573     if (pMask->GetType() == PDFOBJ_ARRAY) {
574       CPDF_Array* pArray = (CPDF_Array*)pMask;
575       if (pArray->GetCount() >= m_nComponents * 2) {
576         for (FX_DWORD i = 0; i < m_nComponents; i++) {
577           int min_num = pArray->GetInteger(i * 2);
578           int max_num = pArray->GetInteger(i * 2 + 1);
579           pCompData[i].m_ColorKeyMin = FX_MAX(min_num, 0);
580           pCompData[i].m_ColorKeyMax = FX_MIN(max_num, max_data);
581         }
582       }
583       bColorKey = TRUE;
584     }
585   }
586   return pCompData;
587 }
588 ICodec_ScanlineDecoder* FPDFAPI_CreateFaxDecoder(
589     const uint8_t* src_buf,
590     FX_DWORD src_size,
591     int width,
592     int height,
593     const CPDF_Dictionary* pParams);
594 ICodec_ScanlineDecoder* FPDFAPI_CreateFlateDecoder(
595     const uint8_t* src_buf,
596     FX_DWORD src_size,
597     int width,
598     int height,
599     int nComps,
600     int bpc,
601     const CPDF_Dictionary* pParams);
602 int CPDF_DIBSource::CreateDecoder() {
603   const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder();
604   if (decoder.IsEmpty()) {
605     return 1;
606   }
607   if (m_bDoBpcCheck && m_bpc == 0) {
608     return 0;
609   }
610   const uint8_t* src_data = m_pStreamAcc->GetData();
611   FX_DWORD src_size = m_pStreamAcc->GetSize();
612   const CPDF_Dictionary* pParams = m_pStreamAcc->GetImageParam();
613   if (decoder == FX_BSTRC("CCITTFaxDecode")) {
614     m_pDecoder = FPDFAPI_CreateFaxDecoder(src_data, src_size, m_Width, m_Height,
615                                           pParams);
616   } else if (decoder == FX_BSTRC("DCTDecode")) {
617     m_pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder(
618         src_data, src_size, m_Width, m_Height, m_nComponents,
619         pParams ? pParams->GetInteger("ColorTransform", 1) : 1);
620     if (!m_pDecoder) {
621       FX_BOOL bTransform = FALSE;
622       int comps, bpc;
623       ICodec_JpegModule* pJpegModule = CPDF_ModuleMgr::Get()->GetJpegModule();
624       if (pJpegModule->LoadInfo(src_data, src_size, m_Width, m_Height, comps,
625                                 bpc, bTransform)) {
626         if (m_nComponents != comps) {
627           FX_Free(m_pCompData);
628           m_nComponents = comps;
629           if (m_Family == PDFCS_LAB && m_nComponents != 3) {
630             m_pCompData = NULL;
631             return 0;
632           }
633           m_pCompData = GetDecodeAndMaskArray(m_bDefaultDecode, m_bColorKey);
634           if (m_pCompData == NULL) {
635             return 0;
636           }
637         }
638         m_bpc = bpc;
639         m_pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder(
640             src_data, src_size, m_Width, m_Height, m_nComponents, bTransform);
641       }
642     }
643   } else if (decoder == FX_BSTRC("FlateDecode")) {
644     m_pDecoder = FPDFAPI_CreateFlateDecoder(
645         src_data, src_size, m_Width, m_Height, m_nComponents, m_bpc, pParams);
646   } else if (decoder == FX_BSTRC("JPXDecode")) {
647     LoadJpxBitmap();
648     return m_pCachedBitmap ? 1 : 0;
649   } else if (decoder == FX_BSTRC("JBIG2Decode")) {
650     m_pCachedBitmap.reset(new CFX_DIBitmap);
651     if (!m_pCachedBitmap->Create(
652             m_Width, m_Height, m_bImageMask ? FXDIB_1bppMask : FXDIB_1bppRgb)) {
653       m_pCachedBitmap.reset();
654       return 0;
655     }
656     m_Status = 1;
657     return 2;
658   } else if (decoder == FX_BSTRC("RunLengthDecode")) {
659     m_pDecoder = CPDF_ModuleMgr::Get()
660                      ->GetCodecModule()
661                      ->GetBasicModule()
662                      ->CreateRunLengthDecoder(src_data, src_size, m_Width,
663                                               m_Height, m_nComponents, m_bpc);
664   }
665   if (!m_pDecoder)
666     return 0;
667
668   FX_SAFE_DWORD requested_pitch =
669       CalculatePitch8(m_bpc, m_nComponents, m_Width, 1);
670   if (!requested_pitch.IsValid()) {
671     return 0;
672   }
673   FX_SAFE_DWORD provided_pitch =
674       CalculatePitch8(m_pDecoder->GetBPC(), m_pDecoder->CountComps(),
675                       m_pDecoder->GetWidth(), 1);
676   if (!provided_pitch.IsValid()) {
677     return 0;
678   }
679   if (provided_pitch.ValueOrDie() < requested_pitch.ValueOrDie()) {
680     return 0;
681   }
682   return 1;
683 }
684 void CPDF_DIBSource::LoadJpxBitmap() {
685   ICodec_JpxModule* pJpxModule = CPDF_ModuleMgr::Get()->GetJpxModule();
686   if (!pJpxModule)
687     return;
688
689   nonstd::unique_ptr<JpxBitMapContext> context(
690       new JpxBitMapContext(pJpxModule));
691   context->set_decoder(pJpxModule->CreateDecoder(m_pStreamAcc->GetData(),
692                                                  m_pStreamAcc->GetSize(),
693                                                  m_pColorSpace == nullptr));
694   if (!context->decoder())
695     return;
696
697   FX_DWORD width = 0;
698   FX_DWORD height = 0;
699   FX_DWORD components = 0;
700   pJpxModule->GetImageInfo(context->decoder(), &width, &height, &components);
701   if ((int)width < m_Width || (int)height < m_Height)
702     return;
703
704   FX_BOOL bSwapRGB = FALSE;
705   if (m_pColorSpace) {
706     if (components != (FX_DWORD)m_pColorSpace->CountComponents())
707       return;
708
709     if (m_pColorSpace == CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB)) {
710       bSwapRGB = TRUE;
711       m_pColorSpace = nullptr;
712     }
713   } else {
714     if (components == 3) {
715       bSwapRGB = TRUE;
716     } else if (components == 4) {
717       m_pColorSpace = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK);
718     }
719     m_nComponents = components;
720   }
721
722   FXDIB_Format format;
723   if (components == 1) {
724     format = FXDIB_8bppRgb;
725   } else if (components <= 3) {
726     format = FXDIB_Rgb;
727   } else if (components == 4) {
728     format = FXDIB_Rgb32;
729   } else {
730     width = (width * components + 2) / 3;
731     format = FXDIB_Rgb;
732   }
733
734   m_pCachedBitmap.reset(new CFX_DIBitmap);
735   if (!m_pCachedBitmap->Create(width, height, format)) {
736     m_pCachedBitmap.reset();
737     return;
738   }
739   m_pCachedBitmap->Clear(0xFFFFFFFF);
740   std::vector<uint8_t> output_offsets(components);
741   for (int i = 0; i < components; ++i)
742     output_offsets[i] = i;
743   if (bSwapRGB) {
744     output_offsets[0] = 2;
745     output_offsets[2] = 0;
746   }
747   if (!pJpxModule->Decode(context->decoder(), m_pCachedBitmap->GetBuffer(),
748                           m_pCachedBitmap->GetPitch(), output_offsets)) {
749     m_pCachedBitmap.reset();
750     return;
751   }
752   if (m_pColorSpace && m_pColorSpace->GetFamily() == PDFCS_INDEXED &&
753       m_bpc < 8) {
754     int scale = 8 - m_bpc;
755     for (FX_DWORD row = 0; row < height; ++row) {
756       uint8_t* scanline = (uint8_t*)m_pCachedBitmap->GetScanline(row);
757       for (FX_DWORD col = 0; col < width; ++col) {
758         *scanline = (*scanline) >> scale;
759         ++scanline;
760       }
761     }
762   }
763   m_bpc = 8;
764 }
765 CPDF_DIBSource* CPDF_DIBSource::LoadMask(FX_DWORD& MatteColor) {
766   MatteColor = 0xFFFFFFFF;
767   CPDF_Stream* pSoftMask = m_pDict->GetStream(FX_BSTRC("SMask"));
768   if (pSoftMask) {
769     CPDF_Array* pMatte = pSoftMask->GetDict()->GetArray(FX_BSTRC("Matte"));
770     if (pMatte != NULL && m_pColorSpace &&
771         (FX_DWORD)m_pColorSpace->CountComponents() <= m_nComponents) {
772       FX_FLOAT* pColor = FX_Alloc(FX_FLOAT, m_nComponents);
773       for (FX_DWORD i = 0; i < m_nComponents; i++) {
774         pColor[i] = pMatte->GetFloat(i);
775       }
776       FX_FLOAT R, G, B;
777       m_pColorSpace->GetRGB(pColor, R, G, B);
778       FX_Free(pColor);
779       MatteColor = FXARGB_MAKE(0, FXSYS_round(R * 255), FXSYS_round(G * 255),
780                                FXSYS_round(B * 255));
781     }
782     return LoadMaskDIB(pSoftMask);
783   }
784   CPDF_Object* pMask = m_pDict->GetElementValue(FX_BSTRC("Mask"));
785   if (pMask == NULL) {
786     return NULL;
787   }
788   if (pMask->GetType() == PDFOBJ_STREAM) {
789     return LoadMaskDIB((CPDF_Stream*)pMask);
790   }
791   return NULL;
792 }
793 int CPDF_DIBSource::StratLoadMask() {
794   m_MatteColor = 0XFFFFFFFF;
795   m_pMaskStream = m_pDict->GetStream(FX_BSTRC("SMask"));
796   if (m_pMaskStream) {
797     CPDF_Array* pMatte = m_pMaskStream->GetDict()->GetArray(FX_BSTRC("Matte"));
798     if (pMatte != NULL && m_pColorSpace &&
799         (FX_DWORD)m_pColorSpace->CountComponents() <= m_nComponents) {
800       FX_FLOAT R, G, B;
801       FX_FLOAT* pColor = FX_Alloc(FX_FLOAT, m_nComponents);
802       for (FX_DWORD i = 0; i < m_nComponents; i++) {
803         pColor[i] = pMatte->GetFloat(i);
804       }
805       m_pColorSpace->GetRGB(pColor, R, G, B);
806       FX_Free(pColor);
807       m_MatteColor = FXARGB_MAKE(0, FXSYS_round(R * 255), FXSYS_round(G * 255),
808                                  FXSYS_round(B * 255));
809     }
810     return StartLoadMaskDIB();
811   }
812   m_pMaskStream = m_pDict->GetElementValue(FX_BSTRC("Mask"));
813   if (m_pMaskStream == NULL) {
814     return 1;
815   }
816   if (m_pMaskStream->GetType() == PDFOBJ_STREAM) {
817     return StartLoadMaskDIB();
818   }
819   return 1;
820 }
821 int CPDF_DIBSource::ContinueLoadMaskDIB(IFX_Pause* pPause) {
822   if (m_pMask == NULL) {
823     return 1;
824   }
825   int ret = m_pMask->ContinueLoadDIBSource(pPause);
826   if (ret == 2) {
827     return ret;
828   }
829   if (m_pColorSpace && m_bStdCS) {
830     m_pColorSpace->EnableStdConversion(FALSE);
831   }
832   if (!ret) {
833     delete m_pMask;
834     m_pMask = NULL;
835     return ret;
836   }
837   return 1;
838 }
839 CPDF_DIBSource* CPDF_DIBSource::DetachMask() {
840   CPDF_DIBSource* pDIBSource = m_pMask;
841   m_pMask = NULL;
842   return pDIBSource;
843 }
844 CPDF_DIBSource* CPDF_DIBSource::LoadMaskDIB(CPDF_Stream* pMask) {
845   CPDF_DIBSource* pMaskSource = new CPDF_DIBSource;
846   if (!pMaskSource->Load(m_pDocument, pMask, NULL, NULL, NULL, NULL, TRUE)) {
847     delete pMaskSource;
848     return NULL;
849   }
850   return pMaskSource;
851 }
852 int CPDF_DIBSource::StartLoadMaskDIB() {
853   m_pMask = new CPDF_DIBSource;
854   int ret = m_pMask->StartLoadDIBSource(
855       m_pDocument, (CPDF_Stream*)m_pMaskStream, FALSE, NULL, NULL, TRUE);
856   if (ret == 2) {
857     if (m_Status == 0) {
858       m_Status = 2;
859     }
860     return 2;
861   }
862   if (!ret) {
863     delete m_pMask;
864     m_pMask = NULL;
865     return 1;
866   }
867   return 1;
868 }
869 void CPDF_DIBSource::LoadPalette() {
870   if (m_bpc == 0) {
871     return;
872   }
873   if (m_bpc * m_nComponents > 8) {
874     return;
875   }
876   if (m_pColorSpace == NULL) {
877     return;
878   }
879   if (m_bpc * m_nComponents == 1) {
880     if (m_bDefaultDecode &&
881         (m_Family == PDFCS_DEVICEGRAY || m_Family == PDFCS_DEVICERGB)) {
882       return;
883     }
884     if (m_pColorSpace->CountComponents() > 3) {
885       return;
886     }
887     FX_FLOAT color_values[3];
888     color_values[0] = m_pCompData[0].m_DecodeMin;
889     color_values[1] = color_values[2] = color_values[0];
890     FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f;
891     m_pColorSpace->GetRGB(color_values, R, G, B);
892     FX_ARGB argb0 = ArgbEncode(255, FXSYS_round(R * 255), FXSYS_round(G * 255),
893                                FXSYS_round(B * 255));
894     color_values[0] += m_pCompData[0].m_DecodeStep;
895     color_values[1] += m_pCompData[0].m_DecodeStep;
896     color_values[2] += m_pCompData[0].m_DecodeStep;
897     m_pColorSpace->GetRGB(color_values, R, G, B);
898     FX_ARGB argb1 = ArgbEncode(255, FXSYS_round(R * 255), FXSYS_round(G * 255),
899                                FXSYS_round(B * 255));
900     if (argb0 != 0xFF000000 || argb1 != 0xFFFFFFFF) {
901       SetPaletteArgb(0, argb0);
902       SetPaletteArgb(1, argb1);
903     }
904     return;
905   }
906   if (m_pColorSpace == CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY) &&
907       m_bpc == 8 && m_bDefaultDecode) {
908   } else {
909     int palette_count = 1 << (m_bpc * m_nComponents);
910     CFX_FixedBufGrow<FX_FLOAT, 16> color_values(m_nComponents);
911     FX_FLOAT* color_value = color_values;
912     for (int i = 0; i < palette_count; i++) {
913       int color_data = i;
914       for (FX_DWORD j = 0; j < m_nComponents; j++) {
915         int encoded_component = color_data % (1 << m_bpc);
916         color_data /= 1 << m_bpc;
917         color_value[j] = m_pCompData[j].m_DecodeMin +
918                          m_pCompData[j].m_DecodeStep * encoded_component;
919       }
920       FX_FLOAT R = 0, G = 0, B = 0;
921       if (m_nComponents == 1 && m_Family == PDFCS_ICCBASED &&
922           m_pColorSpace->CountComponents() > 1) {
923         int nComponents = m_pColorSpace->CountComponents();
924         FX_FLOAT* temp_buf = FX_Alloc(FX_FLOAT, nComponents);
925         for (int i = 0; i < nComponents; i++) {
926           temp_buf[i] = *color_value;
927         }
928         m_pColorSpace->GetRGB(temp_buf, R, G, B);
929         FX_Free(temp_buf);
930       } else {
931         m_pColorSpace->GetRGB(color_value, R, G, B);
932       }
933       SetPaletteArgb(i, ArgbEncode(255, FXSYS_round(R * 255),
934                                    FXSYS_round(G * 255), FXSYS_round(B * 255)));
935     }
936   }
937 }
938 void CPDF_DIBSource::ValidateDictParam() {
939   m_bpc = m_bpc_orig;
940   CPDF_Object* pFilter = m_pDict->GetElementValue(FX_BSTRC("Filter"));
941   if (pFilter) {
942     if (pFilter->GetType() == PDFOBJ_NAME) {
943       CFX_ByteString filter = pFilter->GetString();
944       if (filter == FX_BSTRC("CCITTFaxDecode") ||
945           filter == FX_BSTRC("JBIG2Decode")) {
946         m_bpc = 1;
947         m_nComponents = 1;
948       }
949       if (filter == FX_BSTRC("RunLengthDecode")) {
950         if (m_bpc != 1) {
951           m_bpc = 8;
952         }
953       } else if (filter == FX_BSTRC("DCTDecode")) {
954         m_bpc = 8;
955       }
956     } else if (pFilter->GetType() == PDFOBJ_ARRAY) {
957       CPDF_Array* pArray = (CPDF_Array*)pFilter;
958       if (pArray->GetString(pArray->GetCount() - 1) ==
959               FX_BSTRC("CCITTFaxDecode") ||
960           pArray->GetString(pArray->GetCount() - 1) ==
961               FX_BSTRC("JBIG2Decode")) {
962         m_bpc = 1;
963         m_nComponents = 1;
964       }
965       if (pArray->GetString(pArray->GetCount() - 1) == FX_BSTRC("DCTDecode")) {
966         // Previously, pArray->GetString(pArray->GetCount() - 1) ==
967         // FX_BSTRC("RunLengthDecode") was checked in the "if" statement as
968         // well,
969         // but too many documents don't conform to it.
970         m_bpc = 8;
971       }
972     }
973   }
974   if (m_bpc != 1 && m_bpc != 2 && m_bpc != 4 && m_bpc != 8 && m_bpc != 16) {
975     m_bpc = 0;
976   }
977 }
978 #define NORMALCOLOR_MAX(color, max) \
979   (color) > (max) ? (max) : (color) < 0 ? 0 : (color);
980 void CPDF_DIBSource::TranslateScanline24bpp(uint8_t* dest_scan,
981                                             const uint8_t* src_scan) const {
982   if (m_bpc == 0) {
983     return;
984   }
985   int max_data = (1 << m_bpc) - 1;
986   if (m_bDefaultDecode) {
987     if (m_Family == PDFCS_DEVICERGB || m_Family == PDFCS_CALRGB) {
988       const uint8_t* src_pos = src_scan;
989       switch (m_bpc) {
990         case 16:
991           for (int col = 0; col < m_Width; col++) {
992             *dest_scan++ = src_pos[4];
993             *dest_scan++ = src_pos[2];
994             *dest_scan++ = *src_pos;
995             src_pos += 6;
996           }
997           break;
998         case 8:
999           for (int column = 0; column < m_Width; column++) {
1000             *dest_scan++ = src_pos[2];
1001             *dest_scan++ = src_pos[1];
1002             *dest_scan++ = *src_pos;
1003             src_pos += 3;
1004           }
1005           break;
1006         default:
1007           int src_bit_pos = 0;
1008           int dest_byte_pos = 0;
1009           for (int column = 0; column < m_Width; column++) {
1010             int R = _GetBits8(src_scan, src_bit_pos, m_bpc);
1011             src_bit_pos += m_bpc;
1012             int G = _GetBits8(src_scan, src_bit_pos, m_bpc);
1013             src_bit_pos += m_bpc;
1014             int B = _GetBits8(src_scan, src_bit_pos, m_bpc);
1015             src_bit_pos += m_bpc;
1016             R = NORMALCOLOR_MAX(R, max_data);
1017             G = NORMALCOLOR_MAX(G, max_data);
1018             B = NORMALCOLOR_MAX(B, max_data);
1019             dest_scan[dest_byte_pos] = B * 255 / max_data;
1020             dest_scan[dest_byte_pos + 1] = G * 255 / max_data;
1021             dest_scan[dest_byte_pos + 2] = R * 255 / max_data;
1022             dest_byte_pos += 3;
1023           }
1024           break;
1025       }
1026       return;
1027     }
1028     if (m_bpc == 8) {
1029       if (m_nComponents == m_pColorSpace->CountComponents())
1030         m_pColorSpace->TranslateImageLine(dest_scan, src_scan, m_Width, m_Width,
1031                                           m_Height, TransMask());
1032       return;
1033     }
1034   }
1035   CFX_FixedBufGrow<FX_FLOAT, 16> color_values1(m_nComponents);
1036   FX_FLOAT* color_values = color_values1;
1037   FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f;
1038   if (m_bpc == 8) {
1039     int src_byte_pos = 0;
1040     int dest_byte_pos = 0;
1041     for (int column = 0; column < m_Width; column++) {
1042       for (FX_DWORD color = 0; color < m_nComponents; color++) {
1043         int data = src_scan[src_byte_pos++];
1044         color_values[color] = m_pCompData[color].m_DecodeMin +
1045                               m_pCompData[color].m_DecodeStep * data;
1046       }
1047       if (TransMask()) {
1048         FX_FLOAT k = 1.0f - color_values[3];
1049         R = (1.0f - color_values[0]) * k;
1050         G = (1.0f - color_values[1]) * k;
1051         B = (1.0f - color_values[2]) * k;
1052       } else {
1053         m_pColorSpace->GetRGB(color_values, R, G, B);
1054       }
1055       R = NORMALCOLOR_MAX(R, 1);
1056       G = NORMALCOLOR_MAX(G, 1);
1057       B = NORMALCOLOR_MAX(B, 1);
1058       dest_scan[dest_byte_pos] = (int32_t)(B * 255);
1059       dest_scan[dest_byte_pos + 1] = (int32_t)(G * 255);
1060       dest_scan[dest_byte_pos + 2] = (int32_t)(R * 255);
1061       dest_byte_pos += 3;
1062     }
1063   } else {
1064     int src_bit_pos = 0;
1065     int dest_byte_pos = 0;
1066     for (int column = 0; column < m_Width; column++) {
1067       for (FX_DWORD color = 0; color < m_nComponents; color++) {
1068         int data = _GetBits8(src_scan, src_bit_pos, m_bpc);
1069         color_values[color] = m_pCompData[color].m_DecodeMin +
1070                               m_pCompData[color].m_DecodeStep * data;
1071         src_bit_pos += m_bpc;
1072       }
1073       if (TransMask()) {
1074         FX_FLOAT k = 1.0f - color_values[3];
1075         R = (1.0f - color_values[0]) * k;
1076         G = (1.0f - color_values[1]) * k;
1077         B = (1.0f - color_values[2]) * k;
1078       } else {
1079         m_pColorSpace->GetRGB(color_values, R, G, B);
1080       }
1081       R = NORMALCOLOR_MAX(R, 1);
1082       G = NORMALCOLOR_MAX(G, 1);
1083       B = NORMALCOLOR_MAX(B, 1);
1084       dest_scan[dest_byte_pos] = (int32_t)(B * 255);
1085       dest_scan[dest_byte_pos + 1] = (int32_t)(G * 255);
1086       dest_scan[dest_byte_pos + 2] = (int32_t)(R * 255);
1087       dest_byte_pos += 3;
1088     }
1089   }
1090 }
1091 uint8_t* CPDF_DIBSource::GetBuffer() const {
1092   if (m_pCachedBitmap) {
1093     return m_pCachedBitmap->GetBuffer();
1094   }
1095   return NULL;
1096 }
1097 const uint8_t* CPDF_DIBSource::GetScanline(int line) const {
1098   if (m_bpc == 0) {
1099     return NULL;
1100   }
1101   FX_SAFE_DWORD src_pitch = CalculatePitch8(m_bpc, m_nComponents, m_Width, 1);
1102   if (!src_pitch.IsValid())
1103     return NULL;
1104   FX_DWORD src_pitch_value = src_pitch.ValueOrDie();
1105   const uint8_t* pSrcLine = NULL;
1106   if (m_pCachedBitmap) {
1107     if (line >= m_pCachedBitmap->GetHeight()) {
1108       line = m_pCachedBitmap->GetHeight() - 1;
1109     }
1110     pSrcLine = m_pCachedBitmap->GetScanline(line);
1111   } else if (m_pDecoder) {
1112     pSrcLine = m_pDecoder->GetScanline(line);
1113   } else {
1114     if (m_pStreamAcc->GetSize() >= (line + 1) * src_pitch_value) {
1115       pSrcLine = m_pStreamAcc->GetData() + line * src_pitch_value;
1116     }
1117   }
1118   if (pSrcLine == NULL) {
1119     uint8_t* pLineBuf = m_pMaskedLine ? m_pMaskedLine : m_pLineBuf;
1120     FXSYS_memset(pLineBuf, 0xFF, m_Pitch);
1121     return pLineBuf;
1122   }
1123   if (m_bpc * m_nComponents == 1) {
1124     if (m_bImageMask && m_bDefaultDecode) {
1125       for (FX_DWORD i = 0; i < src_pitch_value; i++) {
1126         m_pLineBuf[i] = ~pSrcLine[i];
1127       }
1128     } else if (m_bColorKey) {
1129       FX_DWORD reset_argb, set_argb;
1130       reset_argb = m_pPalette ? m_pPalette[0] : 0xFF000000;
1131       set_argb = m_pPalette ? m_pPalette[1] : 0xFFFFFFFF;
1132       if (m_pCompData[0].m_ColorKeyMin == 0) {
1133         reset_argb = 0;
1134       }
1135       if (m_pCompData[0].m_ColorKeyMax == 1) {
1136         set_argb = 0;
1137       }
1138       set_argb = FXARGB_TODIB(set_argb);
1139       reset_argb = FXARGB_TODIB(reset_argb);
1140       FX_DWORD* dest_scan = (FX_DWORD*)m_pMaskedLine;
1141       for (int col = 0; col < m_Width; col++) {
1142         if (pSrcLine[col / 8] & (1 << (7 - col % 8))) {
1143           *dest_scan = set_argb;
1144         } else {
1145           *dest_scan = reset_argb;
1146         }
1147         dest_scan++;
1148       }
1149       return m_pMaskedLine;
1150     } else {
1151       FXSYS_memcpy(m_pLineBuf, pSrcLine, src_pitch_value);
1152     }
1153     return m_pLineBuf;
1154   }
1155   if (m_bpc * m_nComponents <= 8) {
1156     if (m_bpc == 8) {
1157       FXSYS_memcpy(m_pLineBuf, pSrcLine, src_pitch_value);
1158     } else {
1159       int src_bit_pos = 0;
1160       for (int col = 0; col < m_Width; col++) {
1161         int color_index = 0;
1162         for (FX_DWORD color = 0; color < m_nComponents; color++) {
1163           int data = _GetBits8(pSrcLine, src_bit_pos, m_bpc);
1164           color_index |= data << (color * m_bpc);
1165           src_bit_pos += m_bpc;
1166         }
1167         m_pLineBuf[col] = color_index;
1168       }
1169     }
1170     if (m_bColorKey) {
1171       uint8_t* pDestPixel = m_pMaskedLine;
1172       const uint8_t* pSrcPixel = m_pLineBuf;
1173       for (int col = 0; col < m_Width; col++) {
1174         uint8_t index = *pSrcPixel++;
1175         if (m_pPalette) {
1176           *pDestPixel++ = FXARGB_B(m_pPalette[index]);
1177           *pDestPixel++ = FXARGB_G(m_pPalette[index]);
1178           *pDestPixel++ = FXARGB_R(m_pPalette[index]);
1179         } else {
1180           *pDestPixel++ = index;
1181           *pDestPixel++ = index;
1182           *pDestPixel++ = index;
1183         }
1184         *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin ||
1185                        index > m_pCompData[0].m_ColorKeyMax)
1186                           ? 0xFF
1187                           : 0;
1188         pDestPixel++;
1189       }
1190       return m_pMaskedLine;
1191     }
1192     return m_pLineBuf;
1193   }
1194   if (m_bColorKey) {
1195     if (m_nComponents == 3 && m_bpc == 8) {
1196       uint8_t* alpha_channel = m_pMaskedLine + 3;
1197       for (int col = 0; col < m_Width; col++) {
1198         const uint8_t* pPixel = pSrcLine + col * 3;
1199         alpha_channel[col * 4] = (pPixel[0] < m_pCompData[0].m_ColorKeyMin ||
1200                                   pPixel[0] > m_pCompData[0].m_ColorKeyMax ||
1201                                   pPixel[1] < m_pCompData[1].m_ColorKeyMin ||
1202                                   pPixel[1] > m_pCompData[1].m_ColorKeyMax ||
1203                                   pPixel[2] < m_pCompData[2].m_ColorKeyMin ||
1204                                   pPixel[2] > m_pCompData[2].m_ColorKeyMax)
1205                                      ? 0xFF
1206                                      : 0;
1207       }
1208     } else {
1209       FXSYS_memset(m_pMaskedLine, 0xFF, m_Pitch);
1210     }
1211   }
1212   if (m_pColorSpace) {
1213     TranslateScanline24bpp(m_pLineBuf, pSrcLine);
1214     pSrcLine = m_pLineBuf;
1215   }
1216   if (m_bColorKey) {
1217     const uint8_t* pSrcPixel = pSrcLine;
1218     uint8_t* pDestPixel = m_pMaskedLine;
1219     for (int col = 0; col < m_Width; col++) {
1220       *pDestPixel++ = *pSrcPixel++;
1221       *pDestPixel++ = *pSrcPixel++;
1222       *pDestPixel++ = *pSrcPixel++;
1223       pDestPixel++;
1224     }
1225     return m_pMaskedLine;
1226   }
1227   return pSrcLine;
1228 }
1229
1230 FX_BOOL CPDF_DIBSource::SkipToScanline(int line, IFX_Pause* pPause) const {
1231   return m_pDecoder && m_pDecoder->SkipToScanline(line, pPause);
1232 }
1233
1234 void CPDF_DIBSource::DownSampleScanline(int line,
1235                                         uint8_t* dest_scan,
1236                                         int dest_bpp,
1237                                         int dest_width,
1238                                         FX_BOOL bFlipX,
1239                                         int clip_left,
1240                                         int clip_width) const {
1241   if (line < 0 || !dest_scan || dest_bpp <= 0 || dest_width <= 0 ||
1242       clip_left < 0 || clip_width <= 0) {
1243     return;
1244   }
1245
1246   FX_DWORD src_width = m_Width;
1247   FX_SAFE_DWORD pitch = CalculatePitch8(m_bpc, m_nComponents, m_Width, 1);
1248   if (!pitch.IsValid())
1249     return;
1250
1251   const uint8_t* pSrcLine = nullptr;
1252   if (m_pCachedBitmap) {
1253     pSrcLine = m_pCachedBitmap->GetScanline(line);
1254   } else if (m_pDecoder) {
1255     pSrcLine = m_pDecoder->GetScanline(line);
1256   } else {
1257     FX_DWORD src_pitch = pitch.ValueOrDie();
1258     pitch *= (line + 1);
1259     if (!pitch.IsValid()) {
1260       return;
1261     }
1262
1263     if (m_pStreamAcc->GetSize() >= pitch.ValueOrDie()) {
1264       pSrcLine = m_pStreamAcc->GetData() + line * src_pitch;
1265     }
1266   }
1267   int orig_Bpp = m_bpc * m_nComponents / 8;
1268   int dest_Bpp = dest_bpp / 8;
1269   if (!pSrcLine) {
1270     FXSYS_memset(dest_scan, 0xFF, dest_Bpp * clip_width);
1271     return;
1272   }
1273
1274   FX_SAFE_INT32 max_src_x = clip_left;
1275   max_src_x += clip_width - 1;
1276   max_src_x *= src_width;
1277   max_src_x /= dest_width;
1278   if (!max_src_x.IsValid())
1279     return;
1280
1281   if (m_bpc * m_nComponents == 1) {
1282     DownSampleScanline1Bit(orig_Bpp, dest_Bpp, src_width, pSrcLine, dest_scan,
1283                            dest_width, bFlipX, clip_left, clip_width);
1284   } else if (m_bpc * m_nComponents <= 8) {
1285     DownSampleScanline8Bit(orig_Bpp, dest_Bpp, src_width, pSrcLine, dest_scan,
1286                            dest_width, bFlipX, clip_left, clip_width);
1287   } else {
1288     DownSampleScanline32Bit(orig_Bpp, dest_Bpp, src_width, pSrcLine, dest_scan,
1289                             dest_width, bFlipX, clip_left, clip_width);
1290   }
1291 }
1292
1293 void CPDF_DIBSource::DownSampleScanline1Bit(int orig_Bpp,
1294                                             int dest_Bpp,
1295                                             FX_DWORD src_width,
1296                                             const uint8_t* pSrcLine,
1297                                             uint8_t* dest_scan,
1298                                             int dest_width,
1299                                             FX_BOOL bFlipX,
1300                                             int clip_left,
1301                                             int clip_width) const {
1302   FX_DWORD set_argb = (FX_DWORD)-1;
1303   FX_DWORD reset_argb = 0;
1304   if (m_bImageMask) {
1305     if (m_bDefaultDecode) {
1306       set_argb = 0;
1307       reset_argb = (FX_DWORD)-1;
1308     }
1309   } else if (m_bColorKey) {
1310     reset_argb = m_pPalette ? m_pPalette[0] : 0xFF000000;
1311     set_argb = m_pPalette ? m_pPalette[1] : 0xFFFFFFFF;
1312     if (m_pCompData[0].m_ColorKeyMin == 0) {
1313       reset_argb = 0;
1314     }
1315     if (m_pCompData[0].m_ColorKeyMax == 1) {
1316       set_argb = 0;
1317     }
1318     set_argb = FXARGB_TODIB(set_argb);
1319     reset_argb = FXARGB_TODIB(reset_argb);
1320     for (int i = 0; i < clip_width; i++) {
1321       FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
1322       if (bFlipX) {
1323         src_x = src_width - src_x - 1;
1324       }
1325       src_x %= src_width;
1326       if (pSrcLine[src_x / 8] & (1 << (7 - src_x % 8))) {
1327         ((FX_DWORD*)dest_scan)[i] = set_argb;
1328       } else {
1329         ((FX_DWORD*)dest_scan)[i] = reset_argb;
1330       }
1331     }
1332     return;
1333   } else {
1334     if (dest_Bpp == 1) {
1335     } else if (m_pPalette) {
1336       reset_argb = m_pPalette[0];
1337       set_argb = m_pPalette[1];
1338     }
1339   }
1340   for (int i = 0; i < clip_width; i++) {
1341     FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
1342     if (bFlipX) {
1343       src_x = src_width - src_x - 1;
1344     }
1345     src_x %= src_width;
1346     int dest_pos = i * dest_Bpp;
1347     if (pSrcLine[src_x / 8] & (1 << (7 - src_x % 8))) {
1348       if (dest_Bpp == 1) {
1349         dest_scan[dest_pos] = (uint8_t)set_argb;
1350       } else if (dest_Bpp == 3) {
1351         dest_scan[dest_pos] = FXARGB_B(set_argb);
1352         dest_scan[dest_pos + 1] = FXARGB_G(set_argb);
1353         dest_scan[dest_pos + 2] = FXARGB_R(set_argb);
1354       } else {
1355         *(FX_DWORD*)(dest_scan + dest_pos) = set_argb;
1356       }
1357     } else {
1358       if (dest_Bpp == 1) {
1359         dest_scan[dest_pos] = (uint8_t)reset_argb;
1360       } else if (dest_Bpp == 3) {
1361         dest_scan[dest_pos] = FXARGB_B(reset_argb);
1362         dest_scan[dest_pos + 1] = FXARGB_G(reset_argb);
1363         dest_scan[dest_pos + 2] = FXARGB_R(reset_argb);
1364       } else {
1365         *(FX_DWORD*)(dest_scan + dest_pos) = reset_argb;
1366       }
1367     }
1368   }
1369 }
1370
1371 void CPDF_DIBSource::DownSampleScanline8Bit(int orig_Bpp,
1372                                             int dest_Bpp,
1373                                             FX_DWORD src_width,
1374                                             const uint8_t* pSrcLine,
1375                                             uint8_t* dest_scan,
1376                                             int dest_width,
1377                                             FX_BOOL bFlipX,
1378                                             int clip_left,
1379                                             int clip_width) const {
1380   if (m_bpc < 8) {
1381     int src_bit_pos = 0;
1382     for (FX_DWORD col = 0; col < src_width; col++) {
1383       int color_index = 0;
1384       for (FX_DWORD color = 0; color < m_nComponents; color++) {
1385         int data = _GetBits8(pSrcLine, src_bit_pos, m_bpc);
1386         color_index |= data << (color * m_bpc);
1387         src_bit_pos += m_bpc;
1388       }
1389       m_pLineBuf[col] = color_index;
1390     }
1391     pSrcLine = m_pLineBuf;
1392   }
1393   if (m_bColorKey) {
1394     for (int i = 0; i < clip_width; i++) {
1395       FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
1396       if (bFlipX) {
1397         src_x = src_width - src_x - 1;
1398       }
1399       src_x %= src_width;
1400       uint8_t* pDestPixel = dest_scan + i * 4;
1401       uint8_t index = pSrcLine[src_x];
1402       if (m_pPalette) {
1403         *pDestPixel++ = FXARGB_B(m_pPalette[index]);
1404         *pDestPixel++ = FXARGB_G(m_pPalette[index]);
1405         *pDestPixel++ = FXARGB_R(m_pPalette[index]);
1406       } else {
1407         *pDestPixel++ = index;
1408         *pDestPixel++ = index;
1409         *pDestPixel++ = index;
1410       }
1411       *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin ||
1412                      index > m_pCompData[0].m_ColorKeyMax)
1413                         ? 0xFF
1414                         : 0;
1415     }
1416     return;
1417   }
1418   for (int i = 0; i < clip_width; i++) {
1419     FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
1420     if (bFlipX) {
1421       src_x = src_width - src_x - 1;
1422     }
1423     src_x %= src_width;
1424     uint8_t index = pSrcLine[src_x];
1425     if (dest_Bpp == 1) {
1426       dest_scan[i] = index;
1427     } else {
1428       int dest_pos = i * dest_Bpp;
1429       FX_ARGB argb = m_pPalette[index];
1430       dest_scan[dest_pos] = FXARGB_B(argb);
1431       dest_scan[dest_pos + 1] = FXARGB_G(argb);
1432       dest_scan[dest_pos + 2] = FXARGB_R(argb);
1433     }
1434   }
1435 }
1436
1437 void CPDF_DIBSource::DownSampleScanline32Bit(int orig_Bpp,
1438                                              int dest_Bpp,
1439                                              FX_DWORD src_width,
1440                                              const uint8_t* pSrcLine,
1441                                              uint8_t* dest_scan,
1442                                              int dest_width,
1443                                              FX_BOOL bFlipX,
1444                                              int clip_left,
1445                                              int clip_width) const {
1446   int last_src_x = -1;
1447   FX_ARGB last_argb = FXARGB_MAKE(0xFF, 0xFF, 0xFF, 0xFF);
1448   FX_FLOAT orig_Not8Bpp = (FX_FLOAT)m_bpc * (FX_FLOAT)m_nComponents / 8.0f;
1449   FX_FLOAT unit_To8Bpc = 255.0f / ((1 << m_bpc) - 1);
1450   for (int i = 0; i < clip_width; i++) {
1451     int dest_x = clip_left + i;
1452     FX_DWORD src_x = (bFlipX ? (dest_width - dest_x - 1) : dest_x) *
1453                      (int64_t)src_width / dest_width;
1454     src_x %= src_width;
1455     const uint8_t* pSrcPixel = nullptr;
1456     if (m_bpc % 8 == 0) {
1457       pSrcPixel = pSrcLine + src_x * orig_Bpp;
1458     } else {
1459       pSrcPixel = pSrcLine + (int)(src_x * orig_Not8Bpp);
1460     }
1461     uint8_t* pDestPixel = dest_scan + i * dest_Bpp;
1462     FX_ARGB argb;
1463     if (src_x == last_src_x) {
1464       argb = last_argb;
1465     } else {
1466       if (m_pColorSpace) {
1467         CFX_FixedBufGrow<uint8_t, 128> temp(orig_Bpp);
1468         uint8_t color[4];
1469         const FX_BOOL bTransMask = TransMask();
1470         if (m_bDefaultDecode) {
1471           if (m_bpc < 8) {
1472             int src_bit_pos = 0;
1473             if (src_x % 2) {
1474               src_bit_pos = 4;
1475             }
1476             for (FX_DWORD j = 0; j < m_nComponents; ++j) {
1477               temp[j] = (uint8_t)(_GetBits8(pSrcPixel, src_bit_pos, m_bpc) *
1478                                   unit_To8Bpc);
1479               src_bit_pos += m_bpc;
1480             }
1481             m_pColorSpace->TranslateImageLine(color, temp, 1, 0, 0, bTransMask);
1482           } else {
1483             m_pColorSpace->TranslateImageLine(color, pSrcPixel, 1, 0, 0,
1484                                               bTransMask);
1485           }
1486         } else {
1487           for (int j = 0; j < m_nComponents; ++j) {
1488             int color_value =
1489                 (int)((m_pCompData[j].m_DecodeMin +
1490                        m_pCompData[j].m_DecodeStep * (FX_FLOAT)pSrcPixel[j]) *
1491                           255.0f +
1492                       0.5f);
1493             temp[j] =
1494                 color_value > 255 ? 255 : (color_value < 0 ? 0 : color_value);
1495           }
1496           m_pColorSpace->TranslateImageLine(color, temp, 1, 0, 0, bTransMask);
1497         }
1498         argb = FXARGB_MAKE(0xFF, color[2], color[1], color[0]);
1499       } else {
1500         argb = FXARGB_MAKE(0xFf, pSrcPixel[2], pSrcPixel[1], pSrcPixel[0]);
1501       }
1502       if (m_bColorKey) {
1503         int alpha = 0xFF;
1504         if (m_nComponents == 3 && m_bpc == 8) {
1505           alpha = (pSrcPixel[0] < m_pCompData[0].m_ColorKeyMin ||
1506                    pSrcPixel[0] > m_pCompData[0].m_ColorKeyMax ||
1507                    pSrcPixel[1] < m_pCompData[1].m_ColorKeyMin ||
1508                    pSrcPixel[1] > m_pCompData[1].m_ColorKeyMax ||
1509                    pSrcPixel[2] < m_pCompData[2].m_ColorKeyMin ||
1510                    pSrcPixel[2] > m_pCompData[2].m_ColorKeyMax)
1511                       ? 0xFF
1512                       : 0;
1513         }
1514         argb &= 0xFFFFFF;
1515         argb |= alpha << 24;
1516       }
1517       last_src_x = src_x;
1518       last_argb = argb;
1519     }
1520     if (dest_Bpp == 4) {
1521       *(FX_DWORD*)pDestPixel = FXARGB_TODIB(argb);
1522     } else {
1523       *pDestPixel++ = FXARGB_B(argb);
1524       *pDestPixel++ = FXARGB_G(argb);
1525       *pDestPixel = FXARGB_R(argb);
1526     }
1527   }
1528 }
1529
1530 FX_BOOL CPDF_DIBSource::TransMask() const {
1531   return m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK &&
1532          m_Family == PDFCS_DEVICECMYK;
1533 }
1534
1535 void CPDF_DIBSource::SetDownSampleSize(int dest_width, int dest_height) const {
1536   if (m_pDecoder) {
1537     m_pDecoder->DownScale(dest_width, dest_height);
1538     ((CPDF_DIBSource*)this)->m_Width = m_pDecoder->GetWidth();
1539     ((CPDF_DIBSource*)this)->m_Height = m_pDecoder->GetHeight();
1540   }
1541 }
1542
1543 void CPDF_DIBSource::ClearImageData() {
1544   if (m_pDecoder) {
1545     m_pDecoder->ClearImageData();
1546   }
1547 }
1548
1549 CPDF_ProgressiveImageLoaderHandle::CPDF_ProgressiveImageLoaderHandle() {
1550   m_pImageLoader = NULL;
1551   m_pCache = NULL;
1552   m_pImage = NULL;
1553 }
1554 CPDF_ProgressiveImageLoaderHandle::~CPDF_ProgressiveImageLoaderHandle() {}
1555 FX_BOOL CPDF_ProgressiveImageLoaderHandle::Start(
1556     CPDF_ImageLoader* pImageLoader,
1557     const CPDF_ImageObject* pImage,
1558     CPDF_PageRenderCache* pCache,
1559     FX_BOOL bStdCS,
1560     FX_DWORD GroupFamily,
1561     FX_BOOL bLoadMask,
1562     CPDF_RenderStatus* pRenderStatus,
1563     int32_t nDownsampleWidth,
1564     int32_t nDownsampleHeight) {
1565   m_pImageLoader = pImageLoader;
1566   m_pCache = pCache;
1567   m_pImage = (CPDF_ImageObject*)pImage;
1568   m_nDownsampleWidth = nDownsampleWidth;
1569   m_nDownsampleHeight = nDownsampleHeight;
1570   FX_BOOL ret;
1571   if (pCache) {
1572     ret = pCache->StartGetCachedBitmap(pImage->m_pImage->GetStream(), bStdCS,
1573                                        GroupFamily, bLoadMask, pRenderStatus,
1574                                        m_nDownsampleWidth, m_nDownsampleHeight);
1575     if (ret == FALSE) {
1576       m_pImageLoader->m_bCached = TRUE;
1577       m_pImageLoader->m_pBitmap = pCache->m_pCurImageCache->DetachBitmap();
1578       m_pImageLoader->m_pMask = pCache->m_pCurImageCache->DetachMask();
1579       m_pImageLoader->m_MatteColor = pCache->m_pCurImageCache->m_MatteColor;
1580     }
1581   } else {
1582     ret = pImage->m_pImage->StartLoadDIBSource(pRenderStatus->m_pFormResource,
1583                                                pRenderStatus->m_pPageResource,
1584                                                bStdCS, GroupFamily, bLoadMask);
1585     if (ret == FALSE) {
1586       m_pImageLoader->m_bCached = FALSE;
1587       m_pImageLoader->m_pBitmap = m_pImage->m_pImage->DetachBitmap();
1588       m_pImageLoader->m_pMask = m_pImage->m_pImage->DetachMask();
1589       m_pImageLoader->m_MatteColor = m_pImage->m_pImage->m_MatteColor;
1590     }
1591   }
1592   return ret;
1593 }
1594 FX_BOOL CPDF_ProgressiveImageLoaderHandle::Continue(IFX_Pause* pPause) {
1595   FX_BOOL ret;
1596   if (m_pCache) {
1597     ret = m_pCache->Continue(pPause);
1598     if (ret == FALSE) {
1599       m_pImageLoader->m_bCached = TRUE;
1600       m_pImageLoader->m_pBitmap = m_pCache->m_pCurImageCache->DetachBitmap();
1601       m_pImageLoader->m_pMask = m_pCache->m_pCurImageCache->DetachMask();
1602       m_pImageLoader->m_MatteColor = m_pCache->m_pCurImageCache->m_MatteColor;
1603     }
1604   } else {
1605     ret = m_pImage->m_pImage->Continue(pPause);
1606     if (ret == FALSE) {
1607       m_pImageLoader->m_bCached = FALSE;
1608       m_pImageLoader->m_pBitmap = m_pImage->m_pImage->DetachBitmap();
1609       m_pImageLoader->m_pMask = m_pImage->m_pImage->DetachMask();
1610       m_pImageLoader->m_MatteColor = m_pImage->m_pImage->m_MatteColor;
1611     }
1612   }
1613   return ret;
1614 }
1615 FX_BOOL CPDF_ImageLoader::Load(const CPDF_ImageObject* pImage,
1616                                CPDF_PageRenderCache* pCache,
1617                                FX_BOOL bStdCS,
1618                                FX_DWORD GroupFamily,
1619                                FX_BOOL bLoadMask,
1620                                CPDF_RenderStatus* pRenderStatus) {
1621   if (pImage == NULL) {
1622     return FALSE;
1623   }
1624   if (pCache) {
1625     pCache->GetCachedBitmap(pImage->m_pImage->GetStream(), m_pBitmap, m_pMask,
1626                             m_MatteColor, bStdCS, GroupFamily, bLoadMask,
1627                             pRenderStatus, m_nDownsampleWidth,
1628                             m_nDownsampleHeight);
1629     m_bCached = TRUE;
1630   } else {
1631     m_pBitmap = pImage->m_pImage->LoadDIBSource(&m_pMask, &m_MatteColor, bStdCS,
1632                                                 GroupFamily, bLoadMask);
1633     m_bCached = FALSE;
1634   }
1635   return FALSE;
1636 }
1637 FX_BOOL CPDF_ImageLoader::StartLoadImage(const CPDF_ImageObject* pImage,
1638                                          CPDF_PageRenderCache* pCache,
1639                                          void*& LoadHandle,
1640                                          FX_BOOL bStdCS,
1641                                          FX_DWORD GroupFamily,
1642                                          FX_BOOL bLoadMask,
1643                                          CPDF_RenderStatus* pRenderStatus,
1644                                          int32_t nDownsampleWidth,
1645                                          int32_t nDownsampleHeight) {
1646   m_nDownsampleWidth = nDownsampleWidth;
1647   m_nDownsampleHeight = nDownsampleHeight;
1648   CPDF_ProgressiveImageLoaderHandle* pLoaderHandle =
1649       new CPDF_ProgressiveImageLoaderHandle;
1650   FX_BOOL ret = pLoaderHandle->Start(this, pImage, pCache, bStdCS, GroupFamily,
1651                                      bLoadMask, pRenderStatus,
1652                                      m_nDownsampleWidth, m_nDownsampleHeight);
1653   LoadHandle = pLoaderHandle;
1654   return ret;
1655 }
1656 FX_BOOL CPDF_ImageLoader::Continue(void* LoadHandle, IFX_Pause* pPause) {
1657   return ((CPDF_ProgressiveImageLoaderHandle*)LoadHandle)->Continue(pPause);
1658 }
1659 CPDF_ImageLoader::~CPDF_ImageLoader() {
1660   if (!m_bCached) {
1661     delete m_pBitmap;
1662     delete m_pMask;
1663   }
1664 }