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