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