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