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