1 // Copyright 2017 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 "core/fpdfapi/render/cpdf_dibsource.h"
8 
9 #include <algorithm>
10 #include <memory>
11 #include <vector>
12 
13 #include "core/fpdfapi/cpdf_modulemgr.h"
14 #include "core/fpdfapi/page/cpdf_docpagedata.h"
15 #include "core/fpdfapi/page/cpdf_image.h"
16 #include "core/fpdfapi/page/cpdf_imageobject.h"
17 #include "core/fpdfapi/parser/cpdf_array.h"
18 #include "core/fpdfapi/parser/cpdf_dictionary.h"
19 #include "core/fpdfapi/parser/cpdf_document.h"
20 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
21 #include "core/fpdfapi/render/cpdf_pagerendercache.h"
22 #include "core/fpdfapi/render/cpdf_renderstatus.h"
23 #include "core/fxcodec/fx_codec.h"
24 #include "core/fxcrt/fx_safe_types.h"
25 #include "third_party/base/ptr_util.h"
26 
27 namespace {
28 
GetBits8(const uint8_t * pData,uint64_t bitpos,size_t nbits)29 unsigned int GetBits8(const uint8_t* pData, uint64_t bitpos, size_t nbits) {
30   ASSERT(nbits == 1 || nbits == 2 || nbits == 4 || nbits == 8 || nbits == 16);
31   ASSERT((bitpos & (nbits - 1)) == 0);
32   unsigned int byte = pData[bitpos / 8];
33   if (nbits == 8)
34     return byte;
35 
36   if (nbits == 16)
37     return byte * 256 + pData[bitpos / 8 + 1];
38 
39   return (byte >> (8 - nbits - (bitpos % 8))) & ((1 << nbits) - 1);
40 }
41 
CalculatePitch8(uint32_t bpc,uint32_t components,int width)42 FX_SAFE_UINT32 CalculatePitch8(uint32_t bpc, uint32_t components, int width) {
43   FX_SAFE_UINT32 pitch = bpc;
44   pitch *= components;
45   pitch *= width;
46   pitch += 7;
47   pitch /= 8;
48   return pitch;
49 }
50 
CalculatePitch32(int bpp,int width)51 FX_SAFE_UINT32 CalculatePitch32(int bpp, int width) {
52   FX_SAFE_UINT32 pitch = bpp;
53   pitch *= width;
54   pitch += 31;
55   pitch /= 32;  // quantized to number of 32-bit words.
56   pitch *= 4;   // and then back to bytes, (not just /8 in one step).
57   return pitch;
58 }
59 
IsAllowedBPCValue(int bpc)60 bool IsAllowedBPCValue(int bpc) {
61   return bpc == 1 || bpc == 2 || bpc == 4 || bpc == 8 || bpc == 16;
62 }
63 
IsAllowedICCComponents(int nComp)64 bool IsAllowedICCComponents(int nComp) {
65   return nComp == 1 || nComp == 3 || nComp == 4;
66 }
67 
68 template <typename T>
ClampValue(T value,T max_value)69 T ClampValue(T value, T max_value) {
70   value = std::min(value, max_value);
71   value = std::max<T>(0, value);
72   return value;
73 }
74 
75 // Wrapper class to use with std::unique_ptr for CJPX_Decoder.
76 class JpxBitMapContext {
77  public:
JpxBitMapContext(CCodec_JpxModule * jpx_module)78   explicit JpxBitMapContext(CCodec_JpxModule* jpx_module)
79       : jpx_module_(jpx_module), decoder_(nullptr) {}
80 
~JpxBitMapContext()81   ~JpxBitMapContext() { jpx_module_->DestroyDecoder(decoder_); }
82 
83   // Takes ownership of |decoder|.
set_decoder(CJPX_Decoder * decoder)84   void set_decoder(CJPX_Decoder* decoder) { decoder_ = decoder; }
85 
decoder()86   CJPX_Decoder* decoder() { return decoder_; }
87 
88  private:
89   CCodec_JpxModule* const jpx_module_;  // Weak pointer.
90   CJPX_Decoder* decoder_;               // Decoder, owned.
91 
92   // Disallow evil constructors
93   JpxBitMapContext(const JpxBitMapContext&);
94   void operator=(const JpxBitMapContext&);
95 };
96 
97 const int kMaxImageDimension = 0x01FFFF;
98 
99 }  // namespace
100 
CPDF_DIBSource()101 CPDF_DIBSource::CPDF_DIBSource()
102     : m_pDocument(nullptr),
103       m_pStream(nullptr),
104       m_pDict(nullptr),
105       m_pColorSpace(nullptr),
106       m_Family(0),
107       m_bpc(0),
108       m_bpc_orig(0),
109       m_nComponents(0),
110       m_GroupFamily(0),
111       m_MatteColor(0),
112       m_bLoadMask(false),
113       m_bDefaultDecode(true),
114       m_bImageMask(false),
115       m_bDoBpcCheck(true),
116       m_bColorKey(false),
117       m_bHasMask(false),
118       m_bStdCS(false),
119       m_pCompData(nullptr),
120       m_pLineBuf(nullptr),
121       m_pMaskedLine(nullptr),
122       m_pMask(nullptr),
123       m_pMaskStream(nullptr),
124       m_Status(0) {}
125 
~CPDF_DIBSource()126 CPDF_DIBSource::~CPDF_DIBSource() {
127   FX_Free(m_pMaskedLine);
128   FX_Free(m_pLineBuf);
129   m_pCachedBitmap.reset();
130   FX_Free(m_pCompData);
131   CPDF_ColorSpace* pCS = m_pColorSpace;
132   if (pCS && m_pDocument) {
133     m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
134   }
135 }
136 
Load(CPDF_Document * pDoc,const CPDF_Stream * pStream)137 bool CPDF_DIBSource::Load(CPDF_Document* pDoc, const CPDF_Stream* pStream) {
138   if (!pStream)
139     return false;
140 
141   m_pDocument = pDoc;
142   m_pDict = pStream->GetDict();
143   if (!m_pDict)
144     return false;
145 
146   m_pStream = pStream;
147   m_Width = m_pDict->GetIntegerFor("Width");
148   m_Height = m_pDict->GetIntegerFor("Height");
149   if (m_Width <= 0 || m_Height <= 0 || m_Width > kMaxImageDimension ||
150       m_Height > kMaxImageDimension) {
151     return false;
152   }
153   m_GroupFamily = 0;
154   m_bLoadMask = false;
155   if (!LoadColorInfo(nullptr, nullptr))
156     return false;
157 
158   if (m_bDoBpcCheck && (m_bpc == 0 || m_nComponents == 0))
159     return false;
160 
161   FX_SAFE_UINT32 src_size =
162       CalculatePitch8(m_bpc, m_nComponents, m_Width) * m_Height;
163   if (!src_size.IsValid())
164     return false;
165 
166   m_pStreamAcc = pdfium::MakeUnique<CPDF_StreamAcc>();
167   m_pStreamAcc->LoadAllData(pStream, false, src_size.ValueOrDie(), true);
168   if (m_pStreamAcc->GetSize() == 0 || !m_pStreamAcc->GetData())
169     return false;
170 
171   if (!CreateDecoder())
172     return false;
173 
174   if (m_bImageMask) {
175     m_bpp = 1;
176     m_bpc = 1;
177     m_nComponents = 1;
178     m_AlphaFlag = 1;
179   } else if (m_bpc * m_nComponents == 1) {
180     m_bpp = 1;
181   } else if (m_bpc * m_nComponents <= 8) {
182     m_bpp = 8;
183   } else {
184     m_bpp = 24;
185   }
186   FX_SAFE_UINT32 pitch = CalculatePitch32(m_bpp, m_Width);
187   if (!pitch.IsValid())
188     return false;
189 
190   m_pLineBuf = FX_Alloc(uint8_t, pitch.ValueOrDie());
191   LoadPalette();
192   if (m_bColorKey) {
193     m_bpp = 32;
194     m_AlphaFlag = 2;
195     pitch = CalculatePitch32(m_bpp, m_Width);
196     if (!pitch.IsValid())
197       return false;
198 
199     m_pMaskedLine = FX_Alloc(uint8_t, pitch.ValueOrDie());
200   }
201   m_Pitch = pitch.ValueOrDie();
202   return true;
203 }
204 
ContinueToLoadMask()205 int CPDF_DIBSource::ContinueToLoadMask() {
206   if (m_bImageMask) {
207     m_bpp = 1;
208     m_bpc = 1;
209     m_nComponents = 1;
210     m_AlphaFlag = 1;
211   } else if (m_bpc * m_nComponents == 1) {
212     m_bpp = 1;
213   } else if (m_bpc * m_nComponents <= 8) {
214     m_bpp = 8;
215   } else {
216     m_bpp = 24;
217   }
218   if (!m_bpc || !m_nComponents) {
219     return 0;
220   }
221   FX_SAFE_UINT32 pitch = CalculatePitch32(m_bpp, m_Width);
222   if (!pitch.IsValid()) {
223     return 0;
224   }
225   m_pLineBuf = FX_Alloc(uint8_t, pitch.ValueOrDie());
226   if (m_pColorSpace && m_bStdCS) {
227     m_pColorSpace->EnableStdConversion(true);
228   }
229   LoadPalette();
230   if (m_bColorKey) {
231     m_bpp = 32;
232     m_AlphaFlag = 2;
233     pitch = CalculatePitch32(m_bpp, m_Width);
234     if (!pitch.IsValid()) {
235       return 0;
236     }
237     m_pMaskedLine = FX_Alloc(uint8_t, pitch.ValueOrDie());
238   }
239   m_Pitch = pitch.ValueOrDie();
240   return 1;
241 }
242 
StartLoadDIBSource(CPDF_Document * pDoc,const CPDF_Stream * pStream,bool bHasMask,CPDF_Dictionary * pFormResources,CPDF_Dictionary * pPageResources,bool bStdCS,uint32_t GroupFamily,bool bLoadMask)243 int CPDF_DIBSource::StartLoadDIBSource(CPDF_Document* pDoc,
244                                        const CPDF_Stream* pStream,
245                                        bool bHasMask,
246                                        CPDF_Dictionary* pFormResources,
247                                        CPDF_Dictionary* pPageResources,
248                                        bool bStdCS,
249                                        uint32_t GroupFamily,
250                                        bool bLoadMask) {
251   if (!pStream) {
252     return 0;
253   }
254   m_pDocument = pDoc;
255   m_pDict = pStream->GetDict();
256   m_pStream = pStream;
257   m_bStdCS = bStdCS;
258   m_bHasMask = bHasMask;
259   m_Width = m_pDict->GetIntegerFor("Width");
260   m_Height = m_pDict->GetIntegerFor("Height");
261   if (m_Width <= 0 || m_Height <= 0 || m_Width > kMaxImageDimension ||
262       m_Height > kMaxImageDimension) {
263     return 0;
264   }
265   m_GroupFamily = GroupFamily;
266   m_bLoadMask = bLoadMask;
267   if (!LoadColorInfo(m_pStream->IsInline() ? pFormResources : nullptr,
268                      pPageResources)) {
269     return 0;
270   }
271   if (m_bDoBpcCheck && (m_bpc == 0 || m_nComponents == 0)) {
272     return 0;
273   }
274   FX_SAFE_UINT32 src_size =
275       CalculatePitch8(m_bpc, m_nComponents, m_Width) * m_Height;
276   if (!src_size.IsValid()) {
277     return 0;
278   }
279   m_pStreamAcc = pdfium::MakeUnique<CPDF_StreamAcc>();
280   m_pStreamAcc->LoadAllData(pStream, false, src_size.ValueOrDie(), true);
281   if (m_pStreamAcc->GetSize() == 0 || !m_pStreamAcc->GetData()) {
282     return 0;
283   }
284   int ret = CreateDecoder();
285   if (!ret)
286     return ret;
287 
288   if (ret != 1) {
289     if (!ContinueToLoadMask()) {
290       return 0;
291     }
292     if (m_bHasMask) {
293       StratLoadMask();
294     }
295     return ret;
296   }
297   if (!ContinueToLoadMask()) {
298     return 0;
299   }
300   if (m_bHasMask) {
301     ret = StratLoadMask();
302   }
303   if (ret == 2) {
304     return ret;
305   }
306   if (m_pColorSpace && m_bStdCS) {
307     m_pColorSpace->EnableStdConversion(false);
308   }
309   return ret;
310 }
311 
ContinueLoadDIBSource(IFX_Pause * pPause)312 int CPDF_DIBSource::ContinueLoadDIBSource(IFX_Pause* pPause) {
313   FXCODEC_STATUS ret;
314   if (m_Status == 1) {
315     const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder();
316     if (decoder == "JPXDecode") {
317       return 0;
318     }
319     CCodec_Jbig2Module* pJbig2Module = CPDF_ModuleMgr::Get()->GetJbig2Module();
320     if (!m_pJbig2Context) {
321       m_pJbig2Context = pdfium::MakeUnique<CCodec_Jbig2Context>();
322       if (m_pStreamAcc->GetImageParam()) {
323         CPDF_Stream* pGlobals =
324             m_pStreamAcc->GetImageParam()->GetStreamFor("JBIG2Globals");
325         if (pGlobals) {
326           m_pGlobalStream = pdfium::MakeUnique<CPDF_StreamAcc>();
327           m_pGlobalStream->LoadAllData(pGlobals, false);
328         }
329       }
330       ret = pJbig2Module->StartDecode(
331           m_pJbig2Context.get(), m_pDocument->CodecContext(), m_Width, m_Height,
332           m_pStreamAcc.get(), m_pGlobalStream.get(),
333           m_pCachedBitmap->GetBuffer(), m_pCachedBitmap->GetPitch(), pPause);
334       if (ret < 0) {
335         m_pCachedBitmap.reset();
336         m_pGlobalStream.reset();
337         m_pJbig2Context.reset();
338         return 0;
339       }
340       if (ret == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
341         return 2;
342       }
343       int ret1 = 1;
344       if (m_bHasMask) {
345         ret1 = ContinueLoadMaskDIB(pPause);
346         m_Status = 2;
347       }
348       if (ret1 == 2) {
349         return ret1;
350       }
351       if (m_pColorSpace && m_bStdCS) {
352         m_pColorSpace->EnableStdConversion(false);
353       }
354       return ret1;
355     }
356     ret = pJbig2Module->ContinueDecode(m_pJbig2Context.get(), pPause);
357     if (ret < 0) {
358       m_pCachedBitmap.reset();
359       m_pGlobalStream.reset();
360       m_pJbig2Context.reset();
361       return 0;
362     }
363     if (ret == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
364       return 2;
365     }
366     int ret1 = 1;
367     if (m_bHasMask) {
368       ret1 = ContinueLoadMaskDIB(pPause);
369       m_Status = 2;
370     }
371     if (ret1 == 2) {
372       return ret1;
373     }
374     if (m_pColorSpace && m_bStdCS) {
375       m_pColorSpace->EnableStdConversion(false);
376     }
377     return ret1;
378   }
379   if (m_Status == 2) {
380     return ContinueLoadMaskDIB(pPause);
381   }
382   return 0;
383 }
384 
LoadColorInfo(const CPDF_Dictionary * pFormResources,const CPDF_Dictionary * pPageResources)385 bool CPDF_DIBSource::LoadColorInfo(const CPDF_Dictionary* pFormResources,
386                                    const CPDF_Dictionary* pPageResources) {
387   m_bpc_orig = m_pDict->GetIntegerFor("BitsPerComponent");
388   if (m_pDict->GetIntegerFor("ImageMask"))
389     m_bImageMask = true;
390 
391   if (m_bImageMask || !m_pDict->KeyExist("ColorSpace")) {
392     if (!m_bImageMask) {
393       CPDF_Object* pFilter = m_pDict->GetDirectObjectFor("Filter");
394       if (pFilter) {
395         CFX_ByteString filter;
396         if (pFilter->IsName()) {
397           filter = pFilter->GetString();
398         } else if (CPDF_Array* pArray = pFilter->AsArray()) {
399           filter = pArray->GetStringAt(pArray->GetCount() - 1);
400         }
401 
402         if (filter == "JPXDecode") {
403           m_bDoBpcCheck = false;
404           return true;
405         }
406       }
407     }
408     m_bImageMask = true;
409     m_bpc = m_nComponents = 1;
410     CPDF_Array* pDecode = m_pDict->GetArrayFor("Decode");
411     m_bDefaultDecode = !pDecode || !pDecode->GetIntegerAt(0);
412     return true;
413   }
414 
415   CPDF_Object* pCSObj = m_pDict->GetDirectObjectFor("ColorSpace");
416   if (!pCSObj)
417     return false;
418 
419   CPDF_DocPageData* pDocPageData = m_pDocument->GetPageData();
420   if (pFormResources)
421     m_pColorSpace = pDocPageData->GetColorSpace(pCSObj, pFormResources);
422   if (!m_pColorSpace)
423     m_pColorSpace = pDocPageData->GetColorSpace(pCSObj, pPageResources);
424   if (!m_pColorSpace)
425     return false;
426 
427   m_Family = m_pColorSpace->GetFamily();
428   m_nComponents = m_pColorSpace->CountComponents();
429   if (m_Family == PDFCS_ICCBASED && pCSObj->IsName()) {
430     CFX_ByteString cs = pCSObj->GetString();
431     if (cs == "DeviceGray") {
432       m_nComponents = 1;
433     } else if (cs == "DeviceRGB") {
434       m_nComponents = 3;
435     } else if (cs == "DeviceCMYK") {
436       m_nComponents = 4;
437     }
438   }
439   ValidateDictParam();
440   m_pCompData = GetDecodeAndMaskArray(m_bDefaultDecode, m_bColorKey);
441   return !!m_pCompData;
442 }
443 
GetDecodeAndMaskArray(bool & bDefaultDecode,bool & bColorKey)444 DIB_COMP_DATA* CPDF_DIBSource::GetDecodeAndMaskArray(bool& bDefaultDecode,
445                                                      bool& bColorKey) {
446   if (!m_pColorSpace) {
447     return nullptr;
448   }
449   DIB_COMP_DATA* pCompData = FX_Alloc(DIB_COMP_DATA, m_nComponents);
450   int max_data = (1 << m_bpc) - 1;
451   CPDF_Array* pDecode = m_pDict->GetArrayFor("Decode");
452   if (pDecode) {
453     for (uint32_t i = 0; i < m_nComponents; i++) {
454       pCompData[i].m_DecodeMin = pDecode->GetNumberAt(i * 2);
455       FX_FLOAT max = pDecode->GetNumberAt(i * 2 + 1);
456       pCompData[i].m_DecodeStep = (max - pCompData[i].m_DecodeMin) / max_data;
457       FX_FLOAT def_value;
458       FX_FLOAT def_min;
459       FX_FLOAT def_max;
460       m_pColorSpace->GetDefaultValue(i, def_value, def_min, def_max);
461       if (m_Family == PDFCS_INDEXED) {
462         def_max = max_data;
463       }
464       if (def_min != pCompData[i].m_DecodeMin || def_max != max) {
465         bDefaultDecode = false;
466       }
467     }
468   } else {
469     for (uint32_t i = 0; i < m_nComponents; i++) {
470       FX_FLOAT def_value;
471       m_pColorSpace->GetDefaultValue(i, def_value, pCompData[i].m_DecodeMin,
472                                      pCompData[i].m_DecodeStep);
473       if (m_Family == PDFCS_INDEXED) {
474         pCompData[i].m_DecodeStep = max_data;
475       }
476       pCompData[i].m_DecodeStep =
477           (pCompData[i].m_DecodeStep - pCompData[i].m_DecodeMin) / max_data;
478     }
479   }
480   if (!m_pDict->KeyExist("SMask")) {
481     CPDF_Object* pMask = m_pDict->GetDirectObjectFor("Mask");
482     if (!pMask) {
483       return pCompData;
484     }
485     if (CPDF_Array* pArray = pMask->AsArray()) {
486       if (pArray->GetCount() >= m_nComponents * 2) {
487         for (uint32_t i = 0; i < m_nComponents; i++) {
488           int min_num = pArray->GetIntegerAt(i * 2);
489           int max_num = pArray->GetIntegerAt(i * 2 + 1);
490           pCompData[i].m_ColorKeyMin = std::max(min_num, 0);
491           pCompData[i].m_ColorKeyMax = std::min(max_num, max_data);
492         }
493       }
494       bColorKey = true;
495     }
496   }
497   return pCompData;
498 }
499 
CreateDecoder()500 int CPDF_DIBSource::CreateDecoder() {
501   const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder();
502   if (decoder.IsEmpty())
503     return 1;
504 
505   if (m_bDoBpcCheck && m_bpc == 0)
506     return 0;
507 
508   if (decoder == "JPXDecode") {
509     LoadJpxBitmap();
510     return m_pCachedBitmap ? 1 : 0;
511   }
512   if (decoder == "JBIG2Decode") {
513     m_pCachedBitmap = pdfium::MakeUnique<CFX_DIBitmap>();
514     if (!m_pCachedBitmap->Create(
515             m_Width, m_Height, m_bImageMask ? FXDIB_1bppMask : FXDIB_1bppRgb)) {
516       m_pCachedBitmap.reset();
517       return 0;
518     }
519     m_Status = 1;
520     return 2;
521   }
522 
523   const uint8_t* src_data = m_pStreamAcc->GetData();
524   uint32_t src_size = m_pStreamAcc->GetSize();
525   const CPDF_Dictionary* pParams = m_pStreamAcc->GetImageParam();
526   if (decoder == "CCITTFaxDecode") {
527     m_pDecoder = FPDFAPI_CreateFaxDecoder(src_data, src_size, m_Width, m_Height,
528                                           pParams);
529   } else if (decoder == "FlateDecode") {
530     m_pDecoder = FPDFAPI_CreateFlateDecoder(
531         src_data, src_size, m_Width, m_Height, m_nComponents, m_bpc, pParams);
532   } else if (decoder == "RunLengthDecode") {
533     m_pDecoder = CPDF_ModuleMgr::Get()
534                      ->GetCodecModule()
535                      ->GetBasicModule()
536                      ->CreateRunLengthDecoder(src_data, src_size, m_Width,
537                                               m_Height, m_nComponents, m_bpc);
538   } else if (decoder == "DCTDecode") {
539     m_pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder(
540         src_data, src_size, m_Width, m_Height, m_nComponents,
541         !pParams || pParams->GetIntegerFor("ColorTransform", 1));
542     if (!m_pDecoder) {
543       bool bTransform = false;
544       int comps;
545       int bpc;
546       CCodec_JpegModule* pJpegModule = CPDF_ModuleMgr::Get()->GetJpegModule();
547       if (pJpegModule->LoadInfo(src_data, src_size, &m_Width, &m_Height, &comps,
548                                 &bpc, &bTransform)) {
549         if (m_nComponents != static_cast<uint32_t>(comps)) {
550           FX_Free(m_pCompData);
551           m_pCompData = nullptr;
552           m_nComponents = static_cast<uint32_t>(comps);
553           if (m_pColorSpace) {
554             switch (m_Family) {
555               case PDFCS_DEVICEGRAY:
556               case PDFCS_DEVICERGB:
557               case PDFCS_DEVICECMYK: {
558                 uint32_t dwMinComps = ComponentsForFamily(m_Family);
559                 if (m_pColorSpace->CountComponents() < dwMinComps ||
560                     m_nComponents < dwMinComps) {
561                   return 0;
562                 }
563                 break;
564               }
565               case PDFCS_LAB: {
566                 if (m_nComponents != 3 || m_pColorSpace->CountComponents() < 3)
567                   return 0;
568                 break;
569               }
570               case PDFCS_ICCBASED: {
571                 if (!IsAllowedICCComponents(m_nComponents) ||
572                     !IsAllowedICCComponents(m_pColorSpace->CountComponents()) ||
573                     m_pColorSpace->CountComponents() < m_nComponents) {
574                   return 0;
575                 }
576                 break;
577               }
578               default: {
579                 if (m_pColorSpace->CountComponents() != m_nComponents)
580                   return 0;
581                 break;
582               }
583             }
584           } else {
585             if (m_Family == PDFCS_LAB && m_nComponents != 3)
586               return 0;
587           }
588           m_pCompData = GetDecodeAndMaskArray(m_bDefaultDecode, m_bColorKey);
589           if (!m_pCompData)
590             return 0;
591         }
592         m_bpc = bpc;
593         m_pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder(
594             src_data, src_size, m_Width, m_Height, m_nComponents, bTransform);
595       }
596     }
597   }
598   if (!m_pDecoder)
599     return 0;
600 
601   FX_SAFE_UINT32 requested_pitch =
602       CalculatePitch8(m_bpc, m_nComponents, m_Width);
603   if (!requested_pitch.IsValid())
604     return 0;
605   FX_SAFE_UINT32 provided_pitch = CalculatePitch8(
606       m_pDecoder->GetBPC(), m_pDecoder->CountComps(), m_pDecoder->GetWidth());
607   if (!provided_pitch.IsValid())
608     return 0;
609   if (provided_pitch.ValueOrDie() < requested_pitch.ValueOrDie())
610     return 0;
611   return 1;
612 }
613 
LoadJpxBitmap()614 void CPDF_DIBSource::LoadJpxBitmap() {
615   CCodec_JpxModule* pJpxModule = CPDF_ModuleMgr::Get()->GetJpxModule();
616   if (!pJpxModule)
617     return;
618 
619   std::unique_ptr<JpxBitMapContext> context(new JpxBitMapContext(pJpxModule));
620   context->set_decoder(pJpxModule->CreateDecoder(
621       m_pStreamAcc->GetData(), m_pStreamAcc->GetSize(), m_pColorSpace));
622   if (!context->decoder())
623     return;
624 
625   uint32_t width = 0;
626   uint32_t height = 0;
627   uint32_t components = 0;
628   pJpxModule->GetImageInfo(context->decoder(), &width, &height, &components);
629   if (static_cast<int>(width) < m_Width || static_cast<int>(height) < m_Height)
630     return;
631 
632   bool bSwapRGB = false;
633   if (m_pColorSpace) {
634     if (components != m_pColorSpace->CountComponents())
635       return;
636 
637     if (m_pColorSpace == CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB)) {
638       bSwapRGB = true;
639       m_pColorSpace = nullptr;
640     }
641   } else {
642     if (components == 3) {
643       bSwapRGB = true;
644     } else if (components == 4) {
645       m_pColorSpace = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK);
646     }
647     m_nComponents = components;
648   }
649 
650   FXDIB_Format format;
651   if (components == 1) {
652     format = FXDIB_8bppRgb;
653   } else if (components <= 3) {
654     format = FXDIB_Rgb;
655   } else if (components == 4) {
656     format = FXDIB_Rgb32;
657   } else {
658     width = (width * components + 2) / 3;
659     format = FXDIB_Rgb;
660   }
661 
662   m_pCachedBitmap = pdfium::MakeUnique<CFX_DIBitmap>();
663   if (!m_pCachedBitmap->Create(width, height, format)) {
664     m_pCachedBitmap.reset();
665     return;
666   }
667   m_pCachedBitmap->Clear(0xFFFFFFFF);
668   std::vector<uint8_t> output_offsets(components);
669   for (uint32_t i = 0; i < components; ++i)
670     output_offsets[i] = i;
671   if (bSwapRGB) {
672     output_offsets[0] = 2;
673     output_offsets[2] = 0;
674   }
675   if (!pJpxModule->Decode(context->decoder(), m_pCachedBitmap->GetBuffer(),
676                           m_pCachedBitmap->GetPitch(), output_offsets)) {
677     m_pCachedBitmap.reset();
678     return;
679   }
680   if (m_pColorSpace && m_pColorSpace->GetFamily() == PDFCS_INDEXED &&
681       m_bpc < 8) {
682     int scale = 8 - m_bpc;
683     for (uint32_t row = 0; row < height; ++row) {
684       uint8_t* scanline =
685           const_cast<uint8_t*>(m_pCachedBitmap->GetScanline(row));
686       for (uint32_t col = 0; col < width; ++col) {
687         *scanline = (*scanline) >> scale;
688         ++scanline;
689       }
690     }
691   }
692   m_bpc = 8;
693 }
694 
StratLoadMask()695 int CPDF_DIBSource::StratLoadMask() {
696   m_MatteColor = 0XFFFFFFFF;
697   m_pMaskStream = m_pDict->GetStreamFor("SMask");
698   if (m_pMaskStream) {
699     CPDF_Array* pMatte = m_pMaskStream->GetDict()->GetArrayFor("Matte");
700     if (pMatte && m_pColorSpace &&
701         m_pColorSpace->CountComponents() <= m_nComponents) {
702       FX_FLOAT R, G, B;
703       std::vector<FX_FLOAT> colors(m_nComponents);
704       for (uint32_t i = 0; i < m_nComponents; i++) {
705         colors[i] = pMatte->GetFloatAt(i);
706       }
707       m_pColorSpace->GetRGB(colors.data(), R, G, B);
708       m_MatteColor = FXARGB_MAKE(0, FXSYS_round(R * 255), FXSYS_round(G * 255),
709                                  FXSYS_round(B * 255));
710     }
711     return StartLoadMaskDIB();
712   }
713 
714   m_pMaskStream = ToStream(m_pDict->GetDirectObjectFor("Mask"));
715   return m_pMaskStream ? StartLoadMaskDIB() : 1;
716 }
717 
ContinueLoadMaskDIB(IFX_Pause * pPause)718 int CPDF_DIBSource::ContinueLoadMaskDIB(IFX_Pause* pPause) {
719   if (!m_pMask) {
720     return 1;
721   }
722   int ret = m_pMask->ContinueLoadDIBSource(pPause);
723   if (ret == 2) {
724     return ret;
725   }
726   if (m_pColorSpace && m_bStdCS) {
727     m_pColorSpace->EnableStdConversion(false);
728   }
729   if (!ret) {
730     delete m_pMask;
731     m_pMask = nullptr;
732     return ret;
733   }
734   return 1;
735 }
736 
DetachMask()737 CPDF_DIBSource* CPDF_DIBSource::DetachMask() {
738   CPDF_DIBSource* pDIBSource = m_pMask;
739   m_pMask = nullptr;
740   return pDIBSource;
741 }
742 
StartLoadMaskDIB()743 int CPDF_DIBSource::StartLoadMaskDIB() {
744   m_pMask = new CPDF_DIBSource;
745   int ret = m_pMask->StartLoadDIBSource(m_pDocument, m_pMaskStream, false,
746                                         nullptr, nullptr, true);
747   if (ret == 2) {
748     if (m_Status == 0)
749       m_Status = 2;
750     return 2;
751   }
752   if (!ret) {
753     delete m_pMask;
754     m_pMask = nullptr;
755     return 1;
756   }
757   return 1;
758 }
759 
LoadPalette()760 void CPDF_DIBSource::LoadPalette() {
761   if (m_bpc == 0) {
762     return;
763   }
764   if (m_bpc * m_nComponents > 8) {
765     return;
766   }
767   if (!m_pColorSpace) {
768     return;
769   }
770   if (m_bpc * m_nComponents == 1) {
771     if (m_bDefaultDecode &&
772         (m_Family == PDFCS_DEVICEGRAY || m_Family == PDFCS_DEVICERGB)) {
773       return;
774     }
775     if (m_pColorSpace->CountComponents() > 3) {
776       return;
777     }
778     FX_FLOAT color_values[3];
779     color_values[0] = m_pCompData[0].m_DecodeMin;
780     color_values[1] = color_values[2] = color_values[0];
781     FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f;
782     m_pColorSpace->GetRGB(color_values, R, G, B);
783     FX_ARGB argb0 = ArgbEncode(255, FXSYS_round(R * 255), FXSYS_round(G * 255),
784                                FXSYS_round(B * 255));
785     color_values[0] += m_pCompData[0].m_DecodeStep;
786     color_values[1] += m_pCompData[0].m_DecodeStep;
787     color_values[2] += m_pCompData[0].m_DecodeStep;
788     m_pColorSpace->GetRGB(color_values, R, G, B);
789     FX_ARGB argb1 = ArgbEncode(255, FXSYS_round(R * 255), FXSYS_round(G * 255),
790                                FXSYS_round(B * 255));
791     if (argb0 != 0xFF000000 || argb1 != 0xFFFFFFFF) {
792       SetPaletteArgb(0, argb0);
793       SetPaletteArgb(1, argb1);
794     }
795     return;
796   }
797   if (m_pColorSpace == CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY) &&
798       m_bpc == 8 && m_bDefaultDecode) {
799   } else {
800     int palette_count = 1 << (m_bpc * m_nComponents);
801     CFX_FixedBufGrow<FX_FLOAT, 16> color_values(m_nComponents);
802     FX_FLOAT* color_value = color_values;
803     for (int i = 0; i < palette_count; i++) {
804       int color_data = i;
805       for (uint32_t j = 0; j < m_nComponents; j++) {
806         int encoded_component = color_data % (1 << m_bpc);
807         color_data /= 1 << m_bpc;
808         color_value[j] = m_pCompData[j].m_DecodeMin +
809                          m_pCompData[j].m_DecodeStep * encoded_component;
810       }
811       FX_FLOAT R = 0, G = 0, B = 0;
812       if (m_nComponents == 1 && m_Family == PDFCS_ICCBASED &&
813           m_pColorSpace->CountComponents() > 1) {
814         int nComponents = m_pColorSpace->CountComponents();
815         std::vector<FX_FLOAT> temp_buf(nComponents);
816         for (int k = 0; k < nComponents; k++) {
817           temp_buf[k] = *color_value;
818         }
819         m_pColorSpace->GetRGB(temp_buf.data(), R, G, B);
820       } else {
821         m_pColorSpace->GetRGB(color_value, R, G, B);
822       }
823       SetPaletteArgb(i, ArgbEncode(255, FXSYS_round(R * 255),
824                                    FXSYS_round(G * 255), FXSYS_round(B * 255)));
825     }
826   }
827 }
828 
ValidateDictParam()829 void CPDF_DIBSource::ValidateDictParam() {
830   m_bpc = m_bpc_orig;
831   CPDF_Object* pFilter = m_pDict->GetDirectObjectFor("Filter");
832   if (pFilter) {
833     if (pFilter->IsName()) {
834       CFX_ByteString filter = pFilter->GetString();
835       if (filter == "CCITTFaxDecode" || filter == "JBIG2Decode") {
836         m_bpc = 1;
837         m_nComponents = 1;
838       } else if (filter == "RunLengthDecode") {
839         if (m_bpc != 1) {
840           m_bpc = 8;
841         }
842       } else if (filter == "DCTDecode") {
843         m_bpc = 8;
844       }
845     } else if (CPDF_Array* pArray = pFilter->AsArray()) {
846       CFX_ByteString filter = pArray->GetStringAt(pArray->GetCount() - 1);
847       if (filter == "CCITTFaxDecode" || filter == "JBIG2Decode") {
848         m_bpc = 1;
849         m_nComponents = 1;
850       } else if (filter == "DCTDecode") {
851         // Previously, filter == "RunLengthDecode" was checked in the "if"
852         // statement as well, but too many documents don't conform to it.
853         m_bpc = 8;
854       }
855     }
856   }
857 
858   if (!IsAllowedBPCValue(m_bpc))
859     m_bpc = 0;
860 }
861 
TranslateScanline24bpp(uint8_t * dest_scan,const uint8_t * src_scan) const862 void CPDF_DIBSource::TranslateScanline24bpp(uint8_t* dest_scan,
863                                             const uint8_t* src_scan) const {
864   if (m_bpc == 0) {
865     return;
866   }
867   unsigned int max_data = (1 << m_bpc) - 1;
868   if (m_bDefaultDecode) {
869     if (m_Family == PDFCS_DEVICERGB || m_Family == PDFCS_CALRGB) {
870       if (m_nComponents != 3)
871         return;
872 
873       const uint8_t* src_pos = src_scan;
874       switch (m_bpc) {
875         case 16:
876           for (int col = 0; col < m_Width; col++) {
877             *dest_scan++ = src_pos[4];
878             *dest_scan++ = src_pos[2];
879             *dest_scan++ = *src_pos;
880             src_pos += 6;
881           }
882           break;
883         case 8:
884           for (int column = 0; column < m_Width; column++) {
885             *dest_scan++ = src_pos[2];
886             *dest_scan++ = src_pos[1];
887             *dest_scan++ = *src_pos;
888             src_pos += 3;
889           }
890           break;
891         default:
892           uint64_t src_bit_pos = 0;
893           size_t dest_byte_pos = 0;
894           for (int column = 0; column < m_Width; column++) {
895             unsigned int R = GetBits8(src_scan, src_bit_pos, m_bpc);
896             src_bit_pos += m_bpc;
897             unsigned int G = GetBits8(src_scan, src_bit_pos, m_bpc);
898             src_bit_pos += m_bpc;
899             unsigned int B = GetBits8(src_scan, src_bit_pos, m_bpc);
900             src_bit_pos += m_bpc;
901             R = std::min(R, max_data);
902             G = std::min(G, max_data);
903             B = std::min(B, max_data);
904             dest_scan[dest_byte_pos] = B * 255 / max_data;
905             dest_scan[dest_byte_pos + 1] = G * 255 / max_data;
906             dest_scan[dest_byte_pos + 2] = R * 255 / max_data;
907             dest_byte_pos += 3;
908           }
909           break;
910       }
911       return;
912     }
913     if (m_bpc == 8) {
914       if (m_nComponents == m_pColorSpace->CountComponents())
915         m_pColorSpace->TranslateImageLine(dest_scan, src_scan, m_Width, m_Width,
916                                           m_Height, TransMask());
917       return;
918     }
919   }
920   CFX_FixedBufGrow<FX_FLOAT, 16> color_values1(m_nComponents);
921   FX_FLOAT* color_values = color_values1;
922   FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f;
923   if (m_bpc == 8) {
924     uint64_t src_byte_pos = 0;
925     size_t dest_byte_pos = 0;
926     for (int column = 0; column < m_Width; column++) {
927       for (uint32_t color = 0; color < m_nComponents; color++) {
928         uint8_t data = src_scan[src_byte_pos++];
929         color_values[color] = m_pCompData[color].m_DecodeMin +
930                               m_pCompData[color].m_DecodeStep * data;
931       }
932       if (TransMask()) {
933         FX_FLOAT k = 1.0f - color_values[3];
934         R = (1.0f - color_values[0]) * k;
935         G = (1.0f - color_values[1]) * k;
936         B = (1.0f - color_values[2]) * k;
937       } else {
938         m_pColorSpace->GetRGB(color_values, R, G, B);
939       }
940       R = ClampValue(R, 1.0f);
941       G = ClampValue(G, 1.0f);
942       B = ClampValue(B, 1.0f);
943       dest_scan[dest_byte_pos] = static_cast<uint8_t>(B * 255);
944       dest_scan[dest_byte_pos + 1] = static_cast<uint8_t>(G * 255);
945       dest_scan[dest_byte_pos + 2] = static_cast<uint8_t>(R * 255);
946       dest_byte_pos += 3;
947     }
948   } else {
949     uint64_t src_bit_pos = 0;
950     size_t dest_byte_pos = 0;
951     for (int column = 0; column < m_Width; column++) {
952       for (uint32_t color = 0; color < m_nComponents; color++) {
953         unsigned int data = GetBits8(src_scan, src_bit_pos, m_bpc);
954         color_values[color] = m_pCompData[color].m_DecodeMin +
955                               m_pCompData[color].m_DecodeStep * data;
956         src_bit_pos += m_bpc;
957       }
958       if (TransMask()) {
959         FX_FLOAT k = 1.0f - color_values[3];
960         R = (1.0f - color_values[0]) * k;
961         G = (1.0f - color_values[1]) * k;
962         B = (1.0f - color_values[2]) * k;
963       } else {
964         m_pColorSpace->GetRGB(color_values, R, G, B);
965       }
966       R = ClampValue(R, 1.0f);
967       G = ClampValue(G, 1.0f);
968       B = ClampValue(B, 1.0f);
969       dest_scan[dest_byte_pos] = static_cast<uint8_t>(B * 255);
970       dest_scan[dest_byte_pos + 1] = static_cast<uint8_t>(G * 255);
971       dest_scan[dest_byte_pos + 2] = static_cast<uint8_t>(R * 255);
972       dest_byte_pos += 3;
973     }
974   }
975 }
976 
GetBuffer() const977 uint8_t* CPDF_DIBSource::GetBuffer() const {
978   return m_pCachedBitmap ? m_pCachedBitmap->GetBuffer() : nullptr;
979 }
980 
GetScanline(int line) const981 const uint8_t* CPDF_DIBSource::GetScanline(int line) const {
982   if (m_bpc == 0) {
983     return nullptr;
984   }
985   FX_SAFE_UINT32 src_pitch = CalculatePitch8(m_bpc, m_nComponents, m_Width);
986   if (!src_pitch.IsValid())
987     return nullptr;
988   uint32_t src_pitch_value = src_pitch.ValueOrDie();
989   const uint8_t* pSrcLine = nullptr;
990   if (m_pCachedBitmap && src_pitch_value <= m_pCachedBitmap->GetPitch()) {
991     if (line >= m_pCachedBitmap->GetHeight()) {
992       line = m_pCachedBitmap->GetHeight() - 1;
993     }
994     pSrcLine = m_pCachedBitmap->GetScanline(line);
995   } else if (m_pDecoder) {
996     pSrcLine = m_pDecoder->GetScanline(line);
997   } else {
998     if (m_pStreamAcc->GetSize() >= (line + 1) * src_pitch_value) {
999       pSrcLine = m_pStreamAcc->GetData() + line * src_pitch_value;
1000     }
1001   }
1002   if (!pSrcLine) {
1003     uint8_t* pLineBuf = m_pMaskedLine ? m_pMaskedLine : m_pLineBuf;
1004     FXSYS_memset(pLineBuf, 0xFF, m_Pitch);
1005     return pLineBuf;
1006   }
1007   if (m_bpc * m_nComponents == 1) {
1008     if (m_bImageMask && m_bDefaultDecode) {
1009       for (uint32_t i = 0; i < src_pitch_value; i++) {
1010         m_pLineBuf[i] = ~pSrcLine[i];
1011       }
1012     } else if (m_bColorKey) {
1013       uint32_t reset_argb, set_argb;
1014       reset_argb = m_pPalette ? m_pPalette.get()[0] : 0xFF000000;
1015       set_argb = m_pPalette ? m_pPalette.get()[1] : 0xFFFFFFFF;
1016       if (m_pCompData[0].m_ColorKeyMin == 0) {
1017         reset_argb = 0;
1018       }
1019       if (m_pCompData[0].m_ColorKeyMax == 1) {
1020         set_argb = 0;
1021       }
1022       set_argb = FXARGB_TODIB(set_argb);
1023       reset_argb = FXARGB_TODIB(reset_argb);
1024       uint32_t* dest_scan = reinterpret_cast<uint32_t*>(m_pMaskedLine);
1025       for (int col = 0; col < m_Width; col++) {
1026         if (pSrcLine[col / 8] & (1 << (7 - col % 8))) {
1027           *dest_scan = set_argb;
1028         } else {
1029           *dest_scan = reset_argb;
1030         }
1031         dest_scan++;
1032       }
1033       return m_pMaskedLine;
1034     } else {
1035       FXSYS_memcpy(m_pLineBuf, pSrcLine, src_pitch_value);
1036     }
1037     return m_pLineBuf;
1038   }
1039   if (m_bpc * m_nComponents <= 8) {
1040     if (m_bpc == 8) {
1041       FXSYS_memcpy(m_pLineBuf, pSrcLine, src_pitch_value);
1042     } else {
1043       uint64_t src_bit_pos = 0;
1044       for (int col = 0; col < m_Width; col++) {
1045         unsigned int color_index = 0;
1046         for (uint32_t color = 0; color < m_nComponents; color++) {
1047           unsigned int data = GetBits8(pSrcLine, src_bit_pos, m_bpc);
1048           color_index |= data << (color * m_bpc);
1049           src_bit_pos += m_bpc;
1050         }
1051         m_pLineBuf[col] = color_index;
1052       }
1053     }
1054     if (m_bColorKey) {
1055       uint8_t* pDestPixel = m_pMaskedLine;
1056       const uint8_t* pSrcPixel = m_pLineBuf;
1057       for (int col = 0; col < m_Width; col++) {
1058         uint8_t index = *pSrcPixel++;
1059         if (m_pPalette) {
1060           *pDestPixel++ = FXARGB_B(m_pPalette.get()[index]);
1061           *pDestPixel++ = FXARGB_G(m_pPalette.get()[index]);
1062           *pDestPixel++ = FXARGB_R(m_pPalette.get()[index]);
1063         } else {
1064           *pDestPixel++ = index;
1065           *pDestPixel++ = index;
1066           *pDestPixel++ = index;
1067         }
1068         *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin ||
1069                        index > m_pCompData[0].m_ColorKeyMax)
1070                           ? 0xFF
1071                           : 0;
1072         pDestPixel++;
1073       }
1074       return m_pMaskedLine;
1075     }
1076     return m_pLineBuf;
1077   }
1078   if (m_bColorKey) {
1079     if (m_nComponents == 3 && m_bpc == 8) {
1080       uint8_t* alpha_channel = m_pMaskedLine + 3;
1081       for (int col = 0; col < m_Width; col++) {
1082         const uint8_t* pPixel = pSrcLine + col * 3;
1083         alpha_channel[col * 4] = (pPixel[0] < m_pCompData[0].m_ColorKeyMin ||
1084                                   pPixel[0] > m_pCompData[0].m_ColorKeyMax ||
1085                                   pPixel[1] < m_pCompData[1].m_ColorKeyMin ||
1086                                   pPixel[1] > m_pCompData[1].m_ColorKeyMax ||
1087                                   pPixel[2] < m_pCompData[2].m_ColorKeyMin ||
1088                                   pPixel[2] > m_pCompData[2].m_ColorKeyMax)
1089                                      ? 0xFF
1090                                      : 0;
1091       }
1092     } else {
1093       FXSYS_memset(m_pMaskedLine, 0xFF, m_Pitch);
1094     }
1095   }
1096   if (m_pColorSpace) {
1097     TranslateScanline24bpp(m_pLineBuf, pSrcLine);
1098     pSrcLine = m_pLineBuf;
1099   }
1100   if (m_bColorKey) {
1101     const uint8_t* pSrcPixel = pSrcLine;
1102     uint8_t* pDestPixel = m_pMaskedLine;
1103     for (int col = 0; col < m_Width; col++) {
1104       *pDestPixel++ = *pSrcPixel++;
1105       *pDestPixel++ = *pSrcPixel++;
1106       *pDestPixel++ = *pSrcPixel++;
1107       pDestPixel++;
1108     }
1109     return m_pMaskedLine;
1110   }
1111   return pSrcLine;
1112 }
1113 
SkipToScanline(int line,IFX_Pause * pPause) const1114 bool CPDF_DIBSource::SkipToScanline(int line, IFX_Pause* pPause) const {
1115   return m_pDecoder && m_pDecoder->SkipToScanline(line, pPause);
1116 }
1117 
DownSampleScanline(int line,uint8_t * dest_scan,int dest_bpp,int dest_width,bool bFlipX,int clip_left,int clip_width) const1118 void CPDF_DIBSource::DownSampleScanline(int line,
1119                                         uint8_t* dest_scan,
1120                                         int dest_bpp,
1121                                         int dest_width,
1122                                         bool bFlipX,
1123                                         int clip_left,
1124                                         int clip_width) const {
1125   if (line < 0 || !dest_scan || dest_bpp <= 0 || dest_width <= 0 ||
1126       clip_left < 0 || clip_width <= 0) {
1127     return;
1128   }
1129 
1130   uint32_t src_width = m_Width;
1131   FX_SAFE_UINT32 pitch = CalculatePitch8(m_bpc, m_nComponents, m_Width);
1132   if (!pitch.IsValid())
1133     return;
1134 
1135   const uint8_t* pSrcLine = nullptr;
1136   if (m_pCachedBitmap) {
1137     pSrcLine = m_pCachedBitmap->GetScanline(line);
1138   } else if (m_pDecoder) {
1139     pSrcLine = m_pDecoder->GetScanline(line);
1140   } else {
1141     uint32_t src_pitch = pitch.ValueOrDie();
1142     pitch *= (line + 1);
1143     if (!pitch.IsValid()) {
1144       return;
1145     }
1146 
1147     if (m_pStreamAcc->GetSize() >= pitch.ValueOrDie()) {
1148       pSrcLine = m_pStreamAcc->GetData() + line * src_pitch;
1149     }
1150   }
1151   int orig_Bpp = m_bpc * m_nComponents / 8;
1152   int dest_Bpp = dest_bpp / 8;
1153   if (!pSrcLine) {
1154     FXSYS_memset(dest_scan, 0xFF, dest_Bpp * clip_width);
1155     return;
1156   }
1157 
1158   FX_SAFE_INT32 max_src_x = clip_left;
1159   max_src_x += clip_width - 1;
1160   max_src_x *= src_width;
1161   max_src_x /= dest_width;
1162   if (!max_src_x.IsValid())
1163     return;
1164 
1165   if (m_bpc * m_nComponents == 1) {
1166     DownSampleScanline1Bit(orig_Bpp, dest_Bpp, src_width, pSrcLine, dest_scan,
1167                            dest_width, bFlipX, clip_left, clip_width);
1168   } else if (m_bpc * m_nComponents <= 8) {
1169     DownSampleScanline8Bit(orig_Bpp, dest_Bpp, src_width, pSrcLine, dest_scan,
1170                            dest_width, bFlipX, clip_left, clip_width);
1171   } else {
1172     DownSampleScanline32Bit(orig_Bpp, dest_Bpp, src_width, pSrcLine, dest_scan,
1173                             dest_width, bFlipX, clip_left, clip_width);
1174   }
1175 }
1176 
DownSampleScanline1Bit(int orig_Bpp,int dest_Bpp,uint32_t src_width,const uint8_t * pSrcLine,uint8_t * dest_scan,int dest_width,bool bFlipX,int clip_left,int clip_width) const1177 void CPDF_DIBSource::DownSampleScanline1Bit(int orig_Bpp,
1178                                             int dest_Bpp,
1179                                             uint32_t src_width,
1180                                             const uint8_t* pSrcLine,
1181                                             uint8_t* dest_scan,
1182                                             int dest_width,
1183                                             bool bFlipX,
1184                                             int clip_left,
1185                                             int clip_width) const {
1186   uint32_t set_argb = (uint32_t)-1;
1187   uint32_t reset_argb = 0;
1188   if (m_bImageMask) {
1189     if (m_bDefaultDecode) {
1190       set_argb = 0;
1191       reset_argb = (uint32_t)-1;
1192     }
1193   } else if (m_bColorKey) {
1194     reset_argb = m_pPalette ? m_pPalette.get()[0] : 0xFF000000;
1195     set_argb = m_pPalette ? m_pPalette.get()[1] : 0xFFFFFFFF;
1196     if (m_pCompData[0].m_ColorKeyMin == 0) {
1197       reset_argb = 0;
1198     }
1199     if (m_pCompData[0].m_ColorKeyMax == 1) {
1200       set_argb = 0;
1201     }
1202     set_argb = FXARGB_TODIB(set_argb);
1203     reset_argb = FXARGB_TODIB(reset_argb);
1204     uint32_t* dest_scan_dword = reinterpret_cast<uint32_t*>(dest_scan);
1205     for (int i = 0; i < clip_width; i++) {
1206       uint32_t src_x = (clip_left + i) * src_width / dest_width;
1207       if (bFlipX) {
1208         src_x = src_width - src_x - 1;
1209       }
1210       src_x %= src_width;
1211       if (pSrcLine[src_x / 8] & (1 << (7 - src_x % 8))) {
1212         dest_scan_dword[i] = set_argb;
1213       } else {
1214         dest_scan_dword[i] = reset_argb;
1215       }
1216     }
1217     return;
1218   } else {
1219     if (dest_Bpp == 1) {
1220     } else if (m_pPalette) {
1221       reset_argb = m_pPalette.get()[0];
1222       set_argb = m_pPalette.get()[1];
1223     }
1224   }
1225   for (int i = 0; i < clip_width; i++) {
1226     uint32_t src_x = (clip_left + i) * src_width / dest_width;
1227     if (bFlipX) {
1228       src_x = src_width - src_x - 1;
1229     }
1230     src_x %= src_width;
1231     int dest_pos = i * dest_Bpp;
1232     if (pSrcLine[src_x / 8] & (1 << (7 - src_x % 8))) {
1233       if (dest_Bpp == 1) {
1234         dest_scan[dest_pos] = static_cast<uint8_t>(set_argb);
1235       } else if (dest_Bpp == 3) {
1236         dest_scan[dest_pos] = FXARGB_B(set_argb);
1237         dest_scan[dest_pos + 1] = FXARGB_G(set_argb);
1238         dest_scan[dest_pos + 2] = FXARGB_R(set_argb);
1239       } else {
1240         *reinterpret_cast<uint32_t*>(dest_scan + dest_pos) = set_argb;
1241       }
1242     } else {
1243       if (dest_Bpp == 1) {
1244         dest_scan[dest_pos] = static_cast<uint8_t>(reset_argb);
1245       } else if (dest_Bpp == 3) {
1246         dest_scan[dest_pos] = FXARGB_B(reset_argb);
1247         dest_scan[dest_pos + 1] = FXARGB_G(reset_argb);
1248         dest_scan[dest_pos + 2] = FXARGB_R(reset_argb);
1249       } else {
1250         *reinterpret_cast<uint32_t*>(dest_scan + dest_pos) = reset_argb;
1251       }
1252     }
1253   }
1254 }
1255 
DownSampleScanline8Bit(int orig_Bpp,int dest_Bpp,uint32_t src_width,const uint8_t * pSrcLine,uint8_t * dest_scan,int dest_width,bool bFlipX,int clip_left,int clip_width) const1256 void CPDF_DIBSource::DownSampleScanline8Bit(int orig_Bpp,
1257                                             int dest_Bpp,
1258                                             uint32_t src_width,
1259                                             const uint8_t* pSrcLine,
1260                                             uint8_t* dest_scan,
1261                                             int dest_width,
1262                                             bool bFlipX,
1263                                             int clip_left,
1264                                             int clip_width) const {
1265   if (m_bpc < 8) {
1266     uint64_t src_bit_pos = 0;
1267     for (uint32_t col = 0; col < src_width; col++) {
1268       unsigned int color_index = 0;
1269       for (uint32_t color = 0; color < m_nComponents; color++) {
1270         unsigned int data = GetBits8(pSrcLine, src_bit_pos, m_bpc);
1271         color_index |= data << (color * m_bpc);
1272         src_bit_pos += m_bpc;
1273       }
1274       m_pLineBuf[col] = color_index;
1275     }
1276     pSrcLine = m_pLineBuf;
1277   }
1278   if (m_bColorKey) {
1279     for (int i = 0; i < clip_width; i++) {
1280       uint32_t src_x = (clip_left + i) * src_width / dest_width;
1281       if (bFlipX) {
1282         src_x = src_width - src_x - 1;
1283       }
1284       src_x %= src_width;
1285       uint8_t* pDestPixel = dest_scan + i * 4;
1286       uint8_t index = pSrcLine[src_x];
1287       if (m_pPalette) {
1288         *pDestPixel++ = FXARGB_B(m_pPalette.get()[index]);
1289         *pDestPixel++ = FXARGB_G(m_pPalette.get()[index]);
1290         *pDestPixel++ = FXARGB_R(m_pPalette.get()[index]);
1291       } else {
1292         *pDestPixel++ = index;
1293         *pDestPixel++ = index;
1294         *pDestPixel++ = index;
1295       }
1296       *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin ||
1297                      index > m_pCompData[0].m_ColorKeyMax)
1298                         ? 0xFF
1299                         : 0;
1300     }
1301     return;
1302   }
1303   for (int i = 0; i < clip_width; i++) {
1304     uint32_t src_x = (clip_left + i) * src_width / dest_width;
1305     if (bFlipX) {
1306       src_x = src_width - src_x - 1;
1307     }
1308     src_x %= src_width;
1309     uint8_t index = pSrcLine[src_x];
1310     if (dest_Bpp == 1) {
1311       dest_scan[i] = index;
1312     } else {
1313       int dest_pos = i * dest_Bpp;
1314       FX_ARGB argb = m_pPalette.get()[index];
1315       dest_scan[dest_pos] = FXARGB_B(argb);
1316       dest_scan[dest_pos + 1] = FXARGB_G(argb);
1317       dest_scan[dest_pos + 2] = FXARGB_R(argb);
1318     }
1319   }
1320 }
1321 
DownSampleScanline32Bit(int orig_Bpp,int dest_Bpp,uint32_t src_width,const uint8_t * pSrcLine,uint8_t * dest_scan,int dest_width,bool bFlipX,int clip_left,int clip_width) const1322 void CPDF_DIBSource::DownSampleScanline32Bit(int orig_Bpp,
1323                                              int dest_Bpp,
1324                                              uint32_t src_width,
1325                                              const uint8_t* pSrcLine,
1326                                              uint8_t* dest_scan,
1327                                              int dest_width,
1328                                              bool bFlipX,
1329                                              int clip_left,
1330                                              int clip_width) const {
1331   // last_src_x used to store the last seen src_x position which should be
1332   // in [0, src_width). Set the initial value to be an invalid src_x value.
1333   uint32_t last_src_x = src_width;
1334   FX_ARGB last_argb = FXARGB_MAKE(0xFF, 0xFF, 0xFF, 0xFF);
1335   FX_FLOAT unit_To8Bpc = 255.0f / ((1 << m_bpc) - 1);
1336   for (int i = 0; i < clip_width; i++) {
1337     int dest_x = clip_left + i;
1338     uint32_t src_x = (bFlipX ? (dest_width - dest_x - 1) : dest_x) *
1339                      (int64_t)src_width / dest_width;
1340     src_x %= src_width;
1341 
1342     uint8_t* pDestPixel = dest_scan + i * dest_Bpp;
1343     FX_ARGB argb;
1344     if (src_x == last_src_x) {
1345       argb = last_argb;
1346     } else {
1347       CFX_FixedBufGrow<uint8_t, 128> extracted_components(m_nComponents);
1348       const uint8_t* pSrcPixel = nullptr;
1349       if (m_bpc % 8 != 0) {
1350         // No need to check for 32-bit overflow, as |src_x| is bounded by
1351         // |src_width| and DownSampleScanline() already checked for overflow
1352         // with the pitch calculation.
1353         size_t num_bits = src_x * m_bpc * m_nComponents;
1354         uint64_t src_bit_pos = num_bits % 8;
1355         pSrcPixel = pSrcLine + num_bits / 8;
1356         for (uint32_t j = 0; j < m_nComponents; ++j) {
1357           extracted_components[j] = static_cast<uint8_t>(
1358               GetBits8(pSrcPixel, src_bit_pos, m_bpc) * unit_To8Bpc);
1359           src_bit_pos += m_bpc;
1360         }
1361         pSrcPixel = extracted_components;
1362       } else {
1363         pSrcPixel = pSrcLine + src_x * orig_Bpp;
1364         if (m_bpc == 16) {
1365           for (uint32_t j = 0; j < m_nComponents; ++j)
1366             extracted_components[j] = pSrcPixel[j * 2];
1367           pSrcPixel = extracted_components;
1368         }
1369       }
1370 
1371       if (m_pColorSpace) {
1372         uint8_t color[4];
1373         const bool bTransMask = TransMask();
1374         if (m_bDefaultDecode) {
1375           m_pColorSpace->TranslateImageLine(color, pSrcPixel, 1, 0, 0,
1376                                             bTransMask);
1377         } else {
1378           for (uint32_t j = 0; j < m_nComponents; ++j) {
1379             FX_FLOAT component_value =
1380                 static_cast<FX_FLOAT>(extracted_components[j]);
1381             int color_value = static_cast<int>(
1382                 (m_pCompData[j].m_DecodeMin +
1383                  m_pCompData[j].m_DecodeStep * component_value) *
1384                     255.0f +
1385                 0.5f);
1386             extracted_components[j] =
1387                 color_value > 255 ? 255 : (color_value < 0 ? 0 : color_value);
1388           }
1389           m_pColorSpace->TranslateImageLine(color, extracted_components, 1, 0,
1390                                             0, bTransMask);
1391         }
1392         argb = FXARGB_MAKE(0xFF, color[2], color[1], color[0]);
1393       } else {
1394         argb = FXARGB_MAKE(0xFF, pSrcPixel[2], pSrcPixel[1], pSrcPixel[0]);
1395       }
1396       if (m_bColorKey) {
1397         int alpha = 0xFF;
1398         if (m_nComponents == 3 && m_bpc == 8) {
1399           alpha = (pSrcPixel[0] < m_pCompData[0].m_ColorKeyMin ||
1400                    pSrcPixel[0] > m_pCompData[0].m_ColorKeyMax ||
1401                    pSrcPixel[1] < m_pCompData[1].m_ColorKeyMin ||
1402                    pSrcPixel[1] > m_pCompData[1].m_ColorKeyMax ||
1403                    pSrcPixel[2] < m_pCompData[2].m_ColorKeyMin ||
1404                    pSrcPixel[2] > m_pCompData[2].m_ColorKeyMax)
1405                       ? 0xFF
1406                       : 0;
1407         }
1408         argb &= 0xFFFFFF;
1409         argb |= alpha << 24;
1410       }
1411       last_src_x = src_x;
1412       last_argb = argb;
1413     }
1414     if (dest_Bpp == 4) {
1415       *reinterpret_cast<uint32_t*>(pDestPixel) = FXARGB_TODIB(argb);
1416     } else {
1417       *pDestPixel++ = FXARGB_B(argb);
1418       *pDestPixel++ = FXARGB_G(argb);
1419       *pDestPixel = FXARGB_R(argb);
1420     }
1421   }
1422 }
1423 
TransMask() const1424 bool CPDF_DIBSource::TransMask() const {
1425   return m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK &&
1426          m_Family == PDFCS_DEVICECMYK;
1427 }
1428