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