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