Remove "this==NULL" and adjust corresponding callers
[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 FX_DWORD CPDF_DIBSource::GetValidBpp() const
915 {
916     FX_DWORD bpc = m_bpc;
917         CPDF_Object * pFilter = m_pDict ? m_pDict->GetElementValue(FX_BSTRC("Filter")) : NULL;
918     if (pFilter) {
919         if (pFilter->GetType() == PDFOBJ_NAME) {
920             CFX_ByteString filter = pFilter->GetString();
921             if (filter == FX_BSTRC("CCITTFaxDecode") || filter == FX_BSTRC("JBIG2Decode")) {
922                 bpc = 1;
923             }
924             if (filter == FX_BSTRC("RunLengthDecode") || filter == FX_BSTRC("DCTDecode")) {
925                 bpc = 8;
926             }
927         } else if (pFilter->GetType() == PDFOBJ_ARRAY) {
928             CPDF_Array *pArray = (CPDF_Array *)pFilter;
929             if (pArray->GetString(pArray->GetCount() - 1) == FX_BSTRC("CCITTFacDecode") ||
930                     pArray->GetString(pArray->GetCount() - 1) == FX_BSTRC("JBIG2Decode")) {
931                 bpc = 1;
932             }
933             if (pArray->GetString(pArray->GetCount() - 1) == FX_BSTRC("RunLengthDecode") ||
934                     pArray->GetString(pArray->GetCount() - 1) == FX_BSTRC("DCTDecode")) {
935                 bpc = 8;
936             }
937         }
938     }
939     return bpc;
940 }
941 #define NORMALCOLOR_MAX(color, max) (color) > (max) ? (max) : (color) < 0 ? 0 : (color);
942 void CPDF_DIBSource::TranslateScanline24bpp(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan) const
943 {
944     int max_data = (1 << m_bpc) - 1;
945     if (m_bDefaultDecode) {
946         if (m_Family == PDFCS_DEVICERGB || m_Family == PDFCS_CALRGB) {
947             if (m_bpc == 16) {
948                 FX_LPBYTE dest_pos = dest_scan;
949                 FX_LPCBYTE src_pos = src_scan;
950                 for (int col = 0; col < m_Width; col ++) {
951                     *dest_scan++ = src_pos[4];
952                     *dest_scan++ = src_pos[2];
953                     *dest_scan++ = *src_pos;
954                     src_pos += 6;
955                 }
956             } else if (m_bpc == 8) {
957                 FX_LPBYTE dest_pos = dest_scan;
958                 FX_LPCBYTE src_pos = src_scan;
959                 for (int column = 0; column < m_Width; column ++) {
960                     *dest_scan++ = src_pos[2];
961                     *dest_scan++ = src_pos[1];
962                     *dest_scan++ = *src_pos;
963                     src_pos += 3;
964                 }
965             } else {
966                 int src_bit_pos = 0;
967                 int dest_byte_pos = 0;
968                 FX_DWORD bpc = GetValidBpp();
969                 for (int column = 0; column < m_Width; column ++) {
970                     int R = _GetBits8(src_scan, src_bit_pos, bpc);
971                     src_bit_pos += bpc;
972                     int G = _GetBits8(src_scan, src_bit_pos, bpc);
973                     src_bit_pos += bpc;
974                     int B = _GetBits8(src_scan, src_bit_pos, bpc);
975                     src_bit_pos += bpc;
976                     R = NORMALCOLOR_MAX(R, max_data);
977                     G = NORMALCOLOR_MAX(G, max_data);
978                     B = NORMALCOLOR_MAX(B, max_data);
979                     dest_scan[dest_byte_pos] = B * 255 / max_data;
980                     dest_scan[dest_byte_pos + 1] = G * 255 / max_data;
981                     dest_scan[dest_byte_pos + 2] = R * 255 / max_data;
982                     dest_byte_pos += 3;
983                 }
984             }
985             return;
986         } else if (m_bpc == 8) {
987             if (m_nComponents == m_pColorSpace->CountComponents())
988                 m_pColorSpace->TranslateImageLine(dest_scan, src_scan, m_Width, m_Width, m_Height,
989                                                   m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK);
990             return;
991         }
992     }
993     CFX_FixedBufGrow<FX_FLOAT, 16> color_values1(m_nComponents);
994     FX_FLOAT* color_values = color_values1;
995     FX_FLOAT R, G, B;
996     if (m_bpc == 8) {
997         int src_byte_pos = 0;
998         int dest_byte_pos = 0;
999         for (int column = 0; column < m_Width; column ++) {
1000             for (FX_DWORD color = 0; color < m_nComponents; color ++) {
1001                 int data = src_scan[src_byte_pos ++];
1002                 color_values[color] = m_pCompData[color].m_DecodeMin +
1003                                       m_pCompData[color].m_DecodeStep * data;
1004             }
1005             if (m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK) {
1006                 FX_FLOAT k = 1.0f - color_values[3];
1007                 R = (1.0f - color_values[0]) * k;
1008                 G = (1.0f - color_values[1]) * k;
1009                 B = (1.0f - color_values[2]) * k;
1010             } else {
1011                 m_pColorSpace->GetRGB(color_values, R, G, B);
1012             }
1013             R = NORMALCOLOR_MAX(R, 1);
1014             G = NORMALCOLOR_MAX(G, 1);
1015             B = NORMALCOLOR_MAX(B, 1);
1016             dest_scan[dest_byte_pos] = (FX_INT32)(B * 255);
1017             dest_scan[dest_byte_pos + 1] = (FX_INT32)(G * 255);
1018             dest_scan[dest_byte_pos + 2] = (FX_INT32)(R * 255);
1019             dest_byte_pos += 3;
1020         }
1021     } else {
1022         int src_bit_pos = 0;
1023         int dest_byte_pos = 0;
1024         FX_DWORD bpc = GetValidBpp();
1025         for (int column = 0; column < m_Width; column ++) {
1026             for (FX_DWORD color = 0; color < m_nComponents; color ++) {
1027                 int data = _GetBits8(src_scan, src_bit_pos, bpc);
1028                 color_values[color] = m_pCompData[color].m_DecodeMin +
1029                                       m_pCompData[color].m_DecodeStep * data;
1030                 src_bit_pos += bpc;
1031             }
1032             if (m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK) {
1033                 FX_FLOAT k = 1.0f - color_values[3];
1034                 R = (1.0f - color_values[0]) * k;
1035                 G = (1.0f - color_values[1]) * k;
1036                 B = (1.0f - color_values[2]) * k;
1037             } else {
1038                 m_pColorSpace->GetRGB(color_values, R, G, B);
1039             }
1040             R = NORMALCOLOR_MAX(R, 1);
1041             G = NORMALCOLOR_MAX(G, 1);
1042             B = NORMALCOLOR_MAX(B, 1);
1043             dest_scan[dest_byte_pos] = (FX_INT32)(B * 255);
1044             dest_scan[dest_byte_pos + 1] = (FX_INT32)(G * 255);
1045             dest_scan[dest_byte_pos + 2] = (FX_INT32)(R * 255);
1046             dest_byte_pos += 3;
1047         }
1048     }
1049 }
1050 FX_LPBYTE CPDF_DIBSource::GetBuffer() const
1051 {
1052     if (m_pCachedBitmap) {
1053         return m_pCachedBitmap->GetBuffer();
1054     }
1055     return NULL;
1056 }
1057 FX_LPCBYTE CPDF_DIBSource::GetScanline(int line) const
1058 {
1059     FX_DWORD src_pitch = (m_Width * m_bpc * m_nComponents + 7) / 8;
1060     FX_LPCBYTE pSrcLine = NULL;
1061     if (m_pCachedBitmap) {
1062         if (line >= m_pCachedBitmap->GetHeight()) {
1063             line = m_pCachedBitmap->GetHeight() - 1;
1064         }
1065         pSrcLine = m_pCachedBitmap->GetScanline(line);
1066     } else if (m_pDecoder) {
1067         pSrcLine = m_pDecoder->GetScanline(line);
1068     } else {
1069         if (m_pStreamAcc->GetSize() >= (line + 1) * src_pitch) {
1070             pSrcLine = m_pStreamAcc->GetData() + line * src_pitch;
1071         }
1072     }
1073     if (pSrcLine == NULL) {
1074         FX_LPBYTE pLineBuf = m_pMaskedLine ? m_pMaskedLine : m_pLineBuf;
1075         FXSYS_memset8(pLineBuf, 0xff, m_Pitch);
1076         return pLineBuf;
1077     }
1078     if (m_bpc * m_nComponents == 1) {
1079         if (m_bImageMask && m_bDefaultDecode) {
1080             for (FX_DWORD i = 0; i < src_pitch; i ++) {
1081                 m_pLineBuf[i] = ~pSrcLine[i];
1082             }
1083         } else if (m_bColorKey) {
1084             FX_DWORD reset_argb, set_argb;
1085             reset_argb = m_pPalette ? m_pPalette[0] : 0xff000000;
1086             set_argb = m_pPalette ? m_pPalette[1] : 0xffffffff;
1087             if (m_pCompData[0].m_ColorKeyMin == 0) {
1088                 reset_argb = 0;
1089             }
1090             if (m_pCompData[0].m_ColorKeyMax == 1) {
1091                 set_argb = 0;
1092             }
1093             set_argb = FXARGB_TODIB(set_argb);
1094             reset_argb = FXARGB_TODIB(reset_argb);
1095             FX_DWORD* dest_scan = (FX_DWORD*)m_pMaskedLine;
1096             for (int col = 0; col < m_Width; col ++) {
1097                 if (pSrcLine[col / 8] & (1 << (7 - col % 8))) {
1098                     *dest_scan = set_argb;
1099                 } else {
1100                     *dest_scan = reset_argb;
1101                 }
1102                 dest_scan ++;
1103             }
1104             return m_pMaskedLine;
1105         } else {
1106             FXSYS_memcpy32(m_pLineBuf, pSrcLine, src_pitch);
1107         }
1108         return m_pLineBuf;
1109     }
1110     if (m_bpc * m_nComponents <= 8) {
1111         if (m_bpc == 8) {
1112             FXSYS_memcpy32(m_pLineBuf, pSrcLine, src_pitch);
1113         } else {
1114             int src_bit_pos = 0;
1115             for (int col = 0; col < m_Width; col ++) {
1116                 int color_index = 0;
1117                 for (FX_DWORD color = 0; color < m_nComponents; color ++) {
1118                     int data = _GetBits8(pSrcLine, src_bit_pos, m_bpc);
1119                     color_index |= data << (color * m_bpc);
1120                     src_bit_pos += m_bpc;
1121                 }
1122                 m_pLineBuf[col] = color_index;
1123             }
1124         }
1125         if (m_bColorKey) {
1126             FX_LPBYTE pDestPixel = m_pMaskedLine;
1127             FX_LPCBYTE pSrcPixel = m_pLineBuf;
1128             for (int col = 0; col < m_Width; col ++) {
1129                 FX_BYTE index = *pSrcPixel++;
1130                 if (m_pPalette) {
1131                     *pDestPixel++ = FXARGB_B(m_pPalette[index]);
1132                     *pDestPixel++ = FXARGB_G(m_pPalette[index]);
1133                     *pDestPixel++ = FXARGB_R(m_pPalette[index]);
1134                 } else {
1135                     *pDestPixel++ = index;
1136                     *pDestPixel++ = index;
1137                     *pDestPixel++ = index;
1138                 }
1139                 *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin || index > m_pCompData[0].m_ColorKeyMax) ? 0xff : 0;
1140                 pDestPixel ++ ;
1141             }
1142             return m_pMaskedLine;
1143         }
1144         return m_pLineBuf;
1145     }
1146     if (m_bColorKey) {
1147         if (m_nComponents == 3 && m_bpc == 8) {
1148             FX_LPBYTE alpha_channel = m_pMaskedLine + 3;
1149             for (int col = 0; col < m_Width; col ++) {
1150                 FX_LPCBYTE pPixel = pSrcLine + col * 3;
1151                 alpha_channel[col * 4] = (pPixel[0] < m_pCompData[0].m_ColorKeyMin ||
1152                                           pPixel[0] > m_pCompData[0].m_ColorKeyMax ||
1153                                           pPixel[1] < m_pCompData[1].m_ColorKeyMin || pPixel[1] > m_pCompData[1].m_ColorKeyMax ||
1154                                           pPixel[2] < m_pCompData[2].m_ColorKeyMin || pPixel[2] > m_pCompData[2].m_ColorKeyMax) ? 0xff : 0;
1155             }
1156         } else {
1157             FXSYS_memset8(m_pMaskedLine, 0xff, m_Pitch);
1158         }
1159     }
1160     if (m_pColorSpace) {
1161         TranslateScanline24bpp(m_pLineBuf, pSrcLine);
1162         pSrcLine = m_pLineBuf;
1163     }
1164     if (m_bColorKey) {
1165         FX_LPCBYTE pSrcPixel = pSrcLine;
1166         FX_LPBYTE pDestPixel = m_pMaskedLine;
1167         for (int col = 0; col < m_Width; col ++) {
1168             *pDestPixel++ = *pSrcPixel++;
1169             *pDestPixel++ = *pSrcPixel++;
1170             *pDestPixel++ = *pSrcPixel++;
1171             pDestPixel ++;
1172         }
1173         return m_pMaskedLine;
1174     }
1175     return pSrcLine;
1176 }
1177 FX_BOOL CPDF_DIBSource::SkipToScanline(int line, IFX_Pause* pPause) const
1178 {
1179     if (m_pDecoder) {
1180         return m_pDecoder->SkipToScanline(line, pPause);
1181     }
1182     return FALSE;
1183 }
1184 void CPDF_DIBSource::DownSampleScanline(int line, FX_LPBYTE dest_scan, int dest_bpp,
1185                                         int dest_width, FX_BOOL bFlipX, int clip_left, int clip_width) const
1186 {
1187     FX_DWORD src_width = m_Width;
1188     FX_DWORD src_pitch = (src_width * m_bpc * m_nComponents + 7) / 8;
1189     FX_LPCBYTE pSrcLine = NULL;
1190     if (m_pCachedBitmap) {
1191         pSrcLine = m_pCachedBitmap->GetScanline(line);
1192     } else if (m_pDecoder) {
1193         pSrcLine = m_pDecoder->GetScanline(line);
1194     } else {
1195         if (m_pStreamAcc->GetSize() >= (line + 1) * src_pitch) {
1196             pSrcLine = m_pStreamAcc->GetData() + line * src_pitch;
1197         }
1198     }
1199     int orig_Bpp = m_bpc * m_nComponents / 8;
1200     int dest_Bpp = dest_bpp / 8;
1201     if (pSrcLine == NULL) {
1202         FXSYS_memset32(dest_scan, 0xff, dest_Bpp * clip_width);
1203         return;
1204     }
1205     CFX_FixedBufGrow<FX_BYTE, 128> temp(orig_Bpp);
1206     if (m_bpc * m_nComponents == 1) {
1207         FX_DWORD set_argb = (FX_DWORD) - 1, reset_argb = 0;
1208         if (m_bImageMask) {
1209             if (m_bDefaultDecode) {
1210                 set_argb = 0;
1211                 reset_argb = (FX_DWORD) - 1;
1212             }
1213         } else if (m_bColorKey) {
1214             reset_argb = m_pPalette ? m_pPalette[0] : 0xff000000;
1215             set_argb = m_pPalette ? m_pPalette[1] : 0xffffffff;
1216             if (m_pCompData[0].m_ColorKeyMin == 0) {
1217                 reset_argb = 0;
1218             }
1219             if (m_pCompData[0].m_ColorKeyMax == 1) {
1220                 set_argb = 0;
1221             }
1222             set_argb = FXARGB_TODIB(set_argb);
1223             reset_argb = FXARGB_TODIB(reset_argb);
1224             for (int i = 0; i < clip_width; i ++) {
1225                 FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
1226                 if (bFlipX) {
1227                     src_x = src_width - src_x - 1;
1228                 }
1229                 src_x %= src_width;
1230                 if (pSrcLine[src_x / 8] & (1 << (7 - src_x % 8))) {
1231                     ((FX_DWORD*)dest_scan)[i] = set_argb;
1232                 } else {
1233                     ((FX_DWORD*)dest_scan)[i] = reset_argb;
1234                 }
1235             }
1236             return;
1237         } else {
1238             if (dest_Bpp == 1) {
1239             } else if (m_pPalette) {
1240                 reset_argb = m_pPalette[0];
1241                 set_argb = m_pPalette[1];
1242             }
1243         }
1244         for (int i = 0; i < clip_width; i ++) {
1245             FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
1246             if (bFlipX) {
1247                 src_x = src_width - src_x - 1;
1248             }
1249             src_x %= src_width;
1250             int dest_pos = i * dest_Bpp;
1251             if (pSrcLine[src_x / 8] & (1 << (7 - src_x % 8))) {
1252                 if (dest_Bpp == 1) {
1253                     dest_scan[dest_pos] = (FX_BYTE)set_argb;
1254                 } else if (dest_Bpp == 3) {
1255                     dest_scan[dest_pos] = FXARGB_B(set_argb);
1256                     dest_scan[dest_pos + 1] = FXARGB_G(set_argb);
1257                     dest_scan[dest_pos + 2] = FXARGB_R(set_argb);
1258                 } else {
1259                     *(FX_DWORD*)(dest_scan + dest_pos) = set_argb;
1260                 }
1261             } else {
1262                 if (dest_Bpp == 1) {
1263                     dest_scan[dest_pos] = (FX_BYTE)reset_argb;
1264                 } else if (dest_Bpp == 3) {
1265                     dest_scan[dest_pos] = FXARGB_B(reset_argb);
1266                     dest_scan[dest_pos + 1] = FXARGB_G(reset_argb);
1267                     dest_scan[dest_pos + 2] = FXARGB_R(reset_argb);
1268                 } else {
1269                     *(FX_DWORD*)(dest_scan + dest_pos) = reset_argb;
1270                 }
1271             }
1272         }
1273         return;
1274     } else if (m_bpc * m_nComponents <= 8) {
1275         if (m_bpc < 8) {
1276             int src_bit_pos = 0;
1277             for (FX_DWORD col = 0; col < src_width; col ++) {
1278                 int color_index = 0;
1279                 for (FX_DWORD color = 0; color < m_nComponents; color ++) {
1280                     int data = _GetBits8(pSrcLine, src_bit_pos, m_bpc);
1281                     color_index |= data << (color * m_bpc);
1282                     src_bit_pos += m_bpc;
1283                 }
1284                 m_pLineBuf[col] = color_index;
1285             }
1286             pSrcLine = m_pLineBuf;
1287         }
1288         if (m_bColorKey) {
1289             for (int i = 0; i < clip_width; i ++) {
1290                 FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
1291                 if (bFlipX) {
1292                     src_x = src_width - src_x - 1;
1293                 }
1294                 src_x %= src_width;
1295                 FX_LPBYTE pDestPixel = dest_scan + i * 4;
1296                 FX_BYTE index = pSrcLine[src_x];
1297                 if (m_pPalette) {
1298                     *pDestPixel++ = FXARGB_B(m_pPalette[index]);
1299                     *pDestPixel++ = FXARGB_G(m_pPalette[index]);
1300                     *pDestPixel++ = FXARGB_R(m_pPalette[index]);
1301                 } else {
1302                     *pDestPixel++ = index;
1303                     *pDestPixel++ = index;
1304                     *pDestPixel++ = index;
1305                 }
1306                 *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin || index > m_pCompData[0].m_ColorKeyMax) ? 0xff : 0;
1307             }
1308             return;
1309         }
1310         for (int i = 0; i < clip_width; i ++) {
1311             FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
1312             if (bFlipX) {
1313                 src_x = src_width - src_x - 1;
1314             }
1315             src_x %= src_width;
1316             FX_BYTE index = pSrcLine[src_x];
1317             if (dest_Bpp == 1) {
1318                 dest_scan[i] = index;
1319             } else {
1320                 int dest_pos = i * dest_Bpp;
1321                 FX_ARGB argb = m_pPalette[index];
1322                 dest_scan[dest_pos] = FXARGB_B(argb);
1323                 dest_scan[dest_pos + 1] = FXARGB_G(argb);
1324                 dest_scan[dest_pos + 2] = FXARGB_R(argb);
1325             }
1326         }
1327         return;
1328     } else {
1329         int last_src_x = -1;
1330         FX_ARGB last_argb;
1331         FX_FLOAT orig_Not8Bpp = (FX_FLOAT)m_bpc * (FX_FLOAT)m_nComponents / 8.0f;
1332         FX_FLOAT unit_To8Bpc = 255.0f / ((1 << m_bpc) - 1);
1333         for (int i = 0; i < clip_width; i ++) {
1334             int dest_x = clip_left + i;
1335             FX_DWORD src_x = (bFlipX ? (dest_width - dest_x - 1) : dest_x) * (FX_INT64)src_width / dest_width;
1336             src_x %= src_width;
1337             FX_LPCBYTE pSrcPixel = NULL;
1338             if (m_bpc % 8 == 0) {
1339                 pSrcPixel = pSrcLine + src_x * orig_Bpp;
1340             } else {
1341                 pSrcPixel = pSrcLine + (int)(src_x * orig_Not8Bpp);
1342             }
1343             FX_LPBYTE pDestPixel = dest_scan + i * dest_Bpp;
1344             FX_ARGB argb;
1345             if (src_x == last_src_x) {
1346                 argb = last_argb;
1347             } else {
1348                 if (m_pColorSpace) {
1349                     FX_BYTE color[4];
1350                     if (!m_bDefaultDecode) {
1351                         for (int i = 0; i < orig_Bpp; i ++) {
1352                             int color_value = (int)((m_pCompData[i].m_DecodeMin + m_pCompData[i].m_DecodeStep * (FX_FLOAT)pSrcPixel[i]) * 255.0f + 0.5f);
1353                             temp[i] = color_value > 255 ? 255 : (color_value < 0 ? 0 : color_value);
1354                         }
1355                         m_pColorSpace->TranslateImageLine(color, temp, 1, 0, 0, m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK);
1356                     } else {
1357                         if (m_bpc < 8) {
1358                             int src_bit_pos = 0;
1359                             if (src_x % 2) {
1360                                 src_bit_pos = 4;
1361                             }
1362                             int value = (1 << m_bpc)  - 1;
1363                             for (FX_DWORD i = 0; i < m_nComponents; i ++) {
1364                                 temp[i] = (FX_BYTE)(_GetBits8(pSrcPixel, src_bit_pos, m_bpc) * unit_To8Bpc);
1365                                 src_bit_pos += m_bpc;
1366                             }
1367                             m_pColorSpace->TranslateImageLine(color, temp, 1, 0, 0, m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK);
1368                         } else {
1369                             m_pColorSpace->TranslateImageLine(color, pSrcPixel, 1, 0, 0, m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK);
1370                         }
1371                     }
1372                     argb = FXARGB_MAKE(0xff, color[2], color[1], color[0]);
1373                 } else {
1374                     argb = FXARGB_MAKE(0xff, pSrcPixel[2], pSrcPixel[1], pSrcPixel[0]);
1375                 }
1376                 if (m_bColorKey) {
1377                     int alpha = 0xff;
1378                     if (m_nComponents == 3 && m_bpc == 8) {
1379                         alpha = (pSrcPixel[0] < m_pCompData[0].m_ColorKeyMin ||
1380                                  pSrcPixel[0] > m_pCompData[0].m_ColorKeyMax ||
1381                                  pSrcPixel[1] < m_pCompData[1].m_ColorKeyMin ||
1382                                  pSrcPixel[1] > m_pCompData[1].m_ColorKeyMax ||
1383                                  pSrcPixel[2] < m_pCompData[2].m_ColorKeyMin ||
1384                                  pSrcPixel[2] > m_pCompData[2].m_ColorKeyMax) ? 0xff : 0;
1385                     }
1386                     argb &= 0xffffff;
1387                     argb |= alpha << 24;
1388                 }
1389                 last_src_x = src_x;
1390                 last_argb = argb;
1391             }
1392             if (dest_Bpp == 4) {
1393                 *(FX_DWORD*)pDestPixel = FXARGB_TODIB(argb);
1394             } else {
1395                 *pDestPixel++ = FXARGB_B(argb);
1396                 *pDestPixel++ = FXARGB_G(argb);
1397                 *pDestPixel = FXARGB_R(argb);
1398             }
1399         }
1400     }
1401 }
1402 void CPDF_DIBSource::SetDownSampleSize(int dest_width, int dest_height) const
1403 {
1404     if (m_pDecoder) {
1405         m_pDecoder->DownScale(dest_width, dest_height);
1406         ((CPDF_DIBSource*)this)->m_Width = m_pDecoder->GetWidth();
1407         ((CPDF_DIBSource*)this)->m_Height = m_pDecoder->GetHeight();
1408     }
1409 }
1410 void CPDF_DIBSource::ClearImageData()
1411 {
1412     if (m_pDecoder) {
1413         m_pDecoder->ClearImageData();
1414     }
1415 }
1416 CPDF_ProgressiveImageLoaderHandle::CPDF_ProgressiveImageLoaderHandle()
1417 {
1418     m_pImageLoader = NULL;
1419     m_pCache = NULL;
1420     m_pImage = NULL;
1421 }
1422 CPDF_ProgressiveImageLoaderHandle::~CPDF_ProgressiveImageLoaderHandle()
1423 {
1424     m_pImageLoader = NULL;
1425     m_pCache = NULL;
1426     m_pImage = NULL;
1427 }
1428 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)
1429 {
1430     m_pImageLoader = pImageLoader;
1431     m_pCache = pCache;
1432     m_pImage = (CPDF_ImageObject*)pImage;
1433     m_nDownsampleWidth = nDownsampleWidth;
1434     m_nDownsampleHeight = nDownsampleHeight;
1435     FX_BOOL ret;
1436     if (pCache) {
1437         ret = pCache->StartGetCachedBitmap(pImage->m_pImage->GetStream(), bStdCS, GroupFamily, bLoadMask, pRenderStatus, m_nDownsampleWidth, m_nDownsampleHeight);
1438         if (ret == FALSE) {
1439             m_pImageLoader->m_bCached = TRUE;
1440             m_pImageLoader->m_pBitmap = pCache->m_pCurImageCache->DetachBitmap();
1441             m_pImageLoader->m_pMask = pCache->m_pCurImageCache->DetachMask();
1442             m_pImageLoader->m_MatteColor = pCache->m_pCurImageCache->m_MatteColor;
1443         }
1444     } else {
1445         ret = pImage->m_pImage->StartLoadDIBSource(pRenderStatus->m_pFormResource, pRenderStatus->m_pPageResource, bStdCS, GroupFamily, bLoadMask);
1446         if (ret == FALSE) {
1447             m_pImageLoader->m_bCached = FALSE;
1448             m_pImageLoader->m_pBitmap = m_pImage->m_pImage->DetachBitmap();
1449             m_pImageLoader->m_pMask = m_pImage->m_pImage->DetachMask();
1450             m_pImageLoader->m_MatteColor = m_pImage->m_pImage->m_MatteColor;
1451         }
1452     }
1453     return ret;
1454 }
1455 FX_BOOL CPDF_ProgressiveImageLoaderHandle::Continue(IFX_Pause* pPause)
1456 {
1457     FX_BOOL ret;
1458     if (m_pCache) {
1459         ret = m_pCache->Continue(pPause);
1460         if (ret == FALSE) {
1461             m_pImageLoader->m_bCached = TRUE;
1462             m_pImageLoader->m_pBitmap = m_pCache->m_pCurImageCache->DetachBitmap();
1463             m_pImageLoader->m_pMask = m_pCache->m_pCurImageCache->DetachMask();
1464             m_pImageLoader->m_MatteColor = m_pCache->m_pCurImageCache->m_MatteColor;
1465         }
1466     } else {
1467         ret = m_pImage->m_pImage->Continue(pPause);
1468         if (ret == FALSE) {
1469             m_pImageLoader->m_bCached = FALSE;
1470             m_pImageLoader->m_pBitmap = m_pImage->m_pImage->DetachBitmap();
1471             m_pImageLoader->m_pMask = m_pImage->m_pImage->DetachMask();
1472             m_pImageLoader->m_MatteColor = m_pImage->m_pImage->m_MatteColor;
1473         }
1474     }
1475     return ret;
1476 }
1477 FX_BOOL CPDF_ImageLoader::Load(const CPDF_ImageObject* pImage, CPDF_PageRenderCache* pCache, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus)
1478 {
1479     if (pImage == NULL) {
1480         return FALSE;
1481     }
1482     if (pCache) {
1483         pCache->GetCachedBitmap(pImage->m_pImage->GetStream(), m_pBitmap, m_pMask, m_MatteColor, bStdCS, GroupFamily, bLoadMask, pRenderStatus, m_nDownsampleWidth, m_nDownsampleHeight);
1484         m_bCached = TRUE;
1485     } else {
1486         m_pBitmap = pImage->m_pImage->LoadDIBSource(&m_pMask, &m_MatteColor, bStdCS, GroupFamily, bLoadMask);
1487         m_bCached = FALSE;
1488     }
1489     return FALSE;
1490 }
1491 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)
1492 {
1493     m_nDownsampleWidth = nDownsampleWidth;
1494     m_nDownsampleHeight = nDownsampleHeight;
1495     CPDF_ProgressiveImageLoaderHandle* pLoaderHandle = NULL;
1496     pLoaderHandle =     FX_NEW CPDF_ProgressiveImageLoaderHandle;
1497     FX_BOOL ret = pLoaderHandle->Start(this, pImage, pCache, bStdCS, GroupFamily, bLoadMask, pRenderStatus, m_nDownsampleWidth, m_nDownsampleHeight);
1498     LoadHandle = pLoaderHandle;
1499     return ret;
1500 }
1501 FX_BOOL CPDF_ImageLoader::Continue(FX_LPVOID LoadHandle, IFX_Pause* pPause)
1502 {
1503     return ((CPDF_ProgressiveImageLoaderHandle*)LoadHandle)->Continue(pPause);
1504 }
1505 CPDF_ImageLoader::~CPDF_ImageLoader()
1506 {
1507     if (!m_bCached) {
1508         if (m_pBitmap) {
1509             delete m_pBitmap;
1510             m_pBitmap = NULL;
1511         }
1512         if (m_pMask) {
1513             delete m_pMask;
1514         }
1515     }
1516 }