Home | History | Annotate | Download | only in fpdf_render
      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 }
   1093