// Copyright 2014 PDFium Authors. All rights reserved. | |
// Use of this source code is governed by a BSD-style license that can be | |
// found in the LICENSE file. | |
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
#include "../../../include/fxge/fx_ge.h" | |
#include "../../../include/fxcodec/fx_codec.h" | |
#include "../../../include/fpdfapi/fpdf_module.h" | |
#include "../../../include/fpdfapi/fpdf_render.h" | |
#include "../../../include/fpdfapi/fpdf_pageobj.h" | |
#include "../fpdf_page/pageint.h" | |
#include "render_int.h" | |
FX_BOOL CPDF_RenderStatus::ProcessImage(CPDF_ImageObject* pImageObj, const CFX_AffineMatrix* pObj2Device) | |
{ | |
CPDF_ImageRenderer render; | |
if (render.Start(this, pImageObj, pObj2Device, m_bStdCS, m_curBlend)) { | |
render.Continue(NULL); | |
} | |
#ifdef _FPDFAPI_MINI_ | |
if (m_DitherBits) { | |
DitherObjectArea(pImageObj, pObj2Device); | |
} | |
#endif | |
return render.m_Result; | |
} | |
#if defined(_FPDFAPI_MINI_) | |
FX_BOOL CPDF_RenderStatus::ProcessInlines(CPDF_InlineImages* pInlines, const CFX_AffineMatrix* pObj2Device) | |
{ | |
int bitmap_alpha = 255; | |
if (!pInlines->m_GeneralState.IsNull()) { | |
bitmap_alpha = FXSYS_round(pInlines->m_GeneralState.GetObject()->m_FillAlpha * 255); | |
} | |
if (pInlines->m_pStream) { | |
CPDF_DIBSource dibsrc; | |
if (!dibsrc.Load(m_pContext->m_pDocument, pInlines->m_pStream, NULL, NULL, NULL, NULL)) { | |
return TRUE; | |
} | |
pInlines->m_pBitmap = dibsrc.Clone(); | |
pInlines->m_pStream->Release(); | |
pInlines->m_pStream = NULL; | |
} | |
if (pInlines->m_pBitmap == NULL) { | |
return TRUE; | |
} | |
FX_ARGB fill_argb = 0; | |
if (pInlines->m_pBitmap->IsAlphaMask()) { | |
fill_argb = GetFillArgb(pInlines); | |
} | |
int flags = 0; | |
if (m_Options.m_Flags & RENDER_FORCE_DOWNSAMPLE) { | |
flags |= RENDER_FORCE_DOWNSAMPLE; | |
} else if (m_Options.m_Flags & RENDER_FORCE_HALFTONE) { | |
flags = 0; | |
} | |
for (int i = 0; i < pInlines->m_Matrices.GetSize(); i ++) { | |
CFX_AffineMatrix image_matrix = pInlines->m_Matrices.GetAt(i); | |
image_matrix.Concat(*pObj2Device); | |
CPDF_ImageRenderer renderer; | |
if (renderer.Start(this, pInlines->m_pBitmap, fill_argb, bitmap_alpha, &image_matrix, flags, FALSE, m_curBlend)) { | |
renderer.Continue(NULL); | |
} | |
} | |
return TRUE; | |
} | |
#endif | |
void CPDF_RenderStatus::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, int left, int top, FX_ARGB mask_argb, | |
int bitmap_alpha, int blend_mode, int Transparency) | |
{ | |
if (pDIBitmap == NULL) { | |
return; | |
} | |
FX_BOOL bIsolated = Transparency & PDFTRANS_ISOLATED; | |
FX_BOOL bGroup = Transparency & PDFTRANS_GROUP; | |
if (blend_mode == FXDIB_BLEND_NORMAL) { | |
if (!pDIBitmap->IsAlphaMask()) { | |
if (bitmap_alpha < 255) { | |
pDIBitmap->MultiplyAlpha(bitmap_alpha); | |
} | |
if (m_pDevice->SetDIBits(pDIBitmap, left, top)) { | |
return; | |
} | |
} else { | |
FX_DWORD fill_argb = m_Options.TranslateColor(mask_argb); | |
if (bitmap_alpha < 255) { | |
((FX_BYTE*)&fill_argb)[3] = ((FX_BYTE*)&fill_argb)[3] * bitmap_alpha / 255; | |
} | |
if (m_pDevice->SetBitMask(pDIBitmap, left, top, fill_argb)) { | |
return; | |
} | |
} | |
} | |
FX_BOOL bBackAlphaRequired = blend_mode && bIsolated && !m_bDropObjects; | |
FX_BOOL bGetBackGround = ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) || | |
(!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) && (m_pDevice->GetRenderCaps() | |
& FXRC_GET_BITS) && !bBackAlphaRequired); | |
if (bGetBackGround) { | |
if (bIsolated || !bGroup) { | |
if (pDIBitmap->IsAlphaMask()) { | |
return; | |
} | |
m_pDevice->SetDIBits(pDIBitmap, left, top, blend_mode); | |
} else { | |
FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), top + pDIBitmap->GetHeight()); | |
rect.Intersect(m_pDevice->GetClipBox()); | |
CFX_DIBitmap* pClone = NULL; | |
FX_BOOL bClone = FALSE; | |
if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) { | |
bClone = TRUE; | |
pClone = m_pDevice->GetBackDrop()->Clone(&rect); | |
CFX_DIBitmap *pForeBitmap = m_pDevice->GetBitmap(); | |
pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), pForeBitmap, rect.left, rect.top); | |
left = left >= 0 ? 0 : left; | |
top = top >= 0 ? 0 : top; | |
if (!pDIBitmap->IsAlphaMask()) | |
pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), pDIBitmap, | |
left, top, blend_mode); | |
else | |
pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(), pDIBitmap, | |
mask_argb, left, top, blend_mode); | |
} else { | |
pClone = pDIBitmap; | |
} | |
if (m_pDevice->GetBackDrop()) { | |
m_pDevice->SetDIBits(pClone, rect.left, rect.top); | |
} else { | |
if (pDIBitmap->IsAlphaMask()) { | |
return; | |
} | |
m_pDevice->SetDIBits(pDIBitmap, rect.left, rect.top, blend_mode); | |
} | |
if (bClone) { | |
delete pClone; | |
} | |
} | |
return; | |
} | |
int back_left, back_top; | |
FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), top + pDIBitmap->GetHeight()); | |
CFX_DIBitmap* pBackdrop = GetBackdrop(m_pCurObj, rect, back_left, back_top, blend_mode > FXDIB_BLEND_NORMAL && bIsolated); | |
if (!pBackdrop) { | |
return; | |
} | |
if (!pDIBitmap->IsAlphaMask()) | |
pBackdrop->CompositeBitmap(left - back_left, top - back_top, pDIBitmap->GetWidth(), pDIBitmap->GetHeight(), pDIBitmap, | |
0, 0, blend_mode); | |
else | |
pBackdrop->CompositeMask(left - back_left, top - back_top, pDIBitmap->GetWidth(), pDIBitmap->GetHeight(), pDIBitmap, | |
mask_argb, 0, 0, blend_mode); | |
CFX_DIBitmap* pBackdrop1 = FX_NEW CFX_DIBitmap; | |
pBackdrop1->Create(pBackdrop->GetWidth(), pBackdrop->GetHeight(), FXDIB_Rgb32); | |
pBackdrop1->Clear((FX_DWORD) - 1); | |
pBackdrop1->CompositeBitmap(0, 0, pBackdrop->GetWidth(), pBackdrop->GetHeight(), pBackdrop, 0, 0); | |
delete pBackdrop; | |
pBackdrop = pBackdrop1; | |
m_pDevice->SetDIBits(pBackdrop, back_left, back_top); | |
delete pBackdrop; | |
} | |
FX_COLORREF CPDF_TransferFunc::TranslateColor(FX_COLORREF rgb) | |
{ | |
return FXSYS_RGB(m_Samples[FXSYS_GetRValue(rgb)], m_Samples[256 + FXSYS_GetGValue(rgb)], | |
m_Samples[512 + FXSYS_GetBValue(rgb)]); | |
} | |
CFX_DIBSource* CPDF_TransferFunc::TranslateImage(const CFX_DIBSource* pSrc, FX_BOOL bAutoDropSrc) | |
{ | |
CPDF_DIBTransferFunc* pDest = FX_NEW CPDF_DIBTransferFunc(this); | |
pDest->LoadSrc(pSrc, bAutoDropSrc); | |
return pDest; | |
} | |
FXDIB_Format CPDF_DIBTransferFunc::GetDestFormat() | |
{ | |
if (m_pSrc->IsAlphaMask()) { | |
return FXDIB_8bppMask; | |
} | |
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
return (m_pSrc->HasAlpha()) ? FXDIB_Argb : FXDIB_Rgb32; | |
#else | |
return (m_pSrc->HasAlpha()) ? FXDIB_Argb : FXDIB_Rgb; | |
#endif | |
} | |
CPDF_DIBTransferFunc::CPDF_DIBTransferFunc(const CPDF_TransferFunc* pTransferFunc) | |
{ | |
m_RampR = pTransferFunc->m_Samples; | |
m_RampG = &pTransferFunc->m_Samples[256]; | |
m_RampB = &pTransferFunc->m_Samples[512]; | |
} | |
void CPDF_DIBTransferFunc::TranslateScanline(FX_LPBYTE dest_buf, FX_LPCBYTE src_buf) const | |
{ | |
int i; | |
FX_BOOL bSkip = FALSE; | |
switch (m_pSrc->GetFormat()) { | |
case FXDIB_1bppRgb: { | |
int r0 = m_RampR[0], g0 = m_RampG[0], b0 = m_RampB[0]; | |
int r1 = m_RampR[255], g1 = m_RampG[255], b1 = m_RampB[255]; | |
for (i = 0; i < m_Width; i ++) { | |
if (src_buf[i / 8] & (1 << (7 - i % 8))) { | |
*dest_buf++ = b1; | |
*dest_buf++ = g1; | |
*dest_buf++ = r1; | |
} else { | |
*dest_buf++ = b0; | |
*dest_buf++ = g0; | |
*dest_buf++ = r0; | |
} | |
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
dest_buf++; | |
#endif | |
} | |
break; | |
} | |
case FXDIB_1bppMask: { | |
int m0 = m_RampR[0], m1 = m_RampR[255]; | |
for (i = 0; i < m_Width; i ++) { | |
if (src_buf[i / 8] & (1 << (7 - i % 8))) { | |
*dest_buf++ = m1; | |
} else { | |
*dest_buf++ = m0; | |
} | |
} | |
break; | |
} | |
case FXDIB_8bppRgb: { | |
FX_ARGB* pPal = m_pSrc->GetPalette(); | |
for (i = 0; i < m_Width; i ++) { | |
if (pPal) { | |
FX_ARGB src_argb = pPal[*src_buf]; | |
*dest_buf++ = m_RampB[FXARGB_R(src_argb)]; | |
*dest_buf++ = m_RampG[FXARGB_G(src_argb)]; | |
*dest_buf++ = m_RampR[FXARGB_B(src_argb)]; | |
} else { | |
FX_DWORD src_byte = *src_buf; | |
*dest_buf++ = m_RampB[src_byte]; | |
*dest_buf++ = m_RampG[src_byte]; | |
*dest_buf++ = m_RampR[src_byte]; | |
} | |
src_buf ++; | |
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
dest_buf++; | |
#endif | |
} | |
break; | |
} | |
case FXDIB_8bppMask: | |
for (i = 0; i < m_Width; i ++) { | |
*dest_buf++ = m_RampR[*(src_buf++)]; | |
} | |
break; | |
case FXDIB_Rgb: | |
for (i = 0; i < m_Width; i ++) { | |
*dest_buf++ = m_RampB[*(src_buf++)]; | |
*dest_buf++ = m_RampG[*(src_buf++)]; | |
*dest_buf++ = m_RampR[*(src_buf++)]; | |
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
dest_buf++; | |
#endif | |
} | |
break; | |
case FXDIB_Rgb32: | |
bSkip = TRUE; | |
case FXDIB_Argb: | |
for (i = 0; i < m_Width; i ++) { | |
*dest_buf++ = m_RampB[*(src_buf++)]; | |
*dest_buf++ = m_RampG[*(src_buf++)]; | |
*dest_buf++ = m_RampR[*(src_buf++)]; | |
if (!bSkip) { | |
*dest_buf++ = *src_buf; | |
} | |
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
else { | |
dest_buf++; | |
} | |
#endif | |
src_buf ++; | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
void CPDF_DIBTransferFunc::TranslateDownSamples(FX_LPBYTE dest_buf, FX_LPCBYTE src_buf, int pixels, int Bpp) const | |
{ | |
if (Bpp == 8) { | |
for (int i = 0; i < pixels; i ++) { | |
*dest_buf++ = m_RampR[*(src_buf++)]; | |
} | |
} else if (Bpp == 24) { | |
for (int i = 0; i < pixels; i ++) { | |
*dest_buf++ = m_RampB[*(src_buf++)]; | |
*dest_buf++ = m_RampG[*(src_buf++)]; | |
*dest_buf++ = m_RampR[*(src_buf++)]; | |
} | |
} else { | |
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
if (!m_pSrc->HasAlpha()) { | |
for (int i = 0; i < pixels; i ++) { | |
*dest_buf++ = m_RampB[*(src_buf++)]; | |
*dest_buf++ = m_RampG[*(src_buf++)]; | |
*dest_buf++ = m_RampR[*(src_buf++)]; | |
dest_buf++; | |
src_buf++; | |
} | |
} else | |
#endif | |
for (int i = 0; i < pixels; i ++) { | |
*dest_buf++ = m_RampB[*(src_buf++)]; | |
*dest_buf++ = m_RampG[*(src_buf++)]; | |
*dest_buf++ = m_RampR[*(src_buf++)]; | |
*dest_buf++ = *(src_buf++); | |
} | |
} | |
} | |
static FX_BOOL _IsSupported(CPDF_ColorSpace* pCS) | |
{ | |
if (pCS->GetFamily() == PDFCS_DEVICERGB || pCS->GetFamily() == PDFCS_DEVICEGRAY || | |
pCS->GetFamily() == PDFCS_DEVICECMYK || pCS->GetFamily() == PDFCS_CALGRAY || | |
pCS->GetFamily() == PDFCS_CALRGB) { | |
return TRUE; | |
} | |
if (pCS->GetFamily() == PDFCS_INDEXED && _IsSupported(pCS->GetBaseCS())) { | |
return TRUE; | |
} | |
return FALSE; | |
} | |
CPDF_ImageRenderer::CPDF_ImageRenderer() | |
{ | |
m_pRenderStatus = NULL; | |
m_pImageObject = NULL; | |
m_Result = TRUE; | |
m_Status = 0; | |
m_pQuickStretcher = NULL; | |
m_pTransformer = NULL; | |
m_DeviceHandle = NULL; | |
m_LoadHandle = NULL; | |
m_pClone = NULL; | |
m_bStdCS = FALSE; | |
m_bPatternColor = FALSE; | |
m_BlendType = FXDIB_BLEND_NORMAL; | |
m_pPattern = NULL; | |
m_pObj2Device = NULL; | |
} | |
CPDF_ImageRenderer::~CPDF_ImageRenderer() | |
{ | |
if (m_pQuickStretcher) { | |
delete m_pQuickStretcher; | |
} | |
if (m_pTransformer) { | |
delete m_pTransformer; | |
} | |
if (m_DeviceHandle) { | |
m_pRenderStatus->m_pDevice->CancelDIBits(m_DeviceHandle); | |
} | |
if (m_LoadHandle) { | |
delete (CPDF_ProgressiveImageLoaderHandle*)m_LoadHandle; | |
} | |
if (m_pClone) { | |
delete m_pClone; | |
} | |
} | |
FX_BOOL CPDF_ImageRenderer::StartLoadDIBSource() | |
{ | |
CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); | |
FX_RECT image_rect = image_rect_f.GetOutterRect(); | |
int dest_width = image_rect.Width(); | |
int dest_height = image_rect.Height(); | |
if (m_ImageMatrix.a < 0) { | |
dest_width = -dest_width; | |
} | |
if (m_ImageMatrix.d > 0) { | |
dest_height = -dest_height; | |
} | |
if (m_Loader.StartLoadImage(m_pImageObject, m_pRenderStatus->m_pContext->m_pPageCache, m_LoadHandle, m_bStdCS, | |
m_pRenderStatus->m_GroupFamily, m_pRenderStatus->m_bLoadMask, m_pRenderStatus, dest_width, dest_height)) { | |
if (m_LoadHandle != NULL) { | |
m_Status = 4; | |
return TRUE; | |
} | |
return FALSE; | |
} | |
return FALSE; | |
} | |
FX_BOOL CPDF_ImageRenderer::StartRenderDIBSource() | |
{ | |
if (m_Loader.m_pBitmap == NULL) { | |
return FALSE; | |
} | |
m_BitmapAlpha = 255; | |
const CPDF_GeneralStateData* pGeneralState = m_pImageObject->m_GeneralState; | |
if (pGeneralState) { | |
m_BitmapAlpha = FXSYS_round(pGeneralState->m_FillAlpha * 255); | |
} | |
m_pDIBSource = m_Loader.m_pBitmap; | |
if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_ALPHA && m_Loader.m_pMask == NULL) { | |
return StartBitmapAlpha(); | |
} | |
#ifndef _FPDFAPI_MINI_ | |
if (pGeneralState && pGeneralState->m_pTR) { | |
if (!pGeneralState->m_pTransferFunc) { | |
((CPDF_GeneralStateData*)pGeneralState)->m_pTransferFunc = m_pRenderStatus->GetTransferFunc(pGeneralState->m_pTR); | |
} | |
if (pGeneralState->m_pTransferFunc && !pGeneralState->m_pTransferFunc->m_bIdentity) { | |
m_pDIBSource = m_Loader.m_pBitmap = pGeneralState->m_pTransferFunc->TranslateImage(m_Loader.m_pBitmap, !m_Loader.m_bCached); | |
if (m_Loader.m_bCached && m_Loader.m_pMask) { | |
m_Loader.m_pMask = m_Loader.m_pMask->Clone(); | |
} | |
m_Loader.m_bCached = FALSE; | |
} | |
} | |
#endif | |
m_FillArgb = 0; | |
m_bPatternColor = FALSE; | |
m_pPattern = NULL; | |
if (m_pDIBSource->IsAlphaMask()) { | |
CPDF_Color* pColor = m_pImageObject->m_ColorState.GetFillColor(); | |
if (pColor && pColor->IsPattern()) { | |
m_pPattern = pColor->GetPattern(); | |
if (m_pPattern != NULL) { | |
m_bPatternColor = TRUE; | |
} | |
} | |
m_FillArgb = m_pRenderStatus->GetFillArgb(m_pImageObject); | |
} else if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_GRAY) { | |
m_pClone = m_pDIBSource->Clone(); | |
m_pClone->ConvertColorScale(m_pRenderStatus->m_Options.m_BackColor, m_pRenderStatus->m_Options.m_ForeColor); | |
m_pDIBSource = m_pClone; | |
} | |
m_Flags = 0; | |
#if !defined(_FPDFAPI_MINI_) | |
if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_DOWNSAMPLE) { | |
m_Flags |= RENDER_FORCE_DOWNSAMPLE; | |
} else if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_HALFTONE) { | |
m_Flags |= RENDER_FORCE_HALFTONE; | |
} | |
#else | |
if (!(m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_HALFTONE)) { | |
if (m_pRenderStatus->m_HalftoneLimit) { | |
CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); | |
FX_RECT image_rect = image_rect_f.GetOutterRect(); | |
FX_RECT image_clip = image_rect; | |
image_rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox()); | |
if (image_rect.Width() && image_rect.Height()) { | |
if ((image_clip.Width() * m_pDIBSource->GetWidth() / image_rect.Width()) * | |
(image_clip.Height() * m_pDIBSource->GetHeight() / image_rect.Height()) > | |
m_pRenderStatus->m_HalftoneLimit) { | |
m_Flags |= RENDER_FORCE_DOWNSAMPLE; | |
} | |
} | |
} else { | |
m_Flags |= RENDER_FORCE_DOWNSAMPLE; | |
} | |
} | |
#endif | |
#ifndef _FPDFAPI_MINI_ | |
if (m_pRenderStatus->m_pDevice->GetDeviceClass() != FXDC_DISPLAY) { | |
CPDF_Object* pFilters = m_pImageObject->m_pImage->GetStream()->GetDict()->GetElementValue(FX_BSTRC("Filter")); | |
if (pFilters) { | |
if (pFilters->GetType() == PDFOBJ_NAME) { | |
CFX_ByteStringC bsDecodeType = pFilters->GetConstString(); | |
if (bsDecodeType == FX_BSTRC("DCTDecode") || bsDecodeType == FX_BSTRC("JPXDecode")) { | |
m_Flags |= FXRENDER_IMAGE_LOSSY; | |
} | |
} else if (pFilters->GetType() == PDFOBJ_ARRAY) { | |
CPDF_Array* pArray = (CPDF_Array*)pFilters; | |
for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) { | |
CFX_ByteStringC bsDecodeType = pArray->GetConstString(i); | |
if (bsDecodeType == FX_BSTRC("DCTDecode") || bsDecodeType == FX_BSTRC("JPXDecode")) { | |
m_Flags |= FXRENDER_IMAGE_LOSSY; | |
break; | |
} | |
} | |
} | |
} | |
} | |
if (m_pRenderStatus->m_Options.m_Flags & RENDER_NOIMAGESMOOTH) { | |
m_Flags |= FXDIB_NOSMOOTH; | |
} else if (m_pImageObject->m_pImage->IsInterpol()) { | |
m_Flags |= FXDIB_INTERPOL; | |
} | |
#endif | |
if (m_Loader.m_pMask) { | |
return DrawMaskedImage(); | |
} | |
if (m_bPatternColor) { | |
return DrawPatternImage(m_pObj2Device); | |
} | |
#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_) | |
if (m_BitmapAlpha == 255 && pGeneralState && pGeneralState->m_FillOP && | |
pGeneralState->m_OPMode == 0 && pGeneralState->m_BlendType == FXDIB_BLEND_NORMAL && pGeneralState->m_StrokeAlpha == 1 && pGeneralState->m_FillAlpha == 1) { | |
CPDF_Document* pDocument = NULL; | |
CPDF_Page* pPage = NULL; | |
if (m_pRenderStatus->m_pContext->m_pPageCache) { | |
pPage = m_pRenderStatus->m_pContext->m_pPageCache->GetPage(); | |
pDocument = pPage->m_pDocument; | |
} else { | |
pDocument = m_pImageObject->m_pImage->GetDocument(); | |
} | |
CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : NULL; | |
CPDF_Object* pCSObj = m_pImageObject->m_pImage->GetStream()->GetDict()->GetElementValue(FX_BSTRC("ColorSpace")); | |
CPDF_ColorSpace* pColorSpace = pDocument->LoadColorSpace(pCSObj, pPageResources); | |
if (pColorSpace) { | |
int format = pColorSpace->GetFamily(); | |
if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION || format == PDFCS_DEVICEN) { | |
m_BlendType = FXDIB_BLEND_DARKEN; | |
} | |
pDocument->GetPageData()->ReleaseColorSpace(pCSObj); | |
} | |
} | |
#endif | |
return StartDIBSource(); | |
} | |
FX_BOOL CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStdCS, int blendType) | |
{ | |
m_pRenderStatus = pStatus; | |
m_bStdCS = bStdCS; | |
m_pImageObject = (CPDF_ImageObject*)pObj; | |
m_BlendType = blendType; | |
m_pObj2Device = pObj2Device; | |
#ifndef _FPDFAPI_MINI_ | |
CPDF_Dictionary* pOC = m_pImageObject->m_pImage->GetOC(); | |
if (pOC && m_pRenderStatus->m_Options.m_pOCContext && !m_pRenderStatus->m_Options.m_pOCContext->CheckOCGVisible(pOC)) { | |
return FALSE; | |
} | |
#endif | |
m_ImageMatrix = m_pImageObject->m_Matrix; | |
m_ImageMatrix.Concat(*pObj2Device); | |
if (StartLoadDIBSource()) { | |
return TRUE; | |
} | |
return StartRenderDIBSource(); | |
} | |
FX_BOOL CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, const CFX_DIBSource* pDIBSource, FX_ARGB bitmap_argb, | |
int bitmap_alpha, const CFX_AffineMatrix* pImage2Device, FX_DWORD flags, FX_BOOL bStdCS, int blendType) | |
{ | |
m_pRenderStatus = pStatus; | |
m_pDIBSource = pDIBSource; | |
m_FillArgb = bitmap_argb; | |
m_BitmapAlpha = bitmap_alpha; | |
m_ImageMatrix = *pImage2Device; | |
m_Flags = flags; | |
m_bStdCS = bStdCS; | |
m_BlendType = blendType; | |
return StartDIBSource(); | |
} | |
FX_BOOL CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device) | |
{ | |
if (m_pRenderStatus->m_bPrint && !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | |
m_Result = FALSE; | |
return FALSE; | |
} | |
FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOutterRect(); | |
rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox()); | |
if (rect.IsEmpty()) { | |
return FALSE; | |
} | |
CFX_AffineMatrix new_matrix = m_ImageMatrix; | |
new_matrix.TranslateI(-rect.left, -rect.top); | |
int width = rect.Width(); | |
int height = rect.Height(); | |
CFX_FxgeDevice bitmap_device1; | |
if (!bitmap_device1.Create(rect.Width(), rect.Height(), FXDIB_Rgb32)) { | |
return TRUE; | |
} | |
bitmap_device1.GetBitmap()->Clear(0xffffff); | |
{ | |
CPDF_RenderStatus bitmap_render; | |
bitmap_render.Initialize(m_pRenderStatus->m_Level + 1, m_pRenderStatus->m_pContext, &bitmap_device1, NULL, NULL, | |
NULL, NULL, &m_pRenderStatus->m_Options, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE); | |
CFX_Matrix patternDevice = *pObj2Device; | |
patternDevice.Translate((FX_FLOAT) - rect.left, (FX_FLOAT) - rect.top); | |
if(m_pPattern->m_PatternType == PATTERN_TILING) { | |
bitmap_render.DrawTilingPattern((CPDF_TilingPattern*)m_pPattern, m_pImageObject, &patternDevice, FALSE); | |
} else { | |
bitmap_render.DrawShadingPattern((CPDF_ShadingPattern*)m_pPattern, m_pImageObject, &patternDevice, FALSE); | |
} | |
} | |
{ | |
CFX_FxgeDevice bitmap_device2; | |
if (!bitmap_device2.Create(rect.Width(), rect.Height(), FXDIB_8bppRgb)) { | |
return TRUE; | |
} | |
bitmap_device2.GetBitmap()->Clear(0); | |
CPDF_RenderStatus bitmap_render; | |
bitmap_render.Initialize(m_pRenderStatus->m_Level + 1, m_pRenderStatus->m_pContext, &bitmap_device2, NULL, NULL, | |
NULL, NULL, NULL, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE); | |
CPDF_ImageRenderer image_render; | |
if (image_render.Start(&bitmap_render, m_pDIBSource, 0xffffffff, 255, &new_matrix, m_Flags, TRUE)) { | |
image_render.Continue(NULL); | |
} | |
if (m_Loader.m_MatteColor != 0xffffffff) { | |
int matte_r = FXARGB_R(m_Loader.m_MatteColor); | |
int matte_g = FXARGB_G(m_Loader.m_MatteColor); | |
int matte_b = FXARGB_B(m_Loader.m_MatteColor); | |
for (int row = 0; row < height; row ++) { | |
FX_LPBYTE dest_scan = (FX_LPBYTE)bitmap_device1.GetBitmap()->GetScanline(row); | |
FX_LPCBYTE mask_scan = bitmap_device2.GetBitmap()->GetScanline(row); | |
for (int col = 0; col < width; col ++) { | |
int alpha = *mask_scan ++; | |
if (alpha) { | |
int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; | |
if (orig < 0) { | |
orig = 0; | |
} else if (orig > 255) { | |
orig = 255; | |
} | |
*dest_scan++ = orig; | |
orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; | |
if (orig < 0) { | |
orig = 0; | |
} else if (orig > 255) { | |
orig = 255; | |
} | |
*dest_scan++ = orig; | |
orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; | |
if (orig < 0) { | |
orig = 0; | |
} else if (orig > 255) { | |
orig = 255; | |
} | |
*dest_scan++ = orig; | |
dest_scan ++; | |
} else { | |
dest_scan += 4; | |
} | |
} | |
} | |
} | |
bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); | |
bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); | |
bitmap_device1.GetBitmap()->MultiplyAlpha(255); | |
} | |
m_pRenderStatus->m_pDevice->SetDIBits(bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); | |
return FALSE; | |
} | |
FX_BOOL CPDF_ImageRenderer::DrawMaskedImage() | |
{ | |
if (m_pRenderStatus->m_bPrint && !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | |
m_Result = FALSE; | |
return FALSE; | |
} | |
FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOutterRect(); | |
rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox()); | |
if (rect.IsEmpty()) { | |
return FALSE; | |
} | |
CFX_AffineMatrix new_matrix = m_ImageMatrix; | |
new_matrix.TranslateI(-rect.left, -rect.top); | |
int width = rect.Width(); | |
int height = rect.Height(); | |
CFX_FxgeDevice bitmap_device1; | |
if (!bitmap_device1.Create(width, height, FXDIB_Rgb32)) { | |
return TRUE; | |
} | |
bitmap_device1.GetBitmap()->Clear(0xffffff); | |
{ | |
CPDF_RenderStatus bitmap_render; | |
bitmap_render.Initialize(m_pRenderStatus->m_Level + 1, m_pRenderStatus->m_pContext, &bitmap_device1, NULL, NULL, | |
NULL, NULL, NULL, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE); | |
CPDF_ImageRenderer image_render; | |
if (image_render.Start(&bitmap_render, m_pDIBSource, 0, 255, &new_matrix, m_Flags, TRUE)) { | |
image_render.Continue(NULL); | |
} | |
} | |
{ | |
CFX_FxgeDevice bitmap_device2; | |
if (!bitmap_device2.Create(width, height, FXDIB_8bppRgb)) { | |
return TRUE; | |
} | |
bitmap_device2.GetBitmap()->Clear(0); | |
CPDF_RenderStatus bitmap_render; | |
bitmap_render.Initialize(m_pRenderStatus->m_Level + 1, m_pRenderStatus->m_pContext, &bitmap_device2, NULL, NULL, | |
NULL, NULL, NULL, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE); | |
CPDF_ImageRenderer image_render; | |
if (image_render.Start(&bitmap_render, m_Loader.m_pMask, 0xffffffff, 255, &new_matrix, m_Flags, TRUE)) { | |
image_render.Continue(NULL); | |
} | |
if (m_Loader.m_MatteColor != 0xffffffff) { | |
int matte_r = FXARGB_R(m_Loader.m_MatteColor); | |
int matte_g = FXARGB_G(m_Loader.m_MatteColor); | |
int matte_b = FXARGB_B(m_Loader.m_MatteColor); | |
for (int row = 0; row < height; row ++) { | |
FX_LPBYTE dest_scan = (FX_LPBYTE)bitmap_device1.GetBitmap()->GetScanline(row); | |
FX_LPCBYTE mask_scan = bitmap_device2.GetBitmap()->GetScanline(row); | |
for (int col = 0; col < width; col ++) { | |
int alpha = *mask_scan ++; | |
if (alpha) { | |
int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; | |
if (orig < 0) { | |
orig = 0; | |
} else if (orig > 255) { | |
orig = 255; | |
} | |
*dest_scan++ = orig; | |
orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; | |
if (orig < 0) { | |
orig = 0; | |
} else if (orig > 255) { | |
orig = 255; | |
} | |
*dest_scan++ = orig; | |
orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; | |
if (orig < 0) { | |
orig = 0; | |
} else if (orig > 255) { | |
orig = 255; | |
} | |
*dest_scan++ = orig; | |
dest_scan ++; | |
} else { | |
dest_scan += 4; | |
} | |
} | |
} | |
} | |
bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); | |
bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); | |
if (m_BitmapAlpha < 255) { | |
bitmap_device1.GetBitmap()->MultiplyAlpha(m_BitmapAlpha); | |
} | |
} | |
m_pRenderStatus->m_pDevice->SetDIBits(bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); | |
return FALSE; | |
} | |
FX_BOOL CPDF_ImageRenderer::StartDIBSource() | |
{ | |
#if !defined(_FPDFAPI_MINI_) | |
if (!(m_Flags & RENDER_FORCE_DOWNSAMPLE) && m_pDIBSource->GetBPP() > 1) { | |
int image_size = m_pDIBSource->GetBPP() / 8 * m_pDIBSource->GetWidth() * m_pDIBSource->GetHeight(); | |
if (image_size > FPDF_HUGE_IMAGE_SIZE && !(m_Flags & RENDER_FORCE_HALFTONE)) { | |
m_Flags |= RENDER_FORCE_DOWNSAMPLE; | |
} | |
} | |
#endif | |
if (m_pRenderStatus->m_pDevice->StartDIBits(m_pDIBSource, m_BitmapAlpha, m_FillArgb, | |
&m_ImageMatrix, m_Flags, m_DeviceHandle, 0, NULL, m_BlendType)) { | |
if (m_DeviceHandle != NULL) { | |
m_Status = 3; | |
return TRUE; | |
} | |
return FALSE; | |
} | |
#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_) | |
CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); | |
FX_RECT image_rect = image_rect_f.GetOutterRect(); | |
int dest_width = image_rect.Width(); | |
int dest_height = image_rect.Height(); | |
if ((FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) || | |
(FXSYS_fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0) ) { | |
if (m_pRenderStatus->m_bPrint && !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | |
m_Result = FALSE; | |
return FALSE; | |
} | |
FX_RECT clip_box = m_pRenderStatus->m_pDevice->GetClipBox(); | |
clip_box.Intersect(image_rect); | |
m_Status = 2; | |
m_pTransformer = FX_NEW CFX_ImageTransformer; | |
m_pTransformer->Start(m_pDIBSource, &m_ImageMatrix, m_Flags, &clip_box); | |
return TRUE; | |
} | |
if (m_ImageMatrix.a < 0) { | |
dest_width = -dest_width; | |
} | |
if (m_ImageMatrix.d > 0) { | |
dest_height = -dest_height; | |
} | |
int dest_left, dest_top; | |
dest_left = dest_width > 0 ? image_rect.left : image_rect.right; | |
dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom; | |
if (m_pDIBSource->IsOpaqueImage() && m_BitmapAlpha == 255) { | |
if (m_pRenderStatus->m_pDevice->StretchDIBits(m_pDIBSource, dest_left, dest_top, | |
dest_width, dest_height, m_Flags, NULL, m_BlendType)) { | |
return FALSE; | |
} | |
} | |
if (m_pDIBSource->IsAlphaMask()) { | |
if (m_BitmapAlpha != 255) { | |
m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); | |
} | |
if (m_pRenderStatus->m_pDevice->StretchBitMask(m_pDIBSource, dest_left, dest_top, dest_width, dest_height, m_FillArgb, m_Flags)) { | |
return FALSE; | |
} | |
} | |
if (m_pRenderStatus->m_bPrint && !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | |
m_Result = FALSE; | |
return TRUE; | |
} | |
FX_RECT clip_box = m_pRenderStatus->m_pDevice->GetClipBox(); | |
FX_RECT dest_rect = clip_box; | |
dest_rect.Intersect(image_rect); | |
FX_RECT dest_clip(dest_rect.left - image_rect.left, dest_rect.top - image_rect.top, | |
dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top); | |
CFX_DIBitmap* pStretched = m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip); | |
if (pStretched) { | |
m_pRenderStatus->CompositeDIBitmap(pStretched, dest_rect.left, dest_rect.top, m_FillArgb, | |
m_BitmapAlpha, m_BlendType, FALSE); | |
delete pStretched; | |
pStretched = NULL; | |
} | |
#endif | |
return FALSE; | |
} | |
FX_BOOL CPDF_ImageRenderer::StartBitmapAlpha() | |
{ | |
#ifndef _FPDFAPI_MINI_ | |
if (m_pDIBSource->IsOpaqueImage()) { | |
CFX_PathData path; | |
path.AppendRect(0, 0, 1, 1); | |
path.Transform(&m_ImageMatrix); | |
FX_DWORD fill_color = ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha); | |
m_pRenderStatus->m_pDevice->DrawPath(&path, NULL, NULL, fill_color, 0, FXFILL_WINDING); | |
} else { | |
const CFX_DIBSource* pAlphaMask = m_pDIBSource->IsAlphaMask() ? m_pDIBSource : m_pDIBSource->GetAlphaMask(); | |
if (FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || FXSYS_fabs(m_ImageMatrix.c) >= 0.5f) { | |
int left, top; | |
CFX_DIBitmap* pTransformed = pAlphaMask->TransformTo(&m_ImageMatrix, left, top); | |
if (pTransformed == NULL) { | |
return TRUE; | |
} | |
m_pRenderStatus->m_pDevice->SetBitMask(pTransformed, left, top, ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha)); | |
delete pTransformed; | |
} else { | |
CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); | |
FX_RECT image_rect = image_rect_f.GetOutterRect(); | |
int dest_width = m_ImageMatrix.a > 0 ? image_rect.Width() : -image_rect.Width(); | |
int dest_height = m_ImageMatrix.d > 0 ? -image_rect.Height() : image_rect.Height(); | |
int left = dest_width > 0 ? image_rect.left : image_rect.right; | |
int top = dest_height > 0 ? image_rect.top : image_rect.bottom; | |
m_pRenderStatus->m_pDevice->StretchBitMask(pAlphaMask, left, top, dest_width, dest_height, | |
ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha)); | |
} | |
if (m_pDIBSource != pAlphaMask) { | |
delete pAlphaMask; | |
} | |
} | |
#endif | |
return FALSE; | |
} | |
FX_BOOL CPDF_ImageRenderer::Continue(IFX_Pause* pPause) | |
{ | |
if (m_Status == 1) { | |
#ifndef _FPDFAPI_MINI_ | |
if (m_pQuickStretcher->Continue(pPause)) { | |
return TRUE; | |
} | |
if (m_pQuickStretcher->m_pBitmap->IsAlphaMask()) | |
m_pRenderStatus->m_pDevice->SetBitMask(m_pQuickStretcher->m_pBitmap, m_pQuickStretcher->m_ResultLeft, | |
m_pQuickStretcher->m_ResultTop, m_FillArgb); | |
else | |
m_pRenderStatus->m_pDevice->SetDIBits(m_pQuickStretcher->m_pBitmap, m_pQuickStretcher->m_ResultLeft, | |
m_pQuickStretcher->m_ResultTop, m_BlendType); | |
return FALSE; | |
#endif | |
} else if (m_Status == 2) { | |
#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_) | |
if (m_pTransformer->Continue(pPause)) { | |
return TRUE; | |
} | |
CFX_DIBitmap* pBitmap = m_pTransformer->m_Storer.Detach(); | |
if (pBitmap == NULL) { | |
return FALSE; | |
} | |
if (pBitmap->IsAlphaMask()) { | |
if (m_BitmapAlpha != 255) { | |
m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); | |
} | |
m_Result = m_pRenderStatus->m_pDevice->SetBitMask(pBitmap, | |
m_pTransformer->m_ResultLeft, m_pTransformer->m_ResultTop, m_FillArgb); | |
} else { | |
if (m_BitmapAlpha != 255) { | |
pBitmap->MultiplyAlpha(m_BitmapAlpha); | |
} | |
m_Result = m_pRenderStatus->m_pDevice->SetDIBits(pBitmap, | |
m_pTransformer->m_ResultLeft, m_pTransformer->m_ResultTop, m_BlendType); | |
} | |
delete pBitmap; | |
return FALSE; | |
#endif | |
} else if (m_Status == 3) { | |
return m_pRenderStatus->m_pDevice->ContinueDIBits(m_DeviceHandle, pPause); | |
} else if (m_Status == 4) { | |
if (m_Loader.Continue(m_LoadHandle, pPause)) { | |
return TRUE; | |
} | |
if (StartRenderDIBSource()) { | |
return Continue(pPause); | |
} | |
return FALSE; | |
} | |
return FALSE; | |
} | |
CPDF_QuickStretcher::CPDF_QuickStretcher() | |
{ | |
m_pBitmap = NULL; | |
m_pDecoder = NULL; | |
m_pCS = NULL; | |
} | |
CPDF_QuickStretcher::~CPDF_QuickStretcher() | |
{ | |
if (m_pBitmap) { | |
delete m_pBitmap; | |
} | |
if (m_pCS) { | |
m_pCS->ReleaseCS(); | |
} | |
if (m_pDecoder) { | |
delete m_pDecoder; | |
} | |
} | |
ICodec_ScanlineDecoder* FPDFAPI_CreateFlateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, | |
int nComps, int bpc, const CPDF_Dictionary* pParams); | |
FX_BOOL CPDF_QuickStretcher::Start(CPDF_ImageObject* pImageObj, CFX_AffineMatrix* pImage2Device, const FX_RECT* pClipBox) | |
{ | |
if (FXSYS_fabs(pImage2Device->a) < FXSYS_fabs(pImage2Device->b) * 10 && FXSYS_fabs(pImage2Device->d) < FXSYS_fabs(pImage2Device->c) * 10) { | |
return FALSE; | |
} | |
CFX_FloatRect image_rect_f = pImage2Device->GetUnitRect(); | |
FX_RECT image_rect = image_rect_f.GetOutterRect(); | |
m_DestWidth = image_rect.Width(); | |
m_DestHeight = image_rect.Height(); | |
m_bFlipX = pImage2Device->a < 0; | |
m_bFlipY = pImage2Device->d > 0; | |
FX_RECT result_rect = *pClipBox; | |
result_rect.Intersect(image_rect); | |
if (result_rect.IsEmpty()) { | |
return FALSE; | |
} | |
m_ResultWidth = result_rect.Width(); | |
m_ResultHeight = result_rect.Height(); | |
m_ResultLeft = result_rect.left; | |
m_ResultTop = result_rect.top; | |
m_ClipLeft = result_rect.left - image_rect.left; | |
m_ClipTop = result_rect.top - image_rect.top; | |
CPDF_Dictionary* pDict = pImageObj->m_pImage->GetDict(); | |
if (pDict->GetInteger(FX_BSTRC("BitsPerComponent")) != 8) { | |
return FALSE; | |
} | |
if (pDict->KeyExist(FX_BSTRC("SMask")) || pDict->KeyExist(FX_BSTRC("Mask"))) { | |
return FALSE; | |
} | |
m_SrcWidth = pDict->GetInteger(FX_BSTRC("Width")); | |
m_SrcHeight = pDict->GetInteger(FX_BSTRC("Height")); | |
m_pCS = NULL; | |
m_Bpp = 3; | |
CPDF_Object* pCSObj = pDict->GetElementValue(FX_BSTRC("ColorSpace")); | |
if (pCSObj == NULL) { | |
return FALSE; | |
} | |
m_pCS = CPDF_ColorSpace::Load(pImageObj->m_pImage->GetDocument(), pCSObj); | |
if (m_pCS == NULL) { | |
return FALSE; | |
} | |
if (!_IsSupported(m_pCS)) { | |
return FALSE; | |
} | |
m_Bpp = m_pCS->CountComponents(); | |
if (m_pCS->sRGB()) { | |
m_pCS->ReleaseCS(); | |
m_pCS = NULL; | |
} | |
CPDF_Stream* pStream = pImageObj->m_pImage->GetStream(); | |
m_StreamAcc.LoadAllData(pStream, FALSE, m_SrcWidth * m_SrcHeight * m_Bpp, TRUE); | |
m_pDecoder = NULL; | |
if (!m_StreamAcc.GetImageDecoder().IsEmpty()) { | |
if (m_StreamAcc.GetImageDecoder() == FX_BSTRC("DCTDecode")) { | |
const CPDF_Dictionary* pParam = m_StreamAcc.GetImageParam(); | |
m_pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder( | |
m_StreamAcc.GetData(), m_StreamAcc.GetSize(), m_SrcWidth, m_SrcHeight, m_Bpp, | |
pParam ? pParam->GetInteger(FX_BSTRC("ColorTransform"), 1) : 1); | |
} else if (m_StreamAcc.GetImageDecoder() == FX_BSTRC("FlateDecode")) { | |
m_pDecoder = FPDFAPI_CreateFlateDecoder( | |
m_StreamAcc.GetData(), m_StreamAcc.GetSize(), m_SrcWidth, m_SrcHeight, m_Bpp, 8, | |
m_StreamAcc.GetImageParam()); | |
} else { | |
return FALSE; | |
} | |
m_pDecoder->DownScale(m_DestWidth, m_DestHeight); | |
} | |
m_pBitmap = FX_NEW CFX_DIBitmap; | |
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
m_pBitmap->Create(m_ResultWidth, m_ResultHeight, FXDIB_Rgb32); | |
#else | |
m_pBitmap->Create(m_ResultWidth, m_ResultHeight, FXDIB_Rgb); | |
#endif | |
m_LineIndex = 0; | |
return TRUE; | |
} | |
FX_BOOL CPDF_QuickStretcher::Continue(IFX_Pause* pPause) | |
{ | |
FX_LPBYTE result_buf = m_pBitmap->GetBuffer(); | |
int src_width = m_pDecoder ? m_pDecoder->GetWidth() : m_SrcWidth; | |
int src_height = m_pDecoder ? m_pDecoder->GetHeight() : m_SrcHeight; | |
int src_pitch = src_width * m_Bpp; | |
while (m_LineIndex < m_ResultHeight) { | |
int dest_y, src_y; | |
if (m_bFlipY) { | |
dest_y = m_ResultHeight - m_LineIndex - 1; | |
src_y = (m_DestHeight - (dest_y + m_ClipTop) - 1) * src_height / m_DestHeight; | |
} else { | |
dest_y = m_LineIndex; | |
src_y = (dest_y + m_ClipTop) * src_height / m_DestHeight; | |
} | |
FX_LPCBYTE src_scan; | |
if (m_pDecoder) { | |
src_scan = m_pDecoder->GetScanline(src_y); | |
if (src_scan == NULL) { | |
break; | |
} | |
} else { | |
src_scan = m_StreamAcc.GetData(); | |
if (src_scan == NULL) { | |
break; | |
} | |
src_scan += src_y * src_pitch; | |
} | |
FX_LPBYTE result_scan = result_buf + dest_y * m_pBitmap->GetPitch(); | |
for (int x = 0; x < m_ResultWidth; x ++) { | |
int dest_x = m_ClipLeft + x; | |
int src_x = (m_bFlipX ? (m_DestWidth - dest_x - 1) : dest_x) * src_width / m_DestWidth; | |
FX_LPCBYTE src_pixel = src_scan + src_x * m_Bpp; | |
if (m_pCS == NULL) { | |
*result_scan = src_pixel[2]; | |
result_scan ++; | |
*result_scan = src_pixel[1]; | |
result_scan ++; | |
*result_scan = src_pixel[0]; | |
result_scan ++; | |
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
result_scan ++; | |
#endif | |
} else { | |
m_pCS->TranslateImageLine(result_scan, src_pixel, 1, 0, 0); | |
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
result_scan += 4; | |
#else | |
result_scan += 3; | |
#endif | |
} | |
} | |
m_LineIndex ++; | |
if (pPause && pPause->NeedToPauseNow()) { | |
return TRUE; | |
} | |
} | |
return FALSE; | |
} | |
CFX_DIBitmap* CPDF_RenderStatus::LoadSMask(CPDF_Dictionary* pSMaskDict, | |
FX_RECT* pClipRect, const CFX_AffineMatrix* pMatrix) | |
{ | |
if (pSMaskDict == NULL) { | |
return NULL; | |
} | |
CFX_DIBitmap* pMask = NULL; | |
int width = pClipRect->right - pClipRect->left; | |
int height = pClipRect->bottom - pClipRect->top; | |
FX_BOOL bLuminosity = FALSE; | |
bLuminosity = pSMaskDict->GetConstString(FX_BSTRC("S")) != FX_BSTRC("Alpha"); | |
CPDF_Stream* pGroup = pSMaskDict->GetStream(FX_BSTRC("G")); | |
if (pGroup == NULL) { | |
return NULL; | |
} | |
CPDF_Function* pFunc = NULL; | |
CPDF_Object* pFuncObj = pSMaskDict->GetElementValue(FX_BSTRC("TR")); | |
if (pFuncObj && (pFuncObj->GetType() == PDFOBJ_DICTIONARY || pFuncObj->GetType() == PDFOBJ_STREAM)) { | |
pFunc = CPDF_Function::Load(pFuncObj); | |
} | |
CFX_AffineMatrix matrix = *pMatrix; | |
matrix.TranslateI(-pClipRect->left, -pClipRect->top); | |
CPDF_Form form(m_pContext->m_pDocument, m_pContext->m_pPageResources, pGroup); | |
form.ParseContent(NULL, NULL, NULL, NULL); | |
CFX_FxgeDevice bitmap_device; | |
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
if (!bitmap_device.Create(width, height, bLuminosity ? FXDIB_Rgb32 : FXDIB_8bppMask)) { | |
return NULL; | |
} | |
#else | |
if (!bitmap_device.Create(width, height, bLuminosity ? FXDIB_Rgb : FXDIB_8bppMask)) { | |
return NULL; | |
} | |
#endif | |
CFX_DIBitmap& bitmap = *bitmap_device.GetBitmap(); | |
CPDF_Object* pCSObj = NULL; | |
CPDF_ColorSpace* pCS = NULL; | |
if (bLuminosity) { | |
CPDF_Array* pBC = pSMaskDict->GetArray(FX_BSTRC("BC")); | |
FX_ARGB back_color = 0xff000000; | |
if (pBC) { | |
pCSObj = pGroup->GetDict()->GetDict(FX_BSTRC("Group"))->GetElementValue(FX_BSTRC("CS")); | |
pCS = m_pContext->m_pDocument->LoadColorSpace(pCSObj); | |
if (pCS) { | |
FX_FLOAT R, G, B; | |
FX_DWORD num_floats = 8; | |
if (pCS->CountComponents() > (FX_INT32)num_floats) { | |
num_floats = (FX_DWORD)pCS->CountComponents(); | |
} | |
CFX_FixedBufGrow<FX_FLOAT, 8> float_array(num_floats); | |
FX_FLOAT* pFloats = float_array; | |
FXSYS_memset32(pFloats, 0, num_floats * sizeof(FX_FLOAT)); | |
int count = pBC->GetCount() > 8 ? 8 : pBC->GetCount(); | |
for (int i = 0; i < count; i ++) { | |
pFloats[i] = pBC->GetNumber(i); | |
} | |
pCS->GetRGB(pFloats, R, G, B); | |
back_color = 0xff000000 | ((FX_INT32)(R * 255) << 16) | ((FX_INT32)(G * 255) << 8) | (FX_INT32)(B * 255); | |
m_pContext->m_pDocument->GetPageData()->ReleaseColorSpace(pCSObj); | |
} | |
} | |
bitmap.Clear(back_color); | |
} else { | |
bitmap.Clear(0); | |
} | |
CPDF_Dictionary* pFormResource = NULL; | |
if (form.m_pFormDict) { | |
pFormResource = form.m_pFormDict->GetDict(FX_BSTRC("Resources")); | |
} | |
CPDF_RenderOptions options; | |
options.m_ColorMode = bLuminosity ? RENDER_COLOR_NORMAL : RENDER_COLOR_ALPHA; | |
CPDF_RenderStatus status; | |
status.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL, NULL, NULL, NULL, | |
&options, 0, m_bDropObjects, pFormResource, TRUE, NULL, 0, pCS ? pCS->GetFamily() : 0, bLuminosity); | |
status.RenderObjectList(&form, &matrix); | |
pMask = FX_NEW CFX_DIBitmap; | |
if (!pMask->Create(width, height, FXDIB_8bppMask)) { | |
delete pMask; | |
return NULL; | |
} | |
FX_LPBYTE dest_buf = pMask->GetBuffer(); | |
int dest_pitch = pMask->GetPitch(); | |
FX_LPBYTE src_buf = bitmap.GetBuffer(); | |
int src_pitch = bitmap.GetPitch(); | |
FX_LPBYTE pTransfer = FX_Alloc(FX_BYTE, 256); | |
if (pFunc) { | |
CFX_FixedBufGrow<FX_FLOAT, 16> results(pFunc->CountOutputs()); | |
for (int i = 0; i < 256; i ++) { | |
FX_FLOAT input = (FX_FLOAT)i / 255.0f; | |
int nresult; | |
pFunc->Call(&input, 1, results, nresult); | |
pTransfer[i] = FXSYS_round(results[0] * 255); | |
} | |
} else { | |
for (int i = 0; i < 256; i ++) { | |
pTransfer[i] = i; | |
} | |
} | |
if (bLuminosity) { | |
int Bpp = bitmap.GetBPP() / 8; | |
for (int row = 0; row < height; row ++) { | |
FX_LPBYTE dest_pos = dest_buf + row * dest_pitch; | |
FX_LPBYTE src_pos = src_buf + row * src_pitch; | |
for (int col = 0; col < width; col ++) { | |
*dest_pos ++ = pTransfer[FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos)]; | |
src_pos += Bpp; | |
} | |
} | |
} else if (pFunc) { | |
int size = dest_pitch * height; | |
for (int i = 0; i < size; i ++) { | |
dest_buf[i] = pTransfer[src_buf[i]]; | |
} | |
} else { | |
FXSYS_memcpy32(dest_buf, src_buf, dest_pitch * height); | |
} | |
if (pFunc) { | |
delete pFunc; | |
} | |
FX_Free(pTransfer); | |
return pMask; | |
} |