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