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