Initial commit.
[pdfium.git] / core / src / fpdfapi / fpdf_render / fpdf_render_image.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 FX_BOOL CPDF_RenderStatus::ProcessImage(CPDF_ImageObject* pImageObj, const CFX_AffineMatrix* pObj2Device)\r
15 {\r
16     CPDF_ImageRenderer render;\r
17     if (render.Start(this, pImageObj, pObj2Device, m_bStdCS, m_curBlend)) {\r
18         render.Continue(NULL);\r
19     }\r
20 #ifdef _FPDFAPI_MINI_\r
21     if (m_DitherBits) {\r
22         DitherObjectArea(pImageObj, pObj2Device);\r
23     }\r
24 #endif\r
25     return render.m_Result;\r
26 }\r
27 #if defined(_FPDFAPI_MINI_)\r
28 FX_BOOL CPDF_RenderStatus::ProcessInlines(CPDF_InlineImages* pInlines, const CFX_AffineMatrix* pObj2Device)\r
29 {\r
30     int bitmap_alpha = 255;\r
31     if (!pInlines->m_GeneralState.IsNull()) {\r
32         bitmap_alpha = FXSYS_round(pInlines->m_GeneralState.GetObject()->m_FillAlpha * 255);\r
33     }\r
34     if (pInlines->m_pStream) {\r
35         CPDF_DIBSource dibsrc;\r
36         if (!dibsrc.Load(m_pContext->m_pDocument, pInlines->m_pStream, NULL, NULL, NULL, NULL)) {\r
37             return TRUE;\r
38         }\r
39         pInlines->m_pBitmap = dibsrc.Clone();\r
40         pInlines->m_pStream->Release();\r
41         pInlines->m_pStream = NULL;\r
42     }\r
43     if (pInlines->m_pBitmap == NULL) {\r
44         return TRUE;\r
45     }\r
46     FX_ARGB fill_argb = 0;\r
47     if (pInlines->m_pBitmap->IsAlphaMask()) {\r
48         fill_argb = GetFillArgb(pInlines);\r
49     }\r
50     int flags = 0;\r
51     if (m_Options.m_Flags & RENDER_FORCE_DOWNSAMPLE) {\r
52         flags |= RENDER_FORCE_DOWNSAMPLE;\r
53     } else if (m_Options.m_Flags & RENDER_FORCE_HALFTONE) {\r
54         flags = 0;\r
55     }\r
56     for (int i = 0; i < pInlines->m_Matrices.GetSize(); i ++) {\r
57         CFX_AffineMatrix image_matrix = pInlines->m_Matrices.GetAt(i);\r
58         image_matrix.Concat(*pObj2Device);\r
59         CPDF_ImageRenderer renderer;\r
60         if (renderer.Start(this, pInlines->m_pBitmap, fill_argb, bitmap_alpha, &image_matrix, flags, FALSE, m_curBlend)) {\r
61             renderer.Continue(NULL);\r
62         }\r
63     }\r
64     return TRUE;\r
65 }\r
66 #endif\r
67 void CPDF_RenderStatus::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, int left, int top, FX_ARGB mask_argb,\r
68         int bitmap_alpha, int blend_mode, int Transparency)\r
69 {\r
70     if (pDIBitmap == NULL) {\r
71         return;\r
72     }\r
73     FX_BOOL bIsolated = Transparency & PDFTRANS_ISOLATED;\r
74     FX_BOOL bGroup = Transparency & PDFTRANS_GROUP;\r
75     if (blend_mode == FXDIB_BLEND_NORMAL) {\r
76         if (!pDIBitmap->IsAlphaMask()) {\r
77             if (bitmap_alpha < 255) {\r
78                 pDIBitmap->MultiplyAlpha(bitmap_alpha);\r
79             }\r
80             if (m_pDevice->SetDIBits(pDIBitmap, left, top)) {\r
81                 return;\r
82             }\r
83         } else {\r
84             FX_DWORD fill_argb = m_Options.TranslateColor(mask_argb);\r
85             if (bitmap_alpha < 255) {\r
86                 ((FX_BYTE*)&fill_argb)[3] = ((FX_BYTE*)&fill_argb)[3] * bitmap_alpha / 255;\r
87             }\r
88             if (m_pDevice->SetBitMask(pDIBitmap, left, top, fill_argb)) {\r
89                 return;\r
90             }\r
91         }\r
92     }\r
93     FX_BOOL bBackAlphaRequired = blend_mode && bIsolated && !m_bDropObjects;\r
94     FX_BOOL bGetBackGround = ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) ||\r
95                              (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) && (m_pDevice->GetRenderCaps()\r
96                                      & FXRC_GET_BITS) && !bBackAlphaRequired);\r
97     if (bGetBackGround) {\r
98         if (bIsolated || !bGroup) {\r
99             if (pDIBitmap->IsAlphaMask()) {\r
100                 return;\r
101             }\r
102             m_pDevice->SetDIBits(pDIBitmap, left, top, blend_mode);\r
103         } else {\r
104             FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), top + pDIBitmap->GetHeight());\r
105             rect.Intersect(m_pDevice->GetClipBox());\r
106             CFX_DIBitmap* pClone = NULL;\r
107             FX_BOOL bClone = FALSE;\r
108             if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) {\r
109                 bClone = TRUE;\r
110                 pClone = m_pDevice->GetBackDrop()->Clone(&rect);\r
111                 CFX_DIBitmap *pForeBitmap = m_pDevice->GetBitmap();\r
112                 pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), pForeBitmap, rect.left, rect.top);\r
113                 left = left >= 0 ? 0 : left;\r
114                 top = top >= 0 ? 0 : top;\r
115                 if (!pDIBitmap->IsAlphaMask())\r
116                     pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), pDIBitmap,\r
117                                             left, top, blend_mode);\r
118                 else\r
119                     pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(), pDIBitmap,\r
120                                           mask_argb, left, top, blend_mode);\r
121             } else {\r
122                 pClone = pDIBitmap;\r
123             }\r
124             if (m_pDevice->GetBackDrop()) {\r
125                 m_pDevice->SetDIBits(pClone, rect.left, rect.top);\r
126             } else {\r
127                 if (pDIBitmap->IsAlphaMask()) {\r
128                     return;\r
129                 }\r
130                 m_pDevice->SetDIBits(pDIBitmap, rect.left, rect.top, blend_mode);\r
131             }\r
132             if (bClone) {\r
133                 delete pClone;\r
134             }\r
135         }\r
136         return;\r
137     }\r
138     int back_left, back_top;\r
139     FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), top + pDIBitmap->GetHeight());\r
140     CFX_DIBitmap* pBackdrop = GetBackdrop(m_pCurObj, rect, back_left, back_top, blend_mode > FXDIB_BLEND_NORMAL && bIsolated);\r
141     if (!pBackdrop) {\r
142         return;\r
143     }\r
144     if (!pDIBitmap->IsAlphaMask())\r
145         pBackdrop->CompositeBitmap(left - back_left, top - back_top, pDIBitmap->GetWidth(), pDIBitmap->GetHeight(), pDIBitmap,\r
146                                    0, 0, blend_mode);\r
147     else\r
148         pBackdrop->CompositeMask(left - back_left, top - back_top, pDIBitmap->GetWidth(), pDIBitmap->GetHeight(), pDIBitmap,\r
149                                  mask_argb, 0, 0, blend_mode);\r
150     CFX_DIBitmap* pBackdrop1 = FX_NEW CFX_DIBitmap;\r
151     pBackdrop1->Create(pBackdrop->GetWidth(), pBackdrop->GetHeight(), FXDIB_Rgb32);\r
152     pBackdrop1->Clear((FX_DWORD) - 1);\r
153     pBackdrop1->CompositeBitmap(0, 0, pBackdrop->GetWidth(), pBackdrop->GetHeight(), pBackdrop, 0, 0);\r
154     delete pBackdrop;\r
155     pBackdrop = pBackdrop1;\r
156     m_pDevice->SetDIBits(pBackdrop, back_left, back_top);\r
157     delete pBackdrop;\r
158 }\r
159 FX_COLORREF CPDF_TransferFunc::TranslateColor(FX_COLORREF rgb)\r
160 {\r
161     return FXSYS_RGB(m_Samples[FXSYS_GetRValue(rgb)], m_Samples[256 + FXSYS_GetGValue(rgb)],\r
162                      m_Samples[512 + FXSYS_GetBValue(rgb)]);\r
163 }\r
164 CFX_DIBSource* CPDF_TransferFunc::TranslateImage(const CFX_DIBSource* pSrc, FX_BOOL bAutoDropSrc)\r
165 {\r
166     CPDF_DIBTransferFunc* pDest = FX_NEW CPDF_DIBTransferFunc(this);\r
167     pDest->LoadSrc(pSrc, bAutoDropSrc);\r
168     return pDest;\r
169 }\r
170 FXDIB_Format CPDF_DIBTransferFunc::GetDestFormat()\r
171 {\r
172     if (m_pSrc->IsAlphaMask()) {\r
173         return FXDIB_8bppMask;\r
174     }\r
175 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
176     return (m_pSrc->HasAlpha()) ? FXDIB_Argb : FXDIB_Rgb32;\r
177 #else\r
178     return (m_pSrc->HasAlpha()) ? FXDIB_Argb : FXDIB_Rgb;\r
179 #endif\r
180 }\r
181 CPDF_DIBTransferFunc::CPDF_DIBTransferFunc(const CPDF_TransferFunc* pTransferFunc)\r
182 {\r
183     m_RampR = pTransferFunc->m_Samples;\r
184     m_RampG = &pTransferFunc->m_Samples[256];\r
185     m_RampB = &pTransferFunc->m_Samples[512];\r
186 }\r
187 void CPDF_DIBTransferFunc::TranslateScanline(FX_LPBYTE dest_buf, FX_LPCBYTE src_buf) const\r
188 {\r
189     int i;\r
190     FX_BOOL bSkip = FALSE;\r
191     switch (m_pSrc->GetFormat()) {\r
192         case FXDIB_1bppRgb: {\r
193                 int r0 = m_RampR[0], g0 = m_RampG[0], b0 = m_RampB[0];\r
194                 int r1 = m_RampR[255], g1 = m_RampG[255], b1 = m_RampB[255];\r
195                 for (i = 0; i < m_Width; i ++) {\r
196                     if (src_buf[i / 8] & (1 << (7 - i % 8))) {\r
197                         *dest_buf++ = b1;\r
198                         *dest_buf++ = g1;\r
199                         *dest_buf++ = r1;\r
200                     } else {\r
201                         *dest_buf++ = b0;\r
202                         *dest_buf++ = g0;\r
203                         *dest_buf++ = r0;\r
204                     }\r
205 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
206                     dest_buf++;\r
207 #endif\r
208                 }\r
209                 break;\r
210             }\r
211         case FXDIB_1bppMask: {\r
212                 int m0 = m_RampR[0], m1 = m_RampR[255];\r
213                 for (i = 0; i < m_Width; i ++) {\r
214                     if (src_buf[i / 8] & (1 << (7 - i % 8))) {\r
215                         *dest_buf++ = m1;\r
216                     } else {\r
217                         *dest_buf++ = m0;\r
218                     }\r
219                 }\r
220                 break;\r
221             }\r
222         case FXDIB_8bppRgb: {\r
223                 FX_ARGB* pPal = m_pSrc->GetPalette();\r
224                 for (i = 0; i < m_Width; i ++) {\r
225                     if (pPal) {\r
226                         FX_ARGB src_argb = pPal[*src_buf];\r
227                         *dest_buf++ = m_RampB[FXARGB_R(src_argb)];\r
228                         *dest_buf++ = m_RampG[FXARGB_G(src_argb)];\r
229                         *dest_buf++ = m_RampR[FXARGB_B(src_argb)];\r
230                     } else {\r
231                         FX_DWORD src_byte = *src_buf;\r
232                         *dest_buf++ = m_RampB[src_byte];\r
233                         *dest_buf++ = m_RampG[src_byte];\r
234                         *dest_buf++ = m_RampR[src_byte];\r
235                     }\r
236                     src_buf ++;\r
237 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
238                     dest_buf++;\r
239 #endif\r
240                 }\r
241                 break;\r
242             }\r
243         case FXDIB_8bppMask:\r
244             for (i = 0; i < m_Width; i ++) {\r
245                 *dest_buf++ = m_RampR[*(src_buf++)];\r
246             }\r
247             break;\r
248         case FXDIB_Rgb:\r
249             for (i = 0; i < m_Width; i ++) {\r
250                 *dest_buf++ = m_RampB[*(src_buf++)];\r
251                 *dest_buf++ = m_RampG[*(src_buf++)];\r
252                 *dest_buf++ = m_RampR[*(src_buf++)];\r
253 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
254                 dest_buf++;\r
255 #endif\r
256             }\r
257             break;\r
258         case FXDIB_Rgb32:\r
259             bSkip = TRUE;\r
260         case FXDIB_Argb:\r
261             for (i = 0; i < m_Width; i ++) {\r
262                 *dest_buf++ = m_RampB[*(src_buf++)];\r
263                 *dest_buf++ = m_RampG[*(src_buf++)];\r
264                 *dest_buf++ = m_RampR[*(src_buf++)];\r
265                 if (!bSkip) {\r
266                     *dest_buf++ = *src_buf;\r
267                 }\r
268 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
269                 else {\r
270                     dest_buf++;\r
271                 }\r
272 #endif\r
273                 src_buf ++;\r
274             }\r
275             break;\r
276         default:\r
277             break;\r
278     }\r
279 }\r
280 void CPDF_DIBTransferFunc::TranslateDownSamples(FX_LPBYTE dest_buf, FX_LPCBYTE src_buf, int pixels, int Bpp) const\r
281 {\r
282     if (Bpp == 8) {\r
283         for (int i = 0; i < pixels; i ++) {\r
284             *dest_buf++ = m_RampR[*(src_buf++)];\r
285         }\r
286     } else if (Bpp == 24) {\r
287         for (int i = 0; i < pixels; i ++) {\r
288             *dest_buf++ = m_RampB[*(src_buf++)];\r
289             *dest_buf++ = m_RampG[*(src_buf++)];\r
290             *dest_buf++ = m_RampR[*(src_buf++)];\r
291         }\r
292     } else {\r
293 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
294         if (!m_pSrc->HasAlpha()) {\r
295             for (int i = 0; i < pixels; i ++) {\r
296                 *dest_buf++ = m_RampB[*(src_buf++)];\r
297                 *dest_buf++ = m_RampG[*(src_buf++)];\r
298                 *dest_buf++ = m_RampR[*(src_buf++)];\r
299                 dest_buf++;\r
300                 src_buf++;\r
301             }\r
302         } else\r
303 #endif\r
304             for (int i = 0; i < pixels; i ++) {\r
305                 *dest_buf++ = m_RampB[*(src_buf++)];\r
306                 *dest_buf++ = m_RampG[*(src_buf++)];\r
307                 *dest_buf++ = m_RampR[*(src_buf++)];\r
308                 *dest_buf++ = *(src_buf++);\r
309             }\r
310     }\r
311 }\r
312 static FX_BOOL _IsSupported(CPDF_ColorSpace* pCS)\r
313 {\r
314     if (pCS->GetFamily() == PDFCS_DEVICERGB || pCS->GetFamily() == PDFCS_DEVICEGRAY ||\r
315             pCS->GetFamily() == PDFCS_DEVICECMYK || pCS->GetFamily() == PDFCS_CALGRAY ||\r
316             pCS->GetFamily() == PDFCS_CALRGB) {\r
317         return TRUE;\r
318     }\r
319     if (pCS->GetFamily() == PDFCS_INDEXED && _IsSupported(pCS->GetBaseCS())) {\r
320         return TRUE;\r
321     }\r
322     return FALSE;\r
323 }\r
324 CPDF_ImageRenderer::CPDF_ImageRenderer()\r
325 {\r
326     m_pRenderStatus = NULL;\r
327     m_pImageObject = NULL;\r
328     m_Result = TRUE;\r
329     m_Status = 0;\r
330     m_pQuickStretcher = NULL;\r
331     m_pTransformer = NULL;\r
332     m_DeviceHandle = NULL;\r
333     m_LoadHandle = NULL;\r
334     m_pClone = NULL;\r
335     m_bStdCS = FALSE;\r
336     m_bPatternColor = FALSE;\r
337     m_BlendType = FXDIB_BLEND_NORMAL;\r
338     m_pPattern = NULL;\r
339     m_pObj2Device = NULL;\r
340 }\r
341 CPDF_ImageRenderer::~CPDF_ImageRenderer()\r
342 {\r
343     if (m_pQuickStretcher) {\r
344         delete m_pQuickStretcher;\r
345     }\r
346     if (m_pTransformer) {\r
347         delete m_pTransformer;\r
348     }\r
349     if (m_DeviceHandle) {\r
350         m_pRenderStatus->m_pDevice->CancelDIBits(m_DeviceHandle);\r
351     }\r
352     if (m_LoadHandle) {\r
353         delete (CPDF_ProgressiveImageLoaderHandle*)m_LoadHandle;\r
354     }\r
355     if (m_pClone) {\r
356         delete m_pClone;\r
357     }\r
358 }\r
359 FX_BOOL CPDF_ImageRenderer::StartLoadDIBSource()\r
360 {\r
361     CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect();\r
362     FX_RECT image_rect = image_rect_f.GetOutterRect();\r
363     int dest_width = image_rect.Width();\r
364     int dest_height = image_rect.Height();\r
365     if (m_ImageMatrix.a < 0) {\r
366         dest_width = -dest_width;\r
367     }\r
368     if (m_ImageMatrix.d > 0) {\r
369         dest_height = -dest_height;\r
370     }\r
371     if (m_Loader.StartLoadImage(m_pImageObject, m_pRenderStatus->m_pContext->m_pPageCache, m_LoadHandle, m_bStdCS,\r
372                                 m_pRenderStatus->m_GroupFamily, m_pRenderStatus->m_bLoadMask, m_pRenderStatus, dest_width, dest_height)) {\r
373         if (m_LoadHandle != NULL) {\r
374             m_Status = 4;\r
375             return TRUE;\r
376         }\r
377         return FALSE;\r
378     }\r
379     return FALSE;\r
380 }\r
381 FX_BOOL CPDF_ImageRenderer::StartRenderDIBSource()\r
382 {\r
383     if (m_Loader.m_pBitmap == NULL) {\r
384         return FALSE;\r
385     }\r
386     m_BitmapAlpha = 255;\r
387     const CPDF_GeneralStateData* pGeneralState = m_pImageObject->m_GeneralState;\r
388     if (pGeneralState) {\r
389         m_BitmapAlpha = FXSYS_round(pGeneralState->m_FillAlpha * 255);\r
390     }\r
391     m_pDIBSource = m_Loader.m_pBitmap;\r
392     if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_ALPHA && m_Loader.m_pMask == NULL) {\r
393         return StartBitmapAlpha();\r
394     }\r
395 #ifndef _FPDFAPI_MINI_\r
396     if (pGeneralState && pGeneralState->m_pTR) {\r
397         if (!pGeneralState->m_pTransferFunc) {\r
398             ((CPDF_GeneralStateData*)pGeneralState)->m_pTransferFunc = m_pRenderStatus->GetTransferFunc(pGeneralState->m_pTR);\r
399         }\r
400         if (pGeneralState->m_pTransferFunc && !pGeneralState->m_pTransferFunc->m_bIdentity) {\r
401             m_pDIBSource = m_Loader.m_pBitmap = pGeneralState->m_pTransferFunc->TranslateImage(m_Loader.m_pBitmap, !m_Loader.m_bCached);\r
402             if (m_Loader.m_bCached && m_Loader.m_pMask) {\r
403                 m_Loader.m_pMask = m_Loader.m_pMask->Clone();\r
404             }\r
405             m_Loader.m_bCached = FALSE;\r
406         }\r
407     }\r
408 #endif\r
409     m_FillArgb = 0;\r
410     m_bPatternColor = FALSE;\r
411     m_pPattern = NULL;\r
412     if (m_pDIBSource->IsAlphaMask()) {\r
413         CPDF_Color* pColor = m_pImageObject->m_ColorState.GetFillColor();\r
414         if (pColor && pColor->IsPattern()) {\r
415             m_pPattern = pColor->GetPattern();\r
416             if (m_pPattern != NULL) {\r
417                 m_bPatternColor = TRUE;\r
418             }\r
419         }\r
420         m_FillArgb = m_pRenderStatus->GetFillArgb(m_pImageObject);\r
421     } else if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_GRAY) {\r
422         m_pClone = m_pDIBSource->Clone();\r
423         m_pClone->ConvertColorScale(m_pRenderStatus->m_Options.m_BackColor, m_pRenderStatus->m_Options.m_ForeColor);\r
424         m_pDIBSource = m_pClone;\r
425     }\r
426     m_Flags = 0;\r
427 #if !defined(_FPDFAPI_MINI_)\r
428     if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_DOWNSAMPLE) {\r
429         m_Flags |= RENDER_FORCE_DOWNSAMPLE;\r
430     } else if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_HALFTONE) {\r
431         m_Flags |= RENDER_FORCE_HALFTONE;\r
432     }\r
433 #else\r
434     if (!(m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_HALFTONE)) {\r
435         if (m_pRenderStatus->m_HalftoneLimit) {\r
436             CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect();\r
437             FX_RECT image_rect = image_rect_f.GetOutterRect();\r
438             FX_RECT image_clip = image_rect;\r
439             image_rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox());\r
440             if (image_rect.Width() && image_rect.Height()) {\r
441                 if ((image_clip.Width() * m_pDIBSource->GetWidth() / image_rect.Width()) *\r
442                         (image_clip.Height() * m_pDIBSource->GetHeight() / image_rect.Height()) >\r
443                         m_pRenderStatus->m_HalftoneLimit) {\r
444                     m_Flags |= RENDER_FORCE_DOWNSAMPLE;\r
445                 }\r
446             }\r
447         } else {\r
448             m_Flags |= RENDER_FORCE_DOWNSAMPLE;\r
449         }\r
450     }\r
451 #endif\r
452 #ifndef _FPDFAPI_MINI_\r
453     if (m_pRenderStatus->m_pDevice->GetDeviceClass() != FXDC_DISPLAY) {\r
454         CPDF_Object* pFilters = m_pImageObject->m_pImage->GetStream()->GetDict()->GetElementValue(FX_BSTRC("Filter"));\r
455         if (pFilters) {\r
456             if (pFilters->GetType() == PDFOBJ_NAME) {\r
457                 CFX_ByteStringC bsDecodeType = pFilters->GetConstString();\r
458                 if (bsDecodeType == FX_BSTRC("DCTDecode") || bsDecodeType == FX_BSTRC("JPXDecode")) {\r
459                     m_Flags |= FXRENDER_IMAGE_LOSSY;\r
460                 }\r
461             } else if (pFilters->GetType() == PDFOBJ_ARRAY) {\r
462                 CPDF_Array* pArray = (CPDF_Array*)pFilters;\r
463                 for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {\r
464                     CFX_ByteStringC bsDecodeType = pArray->GetConstString(i);\r
465                     if (bsDecodeType == FX_BSTRC("DCTDecode") || bsDecodeType == FX_BSTRC("JPXDecode")) {\r
466                         m_Flags |= FXRENDER_IMAGE_LOSSY;\r
467                         break;\r
468                     }\r
469                 }\r
470             }\r
471         }\r
472     }\r
473     if (m_pRenderStatus->m_Options.m_Flags & RENDER_NOIMAGESMOOTH) {\r
474         m_Flags |= FXDIB_NOSMOOTH;\r
475     } else if (m_pImageObject->m_pImage->IsInterpol()) {\r
476         m_Flags |= FXDIB_INTERPOL;\r
477     }\r
478 #endif\r
479     if (m_Loader.m_pMask) {\r
480         return DrawMaskedImage();\r
481     }\r
482     if (m_bPatternColor) {\r
483         return DrawPatternImage(m_pObj2Device);\r
484     }\r
485 #if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_)\r
486     if (m_BitmapAlpha == 255 && pGeneralState && pGeneralState->m_FillOP &&\r
487             pGeneralState->m_OPMode == 0 && pGeneralState->m_BlendType == FXDIB_BLEND_NORMAL && pGeneralState->m_StrokeAlpha == 1 && pGeneralState->m_FillAlpha == 1) {\r
488         CPDF_Document* pDocument = NULL;\r
489         CPDF_Page* pPage = NULL;\r
490         if (m_pRenderStatus->m_pContext->m_pPageCache) {\r
491             pPage = m_pRenderStatus->m_pContext->m_pPageCache->GetPage();\r
492             pDocument = pPage->m_pDocument;\r
493         } else {\r
494             pDocument = m_pImageObject->m_pImage->GetDocument();\r
495         }\r
496         CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : NULL;\r
497         CPDF_Object* pCSObj = m_pImageObject->m_pImage->GetStream()->GetDict()->GetElementValue(FX_BSTRC("ColorSpace"));\r
498         CPDF_ColorSpace* pColorSpace = pDocument->LoadColorSpace(pCSObj, pPageResources);\r
499         if (pColorSpace) {\r
500             int format = pColorSpace->GetFamily();\r
501             if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION || format == PDFCS_DEVICEN) {\r
502                 m_BlendType = FXDIB_BLEND_DARKEN;\r
503             }\r
504             pDocument->GetPageData()->ReleaseColorSpace(pCSObj);\r
505         }\r
506     }\r
507 #endif\r
508     return StartDIBSource();\r
509 }\r
510 FX_BOOL CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStdCS, int blendType)\r
511 {\r
512     m_pRenderStatus = pStatus;\r
513     m_bStdCS = bStdCS;\r
514     m_pImageObject = (CPDF_ImageObject*)pObj;\r
515     m_BlendType = blendType;\r
516     m_pObj2Device = pObj2Device;\r
517 #ifndef _FPDFAPI_MINI_\r
518     CPDF_Dictionary* pOC = m_pImageObject->m_pImage->GetOC();\r
519     if (pOC && m_pRenderStatus->m_Options.m_pOCContext && !m_pRenderStatus->m_Options.m_pOCContext->CheckOCGVisible(pOC)) {\r
520         return FALSE;\r
521     }\r
522 #endif\r
523     m_ImageMatrix = m_pImageObject->m_Matrix;\r
524     m_ImageMatrix.Concat(*pObj2Device);\r
525     if (StartLoadDIBSource()) {\r
526         return TRUE;\r
527     }\r
528     return StartRenderDIBSource();\r
529 }\r
530 FX_BOOL CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, const CFX_DIBSource* pDIBSource, FX_ARGB bitmap_argb,\r
531                                   int bitmap_alpha, const CFX_AffineMatrix* pImage2Device, FX_DWORD flags, FX_BOOL bStdCS, int blendType)\r
532 {\r
533     m_pRenderStatus = pStatus;\r
534     m_pDIBSource = pDIBSource;\r
535     m_FillArgb = bitmap_argb;\r
536     m_BitmapAlpha = bitmap_alpha;\r
537     m_ImageMatrix = *pImage2Device;\r
538     m_Flags = flags;\r
539     m_bStdCS = bStdCS;\r
540     m_BlendType = blendType;\r
541     return StartDIBSource();\r
542 }\r
543 FX_BOOL CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device)\r
544 {\r
545     if (m_pRenderStatus->m_bPrint && !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) {\r
546         m_Result = FALSE;\r
547         return FALSE;\r
548     }\r
549     FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOutterRect();\r
550     rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox());\r
551     if (rect.IsEmpty()) {\r
552         return FALSE;\r
553     }\r
554     CFX_AffineMatrix new_matrix = m_ImageMatrix;\r
555     new_matrix.TranslateI(-rect.left, -rect.top);\r
556     int width = rect.Width();\r
557     int height = rect.Height();\r
558     CFX_FxgeDevice bitmap_device1;\r
559     if (!bitmap_device1.Create(rect.Width(), rect.Height(), FXDIB_Rgb32)) {\r
560         return TRUE;\r
561     }\r
562     bitmap_device1.GetBitmap()->Clear(0xffffff);\r
563     {\r
564         CPDF_RenderStatus bitmap_render;\r
565         bitmap_render.Initialize(m_pRenderStatus->m_Level + 1, m_pRenderStatus->m_pContext, &bitmap_device1, NULL, NULL,\r
566                                  NULL, NULL, &m_pRenderStatus->m_Options, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE);\r
567         CFX_Matrix patternDevice = *pObj2Device;\r
568         patternDevice.Translate((FX_FLOAT) - rect.left, (FX_FLOAT) - rect.top);\r
569         if(m_pPattern->m_PatternType == PATTERN_TILING) {\r
570             bitmap_render.DrawTilingPattern((CPDF_TilingPattern*)m_pPattern, m_pImageObject, &patternDevice, FALSE);\r
571         } else {\r
572             bitmap_render.DrawShadingPattern((CPDF_ShadingPattern*)m_pPattern, m_pImageObject, &patternDevice, FALSE);\r
573         }\r
574     }\r
575     {\r
576         CFX_FxgeDevice bitmap_device2;\r
577         if (!bitmap_device2.Create(rect.Width(), rect.Height(), FXDIB_8bppRgb)) {\r
578             return TRUE;\r
579         }\r
580         bitmap_device2.GetBitmap()->Clear(0);\r
581         CPDF_RenderStatus bitmap_render;\r
582         bitmap_render.Initialize(m_pRenderStatus->m_Level + 1, m_pRenderStatus->m_pContext, &bitmap_device2, NULL, NULL,\r
583                                  NULL, NULL, NULL, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE);\r
584         CPDF_ImageRenderer image_render;\r
585         if (image_render.Start(&bitmap_render, m_pDIBSource, 0xffffffff, 255, &new_matrix, m_Flags, TRUE)) {\r
586             image_render.Continue(NULL);\r
587         }\r
588         if (m_Loader.m_MatteColor != 0xffffffff) {\r
589             int matte_r = FXARGB_R(m_Loader.m_MatteColor);\r
590             int matte_g = FXARGB_G(m_Loader.m_MatteColor);\r
591             int matte_b = FXARGB_B(m_Loader.m_MatteColor);\r
592             for (int row = 0; row < height; row ++) {\r
593                 FX_LPBYTE dest_scan = (FX_LPBYTE)bitmap_device1.GetBitmap()->GetScanline(row);\r
594                 FX_LPCBYTE mask_scan = bitmap_device2.GetBitmap()->GetScanline(row);\r
595                 for (int col = 0; col < width; col ++) {\r
596                     int alpha = *mask_scan ++;\r
597                     if (alpha) {\r
598                         int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b;\r
599                         if (orig < 0) {\r
600                             orig = 0;\r
601                         } else if (orig > 255) {\r
602                             orig = 255;\r
603                         }\r
604                         *dest_scan++ = orig;\r
605                         orig = (*dest_scan - matte_g) * 255 / alpha + matte_g;\r
606                         if (orig < 0) {\r
607                             orig = 0;\r
608                         } else if (orig > 255) {\r
609                             orig = 255;\r
610                         }\r
611                         *dest_scan++ = orig;\r
612                         orig = (*dest_scan - matte_r) * 255 / alpha + matte_r;\r
613                         if (orig < 0) {\r
614                             orig = 0;\r
615                         } else if (orig > 255) {\r
616                             orig = 255;\r
617                         }\r
618                         *dest_scan++ = orig;\r
619                         dest_scan ++;\r
620                     } else {\r
621                         dest_scan += 4;\r
622                     }\r
623                 }\r
624             }\r
625         }\r
626         bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask);\r
627         bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap());\r
628         bitmap_device1.GetBitmap()->MultiplyAlpha(255);\r
629     }\r
630     m_pRenderStatus->m_pDevice->SetDIBits(bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType);\r
631     return FALSE;\r
632 }\r
633 FX_BOOL CPDF_ImageRenderer::DrawMaskedImage()\r
634 {\r
635     if (m_pRenderStatus->m_bPrint && !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) {\r
636         m_Result = FALSE;\r
637         return FALSE;\r
638     }\r
639     FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOutterRect();\r
640     rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox());\r
641     if (rect.IsEmpty()) {\r
642         return FALSE;\r
643     }\r
644     CFX_AffineMatrix new_matrix = m_ImageMatrix;\r
645     new_matrix.TranslateI(-rect.left, -rect.top);\r
646     int width = rect.Width();\r
647     int height = rect.Height();\r
648     CFX_FxgeDevice bitmap_device1;\r
649     if (!bitmap_device1.Create(width, height, FXDIB_Rgb32)) {\r
650         return TRUE;\r
651     }\r
652     bitmap_device1.GetBitmap()->Clear(0xffffff);\r
653     {\r
654         CPDF_RenderStatus bitmap_render;\r
655         bitmap_render.Initialize(m_pRenderStatus->m_Level + 1, m_pRenderStatus->m_pContext, &bitmap_device1, NULL, NULL,\r
656                                  NULL, NULL, NULL, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE);\r
657         CPDF_ImageRenderer image_render;\r
658         if (image_render.Start(&bitmap_render, m_pDIBSource, 0, 255, &new_matrix, m_Flags, TRUE)) {\r
659             image_render.Continue(NULL);\r
660         }\r
661     }\r
662     {\r
663         CFX_FxgeDevice bitmap_device2;\r
664         if (!bitmap_device2.Create(width, height, FXDIB_8bppRgb)) {\r
665             return TRUE;\r
666         }\r
667         bitmap_device2.GetBitmap()->Clear(0);\r
668         CPDF_RenderStatus bitmap_render;\r
669         bitmap_render.Initialize(m_pRenderStatus->m_Level + 1, m_pRenderStatus->m_pContext, &bitmap_device2, NULL, NULL,\r
670                                  NULL, NULL, NULL, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE);\r
671         CPDF_ImageRenderer image_render;\r
672         if (image_render.Start(&bitmap_render, m_Loader.m_pMask, 0xffffffff, 255, &new_matrix, m_Flags, TRUE)) {\r
673             image_render.Continue(NULL);\r
674         }\r
675         if (m_Loader.m_MatteColor != 0xffffffff) {\r
676             int matte_r = FXARGB_R(m_Loader.m_MatteColor);\r
677             int matte_g = FXARGB_G(m_Loader.m_MatteColor);\r
678             int matte_b = FXARGB_B(m_Loader.m_MatteColor);\r
679             for (int row = 0; row < height; row ++) {\r
680                 FX_LPBYTE dest_scan = (FX_LPBYTE)bitmap_device1.GetBitmap()->GetScanline(row);\r
681                 FX_LPCBYTE mask_scan = bitmap_device2.GetBitmap()->GetScanline(row);\r
682                 for (int col = 0; col < width; col ++) {\r
683                     int alpha = *mask_scan ++;\r
684                     if (alpha) {\r
685                         int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b;\r
686                         if (orig < 0) {\r
687                             orig = 0;\r
688                         } else if (orig > 255) {\r
689                             orig = 255;\r
690                         }\r
691                         *dest_scan++ = orig;\r
692                         orig = (*dest_scan - matte_g) * 255 / alpha + matte_g;\r
693                         if (orig < 0) {\r
694                             orig = 0;\r
695                         } else if (orig > 255) {\r
696                             orig = 255;\r
697                         }\r
698                         *dest_scan++ = orig;\r
699                         orig = (*dest_scan - matte_r) * 255 / alpha + matte_r;\r
700                         if (orig < 0) {\r
701                             orig = 0;\r
702                         } else if (orig > 255) {\r
703                             orig = 255;\r
704                         }\r
705                         *dest_scan++ = orig;\r
706                         dest_scan ++;\r
707                     } else {\r
708                         dest_scan += 4;\r
709                     }\r
710                 }\r
711             }\r
712         }\r
713         bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask);\r
714         bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap());\r
715         if (m_BitmapAlpha < 255) {\r
716             bitmap_device1.GetBitmap()->MultiplyAlpha(m_BitmapAlpha);\r
717         }\r
718     }\r
719     m_pRenderStatus->m_pDevice->SetDIBits(bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType);\r
720     return FALSE;\r
721 }\r
722 FX_BOOL CPDF_ImageRenderer::StartDIBSource()\r
723 {\r
724 #if !defined(_FPDFAPI_MINI_)\r
725     if (!(m_Flags & RENDER_FORCE_DOWNSAMPLE) && m_pDIBSource->GetBPP() > 1) {\r
726         int image_size = m_pDIBSource->GetBPP() / 8 * m_pDIBSource->GetWidth() * m_pDIBSource->GetHeight();\r
727         if (image_size > FPDF_HUGE_IMAGE_SIZE && !(m_Flags & RENDER_FORCE_HALFTONE)) {\r
728             m_Flags |= RENDER_FORCE_DOWNSAMPLE;\r
729         }\r
730     }\r
731 #endif\r
732     if (m_pRenderStatus->m_pDevice->StartDIBits(m_pDIBSource, m_BitmapAlpha, m_FillArgb,\r
733             &m_ImageMatrix, m_Flags, m_DeviceHandle, 0, NULL, m_BlendType)) {\r
734         if (m_DeviceHandle != NULL) {\r
735             m_Status = 3;\r
736             return TRUE;\r
737         }\r
738         return FALSE;\r
739     }\r
740 #if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_)\r
741     CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect();\r
742     FX_RECT image_rect = image_rect_f.GetOutterRect();\r
743     int dest_width = image_rect.Width();\r
744     int dest_height = image_rect.Height();\r
745     if ((FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) ||\r
746             (FXSYS_fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0) ) {\r
747         if (m_pRenderStatus->m_bPrint && !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) {\r
748             m_Result = FALSE;\r
749             return FALSE;\r
750         }\r
751         FX_RECT clip_box = m_pRenderStatus->m_pDevice->GetClipBox();\r
752         clip_box.Intersect(image_rect);\r
753         m_Status = 2;\r
754         m_pTransformer = FX_NEW CFX_ImageTransformer;\r
755         m_pTransformer->Start(m_pDIBSource, &m_ImageMatrix, m_Flags, &clip_box);\r
756         return TRUE;\r
757     }\r
758     if (m_ImageMatrix.a < 0) {\r
759         dest_width = -dest_width;\r
760     }\r
761     if (m_ImageMatrix.d > 0) {\r
762         dest_height = -dest_height;\r
763     }\r
764     int dest_left, dest_top;\r
765     dest_left = dest_width > 0 ? image_rect.left : image_rect.right;\r
766     dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom;\r
767     if (m_pDIBSource->IsOpaqueImage() && m_BitmapAlpha == 255) {\r
768         if (m_pRenderStatus->m_pDevice->StretchDIBits(m_pDIBSource, dest_left, dest_top,\r
769                 dest_width, dest_height, m_Flags, NULL, m_BlendType)) {\r
770             return FALSE;\r
771         }\r
772     }\r
773     if (m_pDIBSource->IsAlphaMask()) {\r
774         if (m_BitmapAlpha != 255) {\r
775             m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha);\r
776         }\r
777         if (m_pRenderStatus->m_pDevice->StretchBitMask(m_pDIBSource, dest_left, dest_top, dest_width, dest_height, m_FillArgb, m_Flags)) {\r
778             return FALSE;\r
779         }\r
780     }\r
781     if (m_pRenderStatus->m_bPrint && !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) {\r
782         m_Result = FALSE;\r
783         return TRUE;\r
784     }\r
785     FX_RECT clip_box = m_pRenderStatus->m_pDevice->GetClipBox();\r
786     FX_RECT dest_rect = clip_box;\r
787     dest_rect.Intersect(image_rect);\r
788     FX_RECT dest_clip(dest_rect.left - image_rect.left, dest_rect.top - image_rect.top,\r
789                       dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top);\r
790     CFX_DIBitmap* pStretched = m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip);\r
791     if (pStretched) {\r
792         m_pRenderStatus->CompositeDIBitmap(pStretched, dest_rect.left, dest_rect.top, m_FillArgb,\r
793                                            m_BitmapAlpha, m_BlendType, FALSE);\r
794         delete pStretched;\r
795         pStretched = NULL;\r
796     }\r
797 #endif\r
798     return FALSE;\r
799 }\r
800 FX_BOOL CPDF_ImageRenderer::StartBitmapAlpha()\r
801 {\r
802 #ifndef _FPDFAPI_MINI_\r
803     if (m_pDIBSource->IsOpaqueImage()) {\r
804         CFX_PathData path;\r
805         path.AppendRect(0, 0, 1, 1);\r
806         path.Transform(&m_ImageMatrix);\r
807         FX_DWORD fill_color = ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha);\r
808         m_pRenderStatus->m_pDevice->DrawPath(&path, NULL, NULL, fill_color, 0, FXFILL_WINDING);\r
809     } else {\r
810         const CFX_DIBSource* pAlphaMask = m_pDIBSource->IsAlphaMask() ? m_pDIBSource : m_pDIBSource->GetAlphaMask();\r
811         if (FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || FXSYS_fabs(m_ImageMatrix.c) >= 0.5f) {\r
812             int left, top;\r
813             CFX_DIBitmap* pTransformed = pAlphaMask->TransformTo(&m_ImageMatrix, left, top);\r
814             if (pTransformed == NULL) {\r
815                 return TRUE;\r
816             }\r
817             m_pRenderStatus->m_pDevice->SetBitMask(pTransformed, left, top, ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha));\r
818             delete pTransformed;\r
819         } else {\r
820             CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect();\r
821             FX_RECT image_rect = image_rect_f.GetOutterRect();\r
822             int dest_width = m_ImageMatrix.a > 0 ? image_rect.Width() : -image_rect.Width();\r
823             int dest_height = m_ImageMatrix.d > 0 ? -image_rect.Height() : image_rect.Height();\r
824             int left = dest_width > 0 ? image_rect.left : image_rect.right;\r
825             int top = dest_height > 0 ? image_rect.top : image_rect.bottom;\r
826             m_pRenderStatus->m_pDevice->StretchBitMask(pAlphaMask, left, top, dest_width, dest_height,\r
827                     ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha));\r
828         }\r
829         if (m_pDIBSource != pAlphaMask) {\r
830             delete pAlphaMask;\r
831         }\r
832     }\r
833 #endif\r
834     return FALSE;\r
835 }\r
836 FX_BOOL CPDF_ImageRenderer::Continue(IFX_Pause* pPause)\r
837 {\r
838     if (m_Status == 1) {\r
839 #ifndef _FPDFAPI_MINI_\r
840         if (m_pQuickStretcher->Continue(pPause)) {\r
841             return TRUE;\r
842         }\r
843         if (m_pQuickStretcher->m_pBitmap->IsAlphaMask())\r
844             m_pRenderStatus->m_pDevice->SetBitMask(m_pQuickStretcher->m_pBitmap, m_pQuickStretcher->m_ResultLeft,\r
845                                                    m_pQuickStretcher->m_ResultTop, m_FillArgb);\r
846         else\r
847             m_pRenderStatus->m_pDevice->SetDIBits(m_pQuickStretcher->m_pBitmap, m_pQuickStretcher->m_ResultLeft,\r
848                                                   m_pQuickStretcher->m_ResultTop, m_BlendType);\r
849         return FALSE;\r
850 #endif\r
851     } else if (m_Status == 2) {\r
852 #if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_)\r
853         if (m_pTransformer->Continue(pPause)) {\r
854             return TRUE;\r
855         }\r
856         CFX_DIBitmap* pBitmap = m_pTransformer->m_Storer.Detach();\r
857         if (pBitmap == NULL) {\r
858             return FALSE;\r
859         }\r
860         if (pBitmap->IsAlphaMask()) {\r
861             if (m_BitmapAlpha != 255) {\r
862                 m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha);\r
863             }\r
864             m_Result = m_pRenderStatus->m_pDevice->SetBitMask(pBitmap,\r
865                        m_pTransformer->m_ResultLeft, m_pTransformer->m_ResultTop, m_FillArgb);\r
866         } else {\r
867             if (m_BitmapAlpha != 255) {\r
868                 pBitmap->MultiplyAlpha(m_BitmapAlpha);\r
869             }\r
870             m_Result = m_pRenderStatus->m_pDevice->SetDIBits(pBitmap,\r
871                        m_pTransformer->m_ResultLeft, m_pTransformer->m_ResultTop, m_BlendType);\r
872         }\r
873         delete pBitmap;\r
874         return FALSE;\r
875 #endif\r
876     } else if (m_Status == 3) {\r
877         return m_pRenderStatus->m_pDevice->ContinueDIBits(m_DeviceHandle, pPause);\r
878     } else if (m_Status == 4) {\r
879         if (m_Loader.Continue(m_LoadHandle, pPause)) {\r
880             return TRUE;\r
881         }\r
882         if (StartRenderDIBSource()) {\r
883             return Continue(pPause);\r
884         }\r
885         return FALSE;\r
886     }\r
887     return FALSE;\r
888 }\r
889 CPDF_QuickStretcher::CPDF_QuickStretcher()\r
890 {\r
891     m_pBitmap = NULL;\r
892     m_pDecoder = NULL;\r
893     m_pCS = NULL;\r
894 }\r
895 CPDF_QuickStretcher::~CPDF_QuickStretcher()\r
896 {\r
897     if (m_pBitmap) {\r
898         delete m_pBitmap;\r
899     }\r
900     if (m_pCS) {\r
901         m_pCS->ReleaseCS();\r
902     }\r
903     if (m_pDecoder) {\r
904         delete m_pDecoder;\r
905     }\r
906 }\r
907 ICodec_ScanlineDecoder* FPDFAPI_CreateFlateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,\r
908         int nComps, int bpc, const CPDF_Dictionary* pParams);\r
909 FX_BOOL CPDF_QuickStretcher::Start(CPDF_ImageObject* pImageObj, CFX_AffineMatrix* pImage2Device, const FX_RECT* pClipBox)\r
910 {\r
911     if (FXSYS_fabs(pImage2Device->a) < FXSYS_fabs(pImage2Device->b) * 10 && FXSYS_fabs(pImage2Device->d) < FXSYS_fabs(pImage2Device->c) * 10) {\r
912         return FALSE;\r
913     }\r
914     CFX_FloatRect image_rect_f = pImage2Device->GetUnitRect();\r
915     FX_RECT image_rect = image_rect_f.GetOutterRect();\r
916     m_DestWidth = image_rect.Width();\r
917     m_DestHeight = image_rect.Height();\r
918     m_bFlipX = pImage2Device->a < 0;\r
919     m_bFlipY = pImage2Device->d > 0;\r
920     FX_RECT result_rect = *pClipBox;\r
921     result_rect.Intersect(image_rect);\r
922     if (result_rect.IsEmpty()) {\r
923         return FALSE;\r
924     }\r
925     m_ResultWidth = result_rect.Width();\r
926     m_ResultHeight = result_rect.Height();\r
927     m_ResultLeft = result_rect.left;\r
928     m_ResultTop = result_rect.top;\r
929     m_ClipLeft = result_rect.left - image_rect.left;\r
930     m_ClipTop = result_rect.top - image_rect.top;\r
931     CPDF_Dictionary* pDict = pImageObj->m_pImage->GetDict();\r
932     if (pDict->GetInteger(FX_BSTRC("BitsPerComponent")) != 8) {\r
933         return FALSE;\r
934     }\r
935     if (pDict->KeyExist(FX_BSTRC("SMask")) || pDict->KeyExist(FX_BSTRC("Mask"))) {\r
936         return FALSE;\r
937     }\r
938     m_SrcWidth = pDict->GetInteger(FX_BSTRC("Width"));\r
939     m_SrcHeight = pDict->GetInteger(FX_BSTRC("Height"));\r
940     m_pCS = NULL;\r
941     m_Bpp = 3;\r
942     CPDF_Object* pCSObj = pDict->GetElementValue(FX_BSTRC("ColorSpace"));\r
943     if (pCSObj == NULL) {\r
944         return FALSE;\r
945     }\r
946     m_pCS = CPDF_ColorSpace::Load(pImageObj->m_pImage->GetDocument(), pCSObj);\r
947     if (m_pCS == NULL) {\r
948         return FALSE;\r
949     }\r
950     if (!_IsSupported(m_pCS)) {\r
951         return FALSE;\r
952     }\r
953     m_Bpp = m_pCS->CountComponents();\r
954     if (m_pCS->sRGB()) {\r
955         m_pCS->ReleaseCS();\r
956         m_pCS = NULL;\r
957     }\r
958     CPDF_Stream* pStream = pImageObj->m_pImage->GetStream();\r
959     m_StreamAcc.LoadAllData(pStream, FALSE, m_SrcWidth * m_SrcHeight * m_Bpp, TRUE);\r
960     m_pDecoder = NULL;\r
961     if (!m_StreamAcc.GetImageDecoder().IsEmpty()) {\r
962         if (m_StreamAcc.GetImageDecoder() == FX_BSTRC("DCTDecode")) {\r
963             const CPDF_Dictionary* pParam = m_StreamAcc.GetImageParam();\r
964             m_pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder(\r
965                              m_StreamAcc.GetData(), m_StreamAcc.GetSize(), m_SrcWidth, m_SrcHeight, m_Bpp,\r
966                              pParam ? pParam->GetInteger(FX_BSTRC("ColorTransform"), 1) : 1);\r
967         } else if (m_StreamAcc.GetImageDecoder() == FX_BSTRC("FlateDecode")) {\r
968             m_pDecoder = FPDFAPI_CreateFlateDecoder(\r
969                              m_StreamAcc.GetData(), m_StreamAcc.GetSize(), m_SrcWidth, m_SrcHeight, m_Bpp, 8,\r
970                              m_StreamAcc.GetImageParam());\r
971         } else {\r
972             return FALSE;\r
973         }\r
974         m_pDecoder->DownScale(m_DestWidth, m_DestHeight);\r
975     }\r
976     m_pBitmap = FX_NEW CFX_DIBitmap;\r
977 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
978     m_pBitmap->Create(m_ResultWidth, m_ResultHeight, FXDIB_Rgb32);\r
979 #else\r
980     m_pBitmap->Create(m_ResultWidth, m_ResultHeight, FXDIB_Rgb);\r
981 #endif\r
982     m_LineIndex = 0;\r
983     return TRUE;\r
984 }\r
985 FX_BOOL CPDF_QuickStretcher::Continue(IFX_Pause* pPause)\r
986 {\r
987     FX_LPBYTE result_buf = m_pBitmap->GetBuffer();\r
988     int src_width = m_pDecoder ? m_pDecoder->GetWidth() : m_SrcWidth;\r
989     int src_height = m_pDecoder ? m_pDecoder->GetHeight() : m_SrcHeight;\r
990     int src_pitch = src_width * m_Bpp;\r
991     while (m_LineIndex < m_ResultHeight) {\r
992         int dest_y, src_y;\r
993         if (m_bFlipY) {\r
994             dest_y = m_ResultHeight - m_LineIndex - 1;\r
995             src_y = (m_DestHeight - (dest_y + m_ClipTop) - 1) * src_height / m_DestHeight;\r
996         } else {\r
997             dest_y = m_LineIndex;\r
998             src_y = (dest_y + m_ClipTop) * src_height / m_DestHeight;\r
999         }\r
1000         FX_LPCBYTE src_scan;\r
1001         if (m_pDecoder) {\r
1002             src_scan = m_pDecoder->GetScanline(src_y);\r
1003             if (src_scan == NULL) {\r
1004                 break;\r
1005             }\r
1006         } else {\r
1007             src_scan = m_StreamAcc.GetData();\r
1008             if (src_scan == NULL) {\r
1009                 break;\r
1010             }\r
1011             src_scan += src_y * src_pitch;\r
1012         }\r
1013         FX_LPBYTE result_scan = result_buf + dest_y * m_pBitmap->GetPitch();\r
1014         for (int x = 0; x < m_ResultWidth; x ++) {\r
1015             int dest_x = m_ClipLeft + x;\r
1016             int src_x = (m_bFlipX ? (m_DestWidth - dest_x - 1) : dest_x) * src_width / m_DestWidth;\r
1017             FX_LPCBYTE src_pixel = src_scan + src_x * m_Bpp;\r
1018             if (m_pCS == NULL) {\r
1019                 *result_scan = src_pixel[2];\r
1020                 result_scan ++;\r
1021                 *result_scan = src_pixel[1];\r
1022                 result_scan ++;\r
1023                 *result_scan = src_pixel[0];\r
1024                 result_scan ++;\r
1025 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
1026                 result_scan ++;\r
1027 #endif\r
1028             } else {\r
1029                 m_pCS->TranslateImageLine(result_scan, src_pixel, 1, 0, 0);\r
1030 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
1031                 result_scan += 4;\r
1032 #else\r
1033                 result_scan += 3;\r
1034 #endif\r
1035             }\r
1036         }\r
1037         m_LineIndex ++;\r
1038         if (pPause && pPause->NeedToPauseNow()) {\r
1039             return TRUE;\r
1040         }\r
1041     }\r
1042     return FALSE;\r
1043 }\r
1044 CFX_DIBitmap* CPDF_RenderStatus::LoadSMask(CPDF_Dictionary* pSMaskDict,\r
1045         FX_RECT* pClipRect, const CFX_AffineMatrix* pMatrix)\r
1046 {\r
1047     if (pSMaskDict == NULL) {\r
1048         return NULL;\r
1049     }\r
1050     CFX_DIBitmap* pMask = NULL;\r
1051     int width = pClipRect->right - pClipRect->left;\r
1052     int height = pClipRect->bottom - pClipRect->top;\r
1053     FX_BOOL bLuminosity = FALSE;\r
1054     bLuminosity = pSMaskDict->GetConstString(FX_BSTRC("S")) != FX_BSTRC("Alpha");\r
1055     CPDF_Stream* pGroup = pSMaskDict->GetStream(FX_BSTRC("G"));\r
1056     if (pGroup == NULL) {\r
1057         return NULL;\r
1058     }\r
1059     CPDF_Function* pFunc = NULL;\r
1060     CPDF_Object* pFuncObj = pSMaskDict->GetElementValue(FX_BSTRC("TR"));\r
1061     if (pFuncObj && (pFuncObj->GetType() == PDFOBJ_DICTIONARY || pFuncObj->GetType() == PDFOBJ_STREAM)) {\r
1062         pFunc = CPDF_Function::Load(pFuncObj);\r
1063     }\r
1064     CFX_AffineMatrix matrix = *pMatrix;\r
1065     matrix.TranslateI(-pClipRect->left, -pClipRect->top);\r
1066     CPDF_Form form(m_pContext->m_pDocument, m_pContext->m_pPageResources, pGroup);\r
1067     form.ParseContent(NULL, NULL, NULL, NULL);\r
1068     CFX_FxgeDevice bitmap_device;\r
1069 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
1070     if (!bitmap_device.Create(width, height, bLuminosity ? FXDIB_Rgb32 : FXDIB_8bppMask)) {\r
1071         return NULL;\r
1072     }\r
1073 #else\r
1074     if (!bitmap_device.Create(width, height, bLuminosity ? FXDIB_Rgb : FXDIB_8bppMask)) {\r
1075         return NULL;\r
1076     }\r
1077 #endif\r
1078     CFX_DIBitmap& bitmap = *bitmap_device.GetBitmap();\r
1079     CPDF_Object* pCSObj = NULL;\r
1080     CPDF_ColorSpace* pCS = NULL;\r
1081     if (bLuminosity) {\r
1082         CPDF_Array* pBC = pSMaskDict->GetArray(FX_BSTRC("BC"));\r
1083         FX_ARGB back_color = 0xff000000;\r
1084         if (pBC) {\r
1085             pCSObj = pGroup->GetDict()->GetDict(FX_BSTRC("Group"))->GetElementValue(FX_BSTRC("CS"));\r
1086             pCS = m_pContext->m_pDocument->LoadColorSpace(pCSObj);\r
1087             if (pCS) {\r
1088                 FX_FLOAT R, G, B;\r
1089                 FX_DWORD num_floats = 8;\r
1090                 if (pCS->CountComponents() > (FX_INT32)num_floats) {\r
1091                     num_floats = (FX_DWORD)pCS->CountComponents();\r
1092                 }\r
1093                 CFX_FixedBufGrow<FX_FLOAT, 8> float_array(num_floats);\r
1094                 FX_FLOAT* pFloats = float_array;\r
1095                 FXSYS_memset32(pFloats, 0, num_floats * sizeof(FX_FLOAT));\r
1096                 int count = pBC->GetCount() > 8 ? 8 : pBC->GetCount();\r
1097                 for (int i = 0; i < count; i ++) {\r
1098                     pFloats[i] = pBC->GetNumber(i);\r
1099                 }\r
1100                 pCS->GetRGB(pFloats, R, G, B);\r
1101                 back_color = 0xff000000 | ((FX_INT32)(R * 255) << 16) | ((FX_INT32)(G * 255) << 8) | (FX_INT32)(B * 255);\r
1102                 m_pContext->m_pDocument->GetPageData()->ReleaseColorSpace(pCSObj);\r
1103             }\r
1104         }\r
1105         bitmap.Clear(back_color);\r
1106     } else {\r
1107         bitmap.Clear(0);\r
1108     }\r
1109     CPDF_Dictionary* pFormResource = NULL;\r
1110     if (form.m_pFormDict) {\r
1111         pFormResource = form.m_pFormDict->GetDict(FX_BSTRC("Resources"));\r
1112     }\r
1113     CPDF_RenderOptions options;\r
1114     options.m_ColorMode = bLuminosity ? RENDER_COLOR_NORMAL : RENDER_COLOR_ALPHA;\r
1115     CPDF_RenderStatus status;\r
1116     status.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL, NULL, NULL, NULL,\r
1117                       &options, 0, m_bDropObjects, pFormResource, TRUE, NULL, 0, pCS ? pCS->GetFamily() : 0, bLuminosity);\r
1118     status.RenderObjectList(&form, &matrix);\r
1119     pMask = FX_NEW CFX_DIBitmap;\r
1120     if (!pMask->Create(width, height, FXDIB_8bppMask)) {\r
1121         delete pMask;\r
1122         return NULL;\r
1123     }\r
1124     FX_LPBYTE dest_buf = pMask->GetBuffer();\r
1125     int dest_pitch = pMask->GetPitch();\r
1126     FX_LPBYTE src_buf = bitmap.GetBuffer();\r
1127     int src_pitch = bitmap.GetPitch();\r
1128     FX_LPBYTE pTransfer = FX_Alloc(FX_BYTE, 256);\r
1129     if (pFunc) {\r
1130         CFX_FixedBufGrow<FX_FLOAT, 16> results(pFunc->CountOutputs());\r
1131         for (int i = 0; i < 256; i ++) {\r
1132             FX_FLOAT input = (FX_FLOAT)i / 255.0f;\r
1133             int nresult;\r
1134             pFunc->Call(&input, 1, results, nresult);\r
1135             pTransfer[i] = FXSYS_round(results[0] * 255);\r
1136         }\r
1137     } else {\r
1138         for (int i = 0; i < 256; i ++) {\r
1139             pTransfer[i] = i;\r
1140         }\r
1141     }\r
1142     if (bLuminosity) {\r
1143         int Bpp = bitmap.GetBPP() / 8;\r
1144         for (int row = 0; row < height; row ++) {\r
1145             FX_LPBYTE dest_pos = dest_buf + row * dest_pitch;\r
1146             FX_LPBYTE src_pos = src_buf + row * src_pitch;\r
1147             for (int col = 0; col < width; col ++) {\r
1148                 *dest_pos ++ = pTransfer[FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos)];\r
1149                 src_pos += Bpp;\r
1150             }\r
1151         }\r
1152     } else if (pFunc) {\r
1153         int size = dest_pitch * height;\r
1154         for (int i = 0; i < size; i ++) {\r
1155             dest_buf[i] = pTransfer[src_buf[i]];\r
1156         }\r
1157     } else {\r
1158         FXSYS_memcpy32(dest_buf, src_buf, dest_pitch * height);\r
1159     }\r
1160     if (pFunc) {\r
1161         delete pFunc;\r
1162     }\r
1163     FX_Free(pTransfer);\r
1164     return pMask;\r
1165 }\r