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