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