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