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