diff options
Diffstat (limited to 'core/src/fpdfapi/fpdf_render')
-rw-r--r-- | core/src/fpdfapi/fpdf_render/fpdf_render.cpp | 2976 | ||||
-rw-r--r-- | core/src/fpdfapi/fpdf_render/fpdf_render_cache.cpp | 778 | ||||
-rw-r--r-- | core/src/fpdfapi/fpdf_render/fpdf_render_image.cpp | 2330 | ||||
-rw-r--r-- | core/src/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp | 3048 | ||||
-rw-r--r-- | core/src/fpdfapi/fpdf_render/fpdf_render_pattern.cpp | 2186 | ||||
-rw-r--r-- | core/src/fpdfapi/fpdf_render/fpdf_render_text.cpp | 1520 | ||||
-rw-r--r-- | core/src/fpdfapi/fpdf_render/render_int.h | 924 |
7 files changed, 6881 insertions, 6881 deletions
diff --git a/core/src/fpdfapi/fpdf_render/fpdf_render.cpp b/core/src/fpdfapi/fpdf_render/fpdf_render.cpp index fba698ca62..19624329fb 100644 --- a/core/src/fpdfapi/fpdf_render/fpdf_render.cpp +++ b/core/src/fpdfapi/fpdf_render/fpdf_render.cpp @@ -1,1488 +1,1488 @@ -// 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/fpdfapi/fpdf_render.h"
-#include "../../../include/fpdfapi/fpdf_module.h"
-#include "../fpdf_page/pageint.h"
-#include "../../../include/fxge/fx_ge.h"
-#include "../../../include/fxcodec/fx_codec.h"
-#include "render_int.h"
-CPDF_DocRenderData::CPDF_DocRenderData(CPDF_Document* pPDFDoc)
- : m_pPDFDoc(pPDFDoc)
- , m_pFontCache(NULL)
-{
-}
-CPDF_DocRenderData::~CPDF_DocRenderData()
-{
- Clear(TRUE);
-}
-void CPDF_DocRenderData::Clear(FX_BOOL bRelease)
-{
- FX_POSITION pos;
- {
- pos = m_Type3FaceMap.GetStartPosition();
- while (pos) {
- CPDF_Font* pFont;
- CPDF_CountedObject<CPDF_Type3Cache*>* cache;
- m_Type3FaceMap.GetNextAssoc(pos, pFont, cache);
- if (bRelease || cache->m_nCount < 2) {
- delete cache->m_Obj;
- delete cache;
- m_Type3FaceMap.RemoveKey(pFont);
- }
- }
- }
-#ifndef _FPDFAPI_MINI_
- {
- pos = m_TransferFuncMap.GetStartPosition();
- while (pos) {
- CPDF_Object* key;
- CPDF_CountedObject<CPDF_TransferFunc*>* value;
- m_TransferFuncMap.GetNextAssoc(pos, key, value);
- if (bRelease || value->m_nCount < 2) {
- delete value->m_Obj;
- delete value;
- m_TransferFuncMap.RemoveKey(key);
- }
- }
- }
-#endif
- if (m_pFontCache) {
- if (bRelease) {
- delete m_pFontCache;
- m_pFontCache = NULL;
- } else {
- m_pFontCache->FreeCache(FALSE);
- }
- }
-}
-FX_BOOL CPDF_DocRenderData::Initialize()
-{
- m_pFontCache = FX_NEW CFX_FontCache;
- return TRUE;
-}
-CPDF_Type3Cache* CPDF_DocRenderData::GetCachedType3(CPDF_Type3Font* pFont)
-{
- CPDF_CountedObject<CPDF_Type3Cache*>* pCache;
- if (!m_Type3FaceMap.Lookup(pFont, pCache)) {
- CPDF_Type3Cache* pType3 = FX_NEW CPDF_Type3Cache(pFont);
- pCache = FX_NEW CPDF_CountedObject<CPDF_Type3Cache*>;
- pCache->m_Obj = pType3;
- pCache->m_nCount = 1;
- m_Type3FaceMap.SetAt(pFont, pCache);
- }
- pCache->m_nCount++;
- return pCache->m_Obj;
-}
-void CPDF_DocRenderData::ReleaseCachedType3(CPDF_Type3Font* pFont)
-{
- CPDF_CountedObject<CPDF_Type3Cache*>* pCache;
- if (!m_Type3FaceMap.Lookup(pFont, pCache)) {
- return;
- }
- pCache->m_nCount--;
-}
-class CPDF_RenderModule : public CPDF_RenderModuleDef
-{
-public:
- virtual ~CPDF_RenderModule() {}
- virtual FX_BOOL Installed()
- {
- return TRUE;
- }
- virtual CPDF_DocRenderData* CreateDocData(CPDF_Document* pDoc);
- virtual void DestroyDocData(CPDF_DocRenderData* p);
- virtual void ClearDocData(CPDF_DocRenderData* p);
- virtual CPDF_DocRenderData* GetRenderData()
- {
- return &m_RenderData;
- }
- virtual CPDF_PageRenderCache* CreatePageCache(CPDF_Page* pPage)
- {
- return FX_NEW CPDF_PageRenderCache(pPage);
- }
- virtual void DestroyPageCache(CPDF_PageRenderCache* pCache);
- virtual CPDF_RenderConfig* GetConfig()
- {
- return &m_RenderConfig;
- }
-private:
- CPDF_DocRenderData m_RenderData;
- CPDF_RenderConfig m_RenderConfig;
-};
-CPDF_DocRenderData* CPDF_RenderModule::CreateDocData(CPDF_Document* pDoc)
-{
- CPDF_DocRenderData* pData = FX_NEW CPDF_DocRenderData(pDoc);
- pData->Initialize();
- return pData;
-}
-void CPDF_RenderModule::DestroyDocData(CPDF_DocRenderData* pDocData)
-{
- delete pDocData;
-}
-void CPDF_RenderModule::ClearDocData(CPDF_DocRenderData* p)
-{
- if (p) {
- p->Clear(FALSE);
- }
-}
-void CPDF_RenderModule::DestroyPageCache(CPDF_PageRenderCache* pCache)
-{
- delete pCache;
-}
-void CPDF_ModuleMgr::InitRenderModule()
-{
- if (m_pRenderModule) {
- delete m_pRenderModule;
- }
- m_pRenderModule = FX_NEW CPDF_RenderModule;
-}
-CPDF_RenderOptions::CPDF_RenderOptions()
- : m_ColorMode(RENDER_COLOR_NORMAL)
- , m_Flags(RENDER_CLEARTYPE)
- , m_Interpolation(0)
- , m_AddFlags(0)
- , m_pOCContext(NULL)
- , m_dwLimitCacheSize(1024 * 1024 * 100)
- , m_HalftoneLimit(-1)
-{
-#if defined(_FPDFAPI_MINI_)
- m_Flags |= RENDER_LIMITEDIMAGECACHE;
-#endif
-}
-FX_ARGB CPDF_RenderOptions::TranslateColor(FX_ARGB argb) const
-{
- if (m_ColorMode == RENDER_COLOR_NORMAL) {
- return argb;
- }
- if (m_ColorMode == RENDER_COLOR_ALPHA) {
- return argb;
- }
- int a, r, g, b;
- ArgbDecode(argb, a, r, g, b);
- int gray = FXRGB2GRAY(r, g, b);
- if (m_ColorMode == RENDER_COLOR_TWOCOLOR) {
- int color = (r - gray) * (r - gray) + (g - gray) * (g - gray) + (b - gray) * (b - gray);
- if (gray < 35 && color < 20) {
- return ArgbEncode(a, m_ForeColor);
- }
- if (gray > 221 && color < 20) {
- return ArgbEncode(a, m_BackColor);
- }
- return argb;
- }
- int fr = FXSYS_GetRValue(m_ForeColor);
- int fg = FXSYS_GetGValue(m_ForeColor);
- int fb = FXSYS_GetBValue(m_ForeColor);
- int br = FXSYS_GetRValue(m_BackColor);
- int bg = FXSYS_GetGValue(m_BackColor);
- int bb = FXSYS_GetBValue(m_BackColor);
- r = (br - fr) * gray / 255 + fr;
- g = (bg - fg) * gray / 255 + fg;
- b = (bb - fb) * gray / 255 + fb;
- return ArgbEncode(a, r, g, b);
-}
-CPDF_RenderStatus::CPDF_RenderStatus()
-{
- m_pContext = NULL;
- m_bStopped = FALSE;
- m_Level = 0;
- m_pDevice = NULL;
- m_pCurObj = NULL;
- m_pStopObj = NULL;
- m_HalftoneLimit = 0;
- m_pObjectRenderer = NULL;
- m_bPrint = FALSE;
- m_Transparency = 0;
- m_DitherBits = 0;
- m_bDropObjects = FALSE;
- m_bStdCS = FALSE;
- m_GroupFamily = 0;
- m_bLoadMask = FALSE;
- m_pType3Char = NULL;
- m_T3FillColor = 0;
- m_pFormResource = NULL;
- m_pPageResource = NULL;
- m_curBlend = FXDIB_BLEND_NORMAL;
-}
-CPDF_RenderStatus::~CPDF_RenderStatus()
-{
- if (m_pObjectRenderer) {
- delete m_pObjectRenderer;
- }
-}
-FX_BOOL CPDF_RenderStatus::Initialize(int level, CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice,
- const CFX_AffineMatrix* pDeviceMatrix, const CPDF_PageObject* pStopObj,
- const CPDF_RenderStatus* pParentState, const CPDF_GraphicStates* pInitialStates,
- const CPDF_RenderOptions* pOptions, int transparency, FX_BOOL bDropObjects,
- CPDF_Dictionary* pFormResource, FX_BOOL bStdCS, CPDF_Type3Char* pType3Char,
- FX_ARGB fill_color, FX_DWORD GroupFamily,
- FX_BOOL bLoadMask)
-{
- m_Level = level;
- m_pContext = pContext;
- m_pDevice = pDevice;
- m_DitherBits = pDevice->GetDeviceCaps(FXDC_DITHER_BITS);
- m_bPrint = m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
- if (pDeviceMatrix) {
- m_DeviceMatrix = *pDeviceMatrix;
- }
- m_pStopObj = pStopObj;
- if (pOptions) {
- m_Options = *pOptions;
- }
- m_bDropObjects = bDropObjects;
- m_bStdCS = bStdCS;
- m_T3FillColor = fill_color;
- m_pType3Char = pType3Char;
- m_GroupFamily = GroupFamily;
- m_bLoadMask = bLoadMask;
- m_pFormResource = pFormResource;
- m_pPageResource = m_pContext->m_pPageResources;
- if (pInitialStates && !m_pType3Char) {
- m_InitialStates.CopyStates(*pInitialStates);
- if (pParentState) {
- CPDF_ColorStateData* pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)m_InitialStates.m_ColorState;
- CPDF_ColorStateData* pParentData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)pParentState->m_InitialStates.m_ColorState;
- if (!pColorData || pColorData->m_FillColor.IsNull()) {
- CPDF_ColorStateData* pData = m_InitialStates.m_ColorState.GetModify();
- pData->m_FillRGB = pParentData->m_FillRGB;
- pData->m_FillColor.Copy(&pParentData->m_FillColor);
- }
- if (!pColorData || pColorData->m_StrokeColor.IsNull()) {
- CPDF_ColorStateData* pData = m_InitialStates.m_ColorState.GetModify();
- pData->m_StrokeRGB = pParentData->m_FillRGB;
- pData->m_StrokeColor.Copy(&pParentData->m_StrokeColor);
- }
- }
- } else {
- m_InitialStates.DefaultStates();
- }
-#if defined(_FPDFAPI_MINI_)||defined(_FXCORE_LIMITED_CPU_)
- m_HalftoneLimit = CPDF_ModuleMgr::Get()->GetRenderModule()->GetConfig()->m_HalftoneLimit;
- if (pOptions && pOptions->m_HalftoneLimit >= 0) {
- m_HalftoneLimit = pOptions->m_HalftoneLimit;
- }
-#endif
- m_pObjectRenderer = NULL;
- m_Transparency = transparency;
- return TRUE;
-}
-void CPDF_RenderStatus::RenderObjectList(const CPDF_PageObjects* pObjs, const CFX_AffineMatrix* pObj2Device)
-{
- if (m_Level > 32) {
- return;
- }
- CFX_FloatRect clip_rect = m_pDevice->GetClipBox();
- CFX_AffineMatrix device2object;
- device2object.SetReverse(*pObj2Device);
- device2object.TransformRect(clip_rect);
- int index = 0;
- FX_POSITION pos = pObjs->GetFirstObjectPosition();
- while(pos) {
- index ++;
- CPDF_PageObject* pCurObj = pObjs->GetNextObject(pos);
- if (pCurObj == m_pStopObj) {
- m_bStopped = TRUE;
- return;
- }
- if (!pCurObj) {
- continue;
- }
- if(pCurObj == NULL || pCurObj->m_Left > clip_rect.right || pCurObj->m_Right < clip_rect.left ||
- pCurObj->m_Bottom > clip_rect.top || pCurObj->m_Top < clip_rect.bottom) {
- continue;
- }
- RenderSingleObject(pCurObj, pObj2Device);
- if (m_bStopped) {
- return;
- }
- }
-}
-void CPDF_RenderStatus::RenderSingleObject(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device)
-{
- if (m_Level > 32) {
- return;
- }
- m_pCurObj = pObj;
- if (m_Options.m_pOCContext && pObj->m_ContentMark.NotNull())
- if (!m_Options.m_pOCContext->CheckObjectVisible(pObj)) {
- return;
- }
- ProcessClipPath(pObj->m_ClipPath, pObj2Device);
- if (ProcessTransparency(pObj, pObj2Device)) {
- return;
- }
- ProcessObjectNoClip(pObj, pObj2Device);
-}
-FX_BOOL CPDF_RenderStatus::ContinueSingleObject(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, IFX_Pause* pPause)
-{
- if (m_pObjectRenderer) {
- if (m_pObjectRenderer->Continue(pPause)) {
- return TRUE;
- }
- if (!m_pObjectRenderer->m_Result) {
- DrawObjWithBackground(pObj, pObj2Device);
- }
-#ifdef _FPDFAPI_MINI_
- if (m_DitherBits) {
- DitherObjectArea(pObj, pObj2Device);
- }
-#endif
- delete m_pObjectRenderer;
- m_pObjectRenderer = NULL;
- return FALSE;
- }
- m_pCurObj = pObj;
- if (m_Options.m_pOCContext && pObj->m_ContentMark.NotNull())
- if (!m_Options.m_pOCContext->CheckObjectVisible(pObj)) {
- return FALSE;
- }
- ProcessClipPath(pObj->m_ClipPath, pObj2Device);
- if (ProcessTransparency(pObj, pObj2Device)) {
- return FALSE;
- }
- if (pObj->m_Type == PDFPAGE_IMAGE) {
- m_pObjectRenderer = IPDF_ObjectRenderer::Create(pObj->m_Type);
- if (!m_pObjectRenderer->Start(this, pObj, pObj2Device, FALSE)) {
- if (!m_pObjectRenderer->m_Result) {
- DrawObjWithBackground(pObj, pObj2Device);
- }
-#ifdef _FPDFAPI_MINI_
- if (m_DitherBits) {
- DitherObjectArea(pObj, pObj2Device);
- }
-#endif
- delete m_pObjectRenderer;
- m_pObjectRenderer = NULL;
- return FALSE;
- }
- return ContinueSingleObject(pObj, pObj2Device, pPause);
- }
- ProcessObjectNoClip(pObj, pObj2Device);
- return FALSE;
-}
-IPDF_ObjectRenderer* IPDF_ObjectRenderer::Create(int type)
-{
- IPDF_ObjectRenderer* pRenderer = NULL;
- if (type == PDFPAGE_IMAGE) {
- pRenderer = FX_NEW CPDF_ImageRenderer;
- }
- return pRenderer;
-}
-FX_BOOL CPDF_RenderStatus::GetObjectClippedRect(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bLogical, FX_RECT &rect) const
-{
- rect = pObj->GetBBox(pObj2Device);
- FX_RECT rtClip = m_pDevice->GetClipBox();
- if (!bLogical) {
- CFX_Matrix dCTM = m_pDevice->GetCTM();
- FX_FLOAT a = FXSYS_fabs(dCTM.a);
- FX_FLOAT d = FXSYS_fabs(dCTM.d);
- if (a != 1.0f || d != 1.0f) {
- rect.right = rect.left + (FX_INT32)FXSYS_ceil((FX_FLOAT)rect.Width() * a);
- rect.bottom = rect.top + (FX_INT32)FXSYS_ceil((FX_FLOAT)rect.Height() * d);
- rtClip.right = rtClip.left + (FX_INT32)FXSYS_ceil((FX_FLOAT)rtClip.Width() * a);
- rtClip.bottom = rtClip.top + (FX_INT32)FXSYS_ceil((FX_FLOAT)rtClip.Height() * d);
- }
- }
- rect.Intersect(rtClip);
- return rect.IsEmpty();
-}
-void CPDF_RenderStatus::DitherObjectArea(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device)
-{
- CFX_DIBitmap* pBitmap = m_pDevice->GetBitmap();
- if (pBitmap == NULL) {
- return;
- }
- FX_RECT rect;
- if (GetObjectClippedRect(pObj, pObj2Device, FALSE, rect)) {
- return;
- }
- if (m_DitherBits == 2) {
- static FX_ARGB pal[4] = {0, 85, 170, 255};
- pBitmap->DitherFS(pal, 4, &rect);
- } else if (m_DitherBits == 3) {
- static FX_ARGB pal[8] = {0, 36, 73, 109, 146, 182, 219, 255};
- pBitmap->DitherFS(pal, 8, &rect);
- } else if (m_DitherBits == 4) {
- static FX_ARGB pal[16] = {0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255};
- pBitmap->DitherFS(pal, 16, &rect);
- }
-}
-void CPDF_RenderStatus::ProcessObjectNoClip(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device)
-{
- FX_BOOL bRet = FALSE;
- switch (pObj->m_Type) {
- case PDFPAGE_TEXT:
- bRet = ProcessText((CPDF_TextObject*)pObj, pObj2Device, NULL);
- break;
- case PDFPAGE_PATH:
- bRet = ProcessPath((CPDF_PathObject*)pObj, pObj2Device);
- break;
- case PDFPAGE_IMAGE:
- bRet = ProcessImage((CPDF_ImageObject*)pObj, pObj2Device);
- break;
- case PDFPAGE_SHADING:
- bRet = ProcessShading((CPDF_ShadingObject*)pObj, pObj2Device);
- break;
- case PDFPAGE_FORM:
- bRet = ProcessForm((CPDF_FormObject*)pObj, pObj2Device);
- break;
-#if defined(_FPDFAPI_MINI_)
- case PDFPAGE_INLINES:
- bRet = ProcessInlines((CPDF_InlineImages*)pObj, pObj2Device);
- break;
-#endif
- }
- if (!bRet) {
- DrawObjWithBackground(pObj, pObj2Device);
- }
-}
-FX_BOOL CPDF_RenderStatus::DrawObjWithBlend(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device)
-{
- FX_BOOL bRet = FALSE;
- switch (pObj->m_Type) {
- case PDFPAGE_PATH:
- bRet = ProcessPath((CPDF_PathObject*)pObj, pObj2Device);
- break;
- case PDFPAGE_IMAGE:
- bRet = ProcessImage((CPDF_ImageObject *)pObj, pObj2Device);
- break;
- case PDFPAGE_FORM:
- bRet = ProcessForm((CPDF_FormObject*)pObj, pObj2Device);
- break;
- }
- return bRet;
-}
-void CPDF_RenderStatus::GetScaledMatrix(CFX_Matrix &matrix) const
-{
- CFX_Matrix dCTM = m_pDevice->GetCTM();
- matrix.a *= FXSYS_fabs(dCTM.a);
- matrix.d *= FXSYS_fabs(dCTM.d);
-}
-void CPDF_RenderStatus::DrawObjWithBackground(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device)
-{
-#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_)
- FX_RECT rect;
- if (GetObjectClippedRect(pObj, pObj2Device, FALSE, rect)) {
- return;
- }
- int res = 300;
- if (pObj->m_Type == PDFPAGE_IMAGE && m_pDevice->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
- res = 0;
- }
- CPDF_ScaledRenderBuffer buffer;
- if (!buffer.Initialize(m_pContext, m_pDevice, &rect, pObj, &m_Options, res)) {
- return;
- }
- CFX_AffineMatrix matrix = *pObj2Device;
- matrix.Concat(*buffer.GetMatrix());
- GetScaledMatrix(matrix);
- CPDF_Dictionary* pFormResource = NULL;
- if (pObj->m_Type == PDFPAGE_FORM) {
- CPDF_FormObject* pFormObj = (CPDF_FormObject*)pObj;
- if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) {
- pFormResource = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources"));
- }
- }
- CPDF_RenderStatus status;
- status.Initialize(m_Level + 1, m_pContext, buffer.GetDevice(), buffer.GetMatrix(), NULL, NULL, NULL, &m_Options, m_Transparency, m_bDropObjects, pFormResource);
- status.RenderSingleObject(pObj, &matrix);
- buffer.OutputToDevice();
-#endif
-}
-FX_BOOL CPDF_RenderStatus::ProcessForm(CPDF_FormObject* pFormObj, const CFX_AffineMatrix* pObj2Device)
-{
- CPDF_Dictionary* pOC = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("OC"));
- if (pOC && m_Options.m_pOCContext && !m_Options.m_pOCContext->CheckOCGVisible(pOC)) {
- return TRUE;
- }
- CFX_AffineMatrix matrix = pFormObj->m_FormMatrix;
- matrix.Concat(*pObj2Device);
- CPDF_Dictionary* pResources = NULL;
- if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) {
- pResources = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources"));
- }
- CPDF_RenderStatus status;
- status.Initialize(m_Level + 1, m_pContext, m_pDevice, NULL, m_pStopObj,
- this, pFormObj, &m_Options, m_Transparency, m_bDropObjects, pResources, TRUE);
- status.m_curBlend = m_curBlend;
- m_pDevice->SaveState();
- status.RenderObjectList(pFormObj->m_pForm, &matrix);
- m_bStopped = status.m_bStopped;
- m_pDevice->RestoreState();
- return TRUE;
-}
-FX_BOOL IsAvailableMatrix(const CFX_AffineMatrix& matrix)
-{
- if (matrix.a == 0 || matrix.d == 0) {
- return matrix.b != 0 && matrix.c != 0;
- }
- if (matrix.b == 0 || matrix.c == 0) {
- return matrix.a != 0 && matrix.d != 0;
- }
- return TRUE;
-}
-FX_BOOL CPDF_RenderStatus::ProcessPath(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device)
-{
- int FillType = pPathObj->m_FillType;
- FX_BOOL bStroke = pPathObj->m_bStroke;
- ProcessPathPattern(pPathObj, pObj2Device, FillType, bStroke);
- if (FillType == 0 && !bStroke) {
- return TRUE;
- }
- FX_DWORD fill_argb = 0;
- if (FillType) {
- fill_argb = GetFillArgb(pPathObj);
- }
- FX_DWORD stroke_argb = 0;
- if (bStroke) {
- stroke_argb = GetStrokeArgb(pPathObj);
- }
- CFX_AffineMatrix path_matrix = pPathObj->m_Matrix;
- path_matrix.Concat(*pObj2Device);
- if (!IsAvailableMatrix(path_matrix)) {
- return TRUE;
- }
- if (FillType && (m_Options.m_Flags & RENDER_RECT_AA)) {
- FillType |= FXFILL_RECT_AA;
- }
- if (m_Options.m_Flags & RENDER_FILL_FULLCOVER) {
- FillType |= FXFILL_FULLCOVER;
- }
- if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) {
- FillType |= FXFILL_NOPATHSMOOTH;
- }
- if (bStroke) {
- FillType |= FX_FILL_STROKE;
- }
-#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_)
- const CPDF_GeneralStateData* pGeneralData = ((CPDF_PageObject*)pPathObj)->m_GeneralState;
- if (pGeneralData && pGeneralData->m_StrokeAdjust) {
- FillType |= FX_STROKE_ADJUST;
- }
-#endif
- if (m_pType3Char) {
- FillType |= FX_FILL_TEXT_MODE;
- }
- CFX_GraphStateData graphState(*pPathObj->m_GraphState);
- if (m_Options.m_Flags & RENDER_THINLINE) {
- graphState.m_LineWidth = 0;
- }
- return m_pDevice->DrawPath(pPathObj->m_Path, &path_matrix, &graphState, fill_argb, stroke_argb, FillType, 0, NULL, m_curBlend);
-}
-CPDF_TransferFunc* CPDF_RenderStatus::GetTransferFunc(CPDF_Object* pObj) const
-{
- ASSERT(pObj != NULL);
- CPDF_DocRenderData* pDocCache = m_pContext->m_pDocument->GetRenderData();
- if (!pDocCache) {
- return NULL;
- }
- return pDocCache->GetTransferFunc(pObj);
-}
-FX_ARGB CPDF_RenderStatus::GetFillArgb(const CPDF_PageObject* pObj, FX_BOOL bType3) const
-{
- CPDF_ColorStateData* pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)pObj->m_ColorState;
- if (m_pType3Char && !bType3 && (!m_pType3Char->m_bColored || (m_pType3Char->m_bColored && (!pColorData || pColorData->m_FillColor.IsNull())))) {
- return m_T3FillColor;
- } else if (!pColorData || pColorData->m_FillColor.IsNull()) {
- pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)m_InitialStates.m_ColorState;
- }
- FX_COLORREF rgb = pColorData->m_FillRGB;
- if (rgb == (FX_DWORD) - 1) {
- return 0;
- }
- const CPDF_GeneralStateData* pGeneralData = pObj->m_GeneralState;
- int alpha;
- if (pGeneralData) {
- alpha = (FX_INT32)(pGeneralData->m_FillAlpha * 255);
-#ifndef _FPDFAPI_MINI_
- if (pGeneralData->m_pTR) {
- if (!pGeneralData->m_pTransferFunc) {
- ((CPDF_GeneralStateData*)pGeneralData)->m_pTransferFunc = GetTransferFunc(pGeneralData->m_pTR);
- }
- if (pGeneralData->m_pTransferFunc) {
- rgb = pGeneralData->m_pTransferFunc->TranslateColor(rgb);
- }
- }
-#endif
- } else {
- alpha = 255;
- }
- return m_Options.TranslateColor(ArgbEncode(alpha, rgb));
-}
-FX_ARGB CPDF_RenderStatus::GetStrokeArgb(const CPDF_PageObject* pObj) const
-{
- CPDF_ColorStateData* pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)pObj->m_ColorState;
- if (m_pType3Char && (!m_pType3Char->m_bColored || (m_pType3Char->m_bColored && (!pColorData || pColorData->m_StrokeColor.IsNull())))) {
- return m_T3FillColor;
- } else if (!pColorData || pColorData->m_StrokeColor.IsNull()) {
- pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)m_InitialStates.m_ColorState;
- }
- FX_COLORREF rgb = pColorData->m_StrokeRGB;
- if (rgb == (FX_DWORD) - 1) {
- return 0;
- }
- const CPDF_GeneralStateData* pGeneralData = pObj->m_GeneralState;
- int alpha;
- if (pGeneralData) {
- alpha = (FX_INT32)(pGeneralData->m_StrokeAlpha * 255);
-#ifndef _FPDFAPI_MINI_
- if (pGeneralData->m_pTR) {
- if (!pGeneralData->m_pTransferFunc) {
- ((CPDF_GeneralStateData*)pGeneralData)->m_pTransferFunc = GetTransferFunc(pGeneralData->m_pTR);
- }
- if (pGeneralData->m_pTransferFunc) {
- rgb = pGeneralData->m_pTransferFunc->TranslateColor(rgb);
- }
- }
-#endif
- } else {
- alpha = 255;
- }
- return m_Options.TranslateColor(ArgbEncode(alpha, rgb));
-}
-void CPDF_RenderStatus::ProcessClipPath(CPDF_ClipPath ClipPath, const CFX_AffineMatrix* pObj2Device)
-{
- if (ClipPath.IsNull()) {
- if (m_LastClipPath.IsNull()) {
- return;
- }
- m_pDevice->RestoreState(TRUE);
- m_LastClipPath.SetNull();
- return;
- }
- if (m_LastClipPath == ClipPath) {
- return;
- }
- m_LastClipPath = ClipPath;
- m_pDevice->RestoreState(TRUE);
- int nClipPath = ClipPath.GetPathCount();
- int i;
- for (i = 0; i < nClipPath; i++) {
- const CFX_PathData* pPathData = ClipPath.GetPath(i);
- if (pPathData == NULL) {
- continue;
- }
- if (pPathData->GetPointCount() == 0) {
- CFX_PathData EmptyPath;
- EmptyPath.AppendRect(-1, -1, 0, 0);
- int fill_mode = FXFILL_WINDING;
- m_pDevice->SetClip_PathFill(&EmptyPath, NULL, fill_mode);
- } else {
- int ClipType = ClipPath.GetClipType(i);
- m_pDevice->SetClip_PathFill(pPathData, pObj2Device, ClipType);
- }
- }
- int textcount = ClipPath.GetTextCount();
- if (textcount == 0) {
- return;
- }
- if (m_pDevice->GetDeviceClass() == FXDC_DISPLAY && !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)) {
- return;
- }
- CFX_PathData* pTextClippingPath = NULL;
- for (i = 0; i < textcount; i ++) {
- CPDF_TextObject* pText = ClipPath.GetText(i);
- if (pText == NULL) {
- if (pTextClippingPath) {
- int fill_mode = FXFILL_WINDING;
- if (m_Options.m_Flags & RENDER_NOTEXTSMOOTH) {
- fill_mode |= FXFILL_NOPATHSMOOTH;
- }
- m_pDevice->SetClip_PathFill(pTextClippingPath, NULL, fill_mode);
- delete pTextClippingPath;
- pTextClippingPath = NULL;
- }
- } else {
- if (pTextClippingPath == NULL) {
- pTextClippingPath = FX_NEW CFX_PathData;
- }
- ProcessText(pText, pObj2Device, pTextClippingPath);
- }
- }
- if (pTextClippingPath) {
- delete pTextClippingPath;
- }
-}
-void CPDF_RenderStatus::DrawClipPath(CPDF_ClipPath ClipPath, const CFX_AffineMatrix* pObj2Device)
-{
- if (ClipPath.IsNull()) {
- return;
- }
- int fill_mode = 0;
- if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) {
- fill_mode |= FXFILL_NOPATHSMOOTH;
- }
- int nClipPath = ClipPath.GetPathCount();
- int i;
- for (i = 0; i < nClipPath; i++) {
- const CFX_PathData* pPathData = ClipPath.GetPath(i);
- if (pPathData == NULL) {
- continue;
- }
- CFX_GraphStateData stroke_state;
- if (m_Options.m_Flags & RENDER_THINLINE) {
- stroke_state.m_LineWidth = 0;
- }
- m_pDevice->DrawPath(pPathData, pObj2Device, &stroke_state, 0, 0xffff0000, fill_mode);
- }
-}
-FX_BOOL CPDF_RenderStatus::SelectClipPath(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke)
-{
- CFX_AffineMatrix path_matrix = pPathObj->m_Matrix;
- path_matrix.Concat(*pObj2Device);
- if (bStroke) {
- CFX_GraphStateData graphState(*pPathObj->m_GraphState);
- if (m_Options.m_Flags & RENDER_THINLINE) {
- graphState.m_LineWidth = 0;
- }
- return m_pDevice->SetClip_PathStroke(pPathObj->m_Path, &path_matrix, &graphState);
- }
- int fill_mode = pPathObj->m_FillType;
- if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) {
- fill_mode |= FXFILL_NOPATHSMOOTH;
- }
- return m_pDevice->SetClip_PathFill(pPathObj->m_Path, &path_matrix, fill_mode);
-}
-FX_BOOL CPDF_RenderStatus::ProcessTransparency(const CPDF_PageObject* pPageObj, const CFX_AffineMatrix* pObj2Device)
-{
- const CPDF_GeneralStateData* pGeneralState = pPageObj->m_GeneralState;
- int blend_type = pGeneralState ? pGeneralState->m_BlendType : FXDIB_BLEND_NORMAL;
- if (blend_type == FXDIB_BLEND_UNSUPPORTED) {
- return TRUE;
- }
- CPDF_Dictionary* pSMaskDict = pGeneralState ? (CPDF_Dictionary*)pGeneralState->m_pSoftMask : NULL;
- if (pSMaskDict) {
- if (pPageObj->m_Type == PDFPAGE_IMAGE &&
- ((CPDF_ImageObject*)pPageObj)->m_pImage->GetDict()->KeyExist(FX_BSTRC("SMask"))) {
- pSMaskDict = NULL;
- }
- }
- CPDF_Dictionary* pFormResource = NULL;
- FX_FLOAT group_alpha = 1.0f;
- int Transparency = m_Transparency;
- FX_BOOL bGroupTransparent = FALSE;
- if (pPageObj->m_Type == PDFPAGE_FORM) {
- CPDF_FormObject* pFormObj = (CPDF_FormObject*)pPageObj;
- const CPDF_GeneralStateData *pStateData = pFormObj->m_GeneralState.GetObject();
- if (pStateData) {
- group_alpha = pStateData->m_FillAlpha;
- }
- Transparency = pFormObj->m_pForm->m_Transparency;
- bGroupTransparent = Transparency & PDFTRANS_ISOLATED ? TRUE : FALSE;
- if (pFormObj->m_pForm->m_pFormDict) {
- pFormResource = pFormObj->m_pForm->m_pFormDict->GetDict("Resources");
- }
- }
- FX_BOOL bTextClip = FALSE;
- if (pPageObj->m_ClipPath.NotNull() && pPageObj->m_ClipPath.GetTextCount() &&
- m_pDevice->GetDeviceClass() == FXDC_DISPLAY && !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)) {
- bTextClip = TRUE;
- }
- if ((m_Options.m_Flags & RENDER_OVERPRINT) && pPageObj->m_Type == PDFPAGE_IMAGE && pGeneralState && pGeneralState->m_FillOP && pGeneralState->m_StrokeOP) {
- CPDF_Document* pDocument = NULL;
- CPDF_Page* pPage = NULL;
- if (m_pContext->m_pPageCache) {
- pPage = m_pContext->m_pPageCache->GetPage();
- pDocument = pPage->m_pDocument;
- } else {
- pDocument = ((CPDF_ImageObject*)pPageObj)->m_pImage->GetDocument();
- }
- CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : NULL;
- CPDF_Object* pCSObj = ((CPDF_ImageObject*)pPageObj)->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) {
- blend_type = FXDIB_BLEND_DARKEN;
- }
- pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
- }
- }
- if (pSMaskDict == NULL && group_alpha == 1.0f && blend_type == FXDIB_BLEND_NORMAL && !bTextClip && !bGroupTransparent) {
- return FALSE;
- }
- FX_BOOL isolated = Transparency & PDFTRANS_ISOLATED;
- if (m_bPrint) {
- FX_BOOL bRet = FALSE;
- int rendCaps = m_pDevice->GetRenderCaps();
- if (!((Transparency & PDFTRANS_ISOLATED) || pSMaskDict || bTextClip) && (rendCaps & FXRC_BLEND_MODE)) {
- int oldBlend = m_curBlend;
- m_curBlend = blend_type;
- bRet = DrawObjWithBlend(pPageObj, pObj2Device);
- m_curBlend = oldBlend;
- }
- if (!bRet) {
- DrawObjWithBackground(pPageObj, pObj2Device);
- }
- return TRUE;
- }
- FX_RECT rect = pPageObj->GetBBox(pObj2Device);
- rect.Intersect(m_pDevice->GetClipBox());
- if (rect.IsEmpty()) {
- return TRUE;
- }
- CFX_Matrix deviceCTM = m_pDevice->GetCTM();
- FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a);
- FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d);
- int width = FXSYS_round((FX_FLOAT)rect.Width() * scaleX);
- int height = FXSYS_round((FX_FLOAT)rect.Height() * scaleY);
- CFX_FxgeDevice bitmap_device;
- CFX_DIBitmap* oriDevice = NULL;
- if (!isolated && (m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
- oriDevice = FX_NEW CFX_DIBitmap;
- if (!m_pDevice->CreateCompatibleBitmap(oriDevice, width, height)) {
- return TRUE;
- }
- m_pDevice->GetDIBits(oriDevice, rect.left, rect.top);
- }
- if (!bitmap_device.Create(width, height, FXDIB_Argb, 0, oriDevice)) {
- return TRUE;
- }
- CFX_DIBitmap* bitmap = bitmap_device.GetBitmap();
- bitmap->Clear(0);
- CFX_AffineMatrix new_matrix = *pObj2Device;
- new_matrix.TranslateI(-rect.left, -rect.top);
- new_matrix.Scale(scaleX, scaleY);
- CFX_DIBitmap* pTextMask = NULL;
- if (bTextClip) {
- pTextMask = FX_NEW CFX_DIBitmap;
- if (!pTextMask->Create(width, height, FXDIB_8bppMask)) {
- delete pTextMask;
- return TRUE;
- }
- pTextMask->Clear(0);
- CFX_FxgeDevice text_device;
- text_device.Attach(pTextMask);
- for (FX_DWORD i = 0; i < pPageObj->m_ClipPath.GetTextCount(); i ++) {
- CPDF_TextObject* textobj = pPageObj->m_ClipPath.GetText(i);
- if (textobj == NULL) {
- break;
- }
- CFX_AffineMatrix text_matrix;
- textobj->GetTextMatrix(&text_matrix);
- CPDF_TextRenderer::DrawTextPath(&text_device, textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos,
- textobj->m_TextState.GetFont(), textobj->m_TextState.GetFontSize(),
- &text_matrix, &new_matrix, textobj->m_GraphState, (FX_ARGB) - 1, 0, NULL);
- }
- }
- CPDF_RenderStatus bitmap_render;
- bitmap_render.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL,
- m_pStopObj, NULL, NULL, &m_Options, 0, m_bDropObjects, pFormResource, TRUE);
- bitmap_render.ProcessObjectNoClip(pPageObj, &new_matrix);
- m_bStopped = bitmap_render.m_bStopped;
- if (pSMaskDict) {
- CFX_AffineMatrix smask_matrix;
- FXSYS_memcpy32(&smask_matrix, pGeneralState->m_SMaskMatrix, sizeof smask_matrix);
- smask_matrix.Concat(*pObj2Device);
- CFX_DIBSource* pSMaskSource = LoadSMask(pSMaskDict, &rect, &smask_matrix);
- if (pSMaskSource) {
- bitmap->MultiplyAlpha(pSMaskSource);
- delete pSMaskSource;
- }
- }
- if (pTextMask) {
- bitmap->MultiplyAlpha(pTextMask);
- delete pTextMask;
- pTextMask = NULL;
- }
- if (Transparency & PDFTRANS_GROUP && group_alpha != 1.0f) {
- bitmap->MultiplyAlpha((FX_INT32)(group_alpha * 255));
- }
- Transparency = m_Transparency;
- if (pPageObj->m_Type == PDFPAGE_FORM) {
- Transparency |= PDFTRANS_GROUP;
- }
- CompositeDIBitmap(bitmap, rect.left, rect.top, 0, 255, blend_type, Transparency);
- if (oriDevice) {
- delete oriDevice;
- }
- return TRUE;
-}
-CFX_DIBitmap* CPDF_RenderStatus::GetBackdrop(const CPDF_PageObject* pObj, const FX_RECT& rect, int& left, int& top,
- FX_BOOL bBackAlphaRequired)
-{
- FX_RECT bbox = rect;
- bbox.Intersect(m_pDevice->GetClipBox());
- left = bbox.left;
- top = bbox.top;
- CFX_Matrix deviceCTM = m_pDevice->GetCTM();
- FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a);
- FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d);
- int width = FXSYS_round(bbox.Width() * scaleX);
- int height = FXSYS_round(bbox.Height() * scaleY);
- CFX_DIBitmap* pBackdrop = FX_NEW CFX_DIBitmap;
- if (bBackAlphaRequired && !m_bDropObjects) {
- pBackdrop->Create(width, height, FXDIB_Argb);
- } else {
- m_pDevice->CreateCompatibleBitmap(pBackdrop, width, height);
- }
- if (pBackdrop->GetBuffer() == NULL) {
- delete pBackdrop;
- return NULL;
- }
- FX_BOOL bNeedDraw;
- if (pBackdrop->HasAlpha()) {
- bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT);
- } else {
- bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS);
- }
- if (!bNeedDraw) {
- m_pDevice->GetDIBits(pBackdrop, left, top);
- return pBackdrop;
- }
- CFX_AffineMatrix FinalMatrix = m_DeviceMatrix;
- FinalMatrix.TranslateI(-left, -top);
- FinalMatrix.Scale(scaleX, scaleY);
- pBackdrop->Clear(pBackdrop->HasAlpha() ? 0 : 0xffffffff);
- CFX_FxgeDevice device;
- device.Attach(pBackdrop);
- m_pContext->Render(&device, pObj, &m_Options, &FinalMatrix);
- return pBackdrop;
-}
-void CPDF_RenderContext::GetBackground(CFX_DIBitmap* pBuffer, const CPDF_PageObject* pObj,
- const CPDF_RenderOptions* pOptions, CFX_AffineMatrix* pFinalMatrix)
-{
- CFX_FxgeDevice device;
- device.Attach(pBuffer);
- if (m_pBackgroundDraw) {
- m_pBackgroundDraw->OnDrawBackground(&device, pFinalMatrix);
- } else {
- FX_RECT rect(0, 0, device.GetWidth(), device.GetHeight());
- device.FillRect(&rect, 0xffffffff);
- }
- Render(&device, pObj, pOptions, pFinalMatrix);
-}
-CPDF_GraphicStates* CPDF_RenderStatus::CloneObjStates(const CPDF_GraphicStates* pSrcStates, FX_BOOL bStroke)
-{
- if (!pSrcStates) {
- return NULL;
- }
- CPDF_GraphicStates* pStates = FX_NEW CPDF_GraphicStates;
- if (!pStates) {
- return NULL;
- }
- pStates->CopyStates(*pSrcStates);
- CPDF_Color* pObjColor = bStroke ? pSrcStates->m_ColorState.GetStrokeColor() :
- pSrcStates->m_ColorState.GetFillColor();
- if (!pObjColor->IsNull()) {
- CPDF_ColorStateData* pColorData = pStates->m_ColorState.GetModify();
- pColorData->m_FillRGB = bStroke ? pSrcStates->m_ColorState.GetObject()->m_StrokeRGB :
- pSrcStates->m_ColorState.GetObject()->m_FillRGB;
- pColorData->m_StrokeRGB = pColorData->m_FillRGB;
- }
- return pStates;
-}
-CPDF_RenderContext::CPDF_RenderContext()
-{
-}
-void CPDF_RenderContext::Create(CPDF_Document* pDoc, CPDF_PageRenderCache* pPageCache,
- CPDF_Dictionary* pPageResources, FX_BOOL bFirstLayer)
-{
- m_pBackgroundDraw = NULL;
- m_pDocument = pDoc;
- m_pPageResources = pPageResources;
- m_pPageCache = pPageCache;
- m_bFirstLayer = bFirstLayer;
-}
-void CPDF_RenderContext::Create(CPDF_Page* pPage, FX_BOOL bFirstLayer)
-{
- m_pBackgroundDraw = NULL;
- m_pDocument = pPage->m_pDocument;
- m_pPageResources = pPage->m_pPageResources;
- m_pPageCache = pPage->GetRenderCache();
- m_bFirstLayer = bFirstLayer;
-}
-CPDF_RenderContext::~CPDF_RenderContext()
-{
-}
-void CPDF_RenderContext::Clear()
-{
- m_pDocument = NULL;
- m_pPageResources = NULL;
- m_pPageCache = NULL;
- m_pBackgroundDraw = NULL;
- m_bFirstLayer = TRUE;
- m_ContentList.RemoveAll();
-}
-void CPDF_RenderContext::AppendObjectList(CPDF_PageObjects* pObjs, const CFX_AffineMatrix* pObject2Device)
-{
- _PDF_RenderItem* pItem = m_ContentList.AddSpace();
- pItem->m_pObjectList = pObjs;
- if (pObject2Device) {
- pItem->m_Matrix = *pObject2Device;
- } else {
- pItem->m_Matrix.SetIdentity();
- }
-}
-void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice, const CPDF_RenderOptions* pOptions,
- const CFX_AffineMatrix* pLastMatrix)
-{
- Render(pDevice, NULL, pOptions, pLastMatrix);
-}
-void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice, const CPDF_PageObject* pStopObj,
- const CPDF_RenderOptions* pOptions, const CFX_AffineMatrix* pLastMatrix)
-{
- int count = m_ContentList.GetSize();
- for (int j = 0; j < count; j ++) {
- pDevice->SaveState();
- _PDF_RenderItem* pItem = m_ContentList.GetDataPtr(j);
- if (pLastMatrix) {
- CFX_AffineMatrix FinalMatrix = pItem->m_Matrix;
- FinalMatrix.Concat(*pLastMatrix);
- CPDF_RenderStatus status;
- status.Initialize(0, this, pDevice, pLastMatrix, pStopObj, NULL, NULL, pOptions,
- pItem->m_pObjectList->m_Transparency, FALSE, NULL);
- status.RenderObjectList(pItem->m_pObjectList, &FinalMatrix);
-#if !defined(_FPDFAPI_MINI_)
- if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
- m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize);
- }
-#endif
- if (status.m_bStopped) {
- pDevice->RestoreState();
- break;
- }
- } else {
- CPDF_RenderStatus status;
- status.Initialize(0, this, pDevice, NULL, pStopObj, NULL, NULL, pOptions,
- pItem->m_pObjectList->m_Transparency, FALSE, NULL);
- status.RenderObjectList(pItem->m_pObjectList, &pItem->m_Matrix);
-#if !defined(_FPDFAPI_MINI_)
- if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
- m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize);
- }
-#endif
- if (status.m_bStopped) {
- pDevice->RestoreState();
- break;
- }
- }
- pDevice->RestoreState();
- }
-}
-void CPDF_RenderContext::DrawObjectList(CFX_RenderDevice* pDevice, CPDF_PageObjects* pObjs,
- const CFX_AffineMatrix* pObject2Device, const CPDF_RenderOptions* pOptions)
-{
- AppendObjectList(pObjs, pObject2Device);
- Render(pDevice, pOptions);
-}
-CPDF_ProgressiveRenderer::CPDF_ProgressiveRenderer()
-{
- m_pRenderer = NULL;
- m_pContext = NULL;
- m_pDevice = NULL;
- m_Status = Ready;
-}
-CPDF_ProgressiveRenderer::~CPDF_ProgressiveRenderer()
-{
- Clear();
-}
-void CPDF_ProgressiveRenderer::Clear()
-{
- if (m_pRenderer) {
- delete m_pRenderer;
- m_pDevice->RestoreState();
- m_pRenderer = NULL;
- }
- m_Status = Ready;
-}
-void CPDF_ProgressiveRenderer::Start(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice,
- const CPDF_RenderOptions* pOptions, IFX_Pause* pPause, FX_BOOL bDropObjects)
-{
- if (m_Status != Ready) {
- m_Status = Failed;
- return;
- }
- m_pContext = pContext;
- m_pDevice = pDevice;
- m_pOptions = pOptions;
- m_bDropObjects = bDropObjects;
- if (pContext == NULL || pDevice == NULL) {
- m_Status = Failed;
- return;
- }
- m_Status = ToBeContinued;
- m_ObjectPos = NULL;
- m_LayerIndex = 0;
- m_ObjectIndex = 0;
- m_PrevLastPos = NULL;
- Continue(pPause);
-}
-#ifdef _FPDFAPI_MINI_
-#define RENDER_STEP_LIMIT 20
-#else
-#define RENDER_STEP_LIMIT 100
-#endif
-void CPDF_ProgressiveRenderer::Continue(IFX_Pause* pPause)
-{
- if (m_Status != ToBeContinued) {
- return;
- }
- FX_DWORD nLayers = m_pContext->m_ContentList.GetSize();
- for (; m_LayerIndex < nLayers; m_LayerIndex ++) {
- _PDF_RenderItem* pItem = m_pContext->m_ContentList.GetDataPtr(m_LayerIndex);
- FX_POSITION LastPos = pItem->m_pObjectList->GetLastObjectPosition();
- if (m_ObjectPos == NULL) {
- if (LastPos == m_PrevLastPos) {
- if (!pItem->m_pObjectList->IsParsed()) {
- pItem->m_pObjectList->ContinueParse(pPause);
- if (!pItem->m_pObjectList->IsParsed()) {
- return;
- }
- LastPos = pItem->m_pObjectList->GetLastObjectPosition();
- }
- }
- if (LastPos == m_PrevLastPos) {
- if (m_pRenderer) {
- delete m_pRenderer;
- m_pRenderer = NULL;
- m_pDevice->RestoreState();
- m_ObjectPos = NULL;
- m_PrevLastPos = NULL;
- }
- continue;
- }
- if (m_PrevLastPos) {
- m_ObjectPos = m_PrevLastPos;
- pItem->m_pObjectList->GetNextObject(m_ObjectPos);
- } else {
- m_ObjectPos = pItem->m_pObjectList->GetFirstObjectPosition();
- }
- m_PrevLastPos = LastPos;
- }
- if (m_pRenderer == NULL) {
- m_ObjectPos = pItem->m_pObjectList->GetFirstObjectPosition();
- m_ObjectIndex = 0;
- m_pRenderer = FX_NEW CPDF_RenderStatus();
- m_pRenderer->Initialize(0, m_pContext, m_pDevice, NULL, NULL, NULL, NULL,
- m_pOptions, pItem->m_pObjectList->m_Transparency, m_bDropObjects, NULL);
- m_pDevice->SaveState();
- m_ClipRect = m_pDevice->GetClipBox();
- CFX_AffineMatrix device2object;
- device2object.SetReverse(pItem->m_Matrix);
- device2object.TransformRect(m_ClipRect);
- }
- int objs_to_go = CPDF_ModuleMgr::Get()->GetRenderModule()->GetConfig()->m_RenderStepLimit;
- while (m_ObjectPos) {
- CPDF_PageObject* pCurObj = pItem->m_pObjectList->GetObjectAt(m_ObjectPos);
- if (pCurObj && pCurObj->m_Left <= m_ClipRect.right && pCurObj->m_Right >= m_ClipRect.left &&
- pCurObj->m_Bottom <= m_ClipRect.top && pCurObj->m_Top >= m_ClipRect.bottom) {
- if (m_pRenderer->ContinueSingleObject(pCurObj, &pItem->m_Matrix, pPause)) {
- return;
- }
-#if !defined(_FPDFAPI_MINI_)
- if (pCurObj->m_Type == PDFPAGE_IMAGE && m_pRenderer->m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
- m_pContext->GetPageCache()->CacheOptimization(m_pRenderer->m_Options.m_dwLimitCacheSize);
- }
-#endif
- if (pCurObj->m_Type == PDFPAGE_FORM || pCurObj->m_Type == PDFPAGE_SHADING) {
- objs_to_go = 0;
- } else {
- objs_to_go --;
- }
- }
- m_ObjectIndex ++;
- pItem->m_pObjectList->GetNextObject(m_ObjectPos);
- if (objs_to_go == 0) {
- if (pPause && pPause->NeedToPauseNow()) {
- return;
- }
- objs_to_go = CPDF_ModuleMgr::Get()->GetRenderModule()->GetConfig()->m_RenderStepLimit;
- }
- }
- if (!pItem->m_pObjectList->IsParsed()) {
- return;
- }
- delete m_pRenderer;
- m_pRenderer = NULL;
- m_pDevice->RestoreState();
- m_ObjectPos = NULL;
- m_PrevLastPos = NULL;
- if (pPause && pPause->NeedToPauseNow()) {
- m_LayerIndex++;
- return;
- }
- }
- m_Status = Done;
-}
-int CPDF_ProgressiveRenderer::EstimateProgress()
-{
- if (!m_pContext) {
- return 0;
- }
- FX_DWORD nLayers = m_pContext->m_ContentList.GetSize();
- int nTotal = 0, nRendered = 0;
- for (FX_DWORD layer = 0; layer < nLayers; layer ++) {
- _PDF_RenderItem* pItem = m_pContext->m_ContentList.GetDataPtr(layer);
- int nObjs = pItem->m_pObjectList->CountObjects();
- if (layer == m_LayerIndex) {
- nRendered += m_ObjectIndex;
- } else if (layer < m_LayerIndex) {
- nRendered += nObjs;
- }
- nTotal += nObjs;
- }
- if (nTotal == 0) {
- return 0;
- }
- return 100 * nRendered / nTotal;
-}
-CPDF_TransferFunc* CPDF_DocRenderData::GetTransferFunc(CPDF_Object* pObj)
-{
- if (pObj == NULL) {
- return NULL;
- }
- CPDF_CountedObject<CPDF_TransferFunc*>* pTransferCounter;
- if (!m_TransferFuncMap.Lookup(pObj, pTransferCounter)) {
- CPDF_TransferFunc* pTransfer = NULL;
- CPDF_Function* pFuncs[3] = {NULL, NULL, NULL};
- FX_BOOL bUniTransfer = TRUE;
- int i;
- FX_BOOL bIdentity = TRUE;
- if (pObj->GetType() == PDFOBJ_ARRAY) {
- bUniTransfer = FALSE;
- CPDF_Array* pArray = (CPDF_Array*)pObj;
- if (pArray->GetCount() < 3) {
- return NULL;
- }
- for (FX_DWORD i = 0; i < 3; i ++) {
- pFuncs[2 - i] = CPDF_Function::Load(pArray->GetElementValue(i));
- if (pFuncs[2 - i] == NULL) {
- return NULL;
- }
- }
- } else {
- pFuncs[0] = CPDF_Function::Load(pObj);
- if (pFuncs[0] == NULL) {
- return NULL;
- }
- }
- pTransfer = FX_NEW CPDF_TransferFunc;
- pTransfer->m_pPDFDoc = m_pPDFDoc;
- pTransferCounter = FX_NEW CPDF_CountedObject<CPDF_TransferFunc*>;
- pTransferCounter->m_nCount = 1;
- pTransferCounter->m_Obj = pTransfer;
- m_TransferFuncMap.SetAt(pObj, pTransferCounter);
- static const int kMaxOutputs = 16;
- FX_FLOAT output[kMaxOutputs];
- FXSYS_memset32(output, 0, sizeof(output));
- FX_FLOAT input;
- int noutput;
- for (int v = 0; v < 256; v ++) {
- input = (FX_FLOAT)v / 255.0f;
- if (bUniTransfer) {
- if (pFuncs[0] && pFuncs[0]->CountOutputs() <= kMaxOutputs) {
- pFuncs[0]->Call(&input, 1, output, noutput);
- }
- int o = FXSYS_round(output[0] * 255);
- if (o != v) {
- bIdentity = FALSE;
- }
- for (i = 0; i < 3; i ++) {
- pTransfer->m_Samples[i * 256 + v] = o;
- }
- } else
- for (i = 0; i < 3; i ++) {
- if (pFuncs[i] && pFuncs[i]->CountOutputs() <= kMaxOutputs) {
- pFuncs[i]->Call(&input, 1, output, noutput);
- int o = FXSYS_round(output[0] * 255);
- if (o != v) {
- bIdentity = FALSE;
- }
- pTransfer->m_Samples[i * 256 + v] = o;
- } else {
- pTransfer->m_Samples[i * 256 + v] = v;
- }
- }
- }
- for (i = 0; i < 3; i ++)
- if (pFuncs[i]) {
- delete pFuncs[i];
- }
- pTransfer->m_bIdentity = bIdentity;
- }
- pTransferCounter->m_nCount++;
- return pTransferCounter->m_Obj;
-}
-void CPDF_DocRenderData::ReleaseTransferFunc(CPDF_Object* pObj)
-{
- CPDF_CountedObject<CPDF_TransferFunc*>* pTransferCounter;
- if (!m_TransferFuncMap.Lookup(pObj, pTransferCounter)) {
- return;
- }
- pTransferCounter->m_nCount--;
-}
-CPDF_RenderConfig::CPDF_RenderConfig()
-{
- m_HalftoneLimit = 0;
-#ifdef _FPDFAPI_MINI_
- m_RenderStepLimit = 20;
-#else
- m_RenderStepLimit = 100;
-#endif
-}
-CPDF_RenderConfig::~CPDF_RenderConfig()
-{
-}
-CPDF_DeviceBuffer::CPDF_DeviceBuffer()
-{
- m_pBitmap = NULL;
- m_pDevice = NULL;
- m_pContext = NULL;
- m_pObject = NULL;
-}
-CPDF_DeviceBuffer::~CPDF_DeviceBuffer()
-{
- if (m_pBitmap) {
- delete m_pBitmap;
- }
-}
-FX_BOOL CPDF_DeviceBuffer::Initialize(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, FX_RECT* pRect,
- const CPDF_PageObject* pObj, int max_dpi)
-{
- m_pDevice = pDevice;
- m_pContext = pContext;
- m_Rect = *pRect;
- m_pObject = pObj;
- m_Matrix.TranslateI(-pRect->left, -pRect->top);
-#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_
- int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE);
- int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE);
- if (horz_size && vert_size && max_dpi) {
- int dpih = pDevice->GetDeviceCaps(FXDC_PIXEL_WIDTH) * 254 / (horz_size * 10);
- int dpiv = pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10);
- if (dpih > max_dpi) {
- m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f);
- }
- if (dpiv > max_dpi) {
- m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv);
- }
- }
-#ifdef _FPDFAPI_MINI_
- m_Matrix.Scale(0.5f, 0.5f);
-#endif
-#endif
- CFX_Matrix ctm = m_pDevice->GetCTM();
- FX_FLOAT fScaleX = FXSYS_fabs(ctm.a);
- FX_FLOAT fScaleY = FXSYS_fabs(ctm.d);
- m_Matrix.Concat(fScaleX, 0, 0, fScaleY, 0, 0);
- CFX_FloatRect rect(*pRect);
- m_Matrix.TransformRect(rect);
- FX_RECT bitmap_rect = rect.GetOutterRect();
- m_pBitmap = FX_NEW CFX_DIBitmap;
- m_pBitmap->Create(bitmap_rect.Width(), bitmap_rect.Height(), FXDIB_Argb);
- return TRUE;
-}
-void CPDF_DeviceBuffer::OutputToDevice()
-{
- if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) {
- if (m_Matrix.a == 1.0f && m_Matrix.d == 1.0f) {
- m_pDevice->SetDIBits(m_pBitmap, m_Rect.left, m_Rect.top);
- } else {
- m_pDevice->StretchDIBits(m_pBitmap, m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height());
- }
- } else {
-#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_)
- CFX_DIBitmap buffer;
- m_pDevice->CreateCompatibleBitmap(&buffer, m_pBitmap->GetWidth(), m_pBitmap->GetHeight());
- m_pContext->GetBackground(&buffer, m_pObject, NULL, &m_Matrix);
- buffer.CompositeBitmap(0, 0, buffer.GetWidth(), buffer.GetHeight(), m_pBitmap, 0, 0);
- m_pDevice->StretchDIBits(&buffer, m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height());
-#endif
- }
-}
-CPDF_ScaledRenderBuffer::CPDF_ScaledRenderBuffer()
-{
- m_pBitmapDevice = NULL;
-}
-CPDF_ScaledRenderBuffer::~CPDF_ScaledRenderBuffer()
-{
- if (m_pBitmapDevice) {
- delete m_pBitmapDevice;
- }
-}
-#ifndef _FPDFAPI_MINI_
-#define _FPDFAPI_IMAGESIZE_LIMIT_ (30 * 1024 * 1024)
-#else
-#define _FPDFAPI_IMAGESIZE_LIMIT_ (10 * 1024 * 1024)
-#endif
-FX_BOOL CPDF_ScaledRenderBuffer::Initialize(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, FX_RECT* pRect,
- const CPDF_PageObject* pObj, const CPDF_RenderOptions *pOptions, int max_dpi)
-{
- FXSYS_assert(pRect != NULL);
- m_pDevice = pDevice;
- if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) {
- return TRUE;
- }
- m_pContext = pContext;
- m_Rect = *pRect;
- m_pObject = pObj;
- m_Matrix.TranslateI(-pRect->left, -pRect->top);
- int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE);
- int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE);
- if (horz_size && vert_size && max_dpi) {
- int dpih = pDevice->GetDeviceCaps(FXDC_PIXEL_WIDTH) * 254 / (horz_size * 10);
- int dpiv = pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10);
- if (dpih > max_dpi) {
- m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f);
- }
- if (dpiv > max_dpi) {
- m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv);
- }
- }
- m_pBitmapDevice = FX_NEW CFX_FxgeDevice;
- FXDIB_Format dibFormat = FXDIB_Rgb;
- FX_INT32 bpp = 24;
- if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_ALPHA_OUTPUT) {
- dibFormat = FXDIB_Argb;
- bpp = 32;
- }
- CFX_FloatRect rect;
- FX_INT32 iWidth, iHeight, iPitch;
- while (1) {
- rect = *pRect;
- m_Matrix.TransformRect(rect);
- FX_RECT bitmap_rect = rect.GetOutterRect();
- iWidth = bitmap_rect.Width();
- iHeight = bitmap_rect.Height();
- iPitch = (iWidth * bpp + 31) / 32 * 4;
- if (iWidth * iHeight < 1) {
- return FALSE;
- }
- if (iPitch * iHeight <= _FPDFAPI_IMAGESIZE_LIMIT_ &&
- m_pBitmapDevice->Create(iWidth, iHeight, dibFormat)) {
- break;
- }
- m_Matrix.Scale(0.5f, 0.5f);
- }
-#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_)
- m_pContext->GetBackground(m_pBitmapDevice->GetBitmap(), m_pObject, pOptions, &m_Matrix);
-#endif
- return TRUE;
-}
-void CPDF_ScaledRenderBuffer::OutputToDevice()
-{
- if (m_pBitmapDevice) {
- m_pDevice->StretchDIBits(m_pBitmapDevice->GetBitmap(), m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height());
- }
-}
-FX_BOOL IPDF_OCContext::CheckObjectVisible(const CPDF_PageObject* pObj)
-{
- const CPDF_ContentMarkData* pData = pObj->m_ContentMark;
- int nItems = pData->CountItems();
- for (int i = 0; i < nItems; i ++) {
- CPDF_ContentMarkItem& item = pData->GetItem(i);
- if (item.GetName() == FX_BSTRC("OC") && item.GetParamType() == CPDF_ContentMarkItem::PropertiesDict) {
- CPDF_Dictionary* pOCG = (CPDF_Dictionary*)item.GetParam();
- if (!CheckOCGVisible(pOCG)) {
- return FALSE;
- }
- }
- }
- return TRUE;
-}
+// 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/fpdfapi/fpdf_render.h" +#include "../../../include/fpdfapi/fpdf_module.h" +#include "../fpdf_page/pageint.h" +#include "../../../include/fxge/fx_ge.h" +#include "../../../include/fxcodec/fx_codec.h" +#include "render_int.h" +CPDF_DocRenderData::CPDF_DocRenderData(CPDF_Document* pPDFDoc) + : m_pPDFDoc(pPDFDoc) + , m_pFontCache(NULL) +{ +} +CPDF_DocRenderData::~CPDF_DocRenderData() +{ + Clear(TRUE); +} +void CPDF_DocRenderData::Clear(FX_BOOL bRelease) +{ + FX_POSITION pos; + { + pos = m_Type3FaceMap.GetStartPosition(); + while (pos) { + CPDF_Font* pFont; + CPDF_CountedObject<CPDF_Type3Cache*>* cache; + m_Type3FaceMap.GetNextAssoc(pos, pFont, cache); + if (bRelease || cache->m_nCount < 2) { + delete cache->m_Obj; + delete cache; + m_Type3FaceMap.RemoveKey(pFont); + } + } + } +#ifndef _FPDFAPI_MINI_ + { + pos = m_TransferFuncMap.GetStartPosition(); + while (pos) { + CPDF_Object* key; + CPDF_CountedObject<CPDF_TransferFunc*>* value; + m_TransferFuncMap.GetNextAssoc(pos, key, value); + if (bRelease || value->m_nCount < 2) { + delete value->m_Obj; + delete value; + m_TransferFuncMap.RemoveKey(key); + } + } + } +#endif + if (m_pFontCache) { + if (bRelease) { + delete m_pFontCache; + m_pFontCache = NULL; + } else { + m_pFontCache->FreeCache(FALSE); + } + } +} +FX_BOOL CPDF_DocRenderData::Initialize() +{ + m_pFontCache = FX_NEW CFX_FontCache; + return TRUE; +} +CPDF_Type3Cache* CPDF_DocRenderData::GetCachedType3(CPDF_Type3Font* pFont) +{ + CPDF_CountedObject<CPDF_Type3Cache*>* pCache; + if (!m_Type3FaceMap.Lookup(pFont, pCache)) { + CPDF_Type3Cache* pType3 = FX_NEW CPDF_Type3Cache(pFont); + pCache = FX_NEW CPDF_CountedObject<CPDF_Type3Cache*>; + pCache->m_Obj = pType3; + pCache->m_nCount = 1; + m_Type3FaceMap.SetAt(pFont, pCache); + } + pCache->m_nCount++; + return pCache->m_Obj; +} +void CPDF_DocRenderData::ReleaseCachedType3(CPDF_Type3Font* pFont) +{ + CPDF_CountedObject<CPDF_Type3Cache*>* pCache; + if (!m_Type3FaceMap.Lookup(pFont, pCache)) { + return; + } + pCache->m_nCount--; +} +class CPDF_RenderModule : public CPDF_RenderModuleDef +{ +public: + virtual ~CPDF_RenderModule() {} + virtual FX_BOOL Installed() + { + return TRUE; + } + virtual CPDF_DocRenderData* CreateDocData(CPDF_Document* pDoc); + virtual void DestroyDocData(CPDF_DocRenderData* p); + virtual void ClearDocData(CPDF_DocRenderData* p); + virtual CPDF_DocRenderData* GetRenderData() + { + return &m_RenderData; + } + virtual CPDF_PageRenderCache* CreatePageCache(CPDF_Page* pPage) + { + return FX_NEW CPDF_PageRenderCache(pPage); + } + virtual void DestroyPageCache(CPDF_PageRenderCache* pCache); + virtual CPDF_RenderConfig* GetConfig() + { + return &m_RenderConfig; + } +private: + CPDF_DocRenderData m_RenderData; + CPDF_RenderConfig m_RenderConfig; +}; +CPDF_DocRenderData* CPDF_RenderModule::CreateDocData(CPDF_Document* pDoc) +{ + CPDF_DocRenderData* pData = FX_NEW CPDF_DocRenderData(pDoc); + pData->Initialize(); + return pData; +} +void CPDF_RenderModule::DestroyDocData(CPDF_DocRenderData* pDocData) +{ + delete pDocData; +} +void CPDF_RenderModule::ClearDocData(CPDF_DocRenderData* p) +{ + if (p) { + p->Clear(FALSE); + } +} +void CPDF_RenderModule::DestroyPageCache(CPDF_PageRenderCache* pCache) +{ + delete pCache; +} +void CPDF_ModuleMgr::InitRenderModule() +{ + if (m_pRenderModule) { + delete m_pRenderModule; + } + m_pRenderModule = FX_NEW CPDF_RenderModule; +} +CPDF_RenderOptions::CPDF_RenderOptions() + : m_ColorMode(RENDER_COLOR_NORMAL) + , m_Flags(RENDER_CLEARTYPE) + , m_Interpolation(0) + , m_AddFlags(0) + , m_pOCContext(NULL) + , m_dwLimitCacheSize(1024 * 1024 * 100) + , m_HalftoneLimit(-1) +{ +#if defined(_FPDFAPI_MINI_) + m_Flags |= RENDER_LIMITEDIMAGECACHE; +#endif +} +FX_ARGB CPDF_RenderOptions::TranslateColor(FX_ARGB argb) const +{ + if (m_ColorMode == RENDER_COLOR_NORMAL) { + return argb; + } + if (m_ColorMode == RENDER_COLOR_ALPHA) { + return argb; + } + int a, r, g, b; + ArgbDecode(argb, a, r, g, b); + int gray = FXRGB2GRAY(r, g, b); + if (m_ColorMode == RENDER_COLOR_TWOCOLOR) { + int color = (r - gray) * (r - gray) + (g - gray) * (g - gray) + (b - gray) * (b - gray); + if (gray < 35 && color < 20) { + return ArgbEncode(a, m_ForeColor); + } + if (gray > 221 && color < 20) { + return ArgbEncode(a, m_BackColor); + } + return argb; + } + int fr = FXSYS_GetRValue(m_ForeColor); + int fg = FXSYS_GetGValue(m_ForeColor); + int fb = FXSYS_GetBValue(m_ForeColor); + int br = FXSYS_GetRValue(m_BackColor); + int bg = FXSYS_GetGValue(m_BackColor); + int bb = FXSYS_GetBValue(m_BackColor); + r = (br - fr) * gray / 255 + fr; + g = (bg - fg) * gray / 255 + fg; + b = (bb - fb) * gray / 255 + fb; + return ArgbEncode(a, r, g, b); +} +CPDF_RenderStatus::CPDF_RenderStatus() +{ + m_pContext = NULL; + m_bStopped = FALSE; + m_Level = 0; + m_pDevice = NULL; + m_pCurObj = NULL; + m_pStopObj = NULL; + m_HalftoneLimit = 0; + m_pObjectRenderer = NULL; + m_bPrint = FALSE; + m_Transparency = 0; + m_DitherBits = 0; + m_bDropObjects = FALSE; + m_bStdCS = FALSE; + m_GroupFamily = 0; + m_bLoadMask = FALSE; + m_pType3Char = NULL; + m_T3FillColor = 0; + m_pFormResource = NULL; + m_pPageResource = NULL; + m_curBlend = FXDIB_BLEND_NORMAL; +} +CPDF_RenderStatus::~CPDF_RenderStatus() +{ + if (m_pObjectRenderer) { + delete m_pObjectRenderer; + } +} +FX_BOOL CPDF_RenderStatus::Initialize(int level, CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, + const CFX_AffineMatrix* pDeviceMatrix, const CPDF_PageObject* pStopObj, + const CPDF_RenderStatus* pParentState, const CPDF_GraphicStates* pInitialStates, + const CPDF_RenderOptions* pOptions, int transparency, FX_BOOL bDropObjects, + CPDF_Dictionary* pFormResource, FX_BOOL bStdCS, CPDF_Type3Char* pType3Char, + FX_ARGB fill_color, FX_DWORD GroupFamily, + FX_BOOL bLoadMask) +{ + m_Level = level; + m_pContext = pContext; + m_pDevice = pDevice; + m_DitherBits = pDevice->GetDeviceCaps(FXDC_DITHER_BITS); + m_bPrint = m_pDevice->GetDeviceClass() != FXDC_DISPLAY; + if (pDeviceMatrix) { + m_DeviceMatrix = *pDeviceMatrix; + } + m_pStopObj = pStopObj; + if (pOptions) { + m_Options = *pOptions; + } + m_bDropObjects = bDropObjects; + m_bStdCS = bStdCS; + m_T3FillColor = fill_color; + m_pType3Char = pType3Char; + m_GroupFamily = GroupFamily; + m_bLoadMask = bLoadMask; + m_pFormResource = pFormResource; + m_pPageResource = m_pContext->m_pPageResources; + if (pInitialStates && !m_pType3Char) { + m_InitialStates.CopyStates(*pInitialStates); + if (pParentState) { + CPDF_ColorStateData* pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)m_InitialStates.m_ColorState; + CPDF_ColorStateData* pParentData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)pParentState->m_InitialStates.m_ColorState; + if (!pColorData || pColorData->m_FillColor.IsNull()) { + CPDF_ColorStateData* pData = m_InitialStates.m_ColorState.GetModify(); + pData->m_FillRGB = pParentData->m_FillRGB; + pData->m_FillColor.Copy(&pParentData->m_FillColor); + } + if (!pColorData || pColorData->m_StrokeColor.IsNull()) { + CPDF_ColorStateData* pData = m_InitialStates.m_ColorState.GetModify(); + pData->m_StrokeRGB = pParentData->m_FillRGB; + pData->m_StrokeColor.Copy(&pParentData->m_StrokeColor); + } + } + } else { + m_InitialStates.DefaultStates(); + } +#if defined(_FPDFAPI_MINI_)||defined(_FXCORE_LIMITED_CPU_) + m_HalftoneLimit = CPDF_ModuleMgr::Get()->GetRenderModule()->GetConfig()->m_HalftoneLimit; + if (pOptions && pOptions->m_HalftoneLimit >= 0) { + m_HalftoneLimit = pOptions->m_HalftoneLimit; + } +#endif + m_pObjectRenderer = NULL; + m_Transparency = transparency; + return TRUE; +} +void CPDF_RenderStatus::RenderObjectList(const CPDF_PageObjects* pObjs, const CFX_AffineMatrix* pObj2Device) +{ + if (m_Level > 32) { + return; + } + CFX_FloatRect clip_rect = m_pDevice->GetClipBox(); + CFX_AffineMatrix device2object; + device2object.SetReverse(*pObj2Device); + device2object.TransformRect(clip_rect); + int index = 0; + FX_POSITION pos = pObjs->GetFirstObjectPosition(); + while(pos) { + index ++; + CPDF_PageObject* pCurObj = pObjs->GetNextObject(pos); + if (pCurObj == m_pStopObj) { + m_bStopped = TRUE; + return; + } + if (!pCurObj) { + continue; + } + if(pCurObj == NULL || pCurObj->m_Left > clip_rect.right || pCurObj->m_Right < clip_rect.left || + pCurObj->m_Bottom > clip_rect.top || pCurObj->m_Top < clip_rect.bottom) { + continue; + } + RenderSingleObject(pCurObj, pObj2Device); + if (m_bStopped) { + return; + } + } +} +void CPDF_RenderStatus::RenderSingleObject(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device) +{ + if (m_Level > 32) { + return; + } + m_pCurObj = pObj; + if (m_Options.m_pOCContext && pObj->m_ContentMark.NotNull()) + if (!m_Options.m_pOCContext->CheckObjectVisible(pObj)) { + return; + } + ProcessClipPath(pObj->m_ClipPath, pObj2Device); + if (ProcessTransparency(pObj, pObj2Device)) { + return; + } + ProcessObjectNoClip(pObj, pObj2Device); +} +FX_BOOL CPDF_RenderStatus::ContinueSingleObject(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, IFX_Pause* pPause) +{ + if (m_pObjectRenderer) { + if (m_pObjectRenderer->Continue(pPause)) { + return TRUE; + } + if (!m_pObjectRenderer->m_Result) { + DrawObjWithBackground(pObj, pObj2Device); + } +#ifdef _FPDFAPI_MINI_ + if (m_DitherBits) { + DitherObjectArea(pObj, pObj2Device); + } +#endif + delete m_pObjectRenderer; + m_pObjectRenderer = NULL; + return FALSE; + } + m_pCurObj = pObj; + if (m_Options.m_pOCContext && pObj->m_ContentMark.NotNull()) + if (!m_Options.m_pOCContext->CheckObjectVisible(pObj)) { + return FALSE; + } + ProcessClipPath(pObj->m_ClipPath, pObj2Device); + if (ProcessTransparency(pObj, pObj2Device)) { + return FALSE; + } + if (pObj->m_Type == PDFPAGE_IMAGE) { + m_pObjectRenderer = IPDF_ObjectRenderer::Create(pObj->m_Type); + if (!m_pObjectRenderer->Start(this, pObj, pObj2Device, FALSE)) { + if (!m_pObjectRenderer->m_Result) { + DrawObjWithBackground(pObj, pObj2Device); + } +#ifdef _FPDFAPI_MINI_ + if (m_DitherBits) { + DitherObjectArea(pObj, pObj2Device); + } +#endif + delete m_pObjectRenderer; + m_pObjectRenderer = NULL; + return FALSE; + } + return ContinueSingleObject(pObj, pObj2Device, pPause); + } + ProcessObjectNoClip(pObj, pObj2Device); + return FALSE; +} +IPDF_ObjectRenderer* IPDF_ObjectRenderer::Create(int type) +{ + IPDF_ObjectRenderer* pRenderer = NULL; + if (type == PDFPAGE_IMAGE) { + pRenderer = FX_NEW CPDF_ImageRenderer; + } + return pRenderer; +} +FX_BOOL CPDF_RenderStatus::GetObjectClippedRect(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bLogical, FX_RECT &rect) const +{ + rect = pObj->GetBBox(pObj2Device); + FX_RECT rtClip = m_pDevice->GetClipBox(); + if (!bLogical) { + CFX_Matrix dCTM = m_pDevice->GetCTM(); + FX_FLOAT a = FXSYS_fabs(dCTM.a); + FX_FLOAT d = FXSYS_fabs(dCTM.d); + if (a != 1.0f || d != 1.0f) { + rect.right = rect.left + (FX_INT32)FXSYS_ceil((FX_FLOAT)rect.Width() * a); + rect.bottom = rect.top + (FX_INT32)FXSYS_ceil((FX_FLOAT)rect.Height() * d); + rtClip.right = rtClip.left + (FX_INT32)FXSYS_ceil((FX_FLOAT)rtClip.Width() * a); + rtClip.bottom = rtClip.top + (FX_INT32)FXSYS_ceil((FX_FLOAT)rtClip.Height() * d); + } + } + rect.Intersect(rtClip); + return rect.IsEmpty(); +} +void CPDF_RenderStatus::DitherObjectArea(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device) +{ + CFX_DIBitmap* pBitmap = m_pDevice->GetBitmap(); + if (pBitmap == NULL) { + return; + } + FX_RECT rect; + if (GetObjectClippedRect(pObj, pObj2Device, FALSE, rect)) { + return; + } + if (m_DitherBits == 2) { + static FX_ARGB pal[4] = {0, 85, 170, 255}; + pBitmap->DitherFS(pal, 4, &rect); + } else if (m_DitherBits == 3) { + static FX_ARGB pal[8] = {0, 36, 73, 109, 146, 182, 219, 255}; + pBitmap->DitherFS(pal, 8, &rect); + } else if (m_DitherBits == 4) { + static FX_ARGB pal[16] = {0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255}; + pBitmap->DitherFS(pal, 16, &rect); + } +} +void CPDF_RenderStatus::ProcessObjectNoClip(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device) +{ + FX_BOOL bRet = FALSE; + switch (pObj->m_Type) { + case PDFPAGE_TEXT: + bRet = ProcessText((CPDF_TextObject*)pObj, pObj2Device, NULL); + break; + case PDFPAGE_PATH: + bRet = ProcessPath((CPDF_PathObject*)pObj, pObj2Device); + break; + case PDFPAGE_IMAGE: + bRet = ProcessImage((CPDF_ImageObject*)pObj, pObj2Device); + break; + case PDFPAGE_SHADING: + bRet = ProcessShading((CPDF_ShadingObject*)pObj, pObj2Device); + break; + case PDFPAGE_FORM: + bRet = ProcessForm((CPDF_FormObject*)pObj, pObj2Device); + break; +#if defined(_FPDFAPI_MINI_) + case PDFPAGE_INLINES: + bRet = ProcessInlines((CPDF_InlineImages*)pObj, pObj2Device); + break; +#endif + } + if (!bRet) { + DrawObjWithBackground(pObj, pObj2Device); + } +} +FX_BOOL CPDF_RenderStatus::DrawObjWithBlend(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device) +{ + FX_BOOL bRet = FALSE; + switch (pObj->m_Type) { + case PDFPAGE_PATH: + bRet = ProcessPath((CPDF_PathObject*)pObj, pObj2Device); + break; + case PDFPAGE_IMAGE: + bRet = ProcessImage((CPDF_ImageObject *)pObj, pObj2Device); + break; + case PDFPAGE_FORM: + bRet = ProcessForm((CPDF_FormObject*)pObj, pObj2Device); + break; + } + return bRet; +} +void CPDF_RenderStatus::GetScaledMatrix(CFX_Matrix &matrix) const +{ + CFX_Matrix dCTM = m_pDevice->GetCTM(); + matrix.a *= FXSYS_fabs(dCTM.a); + matrix.d *= FXSYS_fabs(dCTM.d); +} +void CPDF_RenderStatus::DrawObjWithBackground(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device) +{ +#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_) + FX_RECT rect; + if (GetObjectClippedRect(pObj, pObj2Device, FALSE, rect)) { + return; + } + int res = 300; + if (pObj->m_Type == PDFPAGE_IMAGE && m_pDevice->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) { + res = 0; + } + CPDF_ScaledRenderBuffer buffer; + if (!buffer.Initialize(m_pContext, m_pDevice, &rect, pObj, &m_Options, res)) { + return; + } + CFX_AffineMatrix matrix = *pObj2Device; + matrix.Concat(*buffer.GetMatrix()); + GetScaledMatrix(matrix); + CPDF_Dictionary* pFormResource = NULL; + if (pObj->m_Type == PDFPAGE_FORM) { + CPDF_FormObject* pFormObj = (CPDF_FormObject*)pObj; + if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) { + pFormResource = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources")); + } + } + CPDF_RenderStatus status; + status.Initialize(m_Level + 1, m_pContext, buffer.GetDevice(), buffer.GetMatrix(), NULL, NULL, NULL, &m_Options, m_Transparency, m_bDropObjects, pFormResource); + status.RenderSingleObject(pObj, &matrix); + buffer.OutputToDevice(); +#endif +} +FX_BOOL CPDF_RenderStatus::ProcessForm(CPDF_FormObject* pFormObj, const CFX_AffineMatrix* pObj2Device) +{ + CPDF_Dictionary* pOC = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("OC")); + if (pOC && m_Options.m_pOCContext && !m_Options.m_pOCContext->CheckOCGVisible(pOC)) { + return TRUE; + } + CFX_AffineMatrix matrix = pFormObj->m_FormMatrix; + matrix.Concat(*pObj2Device); + CPDF_Dictionary* pResources = NULL; + if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) { + pResources = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources")); + } + CPDF_RenderStatus status; + status.Initialize(m_Level + 1, m_pContext, m_pDevice, NULL, m_pStopObj, + this, pFormObj, &m_Options, m_Transparency, m_bDropObjects, pResources, TRUE); + status.m_curBlend = m_curBlend; + m_pDevice->SaveState(); + status.RenderObjectList(pFormObj->m_pForm, &matrix); + m_bStopped = status.m_bStopped; + m_pDevice->RestoreState(); + return TRUE; +} +FX_BOOL IsAvailableMatrix(const CFX_AffineMatrix& matrix) +{ + if (matrix.a == 0 || matrix.d == 0) { + return matrix.b != 0 && matrix.c != 0; + } + if (matrix.b == 0 || matrix.c == 0) { + return matrix.a != 0 && matrix.d != 0; + } + return TRUE; +} +FX_BOOL CPDF_RenderStatus::ProcessPath(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device) +{ + int FillType = pPathObj->m_FillType; + FX_BOOL bStroke = pPathObj->m_bStroke; + ProcessPathPattern(pPathObj, pObj2Device, FillType, bStroke); + if (FillType == 0 && !bStroke) { + return TRUE; + } + FX_DWORD fill_argb = 0; + if (FillType) { + fill_argb = GetFillArgb(pPathObj); + } + FX_DWORD stroke_argb = 0; + if (bStroke) { + stroke_argb = GetStrokeArgb(pPathObj); + } + CFX_AffineMatrix path_matrix = pPathObj->m_Matrix; + path_matrix.Concat(*pObj2Device); + if (!IsAvailableMatrix(path_matrix)) { + return TRUE; + } + if (FillType && (m_Options.m_Flags & RENDER_RECT_AA)) { + FillType |= FXFILL_RECT_AA; + } + if (m_Options.m_Flags & RENDER_FILL_FULLCOVER) { + FillType |= FXFILL_FULLCOVER; + } + if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) { + FillType |= FXFILL_NOPATHSMOOTH; + } + if (bStroke) { + FillType |= FX_FILL_STROKE; + } +#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_) + const CPDF_GeneralStateData* pGeneralData = ((CPDF_PageObject*)pPathObj)->m_GeneralState; + if (pGeneralData && pGeneralData->m_StrokeAdjust) { + FillType |= FX_STROKE_ADJUST; + } +#endif + if (m_pType3Char) { + FillType |= FX_FILL_TEXT_MODE; + } + CFX_GraphStateData graphState(*pPathObj->m_GraphState); + if (m_Options.m_Flags & RENDER_THINLINE) { + graphState.m_LineWidth = 0; + } + return m_pDevice->DrawPath(pPathObj->m_Path, &path_matrix, &graphState, fill_argb, stroke_argb, FillType, 0, NULL, m_curBlend); +} +CPDF_TransferFunc* CPDF_RenderStatus::GetTransferFunc(CPDF_Object* pObj) const +{ + ASSERT(pObj != NULL); + CPDF_DocRenderData* pDocCache = m_pContext->m_pDocument->GetRenderData(); + if (!pDocCache) { + return NULL; + } + return pDocCache->GetTransferFunc(pObj); +} +FX_ARGB CPDF_RenderStatus::GetFillArgb(const CPDF_PageObject* pObj, FX_BOOL bType3) const +{ + CPDF_ColorStateData* pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)pObj->m_ColorState; + if (m_pType3Char && !bType3 && (!m_pType3Char->m_bColored || (m_pType3Char->m_bColored && (!pColorData || pColorData->m_FillColor.IsNull())))) { + return m_T3FillColor; + } else if (!pColorData || pColorData->m_FillColor.IsNull()) { + pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)m_InitialStates.m_ColorState; + } + FX_COLORREF rgb = pColorData->m_FillRGB; + if (rgb == (FX_DWORD) - 1) { + return 0; + } + const CPDF_GeneralStateData* pGeneralData = pObj->m_GeneralState; + int alpha; + if (pGeneralData) { + alpha = (FX_INT32)(pGeneralData->m_FillAlpha * 255); +#ifndef _FPDFAPI_MINI_ + if (pGeneralData->m_pTR) { + if (!pGeneralData->m_pTransferFunc) { + ((CPDF_GeneralStateData*)pGeneralData)->m_pTransferFunc = GetTransferFunc(pGeneralData->m_pTR); + } + if (pGeneralData->m_pTransferFunc) { + rgb = pGeneralData->m_pTransferFunc->TranslateColor(rgb); + } + } +#endif + } else { + alpha = 255; + } + return m_Options.TranslateColor(ArgbEncode(alpha, rgb)); +} +FX_ARGB CPDF_RenderStatus::GetStrokeArgb(const CPDF_PageObject* pObj) const +{ + CPDF_ColorStateData* pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)pObj->m_ColorState; + if (m_pType3Char && (!m_pType3Char->m_bColored || (m_pType3Char->m_bColored && (!pColorData || pColorData->m_StrokeColor.IsNull())))) { + return m_T3FillColor; + } else if (!pColorData || pColorData->m_StrokeColor.IsNull()) { + pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)m_InitialStates.m_ColorState; + } + FX_COLORREF rgb = pColorData->m_StrokeRGB; + if (rgb == (FX_DWORD) - 1) { + return 0; + } + const CPDF_GeneralStateData* pGeneralData = pObj->m_GeneralState; + int alpha; + if (pGeneralData) { + alpha = (FX_INT32)(pGeneralData->m_StrokeAlpha * 255); +#ifndef _FPDFAPI_MINI_ + if (pGeneralData->m_pTR) { + if (!pGeneralData->m_pTransferFunc) { + ((CPDF_GeneralStateData*)pGeneralData)->m_pTransferFunc = GetTransferFunc(pGeneralData->m_pTR); + } + if (pGeneralData->m_pTransferFunc) { + rgb = pGeneralData->m_pTransferFunc->TranslateColor(rgb); + } + } +#endif + } else { + alpha = 255; + } + return m_Options.TranslateColor(ArgbEncode(alpha, rgb)); +} +void CPDF_RenderStatus::ProcessClipPath(CPDF_ClipPath ClipPath, const CFX_AffineMatrix* pObj2Device) +{ + if (ClipPath.IsNull()) { + if (m_LastClipPath.IsNull()) { + return; + } + m_pDevice->RestoreState(TRUE); + m_LastClipPath.SetNull(); + return; + } + if (m_LastClipPath == ClipPath) { + return; + } + m_LastClipPath = ClipPath; + m_pDevice->RestoreState(TRUE); + int nClipPath = ClipPath.GetPathCount(); + int i; + for (i = 0; i < nClipPath; i++) { + const CFX_PathData* pPathData = ClipPath.GetPath(i); + if (pPathData == NULL) { + continue; + } + if (pPathData->GetPointCount() == 0) { + CFX_PathData EmptyPath; + EmptyPath.AppendRect(-1, -1, 0, 0); + int fill_mode = FXFILL_WINDING; + m_pDevice->SetClip_PathFill(&EmptyPath, NULL, fill_mode); + } else { + int ClipType = ClipPath.GetClipType(i); + m_pDevice->SetClip_PathFill(pPathData, pObj2Device, ClipType); + } + } + int textcount = ClipPath.GetTextCount(); + if (textcount == 0) { + return; + } + if (m_pDevice->GetDeviceClass() == FXDC_DISPLAY && !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)) { + return; + } + CFX_PathData* pTextClippingPath = NULL; + for (i = 0; i < textcount; i ++) { + CPDF_TextObject* pText = ClipPath.GetText(i); + if (pText == NULL) { + if (pTextClippingPath) { + int fill_mode = FXFILL_WINDING; + if (m_Options.m_Flags & RENDER_NOTEXTSMOOTH) { + fill_mode |= FXFILL_NOPATHSMOOTH; + } + m_pDevice->SetClip_PathFill(pTextClippingPath, NULL, fill_mode); + delete pTextClippingPath; + pTextClippingPath = NULL; + } + } else { + if (pTextClippingPath == NULL) { + pTextClippingPath = FX_NEW CFX_PathData; + } + ProcessText(pText, pObj2Device, pTextClippingPath); + } + } + if (pTextClippingPath) { + delete pTextClippingPath; + } +} +void CPDF_RenderStatus::DrawClipPath(CPDF_ClipPath ClipPath, const CFX_AffineMatrix* pObj2Device) +{ + if (ClipPath.IsNull()) { + return; + } + int fill_mode = 0; + if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) { + fill_mode |= FXFILL_NOPATHSMOOTH; + } + int nClipPath = ClipPath.GetPathCount(); + int i; + for (i = 0; i < nClipPath; i++) { + const CFX_PathData* pPathData = ClipPath.GetPath(i); + if (pPathData == NULL) { + continue; + } + CFX_GraphStateData stroke_state; + if (m_Options.m_Flags & RENDER_THINLINE) { + stroke_state.m_LineWidth = 0; + } + m_pDevice->DrawPath(pPathData, pObj2Device, &stroke_state, 0, 0xffff0000, fill_mode); + } +} +FX_BOOL CPDF_RenderStatus::SelectClipPath(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke) +{ + CFX_AffineMatrix path_matrix = pPathObj->m_Matrix; + path_matrix.Concat(*pObj2Device); + if (bStroke) { + CFX_GraphStateData graphState(*pPathObj->m_GraphState); + if (m_Options.m_Flags & RENDER_THINLINE) { + graphState.m_LineWidth = 0; + } + return m_pDevice->SetClip_PathStroke(pPathObj->m_Path, &path_matrix, &graphState); + } + int fill_mode = pPathObj->m_FillType; + if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) { + fill_mode |= FXFILL_NOPATHSMOOTH; + } + return m_pDevice->SetClip_PathFill(pPathObj->m_Path, &path_matrix, fill_mode); +} +FX_BOOL CPDF_RenderStatus::ProcessTransparency(const CPDF_PageObject* pPageObj, const CFX_AffineMatrix* pObj2Device) +{ + const CPDF_GeneralStateData* pGeneralState = pPageObj->m_GeneralState; + int blend_type = pGeneralState ? pGeneralState->m_BlendType : FXDIB_BLEND_NORMAL; + if (blend_type == FXDIB_BLEND_UNSUPPORTED) { + return TRUE; + } + CPDF_Dictionary* pSMaskDict = pGeneralState ? (CPDF_Dictionary*)pGeneralState->m_pSoftMask : NULL; + if (pSMaskDict) { + if (pPageObj->m_Type == PDFPAGE_IMAGE && + ((CPDF_ImageObject*)pPageObj)->m_pImage->GetDict()->KeyExist(FX_BSTRC("SMask"))) { + pSMaskDict = NULL; + } + } + CPDF_Dictionary* pFormResource = NULL; + FX_FLOAT group_alpha = 1.0f; + int Transparency = m_Transparency; + FX_BOOL bGroupTransparent = FALSE; + if (pPageObj->m_Type == PDFPAGE_FORM) { + CPDF_FormObject* pFormObj = (CPDF_FormObject*)pPageObj; + const CPDF_GeneralStateData *pStateData = pFormObj->m_GeneralState.GetObject(); + if (pStateData) { + group_alpha = pStateData->m_FillAlpha; + } + Transparency = pFormObj->m_pForm->m_Transparency; + bGroupTransparent = Transparency & PDFTRANS_ISOLATED ? TRUE : FALSE; + if (pFormObj->m_pForm->m_pFormDict) { + pFormResource = pFormObj->m_pForm->m_pFormDict->GetDict("Resources"); + } + } + FX_BOOL bTextClip = FALSE; + if (pPageObj->m_ClipPath.NotNull() && pPageObj->m_ClipPath.GetTextCount() && + m_pDevice->GetDeviceClass() == FXDC_DISPLAY && !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)) { + bTextClip = TRUE; + } + if ((m_Options.m_Flags & RENDER_OVERPRINT) && pPageObj->m_Type == PDFPAGE_IMAGE && pGeneralState && pGeneralState->m_FillOP && pGeneralState->m_StrokeOP) { + CPDF_Document* pDocument = NULL; + CPDF_Page* pPage = NULL; + if (m_pContext->m_pPageCache) { + pPage = m_pContext->m_pPageCache->GetPage(); + pDocument = pPage->m_pDocument; + } else { + pDocument = ((CPDF_ImageObject*)pPageObj)->m_pImage->GetDocument(); + } + CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : NULL; + CPDF_Object* pCSObj = ((CPDF_ImageObject*)pPageObj)->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) { + blend_type = FXDIB_BLEND_DARKEN; + } + pDocument->GetPageData()->ReleaseColorSpace(pCSObj); + } + } + if (pSMaskDict == NULL && group_alpha == 1.0f && blend_type == FXDIB_BLEND_NORMAL && !bTextClip && !bGroupTransparent) { + return FALSE; + } + FX_BOOL isolated = Transparency & PDFTRANS_ISOLATED; + if (m_bPrint) { + FX_BOOL bRet = FALSE; + int rendCaps = m_pDevice->GetRenderCaps(); + if (!((Transparency & PDFTRANS_ISOLATED) || pSMaskDict || bTextClip) && (rendCaps & FXRC_BLEND_MODE)) { + int oldBlend = m_curBlend; + m_curBlend = blend_type; + bRet = DrawObjWithBlend(pPageObj, pObj2Device); + m_curBlend = oldBlend; + } + if (!bRet) { + DrawObjWithBackground(pPageObj, pObj2Device); + } + return TRUE; + } + FX_RECT rect = pPageObj->GetBBox(pObj2Device); + rect.Intersect(m_pDevice->GetClipBox()); + if (rect.IsEmpty()) { + return TRUE; + } + CFX_Matrix deviceCTM = m_pDevice->GetCTM(); + FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a); + FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d); + int width = FXSYS_round((FX_FLOAT)rect.Width() * scaleX); + int height = FXSYS_round((FX_FLOAT)rect.Height() * scaleY); + CFX_FxgeDevice bitmap_device; + CFX_DIBitmap* oriDevice = NULL; + if (!isolated && (m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) { + oriDevice = FX_NEW CFX_DIBitmap; + if (!m_pDevice->CreateCompatibleBitmap(oriDevice, width, height)) { + return TRUE; + } + m_pDevice->GetDIBits(oriDevice, rect.left, rect.top); + } + if (!bitmap_device.Create(width, height, FXDIB_Argb, 0, oriDevice)) { + return TRUE; + } + CFX_DIBitmap* bitmap = bitmap_device.GetBitmap(); + bitmap->Clear(0); + CFX_AffineMatrix new_matrix = *pObj2Device; + new_matrix.TranslateI(-rect.left, -rect.top); + new_matrix.Scale(scaleX, scaleY); + CFX_DIBitmap* pTextMask = NULL; + if (bTextClip) { + pTextMask = FX_NEW CFX_DIBitmap; + if (!pTextMask->Create(width, height, FXDIB_8bppMask)) { + delete pTextMask; + return TRUE; + } + pTextMask->Clear(0); + CFX_FxgeDevice text_device; + text_device.Attach(pTextMask); + for (FX_DWORD i = 0; i < pPageObj->m_ClipPath.GetTextCount(); i ++) { + CPDF_TextObject* textobj = pPageObj->m_ClipPath.GetText(i); + if (textobj == NULL) { + break; + } + CFX_AffineMatrix text_matrix; + textobj->GetTextMatrix(&text_matrix); + CPDF_TextRenderer::DrawTextPath(&text_device, textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos, + textobj->m_TextState.GetFont(), textobj->m_TextState.GetFontSize(), + &text_matrix, &new_matrix, textobj->m_GraphState, (FX_ARGB) - 1, 0, NULL); + } + } + CPDF_RenderStatus bitmap_render; + bitmap_render.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL, + m_pStopObj, NULL, NULL, &m_Options, 0, m_bDropObjects, pFormResource, TRUE); + bitmap_render.ProcessObjectNoClip(pPageObj, &new_matrix); + m_bStopped = bitmap_render.m_bStopped; + if (pSMaskDict) { + CFX_AffineMatrix smask_matrix; + FXSYS_memcpy32(&smask_matrix, pGeneralState->m_SMaskMatrix, sizeof smask_matrix); + smask_matrix.Concat(*pObj2Device); + CFX_DIBSource* pSMaskSource = LoadSMask(pSMaskDict, &rect, &smask_matrix); + if (pSMaskSource) { + bitmap->MultiplyAlpha(pSMaskSource); + delete pSMaskSource; + } + } + if (pTextMask) { + bitmap->MultiplyAlpha(pTextMask); + delete pTextMask; + pTextMask = NULL; + } + if (Transparency & PDFTRANS_GROUP && group_alpha != 1.0f) { + bitmap->MultiplyAlpha((FX_INT32)(group_alpha * 255)); + } + Transparency = m_Transparency; + if (pPageObj->m_Type == PDFPAGE_FORM) { + Transparency |= PDFTRANS_GROUP; + } + CompositeDIBitmap(bitmap, rect.left, rect.top, 0, 255, blend_type, Transparency); + if (oriDevice) { + delete oriDevice; + } + return TRUE; +} +CFX_DIBitmap* CPDF_RenderStatus::GetBackdrop(const CPDF_PageObject* pObj, const FX_RECT& rect, int& left, int& top, + FX_BOOL bBackAlphaRequired) +{ + FX_RECT bbox = rect; + bbox.Intersect(m_pDevice->GetClipBox()); + left = bbox.left; + top = bbox.top; + CFX_Matrix deviceCTM = m_pDevice->GetCTM(); + FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a); + FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d); + int width = FXSYS_round(bbox.Width() * scaleX); + int height = FXSYS_round(bbox.Height() * scaleY); + CFX_DIBitmap* pBackdrop = FX_NEW CFX_DIBitmap; + if (bBackAlphaRequired && !m_bDropObjects) { + pBackdrop->Create(width, height, FXDIB_Argb); + } else { + m_pDevice->CreateCompatibleBitmap(pBackdrop, width, height); + } + if (pBackdrop->GetBuffer() == NULL) { + delete pBackdrop; + return NULL; + } + FX_BOOL bNeedDraw; + if (pBackdrop->HasAlpha()) { + bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT); + } else { + bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS); + } + if (!bNeedDraw) { + m_pDevice->GetDIBits(pBackdrop, left, top); + return pBackdrop; + } + CFX_AffineMatrix FinalMatrix = m_DeviceMatrix; + FinalMatrix.TranslateI(-left, -top); + FinalMatrix.Scale(scaleX, scaleY); + pBackdrop->Clear(pBackdrop->HasAlpha() ? 0 : 0xffffffff); + CFX_FxgeDevice device; + device.Attach(pBackdrop); + m_pContext->Render(&device, pObj, &m_Options, &FinalMatrix); + return pBackdrop; +} +void CPDF_RenderContext::GetBackground(CFX_DIBitmap* pBuffer, const CPDF_PageObject* pObj, + const CPDF_RenderOptions* pOptions, CFX_AffineMatrix* pFinalMatrix) +{ + CFX_FxgeDevice device; + device.Attach(pBuffer); + if (m_pBackgroundDraw) { + m_pBackgroundDraw->OnDrawBackground(&device, pFinalMatrix); + } else { + FX_RECT rect(0, 0, device.GetWidth(), device.GetHeight()); + device.FillRect(&rect, 0xffffffff); + } + Render(&device, pObj, pOptions, pFinalMatrix); +} +CPDF_GraphicStates* CPDF_RenderStatus::CloneObjStates(const CPDF_GraphicStates* pSrcStates, FX_BOOL bStroke) +{ + if (!pSrcStates) { + return NULL; + } + CPDF_GraphicStates* pStates = FX_NEW CPDF_GraphicStates; + if (!pStates) { + return NULL; + } + pStates->CopyStates(*pSrcStates); + CPDF_Color* pObjColor = bStroke ? pSrcStates->m_ColorState.GetStrokeColor() : + pSrcStates->m_ColorState.GetFillColor(); + if (!pObjColor->IsNull()) { + CPDF_ColorStateData* pColorData = pStates->m_ColorState.GetModify(); + pColorData->m_FillRGB = bStroke ? pSrcStates->m_ColorState.GetObject()->m_StrokeRGB : + pSrcStates->m_ColorState.GetObject()->m_FillRGB; + pColorData->m_StrokeRGB = pColorData->m_FillRGB; + } + return pStates; +} +CPDF_RenderContext::CPDF_RenderContext() +{ +} +void CPDF_RenderContext::Create(CPDF_Document* pDoc, CPDF_PageRenderCache* pPageCache, + CPDF_Dictionary* pPageResources, FX_BOOL bFirstLayer) +{ + m_pBackgroundDraw = NULL; + m_pDocument = pDoc; + m_pPageResources = pPageResources; + m_pPageCache = pPageCache; + m_bFirstLayer = bFirstLayer; +} +void CPDF_RenderContext::Create(CPDF_Page* pPage, FX_BOOL bFirstLayer) +{ + m_pBackgroundDraw = NULL; + m_pDocument = pPage->m_pDocument; + m_pPageResources = pPage->m_pPageResources; + m_pPageCache = pPage->GetRenderCache(); + m_bFirstLayer = bFirstLayer; +} +CPDF_RenderContext::~CPDF_RenderContext() +{ +} +void CPDF_RenderContext::Clear() +{ + m_pDocument = NULL; + m_pPageResources = NULL; + m_pPageCache = NULL; + m_pBackgroundDraw = NULL; + m_bFirstLayer = TRUE; + m_ContentList.RemoveAll(); +} +void CPDF_RenderContext::AppendObjectList(CPDF_PageObjects* pObjs, const CFX_AffineMatrix* pObject2Device) +{ + _PDF_RenderItem* pItem = m_ContentList.AddSpace(); + pItem->m_pObjectList = pObjs; + if (pObject2Device) { + pItem->m_Matrix = *pObject2Device; + } else { + pItem->m_Matrix.SetIdentity(); + } +} +void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice, const CPDF_RenderOptions* pOptions, + const CFX_AffineMatrix* pLastMatrix) +{ + Render(pDevice, NULL, pOptions, pLastMatrix); +} +void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice, const CPDF_PageObject* pStopObj, + const CPDF_RenderOptions* pOptions, const CFX_AffineMatrix* pLastMatrix) +{ + int count = m_ContentList.GetSize(); + for (int j = 0; j < count; j ++) { + pDevice->SaveState(); + _PDF_RenderItem* pItem = m_ContentList.GetDataPtr(j); + if (pLastMatrix) { + CFX_AffineMatrix FinalMatrix = pItem->m_Matrix; + FinalMatrix.Concat(*pLastMatrix); + CPDF_RenderStatus status; + status.Initialize(0, this, pDevice, pLastMatrix, pStopObj, NULL, NULL, pOptions, + pItem->m_pObjectList->m_Transparency, FALSE, NULL); + status.RenderObjectList(pItem->m_pObjectList, &FinalMatrix); +#if !defined(_FPDFAPI_MINI_) + if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) { + m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize); + } +#endif + if (status.m_bStopped) { + pDevice->RestoreState(); + break; + } + } else { + CPDF_RenderStatus status; + status.Initialize(0, this, pDevice, NULL, pStopObj, NULL, NULL, pOptions, + pItem->m_pObjectList->m_Transparency, FALSE, NULL); + status.RenderObjectList(pItem->m_pObjectList, &pItem->m_Matrix); +#if !defined(_FPDFAPI_MINI_) + if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) { + m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize); + } +#endif + if (status.m_bStopped) { + pDevice->RestoreState(); + break; + } + } + pDevice->RestoreState(); + } +} +void CPDF_RenderContext::DrawObjectList(CFX_RenderDevice* pDevice, CPDF_PageObjects* pObjs, + const CFX_AffineMatrix* pObject2Device, const CPDF_RenderOptions* pOptions) +{ + AppendObjectList(pObjs, pObject2Device); + Render(pDevice, pOptions); +} +CPDF_ProgressiveRenderer::CPDF_ProgressiveRenderer() +{ + m_pRenderer = NULL; + m_pContext = NULL; + m_pDevice = NULL; + m_Status = Ready; +} +CPDF_ProgressiveRenderer::~CPDF_ProgressiveRenderer() +{ + Clear(); +} +void CPDF_ProgressiveRenderer::Clear() +{ + if (m_pRenderer) { + delete m_pRenderer; + m_pDevice->RestoreState(); + m_pRenderer = NULL; + } + m_Status = Ready; +} +void CPDF_ProgressiveRenderer::Start(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, + const CPDF_RenderOptions* pOptions, IFX_Pause* pPause, FX_BOOL bDropObjects) +{ + if (m_Status != Ready) { + m_Status = Failed; + return; + } + m_pContext = pContext; + m_pDevice = pDevice; + m_pOptions = pOptions; + m_bDropObjects = bDropObjects; + if (pContext == NULL || pDevice == NULL) { + m_Status = Failed; + return; + } + m_Status = ToBeContinued; + m_ObjectPos = NULL; + m_LayerIndex = 0; + m_ObjectIndex = 0; + m_PrevLastPos = NULL; + Continue(pPause); +} +#ifdef _FPDFAPI_MINI_ +#define RENDER_STEP_LIMIT 20 +#else +#define RENDER_STEP_LIMIT 100 +#endif +void CPDF_ProgressiveRenderer::Continue(IFX_Pause* pPause) +{ + if (m_Status != ToBeContinued) { + return; + } + FX_DWORD nLayers = m_pContext->m_ContentList.GetSize(); + for (; m_LayerIndex < nLayers; m_LayerIndex ++) { + _PDF_RenderItem* pItem = m_pContext->m_ContentList.GetDataPtr(m_LayerIndex); + FX_POSITION LastPos = pItem->m_pObjectList->GetLastObjectPosition(); + if (m_ObjectPos == NULL) { + if (LastPos == m_PrevLastPos) { + if (!pItem->m_pObjectList->IsParsed()) { + pItem->m_pObjectList->ContinueParse(pPause); + if (!pItem->m_pObjectList->IsParsed()) { + return; + } + LastPos = pItem->m_pObjectList->GetLastObjectPosition(); + } + } + if (LastPos == m_PrevLastPos) { + if (m_pRenderer) { + delete m_pRenderer; + m_pRenderer = NULL; + m_pDevice->RestoreState(); + m_ObjectPos = NULL; + m_PrevLastPos = NULL; + } + continue; + } + if (m_PrevLastPos) { + m_ObjectPos = m_PrevLastPos; + pItem->m_pObjectList->GetNextObject(m_ObjectPos); + } else { + m_ObjectPos = pItem->m_pObjectList->GetFirstObjectPosition(); + } + m_PrevLastPos = LastPos; + } + if (m_pRenderer == NULL) { + m_ObjectPos = pItem->m_pObjectList->GetFirstObjectPosition(); + m_ObjectIndex = 0; + m_pRenderer = FX_NEW CPDF_RenderStatus(); + m_pRenderer->Initialize(0, m_pContext, m_pDevice, NULL, NULL, NULL, NULL, + m_pOptions, pItem->m_pObjectList->m_Transparency, m_bDropObjects, NULL); + m_pDevice->SaveState(); + m_ClipRect = m_pDevice->GetClipBox(); + CFX_AffineMatrix device2object; + device2object.SetReverse(pItem->m_Matrix); + device2object.TransformRect(m_ClipRect); + } + int objs_to_go = CPDF_ModuleMgr::Get()->GetRenderModule()->GetConfig()->m_RenderStepLimit; + while (m_ObjectPos) { + CPDF_PageObject* pCurObj = pItem->m_pObjectList->GetObjectAt(m_ObjectPos); + if (pCurObj && pCurObj->m_Left <= m_ClipRect.right && pCurObj->m_Right >= m_ClipRect.left && + pCurObj->m_Bottom <= m_ClipRect.top && pCurObj->m_Top >= m_ClipRect.bottom) { + if (m_pRenderer->ContinueSingleObject(pCurObj, &pItem->m_Matrix, pPause)) { + return; + } +#if !defined(_FPDFAPI_MINI_) + if (pCurObj->m_Type == PDFPAGE_IMAGE && m_pRenderer->m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) { + m_pContext->GetPageCache()->CacheOptimization(m_pRenderer->m_Options.m_dwLimitCacheSize); + } +#endif + if (pCurObj->m_Type == PDFPAGE_FORM || pCurObj->m_Type == PDFPAGE_SHADING) { + objs_to_go = 0; + } else { + objs_to_go --; + } + } + m_ObjectIndex ++; + pItem->m_pObjectList->GetNextObject(m_ObjectPos); + if (objs_to_go == 0) { + if (pPause && pPause->NeedToPauseNow()) { + return; + } + objs_to_go = CPDF_ModuleMgr::Get()->GetRenderModule()->GetConfig()->m_RenderStepLimit; + } + } + if (!pItem->m_pObjectList->IsParsed()) { + return; + } + delete m_pRenderer; + m_pRenderer = NULL; + m_pDevice->RestoreState(); + m_ObjectPos = NULL; + m_PrevLastPos = NULL; + if (pPause && pPause->NeedToPauseNow()) { + m_LayerIndex++; + return; + } + } + m_Status = Done; +} +int CPDF_ProgressiveRenderer::EstimateProgress() +{ + if (!m_pContext) { + return 0; + } + FX_DWORD nLayers = m_pContext->m_ContentList.GetSize(); + int nTotal = 0, nRendered = 0; + for (FX_DWORD layer = 0; layer < nLayers; layer ++) { + _PDF_RenderItem* pItem = m_pContext->m_ContentList.GetDataPtr(layer); + int nObjs = pItem->m_pObjectList->CountObjects(); + if (layer == m_LayerIndex) { + nRendered += m_ObjectIndex; + } else if (layer < m_LayerIndex) { + nRendered += nObjs; + } + nTotal += nObjs; + } + if (nTotal == 0) { + return 0; + } + return 100 * nRendered / nTotal; +} +CPDF_TransferFunc* CPDF_DocRenderData::GetTransferFunc(CPDF_Object* pObj) +{ + if (pObj == NULL) { + return NULL; + } + CPDF_CountedObject<CPDF_TransferFunc*>* pTransferCounter; + if (!m_TransferFuncMap.Lookup(pObj, pTransferCounter)) { + CPDF_TransferFunc* pTransfer = NULL; + CPDF_Function* pFuncs[3] = {NULL, NULL, NULL}; + FX_BOOL bUniTransfer = TRUE; + int i; + FX_BOOL bIdentity = TRUE; + if (pObj->GetType() == PDFOBJ_ARRAY) { + bUniTransfer = FALSE; + CPDF_Array* pArray = (CPDF_Array*)pObj; + if (pArray->GetCount() < 3) { + return NULL; + } + for (FX_DWORD i = 0; i < 3; i ++) { + pFuncs[2 - i] = CPDF_Function::Load(pArray->GetElementValue(i)); + if (pFuncs[2 - i] == NULL) { + return NULL; + } + } + } else { + pFuncs[0] = CPDF_Function::Load(pObj); + if (pFuncs[0] == NULL) { + return NULL; + } + } + pTransfer = FX_NEW CPDF_TransferFunc; + pTransfer->m_pPDFDoc = m_pPDFDoc; + pTransferCounter = FX_NEW CPDF_CountedObject<CPDF_TransferFunc*>; + pTransferCounter->m_nCount = 1; + pTransferCounter->m_Obj = pTransfer; + m_TransferFuncMap.SetAt(pObj, pTransferCounter); + static const int kMaxOutputs = 16; + FX_FLOAT output[kMaxOutputs]; + FXSYS_memset32(output, 0, sizeof(output)); + FX_FLOAT input; + int noutput; + for (int v = 0; v < 256; v ++) { + input = (FX_FLOAT)v / 255.0f; + if (bUniTransfer) { + if (pFuncs[0] && pFuncs[0]->CountOutputs() <= kMaxOutputs) { + pFuncs[0]->Call(&input, 1, output, noutput); + } + int o = FXSYS_round(output[0] * 255); + if (o != v) { + bIdentity = FALSE; + } + for (i = 0; i < 3; i ++) { + pTransfer->m_Samples[i * 256 + v] = o; + } + } else + for (i = 0; i < 3; i ++) { + if (pFuncs[i] && pFuncs[i]->CountOutputs() <= kMaxOutputs) { + pFuncs[i]->Call(&input, 1, output, noutput); + int o = FXSYS_round(output[0] * 255); + if (o != v) { + bIdentity = FALSE; + } + pTransfer->m_Samples[i * 256 + v] = o; + } else { + pTransfer->m_Samples[i * 256 + v] = v; + } + } + } + for (i = 0; i < 3; i ++) + if (pFuncs[i]) { + delete pFuncs[i]; + } + pTransfer->m_bIdentity = bIdentity; + } + pTransferCounter->m_nCount++; + return pTransferCounter->m_Obj; +} +void CPDF_DocRenderData::ReleaseTransferFunc(CPDF_Object* pObj) +{ + CPDF_CountedObject<CPDF_TransferFunc*>* pTransferCounter; + if (!m_TransferFuncMap.Lookup(pObj, pTransferCounter)) { + return; + } + pTransferCounter->m_nCount--; +} +CPDF_RenderConfig::CPDF_RenderConfig() +{ + m_HalftoneLimit = 0; +#ifdef _FPDFAPI_MINI_ + m_RenderStepLimit = 20; +#else + m_RenderStepLimit = 100; +#endif +} +CPDF_RenderConfig::~CPDF_RenderConfig() +{ +} +CPDF_DeviceBuffer::CPDF_DeviceBuffer() +{ + m_pBitmap = NULL; + m_pDevice = NULL; + m_pContext = NULL; + m_pObject = NULL; +} +CPDF_DeviceBuffer::~CPDF_DeviceBuffer() +{ + if (m_pBitmap) { + delete m_pBitmap; + } +} +FX_BOOL CPDF_DeviceBuffer::Initialize(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, FX_RECT* pRect, + const CPDF_PageObject* pObj, int max_dpi) +{ + m_pDevice = pDevice; + m_pContext = pContext; + m_Rect = *pRect; + m_pObject = pObj; + m_Matrix.TranslateI(-pRect->left, -pRect->top); +#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ + int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE); + int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE); + if (horz_size && vert_size && max_dpi) { + int dpih = pDevice->GetDeviceCaps(FXDC_PIXEL_WIDTH) * 254 / (horz_size * 10); + int dpiv = pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10); + if (dpih > max_dpi) { + m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f); + } + if (dpiv > max_dpi) { + m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv); + } + } +#ifdef _FPDFAPI_MINI_ + m_Matrix.Scale(0.5f, 0.5f); +#endif +#endif + CFX_Matrix ctm = m_pDevice->GetCTM(); + FX_FLOAT fScaleX = FXSYS_fabs(ctm.a); + FX_FLOAT fScaleY = FXSYS_fabs(ctm.d); + m_Matrix.Concat(fScaleX, 0, 0, fScaleY, 0, 0); + CFX_FloatRect rect(*pRect); + m_Matrix.TransformRect(rect); + FX_RECT bitmap_rect = rect.GetOutterRect(); + m_pBitmap = FX_NEW CFX_DIBitmap; + m_pBitmap->Create(bitmap_rect.Width(), bitmap_rect.Height(), FXDIB_Argb); + return TRUE; +} +void CPDF_DeviceBuffer::OutputToDevice() +{ + if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) { + if (m_Matrix.a == 1.0f && m_Matrix.d == 1.0f) { + m_pDevice->SetDIBits(m_pBitmap, m_Rect.left, m_Rect.top); + } else { + m_pDevice->StretchDIBits(m_pBitmap, m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height()); + } + } else { +#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_) + CFX_DIBitmap buffer; + m_pDevice->CreateCompatibleBitmap(&buffer, m_pBitmap->GetWidth(), m_pBitmap->GetHeight()); + m_pContext->GetBackground(&buffer, m_pObject, NULL, &m_Matrix); + buffer.CompositeBitmap(0, 0, buffer.GetWidth(), buffer.GetHeight(), m_pBitmap, 0, 0); + m_pDevice->StretchDIBits(&buffer, m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height()); +#endif + } +} +CPDF_ScaledRenderBuffer::CPDF_ScaledRenderBuffer() +{ + m_pBitmapDevice = NULL; +} +CPDF_ScaledRenderBuffer::~CPDF_ScaledRenderBuffer() +{ + if (m_pBitmapDevice) { + delete m_pBitmapDevice; + } +} +#ifndef _FPDFAPI_MINI_ +#define _FPDFAPI_IMAGESIZE_LIMIT_ (30 * 1024 * 1024) +#else +#define _FPDFAPI_IMAGESIZE_LIMIT_ (10 * 1024 * 1024) +#endif +FX_BOOL CPDF_ScaledRenderBuffer::Initialize(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, FX_RECT* pRect, + const CPDF_PageObject* pObj, const CPDF_RenderOptions *pOptions, int max_dpi) +{ + FXSYS_assert(pRect != NULL); + m_pDevice = pDevice; + if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) { + return TRUE; + } + m_pContext = pContext; + m_Rect = *pRect; + m_pObject = pObj; + m_Matrix.TranslateI(-pRect->left, -pRect->top); + int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE); + int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE); + if (horz_size && vert_size && max_dpi) { + int dpih = pDevice->GetDeviceCaps(FXDC_PIXEL_WIDTH) * 254 / (horz_size * 10); + int dpiv = pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10); + if (dpih > max_dpi) { + m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f); + } + if (dpiv > max_dpi) { + m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv); + } + } + m_pBitmapDevice = FX_NEW CFX_FxgeDevice; + FXDIB_Format dibFormat = FXDIB_Rgb; + FX_INT32 bpp = 24; + if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_ALPHA_OUTPUT) { + dibFormat = FXDIB_Argb; + bpp = 32; + } + CFX_FloatRect rect; + FX_INT32 iWidth, iHeight, iPitch; + while (1) { + rect = *pRect; + m_Matrix.TransformRect(rect); + FX_RECT bitmap_rect = rect.GetOutterRect(); + iWidth = bitmap_rect.Width(); + iHeight = bitmap_rect.Height(); + iPitch = (iWidth * bpp + 31) / 32 * 4; + if (iWidth * iHeight < 1) { + return FALSE; + } + if (iPitch * iHeight <= _FPDFAPI_IMAGESIZE_LIMIT_ && + m_pBitmapDevice->Create(iWidth, iHeight, dibFormat)) { + break; + } + m_Matrix.Scale(0.5f, 0.5f); + } +#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_) + m_pContext->GetBackground(m_pBitmapDevice->GetBitmap(), m_pObject, pOptions, &m_Matrix); +#endif + return TRUE; +} +void CPDF_ScaledRenderBuffer::OutputToDevice() +{ + if (m_pBitmapDevice) { + m_pDevice->StretchDIBits(m_pBitmapDevice->GetBitmap(), m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height()); + } +} +FX_BOOL IPDF_OCContext::CheckObjectVisible(const CPDF_PageObject* pObj) +{ + const CPDF_ContentMarkData* pData = pObj->m_ContentMark; + int nItems = pData->CountItems(); + for (int i = 0; i < nItems; i ++) { + CPDF_ContentMarkItem& item = pData->GetItem(i); + if (item.GetName() == FX_BSTRC("OC") && item.GetParamType() == CPDF_ContentMarkItem::PropertiesDict) { + CPDF_Dictionary* pOCG = (CPDF_Dictionary*)item.GetParam(); + if (!CheckOCGVisible(pOCG)) { + return FALSE; + } + } + } + return TRUE; +} diff --git a/core/src/fpdfapi/fpdf_render/fpdf_render_cache.cpp b/core/src/fpdfapi/fpdf_render/fpdf_render_cache.cpp index c5be3391b8..eb08bca8a7 100644 --- a/core/src/fpdfapi/fpdf_render/fpdf_render_cache.cpp +++ b/core/src/fpdfapi/fpdf_render/fpdf_render_cache.cpp @@ -1,389 +1,389 @@ -// 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/fpdfapi/fpdf_render.h"
-#include "../../../include/fpdfapi/fpdf_pageobj.h"
-#include "../../../include/fxge/fx_ge.h"
-#include "../fpdf_page/pageint.h"
-#include "render_int.h"
-struct CACHEINFO {
- FX_DWORD time;
- CPDF_Stream* pStream;
-};
-extern "C" {
- static int compare(const void* data1, const void* data2)
- {
- return ((CACHEINFO*)data1)->time - ((CACHEINFO*)data2)->time;
- }
-};
-void CPDF_Page::ClearRenderCache()
-{
- if (m_pPageRender) {
- m_pPageRender->ClearAll();
- }
-}
-void CPDF_PageRenderCache::ClearAll()
-{
- FX_POSITION pos = m_ImageCaches.GetStartPosition();
- while (pos) {
- FX_LPVOID key, value;
- m_ImageCaches.GetNextAssoc(pos, key, value);
- delete (CPDF_ImageCache*)value;
- }
- m_ImageCaches.RemoveAll();
- m_nCacheSize = 0;
- m_nTimeCount = 0;
-}
-void CPDF_PageRenderCache::CacheOptimization(FX_INT32 dwLimitCacheSize)
-{
- if (m_nCacheSize <= (FX_DWORD)dwLimitCacheSize) {
- return;
- }
- int nCount = m_ImageCaches.GetCount();
- CACHEINFO* pCACHEINFO = (CACHEINFO*)FX_Alloc(FX_BYTE, (sizeof (CACHEINFO)) * nCount);
- FX_POSITION pos = m_ImageCaches.GetStartPosition();
- int i = 0;
- while (pos) {
- FX_LPVOID key, value;
- m_ImageCaches.GetNextAssoc(pos, key, value);
- pCACHEINFO[i].time = ((CPDF_ImageCache*)value)->GetTimeCount();
- pCACHEINFO[i++].pStream = ((CPDF_ImageCache*)value)->GetStream();
- }
- FXSYS_qsort(pCACHEINFO, nCount, sizeof (CACHEINFO), compare);
- FX_DWORD nTimeCount = m_nTimeCount;
- if (nTimeCount + 1 < nTimeCount) {
- for (i = 0; i < nCount; i ++) {
- ((CPDF_ImageCache*)(m_ImageCaches[pCACHEINFO[i].pStream]))->m_dwTimeCount = i;
- }
- m_nTimeCount = nCount;
- }
- i = 0;
- while(nCount > 15) {
- ClearImageCache(pCACHEINFO[i++].pStream);
- nCount--;
- }
- while (m_nCacheSize > (FX_DWORD)dwLimitCacheSize) {
- ClearImageCache(pCACHEINFO[i++].pStream);
- }
- FX_Free(pCACHEINFO);
-}
-void CPDF_PageRenderCache::ClearImageCache(CPDF_Stream* pStream)
-{
- FX_LPVOID value = m_ImageCaches.GetValueAt(pStream);
- if (value == NULL) {
- m_ImageCaches.RemoveKey(pStream);
- return;
- }
- m_nCacheSize -= ((CPDF_ImageCache*)value)->EstimateSize();
- delete (CPDF_ImageCache*)value;
- m_ImageCaches.RemoveKey(pStream);
-}
-FX_DWORD CPDF_PageRenderCache::EstimateSize()
-{
- FX_DWORD dwSize = 0;
- FX_POSITION pos = m_ImageCaches.GetStartPosition();
- while (pos) {
- FX_LPVOID key, value;
- m_ImageCaches.GetNextAssoc(pos, key, value);
- dwSize += ((CPDF_ImageCache*)value)->EstimateSize();
- }
- m_nCacheSize = dwSize;
- return dwSize;
-}
-FX_DWORD CPDF_PageRenderCache::GetCachedSize(CPDF_Stream* pStream) const
-{
- if (pStream == NULL) {
- return m_nCacheSize;
- }
- CPDF_ImageCache* pImageCache;
- if (!m_ImageCaches.Lookup(pStream, (FX_LPVOID&)pImageCache)) {
- return 0;
- }
- return pImageCache->EstimateSize();
-}
-void CPDF_PageRenderCache::GetCachedBitmap(CPDF_Stream* pStream, CFX_DIBSource*& pBitmap, CFX_DIBSource*& pMask, FX_DWORD& MatteColor,
- FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus,
- FX_INT32 downsampleWidth, FX_INT32 downsampleHeight)
-{
- CPDF_ImageCache* pImageCache;
- FX_BOOL bFind = m_ImageCaches.Lookup(pStream, (FX_LPVOID&)pImageCache);
- if (!bFind) {
- pImageCache = FX_NEW CPDF_ImageCache(m_pPage->m_pDocument, pStream);
- }
- m_nTimeCount ++;
- FX_BOOL bCached = pImageCache->GetCachedBitmap(pBitmap, pMask, MatteColor, m_pPage->m_pPageResources, bStdCS, GroupFamily, bLoadMask, pRenderStatus, downsampleWidth, downsampleHeight);
- if (!bFind) {
- m_ImageCaches.SetAt(pStream, pImageCache);
- }
- if (!bCached) {
- m_nCacheSize += pImageCache->EstimateSize();
- }
-}
-FX_BOOL CPDF_PageRenderCache::StartGetCachedBitmap(CPDF_Stream* pStream, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus, FX_INT32 downsampleWidth, FX_INT32 downsampleHeight)
-{
- m_bCurFindCache = m_ImageCaches.Lookup(pStream, (FX_LPVOID&)m_pCurImageCache);
- if (!m_bCurFindCache) {
- m_pCurImageCache = FX_NEW CPDF_ImageCache(m_pPage->m_pDocument, pStream);
- }
- int ret = m_pCurImageCache->StartGetCachedBitmap(pRenderStatus->m_pFormResource, m_pPage->m_pPageResources, bStdCS, GroupFamily, bLoadMask, pRenderStatus, downsampleWidth, downsampleHeight);
- if (ret == 2) {
- return TRUE;
- }
- m_nTimeCount ++;
- if (!m_bCurFindCache) {
- m_ImageCaches.SetAt(pStream, m_pCurImageCache);
- }
- if (!ret) {
- m_nCacheSize += m_pCurImageCache->EstimateSize();
- }
- return FALSE;
-}
-FX_BOOL CPDF_PageRenderCache::Continue(IFX_Pause* pPause)
-{
- int ret = m_pCurImageCache->Continue(pPause);
- if (ret == 2) {
- return TRUE;
- }
- m_nTimeCount ++;
- if (!m_bCurFindCache) {
- m_ImageCaches.SetAt(m_pCurImageCache->GetStream(), m_pCurImageCache);
- }
- if (!ret) {
- m_nCacheSize += m_pCurImageCache->EstimateSize();
- }
- return FALSE;
-}
-void CPDF_PageRenderCache::ResetBitmap(CPDF_Stream* pStream, const CFX_DIBitmap* pBitmap)
-{
- CPDF_ImageCache* pImageCache;
- if (!m_ImageCaches.Lookup(pStream, (FX_LPVOID&)pImageCache)) {
- if (pBitmap == NULL) {
- return;
- }
- pImageCache = FX_NEW CPDF_ImageCache(m_pPage->m_pDocument, pStream);
- m_ImageCaches.SetAt(pStream, pImageCache);
- }
- int oldsize = pImageCache->EstimateSize();
- pImageCache->Reset(pBitmap);
- m_nCacheSize = pImageCache->EstimateSize() - oldsize;
-}
-CPDF_ImageCache::CPDF_ImageCache(CPDF_Document* pDoc, CPDF_Stream* pStream)
- : m_pDocument(pDoc)
- , m_pStream(pStream)
- , m_pCachedBitmap(NULL)
- , m_pCachedMask(NULL)
- , m_dwCacheSize(0)
- , m_dwTimeCount(0)
- , m_pCurBitmap(NULL)
- , m_pCurMask(NULL)
- , m_MatteColor(0)
- , m_pRenderStatus(NULL)
-{
-}
-CPDF_ImageCache::~CPDF_ImageCache()
-{
- if (m_pCachedBitmap) {
- delete m_pCachedBitmap;
- m_pCachedBitmap = NULL;
- }
- if (m_pCachedMask) {
- delete m_pCachedMask;
- m_pCachedMask = NULL;
- }
-}
-void CPDF_ImageCache::Reset(const CFX_DIBitmap* pBitmap)
-{
- if (m_pCachedBitmap) {
- delete m_pCachedBitmap;
- }
- m_pCachedBitmap = NULL;
- if (pBitmap) {
- m_pCachedBitmap = pBitmap->Clone();
- }
- CalcSize();
-}
-void CPDF_PageRenderCache::ClearImageData()
-{
- FX_POSITION pos = m_ImageCaches.GetStartPosition();
- while (pos) {
- FX_LPVOID key, value;
- m_ImageCaches.GetNextAssoc(pos, key, value);
- ((CPDF_ImageCache*)value)->ClearImageData();
- }
-}
-void CPDF_ImageCache::ClearImageData()
-{
- if (m_pCachedBitmap && m_pCachedBitmap->GetBuffer() == NULL) {
- ((CPDF_DIBSource*)m_pCachedBitmap)->ClearImageData();
- }
-}
-static FX_DWORD FPDF_ImageCache_EstimateImageSize(const CFX_DIBSource* pDIB)
-{
- return pDIB && pDIB->GetBuffer() ? (FX_DWORD)pDIB->GetHeight() * pDIB->GetPitch() + (FX_DWORD)pDIB->GetPaletteSize() * 4 : 0;
-}
-FX_BOOL CPDF_ImageCache::GetCachedBitmap(CFX_DIBSource*& pBitmap, CFX_DIBSource*& pMask, FX_DWORD& MatteColor, CPDF_Dictionary* pPageResources,
- FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus,
- FX_INT32 downsampleWidth, FX_INT32 downsampleHeight)
-{
- if (m_pCachedBitmap) {
- pBitmap = m_pCachedBitmap;
- pMask = m_pCachedMask;
- MatteColor = m_MatteColor;
- return TRUE;
- }
- if (!pRenderStatus) {
- return FALSE;
- }
- CPDF_RenderContext*pContext = pRenderStatus->GetContext();
- CPDF_PageRenderCache* pPageRenderCache = pContext->m_pPageCache;
- m_dwTimeCount = pPageRenderCache->GetTimeCount();
- CPDF_DIBSource* pSrc = FX_NEW CPDF_DIBSource;
- CPDF_DIBSource* pMaskSrc = NULL;
- if (!pSrc->Load(m_pDocument, m_pStream, &pMaskSrc, &MatteColor, pRenderStatus->m_pFormResource, pPageResources, bStdCS, GroupFamily, bLoadMask)) {
- delete pSrc;
- pBitmap = NULL;
- return FALSE;
- }
- m_MatteColor = MatteColor;
-#if !defined(_FPDFAPI_MINI_)
- if (pSrc->GetPitch() * pSrc->GetHeight() < FPDF_HUGE_IMAGE_SIZE) {
- m_pCachedBitmap = pSrc->Clone();
- delete pSrc;
- } else {
- m_pCachedBitmap = pSrc;
- }
- if (pMaskSrc) {
- m_pCachedMask = pMaskSrc->Clone();
- delete pMaskSrc;
- }
-#else
- if (pSrc->GetFormat() == FXDIB_8bppRgb && pSrc->GetPalette() &&
- pSrc->GetHeight() * pSrc->GetWidth() * 3 < 1024) {
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
- m_pCachedBitmap = pSrc->CloneConvert(FXDIB_Rgb32);
-#else
- m_pCachedBitmap = pSrc->CloneConvert(FXDIB_Rgb);
-#endif
- delete pSrc;
- } else if (pSrc->GetPitch() * pSrc->GetHeight() < 102400) {
- m_pCachedBitmap = pSrc->Clone();
- delete pSrc;
- } else {
- m_pCachedBitmap = pSrc;
- }
- m_pCachedMask = pMaskSrc;
-#endif
- pBitmap = m_pCachedBitmap;
- pMask = m_pCachedMask;
- CalcSize();
- return FALSE;
-}
-CFX_DIBSource* CPDF_ImageCache::DetachBitmap()
-{
- CFX_DIBSource* pDIBSource = m_pCurBitmap;
- m_pCurBitmap = NULL;
- return pDIBSource;
-}
-CFX_DIBSource* CPDF_ImageCache::DetachMask()
-{
- CFX_DIBSource* pDIBSource = m_pCurMask;
- m_pCurMask = NULL;
- return pDIBSource;
-}
-int CPDF_ImageCache::StartGetCachedBitmap(CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources, FX_BOOL bStdCS,
- FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus,
- FX_INT32 downsampleWidth, FX_INT32 downsampleHeight)
-{
- if (m_pCachedBitmap) {
- m_pCurBitmap = m_pCachedBitmap;
- m_pCurMask = m_pCachedMask;
- return 1;
- }
- if (!pRenderStatus) {
- return 0;
- }
- m_pRenderStatus = pRenderStatus;
- m_pCurBitmap = FX_NEW CPDF_DIBSource;
- int ret = ((CPDF_DIBSource*)m_pCurBitmap)->StartLoadDIBSource(m_pDocument, m_pStream, TRUE, pFormResources, pPageResources, bStdCS, GroupFamily, bLoadMask);
- if (ret == 2) {
- return ret;
- }
- if (!ret) {
- delete m_pCurBitmap;
- m_pCurBitmap = NULL;
- return 0;
- }
- ContinueGetCachedBitmap();
- return 0;
-}
-int CPDF_ImageCache::ContinueGetCachedBitmap()
-{
- m_MatteColor = ((CPDF_DIBSource*)m_pCurBitmap)->m_MatteColor;
- m_pCurMask = ((CPDF_DIBSource*)m_pCurBitmap)->DetachMask();
- CPDF_RenderContext*pContext = m_pRenderStatus->GetContext();
- CPDF_PageRenderCache* pPageRenderCache = pContext->m_pPageCache;
- m_dwTimeCount = pPageRenderCache->GetTimeCount();
-#if !defined(_FPDFAPI_MINI_)
- if (m_pCurBitmap->GetPitch() * m_pCurBitmap->GetHeight() < FPDF_HUGE_IMAGE_SIZE) {
- m_pCachedBitmap = m_pCurBitmap->Clone();
- delete m_pCurBitmap;
- m_pCurBitmap = NULL;
- } else {
- m_pCachedBitmap = m_pCurBitmap;
- }
- if (m_pCurMask) {
- m_pCachedMask = m_pCurMask->Clone();
- delete m_pCurMask;
- m_pCurMask = NULL;
- }
-#else
- if (m_pCurBitmap->GetFormat() == FXDIB_8bppRgb && m_pCurBitmap->GetPalette() &&
- m_pCurBitmap->GetHeight() * m_pCurBitmap->GetWidth() * 3 < 1024) {
- m_pCachedBitmap = m_pCurBitmap->CloneConvert(FXDIB_Rgb32);
- m_pCachedBitmap = m_pCurBitmap->CloneConvert(FXDIB_Rgb);
- delete m_pCurBitmap;
- m_pCurBitmap = NULL;
- } else if (m_pCurBitmap->GetPitch() * m_pCurBitmap->GetHeight() < 102400) {
- m_pCachedBitmap = m_pCurBitmap->Clone();
- delete m_pCurBitmap;
- m_pCurBitmap = NULL;
- } else {
- m_pCachedBitmap = m_pCurBitmap;
- }
- m_pCachedMask = m_pCurMask;
-#endif
- m_pCurBitmap = m_pCachedBitmap;
- m_pCurMask = m_pCachedMask;
- CalcSize();
- return 0;
-}
-int CPDF_ImageCache::Continue(IFX_Pause* pPause)
-{
- int ret = ((CPDF_DIBSource*)m_pCurBitmap)->ContinueLoadDIBSource(pPause);
- if (ret == 2) {
- return ret;
- }
- if (!ret) {
- delete m_pCurBitmap;
- m_pCurBitmap = NULL;
- return 0;
- }
- ContinueGetCachedBitmap();
- return 0;
-}
-void CPDF_ImageCache::CalcSize()
-{
- m_dwCacheSize = FPDF_ImageCache_EstimateImageSize(m_pCachedBitmap) + FPDF_ImageCache_EstimateImageSize(m_pCachedMask);
-}
-void CPDF_Document::ClearRenderFont()
-{
- if (m_pDocRender) {
- CFX_FontCache* pCache = m_pDocRender->GetFontCache();
- if (pCache) {
- pCache->FreeCache(FALSE);
- }
- }
-}
+// 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/fpdfapi/fpdf_render.h" +#include "../../../include/fpdfapi/fpdf_pageobj.h" +#include "../../../include/fxge/fx_ge.h" +#include "../fpdf_page/pageint.h" +#include "render_int.h" +struct CACHEINFO { + FX_DWORD time; + CPDF_Stream* pStream; +}; +extern "C" { + static int compare(const void* data1, const void* data2) + { + return ((CACHEINFO*)data1)->time - ((CACHEINFO*)data2)->time; + } +}; +void CPDF_Page::ClearRenderCache() +{ + if (m_pPageRender) { + m_pPageRender->ClearAll(); + } +} +void CPDF_PageRenderCache::ClearAll() +{ + FX_POSITION pos = m_ImageCaches.GetStartPosition(); + while (pos) { + FX_LPVOID key, value; + m_ImageCaches.GetNextAssoc(pos, key, value); + delete (CPDF_ImageCache*)value; + } + m_ImageCaches.RemoveAll(); + m_nCacheSize = 0; + m_nTimeCount = 0; +} +void CPDF_PageRenderCache::CacheOptimization(FX_INT32 dwLimitCacheSize) +{ + if (m_nCacheSize <= (FX_DWORD)dwLimitCacheSize) { + return; + } + int nCount = m_ImageCaches.GetCount(); + CACHEINFO* pCACHEINFO = (CACHEINFO*)FX_Alloc(FX_BYTE, (sizeof (CACHEINFO)) * nCount); + FX_POSITION pos = m_ImageCaches.GetStartPosition(); + int i = 0; + while (pos) { + FX_LPVOID key, value; + m_ImageCaches.GetNextAssoc(pos, key, value); + pCACHEINFO[i].time = ((CPDF_ImageCache*)value)->GetTimeCount(); + pCACHEINFO[i++].pStream = ((CPDF_ImageCache*)value)->GetStream(); + } + FXSYS_qsort(pCACHEINFO, nCount, sizeof (CACHEINFO), compare); + FX_DWORD nTimeCount = m_nTimeCount; + if (nTimeCount + 1 < nTimeCount) { + for (i = 0; i < nCount; i ++) { + ((CPDF_ImageCache*)(m_ImageCaches[pCACHEINFO[i].pStream]))->m_dwTimeCount = i; + } + m_nTimeCount = nCount; + } + i = 0; + while(nCount > 15) { + ClearImageCache(pCACHEINFO[i++].pStream); + nCount--; + } + while (m_nCacheSize > (FX_DWORD)dwLimitCacheSize) { + ClearImageCache(pCACHEINFO[i++].pStream); + } + FX_Free(pCACHEINFO); +} +void CPDF_PageRenderCache::ClearImageCache(CPDF_Stream* pStream) +{ + FX_LPVOID value = m_ImageCaches.GetValueAt(pStream); + if (value == NULL) { + m_ImageCaches.RemoveKey(pStream); + return; + } + m_nCacheSize -= ((CPDF_ImageCache*)value)->EstimateSize(); + delete (CPDF_ImageCache*)value; + m_ImageCaches.RemoveKey(pStream); +} +FX_DWORD CPDF_PageRenderCache::EstimateSize() +{ + FX_DWORD dwSize = 0; + FX_POSITION pos = m_ImageCaches.GetStartPosition(); + while (pos) { + FX_LPVOID key, value; + m_ImageCaches.GetNextAssoc(pos, key, value); + dwSize += ((CPDF_ImageCache*)value)->EstimateSize(); + } + m_nCacheSize = dwSize; + return dwSize; +} +FX_DWORD CPDF_PageRenderCache::GetCachedSize(CPDF_Stream* pStream) const +{ + if (pStream == NULL) { + return m_nCacheSize; + } + CPDF_ImageCache* pImageCache; + if (!m_ImageCaches.Lookup(pStream, (FX_LPVOID&)pImageCache)) { + return 0; + } + return pImageCache->EstimateSize(); +} +void CPDF_PageRenderCache::GetCachedBitmap(CPDF_Stream* pStream, CFX_DIBSource*& pBitmap, CFX_DIBSource*& pMask, FX_DWORD& MatteColor, + FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus, + FX_INT32 downsampleWidth, FX_INT32 downsampleHeight) +{ + CPDF_ImageCache* pImageCache; + FX_BOOL bFind = m_ImageCaches.Lookup(pStream, (FX_LPVOID&)pImageCache); + if (!bFind) { + pImageCache = FX_NEW CPDF_ImageCache(m_pPage->m_pDocument, pStream); + } + m_nTimeCount ++; + FX_BOOL bCached = pImageCache->GetCachedBitmap(pBitmap, pMask, MatteColor, m_pPage->m_pPageResources, bStdCS, GroupFamily, bLoadMask, pRenderStatus, downsampleWidth, downsampleHeight); + if (!bFind) { + m_ImageCaches.SetAt(pStream, pImageCache); + } + if (!bCached) { + m_nCacheSize += pImageCache->EstimateSize(); + } +} +FX_BOOL CPDF_PageRenderCache::StartGetCachedBitmap(CPDF_Stream* pStream, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus, FX_INT32 downsampleWidth, FX_INT32 downsampleHeight) +{ + m_bCurFindCache = m_ImageCaches.Lookup(pStream, (FX_LPVOID&)m_pCurImageCache); + if (!m_bCurFindCache) { + m_pCurImageCache = FX_NEW CPDF_ImageCache(m_pPage->m_pDocument, pStream); + } + int ret = m_pCurImageCache->StartGetCachedBitmap(pRenderStatus->m_pFormResource, m_pPage->m_pPageResources, bStdCS, GroupFamily, bLoadMask, pRenderStatus, downsampleWidth, downsampleHeight); + if (ret == 2) { + return TRUE; + } + m_nTimeCount ++; + if (!m_bCurFindCache) { + m_ImageCaches.SetAt(pStream, m_pCurImageCache); + } + if (!ret) { + m_nCacheSize += m_pCurImageCache->EstimateSize(); + } + return FALSE; +} +FX_BOOL CPDF_PageRenderCache::Continue(IFX_Pause* pPause) +{ + int ret = m_pCurImageCache->Continue(pPause); + if (ret == 2) { + return TRUE; + } + m_nTimeCount ++; + if (!m_bCurFindCache) { + m_ImageCaches.SetAt(m_pCurImageCache->GetStream(), m_pCurImageCache); + } + if (!ret) { + m_nCacheSize += m_pCurImageCache->EstimateSize(); + } + return FALSE; +} +void CPDF_PageRenderCache::ResetBitmap(CPDF_Stream* pStream, const CFX_DIBitmap* pBitmap) +{ + CPDF_ImageCache* pImageCache; + if (!m_ImageCaches.Lookup(pStream, (FX_LPVOID&)pImageCache)) { + if (pBitmap == NULL) { + return; + } + pImageCache = FX_NEW CPDF_ImageCache(m_pPage->m_pDocument, pStream); + m_ImageCaches.SetAt(pStream, pImageCache); + } + int oldsize = pImageCache->EstimateSize(); + pImageCache->Reset(pBitmap); + m_nCacheSize = pImageCache->EstimateSize() - oldsize; +} +CPDF_ImageCache::CPDF_ImageCache(CPDF_Document* pDoc, CPDF_Stream* pStream) + : m_pDocument(pDoc) + , m_pStream(pStream) + , m_pCachedBitmap(NULL) + , m_pCachedMask(NULL) + , m_dwCacheSize(0) + , m_dwTimeCount(0) + , m_pCurBitmap(NULL) + , m_pCurMask(NULL) + , m_MatteColor(0) + , m_pRenderStatus(NULL) +{ +} +CPDF_ImageCache::~CPDF_ImageCache() +{ + if (m_pCachedBitmap) { + delete m_pCachedBitmap; + m_pCachedBitmap = NULL; + } + if (m_pCachedMask) { + delete m_pCachedMask; + m_pCachedMask = NULL; + } +} +void CPDF_ImageCache::Reset(const CFX_DIBitmap* pBitmap) +{ + if (m_pCachedBitmap) { + delete m_pCachedBitmap; + } + m_pCachedBitmap = NULL; + if (pBitmap) { + m_pCachedBitmap = pBitmap->Clone(); + } + CalcSize(); +} +void CPDF_PageRenderCache::ClearImageData() +{ + FX_POSITION pos = m_ImageCaches.GetStartPosition(); + while (pos) { + FX_LPVOID key, value; + m_ImageCaches.GetNextAssoc(pos, key, value); + ((CPDF_ImageCache*)value)->ClearImageData(); + } +} +void CPDF_ImageCache::ClearImageData() +{ + if (m_pCachedBitmap && m_pCachedBitmap->GetBuffer() == NULL) { + ((CPDF_DIBSource*)m_pCachedBitmap)->ClearImageData(); + } +} +static FX_DWORD FPDF_ImageCache_EstimateImageSize(const CFX_DIBSource* pDIB) +{ + return pDIB && pDIB->GetBuffer() ? (FX_DWORD)pDIB->GetHeight() * pDIB->GetPitch() + (FX_DWORD)pDIB->GetPaletteSize() * 4 : 0; +} +FX_BOOL CPDF_ImageCache::GetCachedBitmap(CFX_DIBSource*& pBitmap, CFX_DIBSource*& pMask, FX_DWORD& MatteColor, CPDF_Dictionary* pPageResources, + FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus, + FX_INT32 downsampleWidth, FX_INT32 downsampleHeight) +{ + if (m_pCachedBitmap) { + pBitmap = m_pCachedBitmap; + pMask = m_pCachedMask; + MatteColor = m_MatteColor; + return TRUE; + } + if (!pRenderStatus) { + return FALSE; + } + CPDF_RenderContext*pContext = pRenderStatus->GetContext(); + CPDF_PageRenderCache* pPageRenderCache = pContext->m_pPageCache; + m_dwTimeCount = pPageRenderCache->GetTimeCount(); + CPDF_DIBSource* pSrc = FX_NEW CPDF_DIBSource; + CPDF_DIBSource* pMaskSrc = NULL; + if (!pSrc->Load(m_pDocument, m_pStream, &pMaskSrc, &MatteColor, pRenderStatus->m_pFormResource, pPageResources, bStdCS, GroupFamily, bLoadMask)) { + delete pSrc; + pBitmap = NULL; + return FALSE; + } + m_MatteColor = MatteColor; +#if !defined(_FPDFAPI_MINI_) + if (pSrc->GetPitch() * pSrc->GetHeight() < FPDF_HUGE_IMAGE_SIZE) { + m_pCachedBitmap = pSrc->Clone(); + delete pSrc; + } else { + m_pCachedBitmap = pSrc; + } + if (pMaskSrc) { + m_pCachedMask = pMaskSrc->Clone(); + delete pMaskSrc; + } +#else + if (pSrc->GetFormat() == FXDIB_8bppRgb && pSrc->GetPalette() && + pSrc->GetHeight() * pSrc->GetWidth() * 3 < 1024) { +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + m_pCachedBitmap = pSrc->CloneConvert(FXDIB_Rgb32); +#else + m_pCachedBitmap = pSrc->CloneConvert(FXDIB_Rgb); +#endif + delete pSrc; + } else if (pSrc->GetPitch() * pSrc->GetHeight() < 102400) { + m_pCachedBitmap = pSrc->Clone(); + delete pSrc; + } else { + m_pCachedBitmap = pSrc; + } + m_pCachedMask = pMaskSrc; +#endif + pBitmap = m_pCachedBitmap; + pMask = m_pCachedMask; + CalcSize(); + return FALSE; +} +CFX_DIBSource* CPDF_ImageCache::DetachBitmap() +{ + CFX_DIBSource* pDIBSource = m_pCurBitmap; + m_pCurBitmap = NULL; + return pDIBSource; +} +CFX_DIBSource* CPDF_ImageCache::DetachMask() +{ + CFX_DIBSource* pDIBSource = m_pCurMask; + m_pCurMask = NULL; + return pDIBSource; +} +int CPDF_ImageCache::StartGetCachedBitmap(CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources, FX_BOOL bStdCS, + FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus, + FX_INT32 downsampleWidth, FX_INT32 downsampleHeight) +{ + if (m_pCachedBitmap) { + m_pCurBitmap = m_pCachedBitmap; + m_pCurMask = m_pCachedMask; + return 1; + } + if (!pRenderStatus) { + return 0; + } + m_pRenderStatus = pRenderStatus; + m_pCurBitmap = FX_NEW CPDF_DIBSource; + int ret = ((CPDF_DIBSource*)m_pCurBitmap)->StartLoadDIBSource(m_pDocument, m_pStream, TRUE, pFormResources, pPageResources, bStdCS, GroupFamily, bLoadMask); + if (ret == 2) { + return ret; + } + if (!ret) { + delete m_pCurBitmap; + m_pCurBitmap = NULL; + return 0; + } + ContinueGetCachedBitmap(); + return 0; +} +int CPDF_ImageCache::ContinueGetCachedBitmap() +{ + m_MatteColor = ((CPDF_DIBSource*)m_pCurBitmap)->m_MatteColor; + m_pCurMask = ((CPDF_DIBSource*)m_pCurBitmap)->DetachMask(); + CPDF_RenderContext*pContext = m_pRenderStatus->GetContext(); + CPDF_PageRenderCache* pPageRenderCache = pContext->m_pPageCache; + m_dwTimeCount = pPageRenderCache->GetTimeCount(); +#if !defined(_FPDFAPI_MINI_) + if (m_pCurBitmap->GetPitch() * m_pCurBitmap->GetHeight() < FPDF_HUGE_IMAGE_SIZE) { + m_pCachedBitmap = m_pCurBitmap->Clone(); + delete m_pCurBitmap; + m_pCurBitmap = NULL; + } else { + m_pCachedBitmap = m_pCurBitmap; + } + if (m_pCurMask) { + m_pCachedMask = m_pCurMask->Clone(); + delete m_pCurMask; + m_pCurMask = NULL; + } +#else + if (m_pCurBitmap->GetFormat() == FXDIB_8bppRgb && m_pCurBitmap->GetPalette() && + m_pCurBitmap->GetHeight() * m_pCurBitmap->GetWidth() * 3 < 1024) { + m_pCachedBitmap = m_pCurBitmap->CloneConvert(FXDIB_Rgb32); + m_pCachedBitmap = m_pCurBitmap->CloneConvert(FXDIB_Rgb); + delete m_pCurBitmap; + m_pCurBitmap = NULL; + } else if (m_pCurBitmap->GetPitch() * m_pCurBitmap->GetHeight() < 102400) { + m_pCachedBitmap = m_pCurBitmap->Clone(); + delete m_pCurBitmap; + m_pCurBitmap = NULL; + } else { + m_pCachedBitmap = m_pCurBitmap; + } + m_pCachedMask = m_pCurMask; +#endif + m_pCurBitmap = m_pCachedBitmap; + m_pCurMask = m_pCachedMask; + CalcSize(); + return 0; +} +int CPDF_ImageCache::Continue(IFX_Pause* pPause) +{ + int ret = ((CPDF_DIBSource*)m_pCurBitmap)->ContinueLoadDIBSource(pPause); + if (ret == 2) { + return ret; + } + if (!ret) { + delete m_pCurBitmap; + m_pCurBitmap = NULL; + return 0; + } + ContinueGetCachedBitmap(); + return 0; +} +void CPDF_ImageCache::CalcSize() +{ + m_dwCacheSize = FPDF_ImageCache_EstimateImageSize(m_pCachedBitmap) + FPDF_ImageCache_EstimateImageSize(m_pCachedMask); +} +void CPDF_Document::ClearRenderFont() +{ + if (m_pDocRender) { + CFX_FontCache* pCache = m_pDocRender->GetFontCache(); + if (pCache) { + pCache->FreeCache(FALSE); + } + } +} diff --git a/core/src/fpdfapi/fpdf_render/fpdf_render_image.cpp b/core/src/fpdfapi/fpdf_render/fpdf_render_image.cpp index c2a7393739..39241e10f4 100644 --- a/core/src/fpdfapi/fpdf_render/fpdf_render_image.cpp +++ b/core/src/fpdfapi/fpdf_render/fpdf_render_image.cpp @@ -1,1165 +1,1165 @@ -// 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;
-}
+// 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; +} diff --git a/core/src/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp b/core/src/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp index fcb5271cc3..e67b46c931 100644 --- a/core/src/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp +++ b/core/src/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp @@ -1,1524 +1,1524 @@ -// 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"
-#include <limits.h>
-static unsigned int _GetBits8(FX_LPCBYTE pData, int bitpos, int nbits)
-{
- unsigned int byte = pData[bitpos / 8];
- if (nbits == 8) {
- return byte;
- } else if (nbits == 4) {
- return (bitpos % 8) ? (byte & 0x0f) : (byte >> 4);
- } else if (nbits == 2) {
- return (byte >> (6 - bitpos % 8)) & 0x03;
- } else if (nbits == 1) {
- return (byte >> (7 - bitpos % 8)) & 0x01;
- } else if (nbits == 16) {
- return byte * 256 + pData[bitpos / 8 + 1];
- }
- return 0;
-}
-CFX_DIBSource* CPDF_Image::LoadDIBSource(CFX_DIBSource** ppMask, FX_DWORD* pMatteColor, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask) const
-{
- CPDF_DIBSource* pSource = FX_NEW CPDF_DIBSource;
- if (pSource->Load(m_pDocument, m_pStream, (CPDF_DIBSource**)ppMask, pMatteColor, NULL, NULL, bStdCS, GroupFamily, bLoadMask)) {
- return pSource;
- }
- delete pSource;
- return NULL;
-}
-CFX_DIBSource* CPDF_Image::DetachBitmap()
-{
- CFX_DIBSource* pBitmap = m_pDIBSource;
- m_pDIBSource = NULL;
- return pBitmap;
-}
-CFX_DIBSource* CPDF_Image::DetachMask()
-{
- CFX_DIBSource* pBitmap = m_pMask;
- m_pMask = NULL;
- return pBitmap;
-}
-FX_BOOL CPDF_Image::StartLoadDIBSource(CPDF_Dictionary* pFormResource, CPDF_Dictionary* pPageResource, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask)
-{
- m_pDIBSource = FX_NEW CPDF_DIBSource;
- int ret = ((CPDF_DIBSource*)m_pDIBSource)->StartLoadDIBSource(m_pDocument, m_pStream, TRUE, pFormResource, pPageResource, bStdCS, GroupFamily, bLoadMask);
- if (ret == 2) {
- return TRUE;
- }
- if (!ret) {
- delete m_pDIBSource;
- m_pDIBSource = NULL;
- return FALSE;
- }
- m_pMask = ((CPDF_DIBSource*)m_pDIBSource)->DetachMask();
- m_MatteColor = ((CPDF_DIBSource*)m_pDIBSource)->m_MatteColor;
- return FALSE;
-}
-FX_BOOL CPDF_Image::Continue(IFX_Pause* pPause)
-{
- int ret = ((CPDF_DIBSource*)m_pDIBSource)->ContinueLoadDIBSource(pPause);
- if (ret == 2) {
- return TRUE;
- }
- if (!ret) {
- delete m_pDIBSource;
- m_pDIBSource = NULL;
- return FALSE;
- }
- m_pMask = ((CPDF_DIBSource*)m_pDIBSource)->DetachMask();
- m_MatteColor = ((CPDF_DIBSource*)m_pDIBSource)->m_MatteColor;
- return FALSE;
-}
-CPDF_DIBSource::CPDF_DIBSource()
-{
- m_pDocument = NULL;
- m_pStreamAcc = NULL;
- m_pDict = NULL;
- m_bpp = 0;
- m_Width = m_Height = 0;
- m_pColorSpace = NULL;
- m_bDefaultDecode = TRUE;
- m_bImageMask = FALSE;
- m_pPalette = NULL;
- m_pCompData = NULL;
- m_bColorKey = FALSE;
- m_pMaskedLine = m_pLineBuf = NULL;
- m_pCachedBitmap = NULL;
- m_pDecoder = NULL;
- m_nComponents = 0;
- m_bpc = 0;
- m_bLoadMask = FALSE;
- m_Family = 0;
- m_pMask = NULL;
- m_MatteColor = 0;
- m_pJbig2Context = NULL;
- m_pGlobalStream = NULL;
- m_bStdCS = FALSE;
- m_pMaskStream = NULL;
- m_Status = 0;
- m_bHasMask = FALSE;
-}
-CPDF_DIBSource::~CPDF_DIBSource()
-{
- if (m_pStreamAcc) {
- delete m_pStreamAcc;
- }
- if (m_pMaskedLine) {
- FX_Free(m_pMaskedLine);
- }
- if (m_pLineBuf) {
- FX_Free(m_pLineBuf);
- }
- if (m_pCachedBitmap) {
- delete m_pCachedBitmap;
- }
- if (m_pDecoder) {
- delete m_pDecoder;
- }
- if (m_pCompData) {
- FX_Free(m_pCompData);
- }
- CPDF_ColorSpace* pCS = m_pColorSpace;
- if (pCS && m_pDocument) {
- m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
- }
- if (m_pJbig2Context) {
- ICodec_Jbig2Module* pJbig2Moudle = CPDF_ModuleMgr::Get()->GetJbig2Module();
- pJbig2Moudle->DestroyJbig2Context(m_pJbig2Context);
- m_pJbig2Context = NULL;
- }
- if (m_pGlobalStream) {
- delete m_pGlobalStream;
- }
- m_pGlobalStream = NULL;
-}
-CFX_DIBitmap* CPDF_DIBSource::GetBitmap() const
-{
- if (m_pCachedBitmap) {
- return m_pCachedBitmap;
- }
- return Clone();
-}
-void CPDF_DIBSource::ReleaseBitmap(CFX_DIBitmap* pBitmap) const
-{
- if (pBitmap && pBitmap != m_pCachedBitmap) {
- delete pBitmap;
- }
-}
-FX_BOOL CPDF_DIBSource::Load(CPDF_Document* pDoc, const CPDF_Stream* pStream, CPDF_DIBSource** ppMask,
- FX_DWORD* pMatteColor, CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask)
-{
- if (pStream == NULL) {
- return FALSE;
- }
- m_pDocument = pDoc;
- m_pDict = pStream->GetDict();
- m_pStream = pStream;
- m_Width = m_pDict->GetInteger(FX_BSTRC("Width"));
- m_Height = m_pDict->GetInteger(FX_BSTRC("Height"));
- if (m_Width <= 0 || m_Height <= 0 || m_Width > 0x01ffff || m_Height > 0x01ffff) {
- return FALSE;
- }
- m_GroupFamily = GroupFamily;
- m_bLoadMask = bLoadMask;
- if (!LoadColorInfo(m_pStream->GetObjNum() != 0 ? NULL : pFormResources, pPageResources)) {
- return FALSE;
- }
- FX_DWORD src_pitch = m_bpc;
- if (m_bpc != 0 && m_nComponents != 0) {
- if (src_pitch > 0 && m_nComponents > (unsigned)INT_MAX / src_pitch) {
- return FALSE;
- }
- src_pitch *= m_nComponents;
- if (src_pitch > 0 && (FX_DWORD)m_Width > (unsigned)INT_MAX / src_pitch) {
- return FALSE;
- }
- src_pitch *= m_Width;
- if (src_pitch + 7 < src_pitch) {
- return FALSE;
- }
- src_pitch += 7;
- src_pitch /= 8;
- if (src_pitch > 0 && (FX_DWORD)m_Height > (unsigned)INT_MAX / src_pitch) {
- return FALSE;
- }
- }
- m_pStreamAcc = FX_NEW CPDF_StreamAcc;
- m_pStreamAcc->LoadAllData(pStream, FALSE, m_Height * src_pitch, TRUE);
- if (m_pStreamAcc->GetSize() == 0 || m_pStreamAcc->GetData() == NULL) {
- return FALSE;
- }
- const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder();
- if (!decoder.IsEmpty() && decoder == FX_BSTRC("CCITTFaxDecode")) {
- m_bpc = 1;
- }
- if (!CreateDecoder()) {
- return FALSE;
- }
- if (m_bImageMask) {
- m_bpp = 1;
- m_bpc = 1;
- m_nComponents = 1;
- m_AlphaFlag = 1;
- } else if (m_bpc * m_nComponents == 1) {
- m_bpp = 1;
- } else if (m_bpc * m_nComponents <= 8) {
- m_bpp = 8;
- } else {
- m_bpp = 24;
- }
- if (!m_bpc || !m_nComponents) {
- return FALSE;
- }
- m_Pitch = m_Width;
- if ((FX_DWORD)m_bpp > (unsigned)INT_MAX / m_Pitch) {
- return FALSE;
- }
- m_Pitch *= m_bpp;
- if (m_Pitch + 31 < m_Pitch) {
- return FALSE;
- }
- m_Pitch += 31;
- m_Pitch = m_Pitch / 32 * 4;
- m_pLineBuf = FX_Alloc(FX_BYTE, m_Pitch);
- if (m_pColorSpace && bStdCS) {
- m_pColorSpace->EnableStdConversion(TRUE);
- }
- LoadPalette();
- if (m_bColorKey) {
- m_bpp = 32;
- m_AlphaFlag = 2;
- m_Pitch = m_Width;
- if ((FX_DWORD)m_bpp > (unsigned)INT_MAX / m_Pitch) {
- return FALSE;
- }
- m_Pitch *= m_bpp;
- if (m_Pitch + 31 < m_Pitch) {
- return FALSE;
- }
- m_Pitch += 31;
- m_Pitch = m_Pitch / 32 * 4;
- m_pMaskedLine = FX_Alloc(FX_BYTE, m_Pitch);
- }
- if (ppMask) {
- *ppMask = LoadMask(*pMatteColor);
- }
- if (m_pColorSpace && bStdCS) {
- m_pColorSpace->EnableStdConversion(FALSE);
- }
- return TRUE;
-}
-int CPDF_DIBSource::ContinueToLoadMask()
-{
- if (m_bImageMask) {
- m_bpp = 1;
- m_bpc = 1;
- m_nComponents = 1;
- m_AlphaFlag = 1;
- } else if (m_bpc * m_nComponents == 1) {
- m_bpp = 1;
- } else if (m_bpc * m_nComponents <= 8) {
- m_bpp = 8;
- } else {
- m_bpp = 24;
- }
- if (!m_bpc || !m_nComponents) {
- return 0;
- }
- m_Pitch = m_Width;
- if ((FX_DWORD)m_bpp > (unsigned)INT_MAX / m_Pitch) {
- return 0;
- }
- m_Pitch *= m_bpp;
- if (m_Pitch + 31 < m_Pitch) {
- return 0;
- }
- m_Pitch += 31;
- m_Pitch = m_Pitch / 32 * 4;
- m_pLineBuf = FX_Alloc(FX_BYTE, m_Pitch);
- if (m_pColorSpace && m_bStdCS) {
- m_pColorSpace->EnableStdConversion(TRUE);
- }
- LoadPalette();
- if (m_bColorKey) {
- m_bpp = 32;
- m_AlphaFlag = 2;
- m_Pitch = m_Width;
- if ((FX_DWORD)m_bpp > (unsigned)INT_MAX / m_Pitch) {
- return 0;
- }
- m_Pitch *= m_bpp;
- if (m_Pitch + 31 < m_Pitch) {
- return 0;
- }
- m_Pitch += 31;
- m_Pitch = m_Pitch / 32 * 4;
- m_pMaskedLine = FX_Alloc(FX_BYTE, m_Pitch);
- }
- return 1;
-}
-int CPDF_DIBSource::StartLoadDIBSource(CPDF_Document* pDoc, const CPDF_Stream* pStream, FX_BOOL bHasMask,
- CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources,
- FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask)
-{
- if (pStream == NULL) {
- return 0;
- }
- m_pDocument = pDoc;
- m_pDict = pStream->GetDict();
- m_pStream = pStream;
- m_bStdCS = bStdCS;
- m_bHasMask = bHasMask;
- m_Width = m_pDict->GetInteger(FX_BSTRC("Width"));
- m_Height = m_pDict->GetInteger(FX_BSTRC("Height"));
- if (m_Width <= 0 || m_Height <= 0 || m_Width > 0x01ffff || m_Height > 0x01ffff) {
- return 0;
- }
- m_GroupFamily = GroupFamily;
- m_bLoadMask = bLoadMask;
- if (!LoadColorInfo(m_pStream->GetObjNum() != 0 ? NULL : pFormResources, pPageResources)) {
- return 0;
- }
- FX_DWORD src_pitch = m_bpc;
- if (m_bpc != 0 && m_nComponents != 0) {
- if (src_pitch > 0 && m_nComponents > (unsigned)INT_MAX / src_pitch) {
- return 0;
- }
- src_pitch *= m_nComponents;
- if (src_pitch > 0 && (FX_DWORD)m_Width > (unsigned)INT_MAX / src_pitch) {
- return 0;
- }
- src_pitch *= m_Width;
- if (src_pitch + 7 < src_pitch) {
- return 0;
- }
- src_pitch += 7;
- src_pitch /= 8;
- if (src_pitch > 0 && (FX_DWORD)m_Height > (unsigned)INT_MAX / src_pitch) {
- return 0;
- }
- }
- m_pStreamAcc = FX_NEW CPDF_StreamAcc;
- m_pStreamAcc->LoadAllData(pStream, FALSE, m_Height * src_pitch, TRUE);
- if (m_pStreamAcc->GetSize() == 0 || m_pStreamAcc->GetData() == NULL) {
- return 0;
- }
- const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder();
- if (!decoder.IsEmpty() && decoder == FX_BSTRC("CCITTFaxDecode")) {
- m_bpc = 1;
- }
- int ret = CreateDecoder();
- if (ret != 1) {
- if (!ret) {
- return ret;
- }
- if (!ContinueToLoadMask()) {
- return 0;
- }
- if (m_bHasMask) {
- StratLoadMask();
- }
- return ret;
- }
- if (!ContinueToLoadMask()) {
- return 0;
- }
- if (m_bHasMask) {
- ret = StratLoadMask();
- }
- if (ret == 2) {
- return ret;
- }
- if (m_pColorSpace && m_bStdCS) {
- m_pColorSpace->EnableStdConversion(FALSE);
- }
- return ret;
-}
-int CPDF_DIBSource::ContinueLoadDIBSource(IFX_Pause* pPause)
-{
- FXCODEC_STATUS ret;
- if (m_Status == 1) {
- const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder();
- if (decoder == FX_BSTRC("JPXDecode")) {
- return 0;
- }
- ICodec_Jbig2Module* pJbig2Moudle = CPDF_ModuleMgr::Get()->GetJbig2Module();
- if (m_pJbig2Context == NULL) {
- m_pJbig2Context = pJbig2Moudle->CreateJbig2Context();
- if (m_pStreamAcc->GetImageParam()) {
- CPDF_Stream* pGlobals = m_pStreamAcc->GetImageParam()->GetStream(FX_BSTRC("JBIG2Globals"));
- if (pGlobals) {
- m_pGlobalStream = FX_NEW CPDF_StreamAcc;
- m_pGlobalStream->LoadAllData(pGlobals, FALSE);
- }
- }
- ret = pJbig2Moudle->StartDecode(m_pJbig2Context, m_Width, m_Height, m_pStreamAcc->GetData(), m_pStreamAcc->GetSize(),
- m_pGlobalStream ? m_pGlobalStream->GetData() : NULL, m_pGlobalStream ? m_pGlobalStream->GetSize() : 0, m_pCachedBitmap->GetBuffer(),
- m_pCachedBitmap->GetPitch(), pPause);
- if (ret < 0) {
- delete m_pCachedBitmap;
- m_pCachedBitmap = NULL;
- if (m_pGlobalStream) {
- delete m_pGlobalStream;
- }
- m_pGlobalStream = NULL;
- pJbig2Moudle->DestroyJbig2Context(m_pJbig2Context);
- m_pJbig2Context = NULL;
- return 0;
- }
- if (ret == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
- return 2;
- }
- int ret1 = 1;
- if (m_bHasMask) {
- ret1 = ContinueLoadMaskDIB(pPause);
- m_Status = 2;
- }
- if (ret1 == 2) {
- return ret1;
- }
- if (m_pColorSpace && m_bStdCS) {
- m_pColorSpace->EnableStdConversion(FALSE);
- }
- return ret1;
- }
- FXCODEC_STATUS ret = pJbig2Moudle->ContinueDecode(m_pJbig2Context, pPause);
- if (ret < 0) {
- delete m_pCachedBitmap;
- m_pCachedBitmap = NULL;
- if (m_pGlobalStream) {
- delete m_pGlobalStream;
- }
- m_pGlobalStream = NULL;
- pJbig2Moudle->DestroyJbig2Context(m_pJbig2Context);
- m_pJbig2Context = NULL;
- return 0;
- }
- if (ret == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
- return 2;
- }
- int ret1 = 1;
- if (m_bHasMask) {
- ret1 = ContinueLoadMaskDIB(pPause);
- m_Status = 2;
- }
- if (ret1 == 2) {
- return ret1;
- }
- if (m_pColorSpace && m_bStdCS) {
- m_pColorSpace->EnableStdConversion(FALSE);
- }
- return ret1;
- } else if (m_Status == 2) {
- return ContinueLoadMaskDIB(pPause);
- }
- return 0;
-}
-FX_BOOL CPDF_DIBSource::LoadColorInfo(CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources)
-{
- if (m_pDict->GetInteger("ImageMask")) {
- m_bImageMask = TRUE;
- }
- if (m_bImageMask || !m_pDict->KeyExist(FX_BSTRC("ColorSpace"))) {
- if (!m_bImageMask) {
- CPDF_Object* pFilter = m_pDict->GetElementValue(FX_BSTRC("Filter"));
- if (pFilter) {
- CFX_ByteString filter;
- if (pFilter->GetType() == PDFOBJ_NAME) {
- filter = pFilter->GetString();
- if (filter == FX_BSTRC("JPXDecode")) {
- return TRUE;
- }
- } else if (pFilter->GetType() == PDFOBJ_ARRAY) {
- CPDF_Array* pArray = (CPDF_Array*)pFilter;
- if (pArray->GetString(pArray->GetCount() - 1) == FX_BSTRC("JPXDecode")) {
- return TRUE;
- }
- }
- }
- }
- m_bImageMask = TRUE;
- m_bpc = m_nComponents = 1;
- CPDF_Array* pDecode = m_pDict->GetArray(FX_BSTRC("Decode"));
- m_bDefaultDecode = pDecode == NULL || pDecode->GetInteger(0) == 0;
- return TRUE;
- }
- CPDF_Object* pCSObj = m_pDict->GetElementValue(FX_BSTRC("ColorSpace"));
- if (pCSObj == NULL) {
- return FALSE;
- }
- CPDF_DocPageData* pDocPageData = m_pDocument->GetPageData();
- if (pFormResources) {
- m_pColorSpace = pDocPageData->GetColorSpace(pCSObj, pFormResources);
- }
- if (m_pColorSpace == NULL) {
- m_pColorSpace = pDocPageData->GetColorSpace(pCSObj, pPageResources);
- }
- if (m_pColorSpace == NULL) {
- return FALSE;
- }
- m_bpc = m_pDict->GetInteger(FX_BSTRC("BitsPerComponent"));
- m_Family = m_pColorSpace->GetFamily();
- m_nComponents = m_pColorSpace->CountComponents();
- if (m_Family == PDFCS_ICCBASED && pCSObj->GetType() == PDFOBJ_NAME) {
- CFX_ByteString cs = pCSObj->GetString();
- if (cs == FX_BSTRC("DeviceGray")) {
- m_nComponents = 1;
- } else if (cs == FX_BSTRC("DeviceRGB")) {
- m_nComponents = 3;
- } else if (cs == FX_BSTRC("DeviceCMYK")) {
- m_nComponents = 4;
- }
- }
- m_pCompData = FX_Alloc(DIB_COMP_DATA, m_nComponents);
- if (m_bpc == 0) {
- return TRUE;
- }
- int max_data = (1 << m_bpc) - 1;
- CPDF_Array* pDecode = m_pDict->GetArray(FX_BSTRC("Decode"));
- if (pDecode) {
- for (FX_DWORD i = 0; i < m_nComponents; i ++) {
- m_pCompData[i].m_DecodeMin = pDecode->GetNumber(i * 2);
- FX_FLOAT max = pDecode->GetNumber(i * 2 + 1);
- m_pCompData[i].m_DecodeStep = (max - m_pCompData[i].m_DecodeMin) / max_data;
- FX_FLOAT def_value, def_min, def_max;
- m_pColorSpace->GetDefaultValue(i, def_value, def_min, def_max);
- if (m_Family == PDFCS_INDEXED) {
- def_max = (FX_FLOAT)max_data;
- }
- if (def_min != m_pCompData[i].m_DecodeMin || def_max != max) {
- m_bDefaultDecode = FALSE;
- }
- }
- } else {
- for (FX_DWORD i = 0; i < m_nComponents; i ++) {
- FX_FLOAT def_value;
- m_pColorSpace->GetDefaultValue(i, def_value, m_pCompData[i].m_DecodeMin, m_pCompData[i].m_DecodeStep);
- if (m_Family == PDFCS_INDEXED) {
- m_pCompData[i].m_DecodeStep = (FX_FLOAT)max_data;
- }
- m_pCompData[i].m_DecodeStep = (m_pCompData[i].m_DecodeStep - m_pCompData[i].m_DecodeMin) / max_data;
- }
- }
- if (!m_pDict->KeyExist(FX_BSTRC("SMask"))) {
- CPDF_Object* pMask = m_pDict->GetElementValue(FX_BSTRC("Mask"));
- if (pMask == NULL) {
- return TRUE;
- }
- if (pMask->GetType() == PDFOBJ_ARRAY) {
- CPDF_Array* pArray = (CPDF_Array*)pMask;
- if (pArray->GetCount() >= m_nComponents * 2)
- for (FX_DWORD i = 0; i < m_nComponents * 2; i ++) {
- if (i % 2) {
- m_pCompData[i / 2].m_ColorKeyMax = pArray->GetInteger(i);
- } else {
- m_pCompData[i / 2].m_ColorKeyMin = pArray->GetInteger(i);
- }
- }
- m_bColorKey = TRUE;
- }
- }
- return TRUE;
-}
-ICodec_ScanlineDecoder* FPDFAPI_CreateFaxDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
- const CPDF_Dictionary* pParams);
-ICodec_ScanlineDecoder* FPDFAPI_CreateFlateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
- int nComps, int bpc, const CPDF_Dictionary* pParams);
-int CPDF_DIBSource::CreateDecoder()
-{
- const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder();
- if (decoder.IsEmpty()) {
- return 1;
- }
- FX_LPCBYTE src_data = m_pStreamAcc->GetData();
- FX_DWORD src_size = m_pStreamAcc->GetSize();
- const CPDF_Dictionary* pParams = m_pStreamAcc->GetImageParam();
- if (decoder == FX_BSTRC("CCITTFaxDecode")) {
- m_pDecoder = FPDFAPI_CreateFaxDecoder(src_data, src_size, m_Width, m_Height, pParams);
- } else if (decoder == FX_BSTRC("DCTDecode")) {
- m_pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder(src_data, src_size, m_Width, m_Height,
- m_nComponents, pParams ? pParams->GetInteger(FX_BSTR("ColorTransform"), 1) : 1);
- if (NULL == m_pDecoder) {
- FX_BOOL bTransform = FALSE;
- int comps, bpc;
- ICodec_JpegModule* pJpegModule = CPDF_ModuleMgr::Get()->GetJpegModule();
- if (pJpegModule->LoadInfo(src_data, src_size, m_Width, m_Height, comps, bpc, bTransform)) {
- m_nComponents = comps;
- m_bpc = bpc;
- m_pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder(src_data, src_size, m_Width, m_Height,
- m_nComponents, bTransform);
- }
- }
- } else if (decoder == FX_BSTRC("FlateDecode")) {
- m_pDecoder = FPDFAPI_CreateFlateDecoder(src_data, src_size, m_Width, m_Height, m_nComponents, m_bpc, pParams);
- } else if (decoder == FX_BSTRC("JPXDecode")) {
- LoadJpxBitmap();
- return m_pCachedBitmap != NULL ? 1 : 0;
- } else if (decoder == FX_BSTRC("JBIG2Decode")) {
- m_pCachedBitmap = FX_NEW CFX_DIBitmap;
- if (!m_pCachedBitmap->Create(m_Width, m_Height, m_bImageMask ? FXDIB_1bppMask : FXDIB_1bppRgb)) {
- delete m_pCachedBitmap;
- m_pCachedBitmap = NULL;
- return 0;
- }
- m_Status = 1;
- return 2;
- } else if (decoder == FX_BSTRC("RunLengthDecode")) {
- m_pDecoder = CPDF_ModuleMgr::Get()->GetCodecModule()->GetBasicModule()->CreateRunLengthDecoder(src_data, src_size, m_Width, m_Height, m_nComponents, m_bpc);
- }
- if (m_pDecoder) {
- int requested_pitch = (m_Width * m_nComponents * m_bpc + 7) / 8;
- int provided_pitch = (m_pDecoder->GetWidth() * m_pDecoder->CountComps() * m_pDecoder->GetBPC() + 7) / 8;
- if (provided_pitch < requested_pitch) {
- return 0;
- }
- return 1;
- }
- return 0;
-}
-void CPDF_DIBSource::LoadJpxBitmap()
-{
- ICodec_JpxModule* pJpxModule = CPDF_ModuleMgr::Get()->GetJpxModule();
- if (pJpxModule == NULL) {
- return;
- }
- FX_LPVOID ctx = pJpxModule->CreateDecoder(m_pStreamAcc->GetData(), m_pStreamAcc->GetSize(), m_pColorSpace != NULL);
- if (ctx == NULL) {
- return;
- }
- FX_DWORD width = 0, height = 0, codestream_nComps = 0, image_nComps = 0;
- pJpxModule->GetImageInfo(ctx, width, height, codestream_nComps, image_nComps);
- if ((int)width < m_Width || (int)height < m_Height) {
- pJpxModule->DestroyDecoder(ctx);
- return;
- }
- int output_nComps;
- FX_BOOL bTranslateColor, bSwapRGB = FALSE;
- if (m_pColorSpace) {
- if (codestream_nComps != (FX_DWORD)m_pColorSpace->CountComponents()) {
- return;
- }
- output_nComps = codestream_nComps;
- bTranslateColor = FALSE;
- if (m_pColorSpace == CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB)) {
- bSwapRGB = TRUE;
- m_pColorSpace = NULL;
- }
- } else {
- bTranslateColor = TRUE;
- if (image_nComps) {
- output_nComps = image_nComps;
- } else {
- output_nComps = codestream_nComps;
- }
- if (output_nComps == 3) {
- bSwapRGB = TRUE;
- } else if (output_nComps == 4) {
- m_pColorSpace = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK);
- bTranslateColor = FALSE;
- }
- m_nComponents = output_nComps;
- }
- FXDIB_Format format;
- if (output_nComps == 1) {
- format = FXDIB_8bppRgb;
- } else if (output_nComps <= 3) {
- format = FXDIB_Rgb;
- } else if (output_nComps == 4) {
- format = FXDIB_Rgb32;
- } else {
- width = (width * output_nComps + 2) / 3;
- format = FXDIB_Rgb;
- }
- m_pCachedBitmap = FX_NEW CFX_DIBitmap;
- if (!m_pCachedBitmap->Create(width, height, format)) {
- delete m_pCachedBitmap;
- m_pCachedBitmap = NULL;
- return;
- }
- m_pCachedBitmap->Clear(0xFFFFFFFF);
- FX_LPBYTE output_offsets = FX_Alloc(FX_BYTE, output_nComps);
- for (int i = 0; i < output_nComps; i ++) {
- output_offsets[i] = i;
- }
- if (bSwapRGB) {
- output_offsets[0] = 2;
- output_offsets[2] = 0;
- }
- if (!pJpxModule->Decode(ctx, m_pCachedBitmap->GetBuffer(), m_pCachedBitmap->GetPitch(), bTranslateColor, output_offsets)) {
- delete m_pCachedBitmap;
- m_pCachedBitmap = NULL;
- return;
- }
- FX_Free(output_offsets);
- pJpxModule->DestroyDecoder(ctx);
- if (m_pColorSpace && m_pColorSpace->GetFamily() == PDFCS_INDEXED && m_bpc < 8) {
- int scale = 8 - m_bpc;
- for (FX_DWORD row = 0; row < height; row ++) {
- FX_LPBYTE scanline = (FX_LPBYTE)m_pCachedBitmap->GetScanline(row);
- for (FX_DWORD col = 0; col < width; col ++) {
- *scanline = (*scanline) >> scale;
- scanline++;
- }
- }
- }
- m_bpc = 8;
-}
-void CPDF_DIBSource::LoadJbig2Bitmap()
-{
- ICodec_Jbig2Module* pJbig2Module = CPDF_ModuleMgr::Get()->GetJbig2Module();
- if (pJbig2Module == NULL) {
- return;
- }
- CPDF_StreamAcc* pGlobalStream = NULL;
- if (m_pStreamAcc->GetImageParam()) {
- CPDF_Stream* pGlobals = m_pStreamAcc->GetImageParam()->GetStream(FX_BSTRC("JBIG2Globals"));
- if (pGlobals) {
- pGlobalStream = FX_NEW CPDF_StreamAcc;
- pGlobalStream->LoadAllData(pGlobals, FALSE);
- }
- }
- m_pCachedBitmap = FX_NEW CFX_DIBitmap;
- if (!m_pCachedBitmap->Create(m_Width, m_Height, m_bImageMask ? FXDIB_1bppMask : FXDIB_1bppRgb)) {
- return;
- }
- int ret = pJbig2Module->Decode(m_Width, m_Height, m_pStreamAcc->GetData(), m_pStreamAcc->GetSize(),
- pGlobalStream ? pGlobalStream->GetData() : NULL, pGlobalStream ? pGlobalStream->GetSize() : 0,
- m_pCachedBitmap->GetBuffer(), m_pCachedBitmap->GetPitch());
- if (ret < 0) {
- delete m_pCachedBitmap;
- m_pCachedBitmap = NULL;
- }
- if (pGlobalStream) {
- delete pGlobalStream;
- }
- m_bpc = 1;
- m_nComponents = 1;
-}
-CPDF_DIBSource* CPDF_DIBSource::LoadMask(FX_DWORD& MatteColor)
-{
- MatteColor = 0xffffffff;
- CPDF_Stream* pSoftMask = m_pDict->GetStream(FX_BSTRC("SMask"));
- if (pSoftMask) {
- CPDF_Array* pMatte = pSoftMask->GetDict()->GetArray(FX_BSTRC("Matte"));
- if (pMatte != NULL && m_pColorSpace && (FX_DWORD)m_pColorSpace->CountComponents() <= m_nComponents) {
- FX_FLOAT* pColor = FX_Alloc(FX_FLOAT, m_nComponents);
- for (FX_DWORD i = 0; i < m_nComponents; i ++) {
- pColor[i] = pMatte->GetFloat(i);
- }
- FX_FLOAT R, G, B;
- m_pColorSpace->GetRGB(pColor, R, G, B);
- FX_Free(pColor);
- MatteColor = FXARGB_MAKE(0, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255));
- }
- return LoadMaskDIB(pSoftMask);
- }
- CPDF_Object* pMask = m_pDict->GetElementValue(FX_BSTRC("Mask"));
- if (pMask == NULL) {
- return NULL;
- }
- if (pMask->GetType() == PDFOBJ_STREAM) {
- return LoadMaskDIB((CPDF_Stream*)pMask);
- }
- return NULL;
-}
-int CPDF_DIBSource::StratLoadMask()
-{
- m_MatteColor = 0xffffffff;
- m_pMaskStream = m_pDict->GetStream(FX_BSTRC("SMask"));
- if (m_pMaskStream) {
- CPDF_Array* pMatte = m_pMaskStream->GetDict()->GetArray(FX_BSTRC("Matte"));
- if (pMatte != NULL && m_pColorSpace && (FX_DWORD)m_pColorSpace->CountComponents() <= m_nComponents) {
- FX_FLOAT R, G, B;
- FX_FLOAT* pColor = FX_Alloc(FX_FLOAT, m_nComponents);
- for (FX_DWORD i = 0; i < m_nComponents; i ++) {
- pColor[i] = pMatte->GetFloat(i);
- }
- m_pColorSpace->GetRGB(pColor, R, G, B);
- FX_Free(pColor);
- m_MatteColor = FXARGB_MAKE(0, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255));
- }
- return StartLoadMaskDIB();
- }
- m_pMaskStream = m_pDict->GetElementValue(FX_BSTRC("Mask"));
- if (m_pMaskStream == NULL) {
- return 1;
- }
- if (m_pMaskStream->GetType() == PDFOBJ_STREAM) {
- return StartLoadMaskDIB();
- }
- return 1;
-}
-int CPDF_DIBSource::ContinueLoadMaskDIB(IFX_Pause* pPause)
-{
- if (m_pMask == NULL) {
- return 1;
- }
- int ret = m_pMask->ContinueLoadDIBSource(pPause);
- if (ret == 2) {
- return ret;
- }
- if (m_pColorSpace && m_bStdCS) {
- m_pColorSpace->EnableStdConversion(FALSE);
- }
- if (!ret) {
- delete m_pMask;
- m_pMask = NULL;
- return ret;
- }
- return 1;
-}
-CPDF_DIBSource* CPDF_DIBSource::DetachMask()
-{
- CPDF_DIBSource* pDIBSource = m_pMask;
- m_pMask = NULL;
- return pDIBSource;
-}
-CPDF_DIBSource* CPDF_DIBSource::LoadMaskDIB(CPDF_Stream* pMask)
-{
- CPDF_DIBSource* pMaskSource = FX_NEW CPDF_DIBSource;
- if (!pMaskSource->Load(m_pDocument, pMask, NULL, NULL, NULL, NULL, TRUE)) {
- delete pMaskSource;
- return NULL;
- }
- return pMaskSource;
-}
-int CPDF_DIBSource::StartLoadMaskDIB()
-{
- m_pMask = FX_NEW CPDF_DIBSource;
- int ret = m_pMask->StartLoadDIBSource(m_pDocument, (CPDF_Stream*)m_pMaskStream, FALSE, NULL, NULL, TRUE);
- if (ret == 2) {
- if (m_Status == 0) {
- m_Status = 2;
- }
- return 2;
- }
- if (!ret) {
- delete m_pMask;
- m_pMask = NULL;
- return 1;
- }
- return 1;
-}
-void CPDF_DIBSource::LoadPalette()
-{
- if (m_bpc * m_nComponents > 8) {
- return;
- }
- if (m_pColorSpace == NULL) {
- return;
- }
- if (m_bpc * m_nComponents == 1) {
- if (m_bDefaultDecode && (m_Family == PDFCS_DEVICEGRAY || m_Family == PDFCS_DEVICERGB)) {
- return;
- }
- if (m_pColorSpace->CountComponents() > 3) {
- return;
- }
- FX_FLOAT color_values[3];
- color_values[0] = m_pCompData[0].m_DecodeMin;
- color_values[1] = color_values[2] = color_values[0];
- FX_FLOAT R, G, B;
- m_pColorSpace->GetRGB(color_values, R, G, B);
- FX_ARGB argb0 = ArgbEncode(255, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255));
- color_values[0] += m_pCompData[0].m_DecodeStep;
- color_values[1] += m_pCompData[0].m_DecodeStep;
- color_values[2] += m_pCompData[0].m_DecodeStep;
- m_pColorSpace->GetRGB(color_values, R, G, B);
- FX_ARGB argb1 = ArgbEncode(255, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255));
- if (argb0 != 0xFF000000 || argb1 != 0xFFFFFFFF) {
- SetPaletteArgb(0, argb0);
- SetPaletteArgb(1, argb1);
- }
- return;
- }
- if (m_pColorSpace == CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY) && m_bpc == 8 && m_bDefaultDecode) {
- } else {
- int palette_count = 1 << (m_bpc * m_nComponents);
- CFX_FixedBufGrow<FX_FLOAT, 16> color_values(m_nComponents);
- FX_FLOAT* color_value = color_values;
- for (int i = 0; i < palette_count; i ++) {
- int color_data = i;
- for (FX_DWORD j = 0; j < m_nComponents; j ++) {
- int encoded_component = color_data % (1 << m_bpc);
- color_data /= 1 << m_bpc;
- color_value[j] = m_pCompData[j].m_DecodeMin + m_pCompData[j].m_DecodeStep * encoded_component;
- }
- FX_FLOAT R = 0, G = 0, B = 0;
- if (m_nComponents == 1 && m_Family == PDFCS_ICCBASED && m_pColorSpace->CountComponents() > 1) {
- int nComponents = m_pColorSpace->CountComponents();
- FX_FLOAT* temp_buf = FX_Alloc(FX_FLOAT, nComponents);
- for (int i = 0; i < nComponents; i++) {
- temp_buf[i] = *color_value;
- }
- m_pColorSpace->GetRGB(temp_buf, R, G, B);
- FX_Free(temp_buf);
- } else {
- m_pColorSpace->GetRGB(color_value, R, G, B);
- }
- SetPaletteArgb(i, ArgbEncode(255, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255)));
- }
- }
-}
-
-FX_DWORD CPDF_DIBSource::GetValidBpp() const
-{
- FX_DWORD bpc = m_bpc;
- CPDF_Object * pFilter = m_pDict->GetElementValue(FX_BSTRC("Filter"));
- if(pFilter)
- {
- if(pFilter->GetType() == PDFOBJ_NAME)
- {
- CFX_ByteString filter = pFilter->GetString();
- if(filter == FX_BSTRC("CCITTFaxDecode") || filter == FX_BSTRC("JBIG2Decode") )
- bpc = 1;
- if(filter == FX_BSTRC("RunLengthDecode") || filter == FX_BSTRC("DCTDecode") )
- bpc = 8;
- }
- else if (pFilter->GetType() == PDFOBJ_ARRAY)
- {
- CPDF_Array *pArray = (CPDF_Array *) pFilter;
- if( pArray->GetString(pArray->GetCount() -1) == FX_BSTRC("CCITTFacDecode") ||
- pArray->GetString(pArray->GetCount() -1) == FX_BSTRC("JBIG2Decode") )
- bpc = 1;
-
- if( pArray->GetString(pArray->GetCount() -1) == FX_BSTRC("RunLengthDecode") ||
- pArray->GetString(pArray->GetCount() -1) == FX_BSTRC("DCTDecode") )
- bpc = 8;
- }
- }
-
- return bpc;
-}
-
-#define NORMALCOLOR_MAX(color, max) (color) > (max) ? (max) : (color) < 0 ? 0 : (color);
-void CPDF_DIBSource::TranslateScanline24bpp(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan) const
-{
- int max_data = (1 << m_bpc) - 1;
- if (m_bDefaultDecode) {
- if (m_Family == PDFCS_DEVICERGB || m_Family == PDFCS_CALRGB) {
- if (m_bpc == 16) {
- FX_LPBYTE dest_pos = dest_scan;
- FX_LPCBYTE src_pos = src_scan;
- for (int col = 0; col < m_Width; col ++) {
- *dest_scan++ = src_pos[4];
- *dest_scan++ = src_pos[2];
- *dest_scan++ = *src_pos;
- src_pos += 6;
- }
- } else if (m_bpc == 8) {
- FX_LPBYTE dest_pos = dest_scan;
- FX_LPCBYTE src_pos = src_scan;
- for (int column = 0; column < m_Width; column ++) {
- *dest_scan++ = src_pos[2];
- *dest_scan++ = src_pos[1];
- *dest_scan++ = *src_pos;
- src_pos += 3;
- }
- } else {
- int src_bit_pos = 0;
- int dest_byte_pos = 0;
-
- FX_DWORD bpc = GetValidBpp();
-
- for (int column = 0; column < m_Width; column ++) {
- int R = _GetBits8(src_scan, src_bit_pos, bpc);
- src_bit_pos += bpc;
- int G = _GetBits8(src_scan, src_bit_pos, bpc);
- src_bit_pos += bpc;
- int B = _GetBits8(src_scan, src_bit_pos, bpc);
- src_bit_pos += bpc;
- R = NORMALCOLOR_MAX(R, max_data);
- G = NORMALCOLOR_MAX(G, max_data);
- B = NORMALCOLOR_MAX(B, max_data);
- dest_scan[dest_byte_pos] = B * 255 / max_data;
- dest_scan[dest_byte_pos + 1] = G * 255 / max_data;
- dest_scan[dest_byte_pos + 2] = R * 255 / max_data;
- dest_byte_pos += 3;
- }
- }
- return;
- } else if (m_bpc == 8) {
- if (m_nComponents == m_pColorSpace->CountComponents())
- m_pColorSpace->TranslateImageLine(dest_scan, src_scan, m_Width, m_Width, m_Height,
- m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK);
- return;
- }
- }
- CFX_FixedBufGrow<FX_FLOAT, 16> color_values1(m_nComponents);
- FX_FLOAT* color_values = color_values1;
- FX_FLOAT R, G, B;
- if (m_bpc == 8) {
- int src_byte_pos = 0;
- int dest_byte_pos = 0;
- for (int column = 0; column < m_Width; column ++) {
- for (FX_DWORD color = 0; color < m_nComponents; color ++) {
- int data = src_scan[src_byte_pos ++];
- color_values[color] = m_pCompData[color].m_DecodeMin +
- m_pCompData[color].m_DecodeStep * data;
- }
- if (m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK) {
- FX_FLOAT k = 1.0f - color_values[3];
- R = (1.0f - color_values[0]) * k;
- G = (1.0f - color_values[1]) * k;
- B = (1.0f - color_values[2]) * k;
- } else {
- m_pColorSpace->GetRGB(color_values, R, G, B);
- }
- R = NORMALCOLOR_MAX(R, 1);
- G = NORMALCOLOR_MAX(G, 1);
- B = NORMALCOLOR_MAX(B, 1);
- dest_scan[dest_byte_pos] = (FX_INT32)(B * 255);
- dest_scan[dest_byte_pos + 1] = (FX_INT32)(G * 255);
- dest_scan[dest_byte_pos + 2] = (FX_INT32)(R * 255);
- dest_byte_pos += 3;
- }
- } else {
- int src_bit_pos = 0;
- int dest_byte_pos = 0;
-
- FX_DWORD bpc = GetValidBpp();
-
- for (int column = 0; column < m_Width; column ++) {
- for (FX_DWORD color = 0; color < m_nComponents; color ++) {
- int data = _GetBits8(src_scan, src_bit_pos, bpc);
- color_values[color] = m_pCompData[color].m_DecodeMin +
- m_pCompData[color].m_DecodeStep * data;
- src_bit_pos += bpc;
- }
- if (m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK) {
- FX_FLOAT k = 1.0f - color_values[3];
- R = (1.0f - color_values[0]) * k;
- G = (1.0f - color_values[1]) * k;
- B = (1.0f - color_values[2]) * k;
- } else {
- m_pColorSpace->GetRGB(color_values, R, G, B);
- }
- R = NORMALCOLOR_MAX(R, 1);
- G = NORMALCOLOR_MAX(G, 1);
- B = NORMALCOLOR_MAX(B, 1);
- dest_scan[dest_byte_pos] = (FX_INT32)(B * 255);
- dest_scan[dest_byte_pos + 1] = (FX_INT32)(G * 255);
- dest_scan[dest_byte_pos + 2] = (FX_INT32)(R * 255);
- dest_byte_pos += 3;
- }
- }
-}
-FX_LPBYTE CPDF_DIBSource::GetBuffer() const
-{
- if (m_pCachedBitmap) {
- return m_pCachedBitmap->GetBuffer();
- }
- return NULL;
-}
-FX_LPCBYTE CPDF_DIBSource::GetScanline(int line) const
-{
- FX_DWORD src_pitch = (m_Width * m_bpc * m_nComponents + 7) / 8;
- FX_LPCBYTE pSrcLine = NULL;
- if (m_pCachedBitmap) {
- if (line >= m_pCachedBitmap->GetHeight()) {
- line = m_pCachedBitmap->GetHeight() - 1;
- }
- pSrcLine = m_pCachedBitmap->GetScanline(line);
- } else if (m_pDecoder) {
- pSrcLine = m_pDecoder->GetScanline(line);
- } else {
- if (m_pStreamAcc->GetSize() >= (line + 1) * src_pitch) {
- pSrcLine = m_pStreamAcc->GetData() + line * src_pitch;
- }
- }
- if (pSrcLine == NULL) {
- FX_LPBYTE pLineBuf = m_pMaskedLine ? m_pMaskedLine : m_pLineBuf;
- FXSYS_memset8(pLineBuf, 0xff, m_Pitch);
- return pLineBuf;
- }
- if (m_bpc * m_nComponents == 1) {
- if (m_bImageMask && m_bDefaultDecode) {
- for (FX_DWORD i = 0; i < src_pitch; i ++) {
- m_pLineBuf[i] = ~pSrcLine[i];
- }
- } else if (m_bColorKey) {
- FX_DWORD reset_argb, set_argb;
- reset_argb = m_pPalette ? m_pPalette[0] : 0xff000000;
- set_argb = m_pPalette ? m_pPalette[1] : 0xffffffff;
- if (m_pCompData[0].m_ColorKeyMin == 0) {
- reset_argb = 0;
- }
- if (m_pCompData[0].m_ColorKeyMax == 1) {
- set_argb = 0;
- }
- set_argb = FXARGB_TODIB(set_argb);
- reset_argb = FXARGB_TODIB(reset_argb);
- FX_DWORD* dest_scan = (FX_DWORD*)m_pMaskedLine;
- for (int col = 0; col < m_Width; col ++) {
- if (pSrcLine[col / 8] & (1 << (7 - col % 8))) {
- *dest_scan = set_argb;
- } else {
- *dest_scan = reset_argb;
- }
- dest_scan ++;
- }
- return m_pMaskedLine;
- } else {
- FXSYS_memcpy32(m_pLineBuf, pSrcLine, src_pitch);
- }
- return m_pLineBuf;
- }
- if (m_bpc * m_nComponents <= 8) {
- if (m_bpc == 8) {
- FXSYS_memcpy32(m_pLineBuf, pSrcLine, src_pitch);
- } else {
- int src_bit_pos = 0;
- for (int col = 0; col < m_Width; col ++) {
- int color_index = 0;
- for (FX_DWORD color = 0; color < m_nComponents; color ++) {
- int data = _GetBits8(pSrcLine, src_bit_pos, m_bpc);
- color_index |= data << (color * m_bpc);
- src_bit_pos += m_bpc;
- }
- m_pLineBuf[col] = color_index;
- }
- }
- if (m_bColorKey) {
- FX_LPBYTE pDestPixel = m_pMaskedLine;
- FX_LPCBYTE pSrcPixel = m_pLineBuf;
- for (int col = 0; col < m_Width; col ++) {
- FX_BYTE index = *pSrcPixel++;
- if (m_pPalette) {
- *pDestPixel++ = FXARGB_B(m_pPalette[index]);
- *pDestPixel++ = FXARGB_G(m_pPalette[index]);
- *pDestPixel++ = FXARGB_R(m_pPalette[index]);
- } else {
- *pDestPixel++ = index;
- *pDestPixel++ = index;
- *pDestPixel++ = index;
- }
- *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin || index > m_pCompData[0].m_ColorKeyMax) ? 0xff : 0;
- pDestPixel ++ ;
- }
- return m_pMaskedLine;
- }
- return m_pLineBuf;
- }
- if (m_bColorKey) {
- if (m_nComponents == 3 && m_bpc == 8) {
- FX_LPBYTE alpha_channel = m_pMaskedLine + 3;
- for (int col = 0; col < m_Width; col ++) {
- FX_LPCBYTE pPixel = pSrcLine + col * 3;
- alpha_channel[col * 4] = (pPixel[0] < m_pCompData[0].m_ColorKeyMin ||
- pPixel[0] > m_pCompData[0].m_ColorKeyMax ||
- pPixel[1] < m_pCompData[1].m_ColorKeyMin || pPixel[1] > m_pCompData[1].m_ColorKeyMax ||
- pPixel[2] < m_pCompData[2].m_ColorKeyMin || pPixel[2] > m_pCompData[2].m_ColorKeyMax) ? 0xff : 0;
- }
- } else {
- FXSYS_memset8(m_pMaskedLine, 0xff, m_Pitch);
- }
- }
- if (m_pColorSpace) {
- TranslateScanline24bpp(m_pLineBuf, pSrcLine);
- pSrcLine = m_pLineBuf;
- }
- if (m_bColorKey) {
- FX_LPCBYTE pSrcPixel = pSrcLine;
- FX_LPBYTE pDestPixel = m_pMaskedLine;
- for (int col = 0; col < m_Width; col ++) {
- *pDestPixel++ = *pSrcPixel++;
- *pDestPixel++ = *pSrcPixel++;
- *pDestPixel++ = *pSrcPixel++;
- pDestPixel ++;
- }
- return m_pMaskedLine;
- }
- return pSrcLine;
-}
-FX_BOOL CPDF_DIBSource::SkipToScanline(int line, IFX_Pause* pPause) const
-{
- if (m_pDecoder) {
- return m_pDecoder->SkipToScanline(line, pPause);
- }
- return FALSE;
-}
-void CPDF_DIBSource::DownSampleScanline(int line, FX_LPBYTE dest_scan, int dest_bpp,
- int dest_width, FX_BOOL bFlipX, int clip_left, int clip_width) const
-{
- FX_DWORD src_width = m_Width;
- FX_DWORD src_pitch = (src_width * m_bpc * m_nComponents + 7) / 8;
- FX_LPCBYTE pSrcLine = NULL;
- if (m_pCachedBitmap) {
- pSrcLine = m_pCachedBitmap->GetScanline(line);
- } else if (m_pDecoder) {
- pSrcLine = m_pDecoder->GetScanline(line);
- } else {
- if (m_pStreamAcc->GetSize() >= (line + 1) * src_pitch) {
- pSrcLine = m_pStreamAcc->GetData() + line * src_pitch;
- }
- }
- int orig_Bpp = m_bpc * m_nComponents / 8;
- int dest_Bpp = dest_bpp / 8;
- if (pSrcLine == NULL) {
- FXSYS_memset32(dest_scan, 0xff, dest_Bpp * clip_width);
- return;
- }
- CFX_FixedBufGrow<FX_BYTE, 128> temp(orig_Bpp);
- if (m_bpc * m_nComponents == 1) {
- FX_DWORD set_argb = (FX_DWORD) - 1, reset_argb = 0;
- if (m_bImageMask) {
- if (m_bDefaultDecode) {
- set_argb = 0;
- reset_argb = (FX_DWORD) - 1;
- }
- } else if (m_bColorKey) {
- reset_argb = m_pPalette ? m_pPalette[0] : 0xff000000;
- set_argb = m_pPalette ? m_pPalette[1] : 0xffffffff;
- if (m_pCompData[0].m_ColorKeyMin == 0) {
- reset_argb = 0;
- }
- if (m_pCompData[0].m_ColorKeyMax == 1) {
- set_argb = 0;
- }
- set_argb = FXARGB_TODIB(set_argb);
- reset_argb = FXARGB_TODIB(reset_argb);
- for (int i = 0; i < clip_width; i ++) {
- FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
- if (bFlipX) {
- src_x = src_width - src_x - 1;
- }
- src_x %= src_width;
- if (pSrcLine[src_x / 8] & (1 << (7 - src_x % 8))) {
- ((FX_DWORD*)dest_scan)[i] = set_argb;
- } else {
- ((FX_DWORD*)dest_scan)[i] = reset_argb;
- }
- }
- return;
- } else {
- if (dest_Bpp == 1) {
- } else if (m_pPalette) {
- reset_argb = m_pPalette[0];
- set_argb = m_pPalette[1];
- }
- }
- for (int i = 0; i < clip_width; i ++) {
- FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
- if (bFlipX) {
- src_x = src_width - src_x - 1;
- }
- src_x %= src_width;
- int dest_pos = i * dest_Bpp;
- if (pSrcLine[src_x / 8] & (1 << (7 - src_x % 8))) {
- if (dest_Bpp == 1) {
- dest_scan[dest_pos] = (FX_BYTE)set_argb;
- } else if (dest_Bpp == 3) {
- dest_scan[dest_pos] = FXARGB_B(set_argb);
- dest_scan[dest_pos + 1] = FXARGB_G(set_argb);
- dest_scan[dest_pos + 2] = FXARGB_R(set_argb);
- } else {
- *(FX_DWORD*)(dest_scan + dest_pos) = set_argb;
- }
- } else {
- if (dest_Bpp == 1) {
- dest_scan[dest_pos] = (FX_BYTE)reset_argb;
- } else if (dest_Bpp == 3) {
- dest_scan[dest_pos] = FXARGB_B(reset_argb);
- dest_scan[dest_pos + 1] = FXARGB_G(reset_argb);
- dest_scan[dest_pos + 2] = FXARGB_R(reset_argb);
- } else {
- *(FX_DWORD*)(dest_scan + dest_pos) = reset_argb;
- }
- }
- }
- return;
- } else if (m_bpc * m_nComponents <= 8) {
- if (m_bpc < 8) {
- int src_bit_pos = 0;
- for (FX_DWORD col = 0; col < src_width; col ++) {
- int color_index = 0;
- for (FX_DWORD color = 0; color < m_nComponents; color ++) {
- int data = _GetBits8(pSrcLine, src_bit_pos, m_bpc);
- color_index |= data << (color * m_bpc);
- src_bit_pos += m_bpc;
- }
- m_pLineBuf[col] = color_index;
- }
- pSrcLine = m_pLineBuf;
- }
- if (m_bColorKey) {
- for (int i = 0; i < clip_width; i ++) {
- FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
- if (bFlipX) {
- src_x = src_width - src_x - 1;
- }
- src_x %= src_width;
- FX_LPBYTE pDestPixel = dest_scan + i * 4;
- FX_BYTE index = pSrcLine[src_x];
- if (m_pPalette) {
- *pDestPixel++ = FXARGB_B(m_pPalette[index]);
- *pDestPixel++ = FXARGB_G(m_pPalette[index]);
- *pDestPixel++ = FXARGB_R(m_pPalette[index]);
- } else {
- *pDestPixel++ = index;
- *pDestPixel++ = index;
- *pDestPixel++ = index;
- }
- *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin || index > m_pCompData[0].m_ColorKeyMax) ? 0xff : 0;
- }
- return;
- }
- for (int i = 0; i < clip_width; i ++) {
- FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
- if (bFlipX) {
- src_x = src_width - src_x - 1;
- }
- src_x %= src_width;
- FX_BYTE index = pSrcLine[src_x];
- if (dest_Bpp == 1) {
- dest_scan[i] = index;
- } else {
- int dest_pos = i * dest_Bpp;
- FX_ARGB argb = m_pPalette[index];
- dest_scan[dest_pos] = FXARGB_B(argb);
- dest_scan[dest_pos + 1] = FXARGB_G(argb);
- dest_scan[dest_pos + 2] = FXARGB_R(argb);
- }
- }
- return;
- } else {
- int last_src_x = -1;
- FX_ARGB last_argb;
- FX_FLOAT orig_Not8Bpp = (FX_FLOAT)m_bpc * (FX_FLOAT)m_nComponents / 8.0f;
- FX_FLOAT unit_To8Bpc = 255.0f / ((1 << m_bpc) - 1);
- for (int i = 0; i < clip_width; i ++) {
- int dest_x = clip_left + i;
- FX_DWORD src_x = (bFlipX ? (dest_width - dest_x - 1) : dest_x) * (FX_INT64)src_width / dest_width;
- src_x %= src_width;
- FX_LPCBYTE pSrcPixel = NULL;
- if (m_bpc % 8 == 0) {
- pSrcPixel = pSrcLine + src_x * orig_Bpp;
- } else {
- pSrcPixel = pSrcLine + (int)(src_x * orig_Not8Bpp);
- }
- FX_LPBYTE pDestPixel = dest_scan + i * dest_Bpp;
- FX_ARGB argb;
- if (src_x == last_src_x) {
- argb = last_argb;
- } else {
- if (m_pColorSpace) {
- FX_BYTE color[4];
- if (!m_bDefaultDecode) {
- for (int i = 0; i < orig_Bpp; i ++) {
- int color_value = (int)((m_pCompData[i].m_DecodeMin + m_pCompData[i].m_DecodeStep * (FX_FLOAT)pSrcPixel[i]) * 255.0f + 0.5f);
- temp[i] = color_value > 255 ? 255 : (color_value < 0 ? 0 : color_value);
- }
- m_pColorSpace->TranslateImageLine(color, temp, 1, 0, 0, m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK);
- } else {
- if (m_bpc < 8) {
- int src_bit_pos = 0;
- if (src_x % 2) {
- src_bit_pos = 4;
- }
- int value = (1 << m_bpc) - 1;
- for (FX_DWORD i = 0; i < m_nComponents; i ++) {
- temp[i] = (FX_BYTE)(_GetBits8(pSrcPixel, src_bit_pos, m_bpc) * unit_To8Bpc);
- src_bit_pos += m_bpc;
- }
- m_pColorSpace->TranslateImageLine(color, temp, 1, 0, 0, m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK);
- } else {
- m_pColorSpace->TranslateImageLine(color, pSrcPixel, 1, 0, 0, m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK);
- }
- }
- argb = FXARGB_MAKE(0xff, color[2], color[1], color[0]);
- } else {
- argb = FXARGB_MAKE(0xff, pSrcPixel[2], pSrcPixel[1], pSrcPixel[0]);
- }
- if (m_bColorKey) {
- int alpha = 0xff;
- if (m_nComponents == 3 && m_bpc == 8) {
- alpha = (pSrcPixel[0] < m_pCompData[0].m_ColorKeyMin ||
- pSrcPixel[0] > m_pCompData[0].m_ColorKeyMax ||
- pSrcPixel[1] < m_pCompData[1].m_ColorKeyMin ||
- pSrcPixel[1] > m_pCompData[1].m_ColorKeyMax ||
- pSrcPixel[2] < m_pCompData[2].m_ColorKeyMin ||
- pSrcPixel[2] > m_pCompData[2].m_ColorKeyMax) ? 0xff : 0;
- }
- argb &= 0xffffff;
- argb |= alpha << 24;
- }
- last_src_x = src_x;
- last_argb = argb;
- }
- if (dest_Bpp == 4) {
- *(FX_DWORD*)pDestPixel = FXARGB_TODIB(argb);
- } else {
- *pDestPixel++ = FXARGB_B(argb);
- *pDestPixel++ = FXARGB_G(argb);
- *pDestPixel = FXARGB_R(argb);
- }
- }
- }
-}
-void CPDF_DIBSource::SetDownSampleSize(int dest_width, int dest_height) const
-{
- if (m_pDecoder) {
- m_pDecoder->DownScale(dest_width, dest_height);
- ((CPDF_DIBSource*)this)->m_Width = m_pDecoder->GetWidth();
- ((CPDF_DIBSource*)this)->m_Height = m_pDecoder->GetHeight();
- }
-}
-void CPDF_DIBSource::ClearImageData()
-{
- if (m_pDecoder) {
- m_pDecoder->ClearImageData();
- }
-}
-CPDF_ProgressiveImageLoaderHandle::CPDF_ProgressiveImageLoaderHandle()
-{
- m_pImageLoader = NULL;
- m_pCache = NULL;
- m_pImage = NULL;
-}
-CPDF_ProgressiveImageLoaderHandle::~CPDF_ProgressiveImageLoaderHandle()
-{
- m_pImageLoader = NULL;
- m_pCache = NULL;
- m_pImage = NULL;
-}
-FX_BOOL CPDF_ProgressiveImageLoaderHandle::Start(CPDF_ImageLoader* pImageLoader, const CPDF_ImageObject* pImage, CPDF_PageRenderCache* pCache, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus, FX_INT32 nDownsampleWidth, FX_INT32 nDownsampleHeight)
-{
- m_pImageLoader = pImageLoader;
- m_pCache = pCache;
- m_pImage = (CPDF_ImageObject*)pImage;
- m_nDownsampleWidth = nDownsampleWidth;
- m_nDownsampleHeight = nDownsampleHeight;
- FX_BOOL ret;
- if (pCache) {
- ret = pCache->StartGetCachedBitmap(pImage->m_pImage->GetStream(), bStdCS, GroupFamily, bLoadMask, pRenderStatus, m_nDownsampleWidth, m_nDownsampleHeight);
- if (ret == FALSE) {
- m_pImageLoader->m_bCached = TRUE;
- m_pImageLoader->m_pBitmap = pCache->m_pCurImageCache->DetachBitmap();
- m_pImageLoader->m_pMask = pCache->m_pCurImageCache->DetachMask();
- m_pImageLoader->m_MatteColor = pCache->m_pCurImageCache->m_MatteColor;
- }
- } else {
- ret = pImage->m_pImage->StartLoadDIBSource(pRenderStatus->m_pFormResource, pRenderStatus->m_pPageResource, bStdCS, GroupFamily, bLoadMask);
- if (ret == FALSE) {
- m_pImageLoader->m_bCached = FALSE;
- m_pImageLoader->m_pBitmap = m_pImage->m_pImage->DetachBitmap();
- m_pImageLoader->m_pMask = m_pImage->m_pImage->DetachMask();
- m_pImageLoader->m_MatteColor = m_pImage->m_pImage->m_MatteColor;
- }
- }
- return ret;
-}
-FX_BOOL CPDF_ProgressiveImageLoaderHandle::Continue(IFX_Pause* pPause)
-{
- FX_BOOL ret;
- if (m_pCache) {
- ret = m_pCache->Continue(pPause);
- if (ret == FALSE) {
- m_pImageLoader->m_bCached = TRUE;
- m_pImageLoader->m_pBitmap = m_pCache->m_pCurImageCache->DetachBitmap();
- m_pImageLoader->m_pMask = m_pCache->m_pCurImageCache->DetachMask();
- m_pImageLoader->m_MatteColor = m_pCache->m_pCurImageCache->m_MatteColor;
- }
- } else {
- ret = m_pImage->m_pImage->Continue(pPause);
- if (ret == FALSE) {
- m_pImageLoader->m_bCached = FALSE;
- m_pImageLoader->m_pBitmap = m_pImage->m_pImage->DetachBitmap();
- m_pImageLoader->m_pMask = m_pImage->m_pImage->DetachMask();
- m_pImageLoader->m_MatteColor = m_pImage->m_pImage->m_MatteColor;
- }
- }
- return ret;
-}
-FX_BOOL CPDF_ImageLoader::Load(const CPDF_ImageObject* pImage, CPDF_PageRenderCache* pCache, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus)
-{
- if (pImage == NULL) {
- return FALSE;
- }
- if (pCache) {
- pCache->GetCachedBitmap(pImage->m_pImage->GetStream(), m_pBitmap, m_pMask, m_MatteColor, bStdCS, GroupFamily, bLoadMask, pRenderStatus, m_nDownsampleWidth, m_nDownsampleHeight);
- m_bCached = TRUE;
- } else {
- m_pBitmap = pImage->m_pImage->LoadDIBSource(&m_pMask, &m_MatteColor, bStdCS, GroupFamily, bLoadMask);
- m_bCached = FALSE;
- }
- return FALSE;
-}
-FX_BOOL CPDF_ImageLoader::StartLoadImage(const CPDF_ImageObject* pImage, CPDF_PageRenderCache* pCache, FX_LPVOID& LoadHandle, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus, FX_INT32 nDownsampleWidth, FX_INT32 nDownsampleHeight)
-{
- m_nDownsampleWidth = nDownsampleWidth;
- m_nDownsampleHeight = nDownsampleHeight;
- CPDF_ProgressiveImageLoaderHandle* pLoaderHandle = NULL;
- pLoaderHandle = FX_NEW CPDF_ProgressiveImageLoaderHandle;
- FX_BOOL ret = pLoaderHandle->Start(this, pImage, pCache, bStdCS, GroupFamily, bLoadMask, pRenderStatus, m_nDownsampleWidth, m_nDownsampleHeight);
- LoadHandle = pLoaderHandle;
- return ret;
-}
-FX_BOOL CPDF_ImageLoader::Continue(FX_LPVOID LoadHandle, IFX_Pause* pPause)
-{
- return ((CPDF_ProgressiveImageLoaderHandle*)LoadHandle)->Continue(pPause);
-}
-CPDF_ImageLoader::~CPDF_ImageLoader()
-{
- if (!m_bCached) {
- if (m_pBitmap) {
- delete m_pBitmap;
- m_pBitmap = NULL;
- }
- if (m_pMask) {
- delete m_pMask;
- }
- }
-}
+// 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" +#include <limits.h> +static unsigned int _GetBits8(FX_LPCBYTE pData, int bitpos, int nbits) +{ + unsigned int byte = pData[bitpos / 8]; + if (nbits == 8) { + return byte; + } else if (nbits == 4) { + return (bitpos % 8) ? (byte & 0x0f) : (byte >> 4); + } else if (nbits == 2) { + return (byte >> (6 - bitpos % 8)) & 0x03; + } else if (nbits == 1) { + return (byte >> (7 - bitpos % 8)) & 0x01; + } else if (nbits == 16) { + return byte * 256 + pData[bitpos / 8 + 1]; + } + return 0; +} +CFX_DIBSource* CPDF_Image::LoadDIBSource(CFX_DIBSource** ppMask, FX_DWORD* pMatteColor, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask) const +{ + CPDF_DIBSource* pSource = FX_NEW CPDF_DIBSource; + if (pSource->Load(m_pDocument, m_pStream, (CPDF_DIBSource**)ppMask, pMatteColor, NULL, NULL, bStdCS, GroupFamily, bLoadMask)) { + return pSource; + } + delete pSource; + return NULL; +} +CFX_DIBSource* CPDF_Image::DetachBitmap() +{ + CFX_DIBSource* pBitmap = m_pDIBSource; + m_pDIBSource = NULL; + return pBitmap; +} +CFX_DIBSource* CPDF_Image::DetachMask() +{ + CFX_DIBSource* pBitmap = m_pMask; + m_pMask = NULL; + return pBitmap; +} +FX_BOOL CPDF_Image::StartLoadDIBSource(CPDF_Dictionary* pFormResource, CPDF_Dictionary* pPageResource, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask) +{ + m_pDIBSource = FX_NEW CPDF_DIBSource; + int ret = ((CPDF_DIBSource*)m_pDIBSource)->StartLoadDIBSource(m_pDocument, m_pStream, TRUE, pFormResource, pPageResource, bStdCS, GroupFamily, bLoadMask); + if (ret == 2) { + return TRUE; + } + if (!ret) { + delete m_pDIBSource; + m_pDIBSource = NULL; + return FALSE; + } + m_pMask = ((CPDF_DIBSource*)m_pDIBSource)->DetachMask(); + m_MatteColor = ((CPDF_DIBSource*)m_pDIBSource)->m_MatteColor; + return FALSE; +} +FX_BOOL CPDF_Image::Continue(IFX_Pause* pPause) +{ + int ret = ((CPDF_DIBSource*)m_pDIBSource)->ContinueLoadDIBSource(pPause); + if (ret == 2) { + return TRUE; + } + if (!ret) { + delete m_pDIBSource; + m_pDIBSource = NULL; + return FALSE; + } + m_pMask = ((CPDF_DIBSource*)m_pDIBSource)->DetachMask(); + m_MatteColor = ((CPDF_DIBSource*)m_pDIBSource)->m_MatteColor; + return FALSE; +} +CPDF_DIBSource::CPDF_DIBSource() +{ + m_pDocument = NULL; + m_pStreamAcc = NULL; + m_pDict = NULL; + m_bpp = 0; + m_Width = m_Height = 0; + m_pColorSpace = NULL; + m_bDefaultDecode = TRUE; + m_bImageMask = FALSE; + m_pPalette = NULL; + m_pCompData = NULL; + m_bColorKey = FALSE; + m_pMaskedLine = m_pLineBuf = NULL; + m_pCachedBitmap = NULL; + m_pDecoder = NULL; + m_nComponents = 0; + m_bpc = 0; + m_bLoadMask = FALSE; + m_Family = 0; + m_pMask = NULL; + m_MatteColor = 0; + m_pJbig2Context = NULL; + m_pGlobalStream = NULL; + m_bStdCS = FALSE; + m_pMaskStream = NULL; + m_Status = 0; + m_bHasMask = FALSE; +} +CPDF_DIBSource::~CPDF_DIBSource() +{ + if (m_pStreamAcc) { + delete m_pStreamAcc; + } + if (m_pMaskedLine) { + FX_Free(m_pMaskedLine); + } + if (m_pLineBuf) { + FX_Free(m_pLineBuf); + } + if (m_pCachedBitmap) { + delete m_pCachedBitmap; + } + if (m_pDecoder) { + delete m_pDecoder; + } + if (m_pCompData) { + FX_Free(m_pCompData); + } + CPDF_ColorSpace* pCS = m_pColorSpace; + if (pCS && m_pDocument) { + m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); + } + if (m_pJbig2Context) { + ICodec_Jbig2Module* pJbig2Moudle = CPDF_ModuleMgr::Get()->GetJbig2Module(); + pJbig2Moudle->DestroyJbig2Context(m_pJbig2Context); + m_pJbig2Context = NULL; + } + if (m_pGlobalStream) { + delete m_pGlobalStream; + } + m_pGlobalStream = NULL; +} +CFX_DIBitmap* CPDF_DIBSource::GetBitmap() const +{ + if (m_pCachedBitmap) { + return m_pCachedBitmap; + } + return Clone(); +} +void CPDF_DIBSource::ReleaseBitmap(CFX_DIBitmap* pBitmap) const +{ + if (pBitmap && pBitmap != m_pCachedBitmap) { + delete pBitmap; + } +} +FX_BOOL CPDF_DIBSource::Load(CPDF_Document* pDoc, const CPDF_Stream* pStream, CPDF_DIBSource** ppMask, + FX_DWORD* pMatteColor, CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask) +{ + if (pStream == NULL) { + return FALSE; + } + m_pDocument = pDoc; + m_pDict = pStream->GetDict(); + m_pStream = pStream; + m_Width = m_pDict->GetInteger(FX_BSTRC("Width")); + m_Height = m_pDict->GetInteger(FX_BSTRC("Height")); + if (m_Width <= 0 || m_Height <= 0 || m_Width > 0x01ffff || m_Height > 0x01ffff) { + return FALSE; + } + m_GroupFamily = GroupFamily; + m_bLoadMask = bLoadMask; + if (!LoadColorInfo(m_pStream->GetObjNum() != 0 ? NULL : pFormResources, pPageResources)) { + return FALSE; + } + FX_DWORD src_pitch = m_bpc; + if (m_bpc != 0 && m_nComponents != 0) { + if (src_pitch > 0 && m_nComponents > (unsigned)INT_MAX / src_pitch) { + return FALSE; + } + src_pitch *= m_nComponents; + if (src_pitch > 0 && (FX_DWORD)m_Width > (unsigned)INT_MAX / src_pitch) { + return FALSE; + } + src_pitch *= m_Width; + if (src_pitch + 7 < src_pitch) { + return FALSE; + } + src_pitch += 7; + src_pitch /= 8; + if (src_pitch > 0 && (FX_DWORD)m_Height > (unsigned)INT_MAX / src_pitch) { + return FALSE; + } + } + m_pStreamAcc = FX_NEW CPDF_StreamAcc; + m_pStreamAcc->LoadAllData(pStream, FALSE, m_Height * src_pitch, TRUE); + if (m_pStreamAcc->GetSize() == 0 || m_pStreamAcc->GetData() == NULL) { + return FALSE; + } + const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder(); + if (!decoder.IsEmpty() && decoder == FX_BSTRC("CCITTFaxDecode")) { + m_bpc = 1; + } + if (!CreateDecoder()) { + return FALSE; + } + if (m_bImageMask) { + m_bpp = 1; + m_bpc = 1; + m_nComponents = 1; + m_AlphaFlag = 1; + } else if (m_bpc * m_nComponents == 1) { + m_bpp = 1; + } else if (m_bpc * m_nComponents <= 8) { + m_bpp = 8; + } else { + m_bpp = 24; + } + if (!m_bpc || !m_nComponents) { + return FALSE; + } + m_Pitch = m_Width; + if ((FX_DWORD)m_bpp > (unsigned)INT_MAX / m_Pitch) { + return FALSE; + } + m_Pitch *= m_bpp; + if (m_Pitch + 31 < m_Pitch) { + return FALSE; + } + m_Pitch += 31; + m_Pitch = m_Pitch / 32 * 4; + m_pLineBuf = FX_Alloc(FX_BYTE, m_Pitch); + if (m_pColorSpace && bStdCS) { + m_pColorSpace->EnableStdConversion(TRUE); + } + LoadPalette(); + if (m_bColorKey) { + m_bpp = 32; + m_AlphaFlag = 2; + m_Pitch = m_Width; + if ((FX_DWORD)m_bpp > (unsigned)INT_MAX / m_Pitch) { + return FALSE; + } + m_Pitch *= m_bpp; + if (m_Pitch + 31 < m_Pitch) { + return FALSE; + } + m_Pitch += 31; + m_Pitch = m_Pitch / 32 * 4; + m_pMaskedLine = FX_Alloc(FX_BYTE, m_Pitch); + } + if (ppMask) { + *ppMask = LoadMask(*pMatteColor); + } + if (m_pColorSpace && bStdCS) { + m_pColorSpace->EnableStdConversion(FALSE); + } + return TRUE; +} +int CPDF_DIBSource::ContinueToLoadMask() +{ + if (m_bImageMask) { + m_bpp = 1; + m_bpc = 1; + m_nComponents = 1; + m_AlphaFlag = 1; + } else if (m_bpc * m_nComponents == 1) { + m_bpp = 1; + } else if (m_bpc * m_nComponents <= 8) { + m_bpp = 8; + } else { + m_bpp = 24; + } + if (!m_bpc || !m_nComponents) { + return 0; + } + m_Pitch = m_Width; + if ((FX_DWORD)m_bpp > (unsigned)INT_MAX / m_Pitch) { + return 0; + } + m_Pitch *= m_bpp; + if (m_Pitch + 31 < m_Pitch) { + return 0; + } + m_Pitch += 31; + m_Pitch = m_Pitch / 32 * 4; + m_pLineBuf = FX_Alloc(FX_BYTE, m_Pitch); + if (m_pColorSpace && m_bStdCS) { + m_pColorSpace->EnableStdConversion(TRUE); + } + LoadPalette(); + if (m_bColorKey) { + m_bpp = 32; + m_AlphaFlag = 2; + m_Pitch = m_Width; + if ((FX_DWORD)m_bpp > (unsigned)INT_MAX / m_Pitch) { + return 0; + } + m_Pitch *= m_bpp; + if (m_Pitch + 31 < m_Pitch) { + return 0; + } + m_Pitch += 31; + m_Pitch = m_Pitch / 32 * 4; + m_pMaskedLine = FX_Alloc(FX_BYTE, m_Pitch); + } + return 1; +} +int CPDF_DIBSource::StartLoadDIBSource(CPDF_Document* pDoc, const CPDF_Stream* pStream, FX_BOOL bHasMask, + CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources, + FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask) +{ + if (pStream == NULL) { + return 0; + } + m_pDocument = pDoc; + m_pDict = pStream->GetDict(); + m_pStream = pStream; + m_bStdCS = bStdCS; + m_bHasMask = bHasMask; + m_Width = m_pDict->GetInteger(FX_BSTRC("Width")); + m_Height = m_pDict->GetInteger(FX_BSTRC("Height")); + if (m_Width <= 0 || m_Height <= 0 || m_Width > 0x01ffff || m_Height > 0x01ffff) { + return 0; + } + m_GroupFamily = GroupFamily; + m_bLoadMask = bLoadMask; + if (!LoadColorInfo(m_pStream->GetObjNum() != 0 ? NULL : pFormResources, pPageResources)) { + return 0; + } + FX_DWORD src_pitch = m_bpc; + if (m_bpc != 0 && m_nComponents != 0) { + if (src_pitch > 0 && m_nComponents > (unsigned)INT_MAX / src_pitch) { + return 0; + } + src_pitch *= m_nComponents; + if (src_pitch > 0 && (FX_DWORD)m_Width > (unsigned)INT_MAX / src_pitch) { + return 0; + } + src_pitch *= m_Width; + if (src_pitch + 7 < src_pitch) { + return 0; + } + src_pitch += 7; + src_pitch /= 8; + if (src_pitch > 0 && (FX_DWORD)m_Height > (unsigned)INT_MAX / src_pitch) { + return 0; + } + } + m_pStreamAcc = FX_NEW CPDF_StreamAcc; + m_pStreamAcc->LoadAllData(pStream, FALSE, m_Height * src_pitch, TRUE); + if (m_pStreamAcc->GetSize() == 0 || m_pStreamAcc->GetData() == NULL) { + return 0; + } + const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder(); + if (!decoder.IsEmpty() && decoder == FX_BSTRC("CCITTFaxDecode")) { + m_bpc = 1; + } + int ret = CreateDecoder(); + if (ret != 1) { + if (!ret) { + return ret; + } + if (!ContinueToLoadMask()) { + return 0; + } + if (m_bHasMask) { + StratLoadMask(); + } + return ret; + } + if (!ContinueToLoadMask()) { + return 0; + } + if (m_bHasMask) { + ret = StratLoadMask(); + } + if (ret == 2) { + return ret; + } + if (m_pColorSpace && m_bStdCS) { + m_pColorSpace->EnableStdConversion(FALSE); + } + return ret; +} +int CPDF_DIBSource::ContinueLoadDIBSource(IFX_Pause* pPause) +{ + FXCODEC_STATUS ret; + if (m_Status == 1) { + const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder(); + if (decoder == FX_BSTRC("JPXDecode")) { + return 0; + } + ICodec_Jbig2Module* pJbig2Moudle = CPDF_ModuleMgr::Get()->GetJbig2Module(); + if (m_pJbig2Context == NULL) { + m_pJbig2Context = pJbig2Moudle->CreateJbig2Context(); + if (m_pStreamAcc->GetImageParam()) { + CPDF_Stream* pGlobals = m_pStreamAcc->GetImageParam()->GetStream(FX_BSTRC("JBIG2Globals")); + if (pGlobals) { + m_pGlobalStream = FX_NEW CPDF_StreamAcc; + m_pGlobalStream->LoadAllData(pGlobals, FALSE); + } + } + ret = pJbig2Moudle->StartDecode(m_pJbig2Context, m_Width, m_Height, m_pStreamAcc->GetData(), m_pStreamAcc->GetSize(), + m_pGlobalStream ? m_pGlobalStream->GetData() : NULL, m_pGlobalStream ? m_pGlobalStream->GetSize() : 0, m_pCachedBitmap->GetBuffer(), + m_pCachedBitmap->GetPitch(), pPause); + if (ret < 0) { + delete m_pCachedBitmap; + m_pCachedBitmap = NULL; + if (m_pGlobalStream) { + delete m_pGlobalStream; + } + m_pGlobalStream = NULL; + pJbig2Moudle->DestroyJbig2Context(m_pJbig2Context); + m_pJbig2Context = NULL; + return 0; + } + if (ret == FXCODEC_STATUS_DECODE_TOBECONTINUE) { + return 2; + } + int ret1 = 1; + if (m_bHasMask) { + ret1 = ContinueLoadMaskDIB(pPause); + m_Status = 2; + } + if (ret1 == 2) { + return ret1; + } + if (m_pColorSpace && m_bStdCS) { + m_pColorSpace->EnableStdConversion(FALSE); + } + return ret1; + } + FXCODEC_STATUS ret = pJbig2Moudle->ContinueDecode(m_pJbig2Context, pPause); + if (ret < 0) { + delete m_pCachedBitmap; + m_pCachedBitmap = NULL; + if (m_pGlobalStream) { + delete m_pGlobalStream; + } + m_pGlobalStream = NULL; + pJbig2Moudle->DestroyJbig2Context(m_pJbig2Context); + m_pJbig2Context = NULL; + return 0; + } + if (ret == FXCODEC_STATUS_DECODE_TOBECONTINUE) { + return 2; + } + int ret1 = 1; + if (m_bHasMask) { + ret1 = ContinueLoadMaskDIB(pPause); + m_Status = 2; + } + if (ret1 == 2) { + return ret1; + } + if (m_pColorSpace && m_bStdCS) { + m_pColorSpace->EnableStdConversion(FALSE); + } + return ret1; + } else if (m_Status == 2) { + return ContinueLoadMaskDIB(pPause); + } + return 0; +} +FX_BOOL CPDF_DIBSource::LoadColorInfo(CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources) +{ + if (m_pDict->GetInteger("ImageMask")) { + m_bImageMask = TRUE; + } + if (m_bImageMask || !m_pDict->KeyExist(FX_BSTRC("ColorSpace"))) { + if (!m_bImageMask) { + CPDF_Object* pFilter = m_pDict->GetElementValue(FX_BSTRC("Filter")); + if (pFilter) { + CFX_ByteString filter; + if (pFilter->GetType() == PDFOBJ_NAME) { + filter = pFilter->GetString(); + if (filter == FX_BSTRC("JPXDecode")) { + return TRUE; + } + } else if (pFilter->GetType() == PDFOBJ_ARRAY) { + CPDF_Array* pArray = (CPDF_Array*)pFilter; + if (pArray->GetString(pArray->GetCount() - 1) == FX_BSTRC("JPXDecode")) { + return TRUE; + } + } + } + } + m_bImageMask = TRUE; + m_bpc = m_nComponents = 1; + CPDF_Array* pDecode = m_pDict->GetArray(FX_BSTRC("Decode")); + m_bDefaultDecode = pDecode == NULL || pDecode->GetInteger(0) == 0; + return TRUE; + } + CPDF_Object* pCSObj = m_pDict->GetElementValue(FX_BSTRC("ColorSpace")); + if (pCSObj == NULL) { + return FALSE; + } + CPDF_DocPageData* pDocPageData = m_pDocument->GetPageData(); + if (pFormResources) { + m_pColorSpace = pDocPageData->GetColorSpace(pCSObj, pFormResources); + } + if (m_pColorSpace == NULL) { + m_pColorSpace = pDocPageData->GetColorSpace(pCSObj, pPageResources); + } + if (m_pColorSpace == NULL) { + return FALSE; + } + m_bpc = m_pDict->GetInteger(FX_BSTRC("BitsPerComponent")); + m_Family = m_pColorSpace->GetFamily(); + m_nComponents = m_pColorSpace->CountComponents(); + if (m_Family == PDFCS_ICCBASED && pCSObj->GetType() == PDFOBJ_NAME) { + CFX_ByteString cs = pCSObj->GetString(); + if (cs == FX_BSTRC("DeviceGray")) { + m_nComponents = 1; + } else if (cs == FX_BSTRC("DeviceRGB")) { + m_nComponents = 3; + } else if (cs == FX_BSTRC("DeviceCMYK")) { + m_nComponents = 4; + } + } + m_pCompData = FX_Alloc(DIB_COMP_DATA, m_nComponents); + if (m_bpc == 0) { + return TRUE; + } + int max_data = (1 << m_bpc) - 1; + CPDF_Array* pDecode = m_pDict->GetArray(FX_BSTRC("Decode")); + if (pDecode) { + for (FX_DWORD i = 0; i < m_nComponents; i ++) { + m_pCompData[i].m_DecodeMin = pDecode->GetNumber(i * 2); + FX_FLOAT max = pDecode->GetNumber(i * 2 + 1); + m_pCompData[i].m_DecodeStep = (max - m_pCompData[i].m_DecodeMin) / max_data; + FX_FLOAT def_value, def_min, def_max; + m_pColorSpace->GetDefaultValue(i, def_value, def_min, def_max); + if (m_Family == PDFCS_INDEXED) { + def_max = (FX_FLOAT)max_data; + } + if (def_min != m_pCompData[i].m_DecodeMin || def_max != max) { + m_bDefaultDecode = FALSE; + } + } + } else { + for (FX_DWORD i = 0; i < m_nComponents; i ++) { + FX_FLOAT def_value; + m_pColorSpace->GetDefaultValue(i, def_value, m_pCompData[i].m_DecodeMin, m_pCompData[i].m_DecodeStep); + if (m_Family == PDFCS_INDEXED) { + m_pCompData[i].m_DecodeStep = (FX_FLOAT)max_data; + } + m_pCompData[i].m_DecodeStep = (m_pCompData[i].m_DecodeStep - m_pCompData[i].m_DecodeMin) / max_data; + } + } + if (!m_pDict->KeyExist(FX_BSTRC("SMask"))) { + CPDF_Object* pMask = m_pDict->GetElementValue(FX_BSTRC("Mask")); + if (pMask == NULL) { + return TRUE; + } + if (pMask->GetType() == PDFOBJ_ARRAY) { + CPDF_Array* pArray = (CPDF_Array*)pMask; + if (pArray->GetCount() >= m_nComponents * 2) + for (FX_DWORD i = 0; i < m_nComponents * 2; i ++) { + if (i % 2) { + m_pCompData[i / 2].m_ColorKeyMax = pArray->GetInteger(i); + } else { + m_pCompData[i / 2].m_ColorKeyMin = pArray->GetInteger(i); + } + } + m_bColorKey = TRUE; + } + } + return TRUE; +} +ICodec_ScanlineDecoder* FPDFAPI_CreateFaxDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, + const CPDF_Dictionary* pParams); +ICodec_ScanlineDecoder* FPDFAPI_CreateFlateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, + int nComps, int bpc, const CPDF_Dictionary* pParams); +int CPDF_DIBSource::CreateDecoder() +{ + const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder(); + if (decoder.IsEmpty()) { + return 1; + } + FX_LPCBYTE src_data = m_pStreamAcc->GetData(); + FX_DWORD src_size = m_pStreamAcc->GetSize(); + const CPDF_Dictionary* pParams = m_pStreamAcc->GetImageParam(); + if (decoder == FX_BSTRC("CCITTFaxDecode")) { + m_pDecoder = FPDFAPI_CreateFaxDecoder(src_data, src_size, m_Width, m_Height, pParams); + } else if (decoder == FX_BSTRC("DCTDecode")) { + m_pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder(src_data, src_size, m_Width, m_Height, + m_nComponents, pParams ? pParams->GetInteger(FX_BSTR("ColorTransform"), 1) : 1); + if (NULL == m_pDecoder) { + FX_BOOL bTransform = FALSE; + int comps, bpc; + ICodec_JpegModule* pJpegModule = CPDF_ModuleMgr::Get()->GetJpegModule(); + if (pJpegModule->LoadInfo(src_data, src_size, m_Width, m_Height, comps, bpc, bTransform)) { + m_nComponents = comps; + m_bpc = bpc; + m_pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder(src_data, src_size, m_Width, m_Height, + m_nComponents, bTransform); + } + } + } else if (decoder == FX_BSTRC("FlateDecode")) { + m_pDecoder = FPDFAPI_CreateFlateDecoder(src_data, src_size, m_Width, m_Height, m_nComponents, m_bpc, pParams); + } else if (decoder == FX_BSTRC("JPXDecode")) { + LoadJpxBitmap(); + return m_pCachedBitmap != NULL ? 1 : 0; + } else if (decoder == FX_BSTRC("JBIG2Decode")) { + m_pCachedBitmap = FX_NEW CFX_DIBitmap; + if (!m_pCachedBitmap->Create(m_Width, m_Height, m_bImageMask ? FXDIB_1bppMask : FXDIB_1bppRgb)) { + delete m_pCachedBitmap; + m_pCachedBitmap = NULL; + return 0; + } + m_Status = 1; + return 2; + } else if (decoder == FX_BSTRC("RunLengthDecode")) { + m_pDecoder = CPDF_ModuleMgr::Get()->GetCodecModule()->GetBasicModule()->CreateRunLengthDecoder(src_data, src_size, m_Width, m_Height, m_nComponents, m_bpc); + } + if (m_pDecoder) { + int requested_pitch = (m_Width * m_nComponents * m_bpc + 7) / 8; + int provided_pitch = (m_pDecoder->GetWidth() * m_pDecoder->CountComps() * m_pDecoder->GetBPC() + 7) / 8; + if (provided_pitch < requested_pitch) { + return 0; + } + return 1; + } + return 0; +} +void CPDF_DIBSource::LoadJpxBitmap() +{ + ICodec_JpxModule* pJpxModule = CPDF_ModuleMgr::Get()->GetJpxModule(); + if (pJpxModule == NULL) { + return; + } + FX_LPVOID ctx = pJpxModule->CreateDecoder(m_pStreamAcc->GetData(), m_pStreamAcc->GetSize(), m_pColorSpace != NULL); + if (ctx == NULL) { + return; + } + FX_DWORD width = 0, height = 0, codestream_nComps = 0, image_nComps = 0; + pJpxModule->GetImageInfo(ctx, width, height, codestream_nComps, image_nComps); + if ((int)width < m_Width || (int)height < m_Height) { + pJpxModule->DestroyDecoder(ctx); + return; + } + int output_nComps; + FX_BOOL bTranslateColor, bSwapRGB = FALSE; + if (m_pColorSpace) { + if (codestream_nComps != (FX_DWORD)m_pColorSpace->CountComponents()) { + return; + } + output_nComps = codestream_nComps; + bTranslateColor = FALSE; + if (m_pColorSpace == CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB)) { + bSwapRGB = TRUE; + m_pColorSpace = NULL; + } + } else { + bTranslateColor = TRUE; + if (image_nComps) { + output_nComps = image_nComps; + } else { + output_nComps = codestream_nComps; + } + if (output_nComps == 3) { + bSwapRGB = TRUE; + } else if (output_nComps == 4) { + m_pColorSpace = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK); + bTranslateColor = FALSE; + } + m_nComponents = output_nComps; + } + FXDIB_Format format; + if (output_nComps == 1) { + format = FXDIB_8bppRgb; + } else if (output_nComps <= 3) { + format = FXDIB_Rgb; + } else if (output_nComps == 4) { + format = FXDIB_Rgb32; + } else { + width = (width * output_nComps + 2) / 3; + format = FXDIB_Rgb; + } + m_pCachedBitmap = FX_NEW CFX_DIBitmap; + if (!m_pCachedBitmap->Create(width, height, format)) { + delete m_pCachedBitmap; + m_pCachedBitmap = NULL; + return; + } + m_pCachedBitmap->Clear(0xFFFFFFFF); + FX_LPBYTE output_offsets = FX_Alloc(FX_BYTE, output_nComps); + for (int i = 0; i < output_nComps; i ++) { + output_offsets[i] = i; + } + if (bSwapRGB) { + output_offsets[0] = 2; + output_offsets[2] = 0; + } + if (!pJpxModule->Decode(ctx, m_pCachedBitmap->GetBuffer(), m_pCachedBitmap->GetPitch(), bTranslateColor, output_offsets)) { + delete m_pCachedBitmap; + m_pCachedBitmap = NULL; + return; + } + FX_Free(output_offsets); + pJpxModule->DestroyDecoder(ctx); + if (m_pColorSpace && m_pColorSpace->GetFamily() == PDFCS_INDEXED && m_bpc < 8) { + int scale = 8 - m_bpc; + for (FX_DWORD row = 0; row < height; row ++) { + FX_LPBYTE scanline = (FX_LPBYTE)m_pCachedBitmap->GetScanline(row); + for (FX_DWORD col = 0; col < width; col ++) { + *scanline = (*scanline) >> scale; + scanline++; + } + } + } + m_bpc = 8; +} +void CPDF_DIBSource::LoadJbig2Bitmap() +{ + ICodec_Jbig2Module* pJbig2Module = CPDF_ModuleMgr::Get()->GetJbig2Module(); + if (pJbig2Module == NULL) { + return; + } + CPDF_StreamAcc* pGlobalStream = NULL; + if (m_pStreamAcc->GetImageParam()) { + CPDF_Stream* pGlobals = m_pStreamAcc->GetImageParam()->GetStream(FX_BSTRC("JBIG2Globals")); + if (pGlobals) { + pGlobalStream = FX_NEW CPDF_StreamAcc; + pGlobalStream->LoadAllData(pGlobals, FALSE); + } + } + m_pCachedBitmap = FX_NEW CFX_DIBitmap; + if (!m_pCachedBitmap->Create(m_Width, m_Height, m_bImageMask ? FXDIB_1bppMask : FXDIB_1bppRgb)) { + return; + } + int ret = pJbig2Module->Decode(m_Width, m_Height, m_pStreamAcc->GetData(), m_pStreamAcc->GetSize(), + pGlobalStream ? pGlobalStream->GetData() : NULL, pGlobalStream ? pGlobalStream->GetSize() : 0, + m_pCachedBitmap->GetBuffer(), m_pCachedBitmap->GetPitch()); + if (ret < 0) { + delete m_pCachedBitmap; + m_pCachedBitmap = NULL; + } + if (pGlobalStream) { + delete pGlobalStream; + } + m_bpc = 1; + m_nComponents = 1; +} +CPDF_DIBSource* CPDF_DIBSource::LoadMask(FX_DWORD& MatteColor) +{ + MatteColor = 0xffffffff; + CPDF_Stream* pSoftMask = m_pDict->GetStream(FX_BSTRC("SMask")); + if (pSoftMask) { + CPDF_Array* pMatte = pSoftMask->GetDict()->GetArray(FX_BSTRC("Matte")); + if (pMatte != NULL && m_pColorSpace && (FX_DWORD)m_pColorSpace->CountComponents() <= m_nComponents) { + FX_FLOAT* pColor = FX_Alloc(FX_FLOAT, m_nComponents); + for (FX_DWORD i = 0; i < m_nComponents; i ++) { + pColor[i] = pMatte->GetFloat(i); + } + FX_FLOAT R, G, B; + m_pColorSpace->GetRGB(pColor, R, G, B); + FX_Free(pColor); + MatteColor = FXARGB_MAKE(0, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255)); + } + return LoadMaskDIB(pSoftMask); + } + CPDF_Object* pMask = m_pDict->GetElementValue(FX_BSTRC("Mask")); + if (pMask == NULL) { + return NULL; + } + if (pMask->GetType() == PDFOBJ_STREAM) { + return LoadMaskDIB((CPDF_Stream*)pMask); + } + return NULL; +} +int CPDF_DIBSource::StratLoadMask() +{ + m_MatteColor = 0xffffffff; + m_pMaskStream = m_pDict->GetStream(FX_BSTRC("SMask")); + if (m_pMaskStream) { + CPDF_Array* pMatte = m_pMaskStream->GetDict()->GetArray(FX_BSTRC("Matte")); + if (pMatte != NULL && m_pColorSpace && (FX_DWORD)m_pColorSpace->CountComponents() <= m_nComponents) { + FX_FLOAT R, G, B; + FX_FLOAT* pColor = FX_Alloc(FX_FLOAT, m_nComponents); + for (FX_DWORD i = 0; i < m_nComponents; i ++) { + pColor[i] = pMatte->GetFloat(i); + } + m_pColorSpace->GetRGB(pColor, R, G, B); + FX_Free(pColor); + m_MatteColor = FXARGB_MAKE(0, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255)); + } + return StartLoadMaskDIB(); + } + m_pMaskStream = m_pDict->GetElementValue(FX_BSTRC("Mask")); + if (m_pMaskStream == NULL) { + return 1; + } + if (m_pMaskStream->GetType() == PDFOBJ_STREAM) { + return StartLoadMaskDIB(); + } + return 1; +} +int CPDF_DIBSource::ContinueLoadMaskDIB(IFX_Pause* pPause) +{ + if (m_pMask == NULL) { + return 1; + } + int ret = m_pMask->ContinueLoadDIBSource(pPause); + if (ret == 2) { + return ret; + } + if (m_pColorSpace && m_bStdCS) { + m_pColorSpace->EnableStdConversion(FALSE); + } + if (!ret) { + delete m_pMask; + m_pMask = NULL; + return ret; + } + return 1; +} +CPDF_DIBSource* CPDF_DIBSource::DetachMask() +{ + CPDF_DIBSource* pDIBSource = m_pMask; + m_pMask = NULL; + return pDIBSource; +} +CPDF_DIBSource* CPDF_DIBSource::LoadMaskDIB(CPDF_Stream* pMask) +{ + CPDF_DIBSource* pMaskSource = FX_NEW CPDF_DIBSource; + if (!pMaskSource->Load(m_pDocument, pMask, NULL, NULL, NULL, NULL, TRUE)) { + delete pMaskSource; + return NULL; + } + return pMaskSource; +} +int CPDF_DIBSource::StartLoadMaskDIB() +{ + m_pMask = FX_NEW CPDF_DIBSource; + int ret = m_pMask->StartLoadDIBSource(m_pDocument, (CPDF_Stream*)m_pMaskStream, FALSE, NULL, NULL, TRUE); + if (ret == 2) { + if (m_Status == 0) { + m_Status = 2; + } + return 2; + } + if (!ret) { + delete m_pMask; + m_pMask = NULL; + return 1; + } + return 1; +} +void CPDF_DIBSource::LoadPalette() +{ + if (m_bpc * m_nComponents > 8) { + return; + } + if (m_pColorSpace == NULL) { + return; + } + if (m_bpc * m_nComponents == 1) { + if (m_bDefaultDecode && (m_Family == PDFCS_DEVICEGRAY || m_Family == PDFCS_DEVICERGB)) { + return; + } + if (m_pColorSpace->CountComponents() > 3) { + return; + } + FX_FLOAT color_values[3]; + color_values[0] = m_pCompData[0].m_DecodeMin; + color_values[1] = color_values[2] = color_values[0]; + FX_FLOAT R, G, B; + m_pColorSpace->GetRGB(color_values, R, G, B); + FX_ARGB argb0 = ArgbEncode(255, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255)); + color_values[0] += m_pCompData[0].m_DecodeStep; + color_values[1] += m_pCompData[0].m_DecodeStep; + color_values[2] += m_pCompData[0].m_DecodeStep; + m_pColorSpace->GetRGB(color_values, R, G, B); + FX_ARGB argb1 = ArgbEncode(255, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255)); + if (argb0 != 0xFF000000 || argb1 != 0xFFFFFFFF) { + SetPaletteArgb(0, argb0); + SetPaletteArgb(1, argb1); + } + return; + } + if (m_pColorSpace == CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY) && m_bpc == 8 && m_bDefaultDecode) { + } else { + int palette_count = 1 << (m_bpc * m_nComponents); + CFX_FixedBufGrow<FX_FLOAT, 16> color_values(m_nComponents); + FX_FLOAT* color_value = color_values; + for (int i = 0; i < palette_count; i ++) { + int color_data = i; + for (FX_DWORD j = 0; j < m_nComponents; j ++) { + int encoded_component = color_data % (1 << m_bpc); + color_data /= 1 << m_bpc; + color_value[j] = m_pCompData[j].m_DecodeMin + m_pCompData[j].m_DecodeStep * encoded_component; + } + FX_FLOAT R = 0, G = 0, B = 0; + if (m_nComponents == 1 && m_Family == PDFCS_ICCBASED && m_pColorSpace->CountComponents() > 1) { + int nComponents = m_pColorSpace->CountComponents(); + FX_FLOAT* temp_buf = FX_Alloc(FX_FLOAT, nComponents); + for (int i = 0; i < nComponents; i++) { + temp_buf[i] = *color_value; + } + m_pColorSpace->GetRGB(temp_buf, R, G, B); + FX_Free(temp_buf); + } else { + m_pColorSpace->GetRGB(color_value, R, G, B); + } + SetPaletteArgb(i, ArgbEncode(255, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255))); + } + } +} + +FX_DWORD CPDF_DIBSource::GetValidBpp() const +{ + FX_DWORD bpc = m_bpc; + CPDF_Object * pFilter = m_pDict->GetElementValue(FX_BSTRC("Filter")); + if(pFilter) + { + if(pFilter->GetType() == PDFOBJ_NAME) + { + CFX_ByteString filter = pFilter->GetString(); + if(filter == FX_BSTRC("CCITTFaxDecode") || filter == FX_BSTRC("JBIG2Decode") ) + bpc = 1; + if(filter == FX_BSTRC("RunLengthDecode") || filter == FX_BSTRC("DCTDecode") ) + bpc = 8; + } + else if (pFilter->GetType() == PDFOBJ_ARRAY) + { + CPDF_Array *pArray = (CPDF_Array *) pFilter; + if( pArray->GetString(pArray->GetCount() -1) == FX_BSTRC("CCITTFacDecode") || + pArray->GetString(pArray->GetCount() -1) == FX_BSTRC("JBIG2Decode") ) + bpc = 1; + + if( pArray->GetString(pArray->GetCount() -1) == FX_BSTRC("RunLengthDecode") || + pArray->GetString(pArray->GetCount() -1) == FX_BSTRC("DCTDecode") ) + bpc = 8; + } + } + + return bpc; +} + +#define NORMALCOLOR_MAX(color, max) (color) > (max) ? (max) : (color) < 0 ? 0 : (color); +void CPDF_DIBSource::TranslateScanline24bpp(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan) const +{ + int max_data = (1 << m_bpc) - 1; + if (m_bDefaultDecode) { + if (m_Family == PDFCS_DEVICERGB || m_Family == PDFCS_CALRGB) { + if (m_bpc == 16) { + FX_LPBYTE dest_pos = dest_scan; + FX_LPCBYTE src_pos = src_scan; + for (int col = 0; col < m_Width; col ++) { + *dest_scan++ = src_pos[4]; + *dest_scan++ = src_pos[2]; + *dest_scan++ = *src_pos; + src_pos += 6; + } + } else if (m_bpc == 8) { + FX_LPBYTE dest_pos = dest_scan; + FX_LPCBYTE src_pos = src_scan; + for (int column = 0; column < m_Width; column ++) { + *dest_scan++ = src_pos[2]; + *dest_scan++ = src_pos[1]; + *dest_scan++ = *src_pos; + src_pos += 3; + } + } else { + int src_bit_pos = 0; + int dest_byte_pos = 0; + + FX_DWORD bpc = GetValidBpp(); + + for (int column = 0; column < m_Width; column ++) { + int R = _GetBits8(src_scan, src_bit_pos, bpc); + src_bit_pos += bpc; + int G = _GetBits8(src_scan, src_bit_pos, bpc); + src_bit_pos += bpc; + int B = _GetBits8(src_scan, src_bit_pos, bpc); + src_bit_pos += bpc; + R = NORMALCOLOR_MAX(R, max_data); + G = NORMALCOLOR_MAX(G, max_data); + B = NORMALCOLOR_MAX(B, max_data); + dest_scan[dest_byte_pos] = B * 255 / max_data; + dest_scan[dest_byte_pos + 1] = G * 255 / max_data; + dest_scan[dest_byte_pos + 2] = R * 255 / max_data; + dest_byte_pos += 3; + } + } + return; + } else if (m_bpc == 8) { + if (m_nComponents == m_pColorSpace->CountComponents()) + m_pColorSpace->TranslateImageLine(dest_scan, src_scan, m_Width, m_Width, m_Height, + m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK); + return; + } + } + CFX_FixedBufGrow<FX_FLOAT, 16> color_values1(m_nComponents); + FX_FLOAT* color_values = color_values1; + FX_FLOAT R, G, B; + if (m_bpc == 8) { + int src_byte_pos = 0; + int dest_byte_pos = 0; + for (int column = 0; column < m_Width; column ++) { + for (FX_DWORD color = 0; color < m_nComponents; color ++) { + int data = src_scan[src_byte_pos ++]; + color_values[color] = m_pCompData[color].m_DecodeMin + + m_pCompData[color].m_DecodeStep * data; + } + if (m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK) { + FX_FLOAT k = 1.0f - color_values[3]; + R = (1.0f - color_values[0]) * k; + G = (1.0f - color_values[1]) * k; + B = (1.0f - color_values[2]) * k; + } else { + m_pColorSpace->GetRGB(color_values, R, G, B); + } + R = NORMALCOLOR_MAX(R, 1); + G = NORMALCOLOR_MAX(G, 1); + B = NORMALCOLOR_MAX(B, 1); + dest_scan[dest_byte_pos] = (FX_INT32)(B * 255); + dest_scan[dest_byte_pos + 1] = (FX_INT32)(G * 255); + dest_scan[dest_byte_pos + 2] = (FX_INT32)(R * 255); + dest_byte_pos += 3; + } + } else { + int src_bit_pos = 0; + int dest_byte_pos = 0; + + FX_DWORD bpc = GetValidBpp(); + + for (int column = 0; column < m_Width; column ++) { + for (FX_DWORD color = 0; color < m_nComponents; color ++) { + int data = _GetBits8(src_scan, src_bit_pos, bpc); + color_values[color] = m_pCompData[color].m_DecodeMin + + m_pCompData[color].m_DecodeStep * data; + src_bit_pos += bpc; + } + if (m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK) { + FX_FLOAT k = 1.0f - color_values[3]; + R = (1.0f - color_values[0]) * k; + G = (1.0f - color_values[1]) * k; + B = (1.0f - color_values[2]) * k; + } else { + m_pColorSpace->GetRGB(color_values, R, G, B); + } + R = NORMALCOLOR_MAX(R, 1); + G = NORMALCOLOR_MAX(G, 1); + B = NORMALCOLOR_MAX(B, 1); + dest_scan[dest_byte_pos] = (FX_INT32)(B * 255); + dest_scan[dest_byte_pos + 1] = (FX_INT32)(G * 255); + dest_scan[dest_byte_pos + 2] = (FX_INT32)(R * 255); + dest_byte_pos += 3; + } + } +} +FX_LPBYTE CPDF_DIBSource::GetBuffer() const +{ + if (m_pCachedBitmap) { + return m_pCachedBitmap->GetBuffer(); + } + return NULL; +} +FX_LPCBYTE CPDF_DIBSource::GetScanline(int line) const +{ + FX_DWORD src_pitch = (m_Width * m_bpc * m_nComponents + 7) / 8; + FX_LPCBYTE pSrcLine = NULL; + if (m_pCachedBitmap) { + if (line >= m_pCachedBitmap->GetHeight()) { + line = m_pCachedBitmap->GetHeight() - 1; + } + pSrcLine = m_pCachedBitmap->GetScanline(line); + } else if (m_pDecoder) { + pSrcLine = m_pDecoder->GetScanline(line); + } else { + if (m_pStreamAcc->GetSize() >= (line + 1) * src_pitch) { + pSrcLine = m_pStreamAcc->GetData() + line * src_pitch; + } + } + if (pSrcLine == NULL) { + FX_LPBYTE pLineBuf = m_pMaskedLine ? m_pMaskedLine : m_pLineBuf; + FXSYS_memset8(pLineBuf, 0xff, m_Pitch); + return pLineBuf; + } + if (m_bpc * m_nComponents == 1) { + if (m_bImageMask && m_bDefaultDecode) { + for (FX_DWORD i = 0; i < src_pitch; i ++) { + m_pLineBuf[i] = ~pSrcLine[i]; + } + } else if (m_bColorKey) { + FX_DWORD reset_argb, set_argb; + reset_argb = m_pPalette ? m_pPalette[0] : 0xff000000; + set_argb = m_pPalette ? m_pPalette[1] : 0xffffffff; + if (m_pCompData[0].m_ColorKeyMin == 0) { + reset_argb = 0; + } + if (m_pCompData[0].m_ColorKeyMax == 1) { + set_argb = 0; + } + set_argb = FXARGB_TODIB(set_argb); + reset_argb = FXARGB_TODIB(reset_argb); + FX_DWORD* dest_scan = (FX_DWORD*)m_pMaskedLine; + for (int col = 0; col < m_Width; col ++) { + if (pSrcLine[col / 8] & (1 << (7 - col % 8))) { + *dest_scan = set_argb; + } else { + *dest_scan = reset_argb; + } + dest_scan ++; + } + return m_pMaskedLine; + } else { + FXSYS_memcpy32(m_pLineBuf, pSrcLine, src_pitch); + } + return m_pLineBuf; + } + if (m_bpc * m_nComponents <= 8) { + if (m_bpc == 8) { + FXSYS_memcpy32(m_pLineBuf, pSrcLine, src_pitch); + } else { + int src_bit_pos = 0; + for (int col = 0; col < m_Width; col ++) { + int color_index = 0; + for (FX_DWORD color = 0; color < m_nComponents; color ++) { + int data = _GetBits8(pSrcLine, src_bit_pos, m_bpc); + color_index |= data << (color * m_bpc); + src_bit_pos += m_bpc; + } + m_pLineBuf[col] = color_index; + } + } + if (m_bColorKey) { + FX_LPBYTE pDestPixel = m_pMaskedLine; + FX_LPCBYTE pSrcPixel = m_pLineBuf; + for (int col = 0; col < m_Width; col ++) { + FX_BYTE index = *pSrcPixel++; + if (m_pPalette) { + *pDestPixel++ = FXARGB_B(m_pPalette[index]); + *pDestPixel++ = FXARGB_G(m_pPalette[index]); + *pDestPixel++ = FXARGB_R(m_pPalette[index]); + } else { + *pDestPixel++ = index; + *pDestPixel++ = index; + *pDestPixel++ = index; + } + *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin || index > m_pCompData[0].m_ColorKeyMax) ? 0xff : 0; + pDestPixel ++ ; + } + return m_pMaskedLine; + } + return m_pLineBuf; + } + if (m_bColorKey) { + if (m_nComponents == 3 && m_bpc == 8) { + FX_LPBYTE alpha_channel = m_pMaskedLine + 3; + for (int col = 0; col < m_Width; col ++) { + FX_LPCBYTE pPixel = pSrcLine + col * 3; + alpha_channel[col * 4] = (pPixel[0] < m_pCompData[0].m_ColorKeyMin || + pPixel[0] > m_pCompData[0].m_ColorKeyMax || + pPixel[1] < m_pCompData[1].m_ColorKeyMin || pPixel[1] > m_pCompData[1].m_ColorKeyMax || + pPixel[2] < m_pCompData[2].m_ColorKeyMin || pPixel[2] > m_pCompData[2].m_ColorKeyMax) ? 0xff : 0; + } + } else { + FXSYS_memset8(m_pMaskedLine, 0xff, m_Pitch); + } + } + if (m_pColorSpace) { + TranslateScanline24bpp(m_pLineBuf, pSrcLine); + pSrcLine = m_pLineBuf; + } + if (m_bColorKey) { + FX_LPCBYTE pSrcPixel = pSrcLine; + FX_LPBYTE pDestPixel = m_pMaskedLine; + for (int col = 0; col < m_Width; col ++) { + *pDestPixel++ = *pSrcPixel++; + *pDestPixel++ = *pSrcPixel++; + *pDestPixel++ = *pSrcPixel++; + pDestPixel ++; + } + return m_pMaskedLine; + } + return pSrcLine; +} +FX_BOOL CPDF_DIBSource::SkipToScanline(int line, IFX_Pause* pPause) const +{ + if (m_pDecoder) { + return m_pDecoder->SkipToScanline(line, pPause); + } + return FALSE; +} +void CPDF_DIBSource::DownSampleScanline(int line, FX_LPBYTE dest_scan, int dest_bpp, + int dest_width, FX_BOOL bFlipX, int clip_left, int clip_width) const +{ + FX_DWORD src_width = m_Width; + FX_DWORD src_pitch = (src_width * m_bpc * m_nComponents + 7) / 8; + FX_LPCBYTE pSrcLine = NULL; + if (m_pCachedBitmap) { + pSrcLine = m_pCachedBitmap->GetScanline(line); + } else if (m_pDecoder) { + pSrcLine = m_pDecoder->GetScanline(line); + } else { + if (m_pStreamAcc->GetSize() >= (line + 1) * src_pitch) { + pSrcLine = m_pStreamAcc->GetData() + line * src_pitch; + } + } + int orig_Bpp = m_bpc * m_nComponents / 8; + int dest_Bpp = dest_bpp / 8; + if (pSrcLine == NULL) { + FXSYS_memset32(dest_scan, 0xff, dest_Bpp * clip_width); + return; + } + CFX_FixedBufGrow<FX_BYTE, 128> temp(orig_Bpp); + if (m_bpc * m_nComponents == 1) { + FX_DWORD set_argb = (FX_DWORD) - 1, reset_argb = 0; + if (m_bImageMask) { + if (m_bDefaultDecode) { + set_argb = 0; + reset_argb = (FX_DWORD) - 1; + } + } else if (m_bColorKey) { + reset_argb = m_pPalette ? m_pPalette[0] : 0xff000000; + set_argb = m_pPalette ? m_pPalette[1] : 0xffffffff; + if (m_pCompData[0].m_ColorKeyMin == 0) { + reset_argb = 0; + } + if (m_pCompData[0].m_ColorKeyMax == 1) { + set_argb = 0; + } + set_argb = FXARGB_TODIB(set_argb); + reset_argb = FXARGB_TODIB(reset_argb); + for (int i = 0; i < clip_width; i ++) { + FX_DWORD src_x = (clip_left + i) * src_width / dest_width; + if (bFlipX) { + src_x = src_width - src_x - 1; + } + src_x %= src_width; + if (pSrcLine[src_x / 8] & (1 << (7 - src_x % 8))) { + ((FX_DWORD*)dest_scan)[i] = set_argb; + } else { + ((FX_DWORD*)dest_scan)[i] = reset_argb; + } + } + return; + } else { + if (dest_Bpp == 1) { + } else if (m_pPalette) { + reset_argb = m_pPalette[0]; + set_argb = m_pPalette[1]; + } + } + for (int i = 0; i < clip_width; i ++) { + FX_DWORD src_x = (clip_left + i) * src_width / dest_width; + if (bFlipX) { + src_x = src_width - src_x - 1; + } + src_x %= src_width; + int dest_pos = i * dest_Bpp; + if (pSrcLine[src_x / 8] & (1 << (7 - src_x % 8))) { + if (dest_Bpp == 1) { + dest_scan[dest_pos] = (FX_BYTE)set_argb; + } else if (dest_Bpp == 3) { + dest_scan[dest_pos] = FXARGB_B(set_argb); + dest_scan[dest_pos + 1] = FXARGB_G(set_argb); + dest_scan[dest_pos + 2] = FXARGB_R(set_argb); + } else { + *(FX_DWORD*)(dest_scan + dest_pos) = set_argb; + } + } else { + if (dest_Bpp == 1) { + dest_scan[dest_pos] = (FX_BYTE)reset_argb; + } else if (dest_Bpp == 3) { + dest_scan[dest_pos] = FXARGB_B(reset_argb); + dest_scan[dest_pos + 1] = FXARGB_G(reset_argb); + dest_scan[dest_pos + 2] = FXARGB_R(reset_argb); + } else { + *(FX_DWORD*)(dest_scan + dest_pos) = reset_argb; + } + } + } + return; + } else if (m_bpc * m_nComponents <= 8) { + if (m_bpc < 8) { + int src_bit_pos = 0; + for (FX_DWORD col = 0; col < src_width; col ++) { + int color_index = 0; + for (FX_DWORD color = 0; color < m_nComponents; color ++) { + int data = _GetBits8(pSrcLine, src_bit_pos, m_bpc); + color_index |= data << (color * m_bpc); + src_bit_pos += m_bpc; + } + m_pLineBuf[col] = color_index; + } + pSrcLine = m_pLineBuf; + } + if (m_bColorKey) { + for (int i = 0; i < clip_width; i ++) { + FX_DWORD src_x = (clip_left + i) * src_width / dest_width; + if (bFlipX) { + src_x = src_width - src_x - 1; + } + src_x %= src_width; + FX_LPBYTE pDestPixel = dest_scan + i * 4; + FX_BYTE index = pSrcLine[src_x]; + if (m_pPalette) { + *pDestPixel++ = FXARGB_B(m_pPalette[index]); + *pDestPixel++ = FXARGB_G(m_pPalette[index]); + *pDestPixel++ = FXARGB_R(m_pPalette[index]); + } else { + *pDestPixel++ = index; + *pDestPixel++ = index; + *pDestPixel++ = index; + } + *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin || index > m_pCompData[0].m_ColorKeyMax) ? 0xff : 0; + } + return; + } + for (int i = 0; i < clip_width; i ++) { + FX_DWORD src_x = (clip_left + i) * src_width / dest_width; + if (bFlipX) { + src_x = src_width - src_x - 1; + } + src_x %= src_width; + FX_BYTE index = pSrcLine[src_x]; + if (dest_Bpp == 1) { + dest_scan[i] = index; + } else { + int dest_pos = i * dest_Bpp; + FX_ARGB argb = m_pPalette[index]; + dest_scan[dest_pos] = FXARGB_B(argb); + dest_scan[dest_pos + 1] = FXARGB_G(argb); + dest_scan[dest_pos + 2] = FXARGB_R(argb); + } + } + return; + } else { + int last_src_x = -1; + FX_ARGB last_argb; + FX_FLOAT orig_Not8Bpp = (FX_FLOAT)m_bpc * (FX_FLOAT)m_nComponents / 8.0f; + FX_FLOAT unit_To8Bpc = 255.0f / ((1 << m_bpc) - 1); + for (int i = 0; i < clip_width; i ++) { + int dest_x = clip_left + i; + FX_DWORD src_x = (bFlipX ? (dest_width - dest_x - 1) : dest_x) * (FX_INT64)src_width / dest_width; + src_x %= src_width; + FX_LPCBYTE pSrcPixel = NULL; + if (m_bpc % 8 == 0) { + pSrcPixel = pSrcLine + src_x * orig_Bpp; + } else { + pSrcPixel = pSrcLine + (int)(src_x * orig_Not8Bpp); + } + FX_LPBYTE pDestPixel = dest_scan + i * dest_Bpp; + FX_ARGB argb; + if (src_x == last_src_x) { + argb = last_argb; + } else { + if (m_pColorSpace) { + FX_BYTE color[4]; + if (!m_bDefaultDecode) { + for (int i = 0; i < orig_Bpp; i ++) { + int color_value = (int)((m_pCompData[i].m_DecodeMin + m_pCompData[i].m_DecodeStep * (FX_FLOAT)pSrcPixel[i]) * 255.0f + 0.5f); + temp[i] = color_value > 255 ? 255 : (color_value < 0 ? 0 : color_value); + } + m_pColorSpace->TranslateImageLine(color, temp, 1, 0, 0, m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK); + } else { + if (m_bpc < 8) { + int src_bit_pos = 0; + if (src_x % 2) { + src_bit_pos = 4; + } + int value = (1 << m_bpc) - 1; + for (FX_DWORD i = 0; i < m_nComponents; i ++) { + temp[i] = (FX_BYTE)(_GetBits8(pSrcPixel, src_bit_pos, m_bpc) * unit_To8Bpc); + src_bit_pos += m_bpc; + } + m_pColorSpace->TranslateImageLine(color, temp, 1, 0, 0, m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK); + } else { + m_pColorSpace->TranslateImageLine(color, pSrcPixel, 1, 0, 0, m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && m_Family == PDFCS_DEVICECMYK); + } + } + argb = FXARGB_MAKE(0xff, color[2], color[1], color[0]); + } else { + argb = FXARGB_MAKE(0xff, pSrcPixel[2], pSrcPixel[1], pSrcPixel[0]); + } + if (m_bColorKey) { + int alpha = 0xff; + if (m_nComponents == 3 && m_bpc == 8) { + alpha = (pSrcPixel[0] < m_pCompData[0].m_ColorKeyMin || + pSrcPixel[0] > m_pCompData[0].m_ColorKeyMax || + pSrcPixel[1] < m_pCompData[1].m_ColorKeyMin || + pSrcPixel[1] > m_pCompData[1].m_ColorKeyMax || + pSrcPixel[2] < m_pCompData[2].m_ColorKeyMin || + pSrcPixel[2] > m_pCompData[2].m_ColorKeyMax) ? 0xff : 0; + } + argb &= 0xffffff; + argb |= alpha << 24; + } + last_src_x = src_x; + last_argb = argb; + } + if (dest_Bpp == 4) { + *(FX_DWORD*)pDestPixel = FXARGB_TODIB(argb); + } else { + *pDestPixel++ = FXARGB_B(argb); + *pDestPixel++ = FXARGB_G(argb); + *pDestPixel = FXARGB_R(argb); + } + } + } +} +void CPDF_DIBSource::SetDownSampleSize(int dest_width, int dest_height) const +{ + if (m_pDecoder) { + m_pDecoder->DownScale(dest_width, dest_height); + ((CPDF_DIBSource*)this)->m_Width = m_pDecoder->GetWidth(); + ((CPDF_DIBSource*)this)->m_Height = m_pDecoder->GetHeight(); + } +} +void CPDF_DIBSource::ClearImageData() +{ + if (m_pDecoder) { + m_pDecoder->ClearImageData(); + } +} +CPDF_ProgressiveImageLoaderHandle::CPDF_ProgressiveImageLoaderHandle() +{ + m_pImageLoader = NULL; + m_pCache = NULL; + m_pImage = NULL; +} +CPDF_ProgressiveImageLoaderHandle::~CPDF_ProgressiveImageLoaderHandle() +{ + m_pImageLoader = NULL; + m_pCache = NULL; + m_pImage = NULL; +} +FX_BOOL CPDF_ProgressiveImageLoaderHandle::Start(CPDF_ImageLoader* pImageLoader, const CPDF_ImageObject* pImage, CPDF_PageRenderCache* pCache, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus, FX_INT32 nDownsampleWidth, FX_INT32 nDownsampleHeight) +{ + m_pImageLoader = pImageLoader; + m_pCache = pCache; + m_pImage = (CPDF_ImageObject*)pImage; + m_nDownsampleWidth = nDownsampleWidth; + m_nDownsampleHeight = nDownsampleHeight; + FX_BOOL ret; + if (pCache) { + ret = pCache->StartGetCachedBitmap(pImage->m_pImage->GetStream(), bStdCS, GroupFamily, bLoadMask, pRenderStatus, m_nDownsampleWidth, m_nDownsampleHeight); + if (ret == FALSE) { + m_pImageLoader->m_bCached = TRUE; + m_pImageLoader->m_pBitmap = pCache->m_pCurImageCache->DetachBitmap(); + m_pImageLoader->m_pMask = pCache->m_pCurImageCache->DetachMask(); + m_pImageLoader->m_MatteColor = pCache->m_pCurImageCache->m_MatteColor; + } + } else { + ret = pImage->m_pImage->StartLoadDIBSource(pRenderStatus->m_pFormResource, pRenderStatus->m_pPageResource, bStdCS, GroupFamily, bLoadMask); + if (ret == FALSE) { + m_pImageLoader->m_bCached = FALSE; + m_pImageLoader->m_pBitmap = m_pImage->m_pImage->DetachBitmap(); + m_pImageLoader->m_pMask = m_pImage->m_pImage->DetachMask(); + m_pImageLoader->m_MatteColor = m_pImage->m_pImage->m_MatteColor; + } + } + return ret; +} +FX_BOOL CPDF_ProgressiveImageLoaderHandle::Continue(IFX_Pause* pPause) +{ + FX_BOOL ret; + if (m_pCache) { + ret = m_pCache->Continue(pPause); + if (ret == FALSE) { + m_pImageLoader->m_bCached = TRUE; + m_pImageLoader->m_pBitmap = m_pCache->m_pCurImageCache->DetachBitmap(); + m_pImageLoader->m_pMask = m_pCache->m_pCurImageCache->DetachMask(); + m_pImageLoader->m_MatteColor = m_pCache->m_pCurImageCache->m_MatteColor; + } + } else { + ret = m_pImage->m_pImage->Continue(pPause); + if (ret == FALSE) { + m_pImageLoader->m_bCached = FALSE; + m_pImageLoader->m_pBitmap = m_pImage->m_pImage->DetachBitmap(); + m_pImageLoader->m_pMask = m_pImage->m_pImage->DetachMask(); + m_pImageLoader->m_MatteColor = m_pImage->m_pImage->m_MatteColor; + } + } + return ret; +} +FX_BOOL CPDF_ImageLoader::Load(const CPDF_ImageObject* pImage, CPDF_PageRenderCache* pCache, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus) +{ + if (pImage == NULL) { + return FALSE; + } + if (pCache) { + pCache->GetCachedBitmap(pImage->m_pImage->GetStream(), m_pBitmap, m_pMask, m_MatteColor, bStdCS, GroupFamily, bLoadMask, pRenderStatus, m_nDownsampleWidth, m_nDownsampleHeight); + m_bCached = TRUE; + } else { + m_pBitmap = pImage->m_pImage->LoadDIBSource(&m_pMask, &m_MatteColor, bStdCS, GroupFamily, bLoadMask); + m_bCached = FALSE; + } + return FALSE; +} +FX_BOOL CPDF_ImageLoader::StartLoadImage(const CPDF_ImageObject* pImage, CPDF_PageRenderCache* pCache, FX_LPVOID& LoadHandle, FX_BOOL bStdCS, FX_DWORD GroupFamily, FX_BOOL bLoadMask, CPDF_RenderStatus* pRenderStatus, FX_INT32 nDownsampleWidth, FX_INT32 nDownsampleHeight) +{ + m_nDownsampleWidth = nDownsampleWidth; + m_nDownsampleHeight = nDownsampleHeight; + CPDF_ProgressiveImageLoaderHandle* pLoaderHandle = NULL; + pLoaderHandle = FX_NEW CPDF_ProgressiveImageLoaderHandle; + FX_BOOL ret = pLoaderHandle->Start(this, pImage, pCache, bStdCS, GroupFamily, bLoadMask, pRenderStatus, m_nDownsampleWidth, m_nDownsampleHeight); + LoadHandle = pLoaderHandle; + return ret; +} +FX_BOOL CPDF_ImageLoader::Continue(FX_LPVOID LoadHandle, IFX_Pause* pPause) +{ + return ((CPDF_ProgressiveImageLoaderHandle*)LoadHandle)->Continue(pPause); +} +CPDF_ImageLoader::~CPDF_ImageLoader() +{ + if (!m_bCached) { + if (m_pBitmap) { + delete m_pBitmap; + m_pBitmap = NULL; + } + if (m_pMask) { + delete m_pMask; + } + } +} diff --git a/core/src/fpdfapi/fpdf_render/fpdf_render_pattern.cpp b/core/src/fpdfapi/fpdf_render/fpdf_render_pattern.cpp index 8cc30a72a1..4b4f929179 100644 --- a/core/src/fpdfapi/fpdf_render/fpdf_render_pattern.cpp +++ b/core/src/fpdfapi/fpdf_render/fpdf_render_pattern.cpp @@ -1,1093 +1,1093 @@ -// 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/fpdfapi/fpdf_render.h"
-#include "../../../include/fpdfapi/fpdf_pageobj.h"
-#include "../../../include/fxge/fx_ge.h"
-#include "../fpdf_page/pageint.h"
-#include "render_int.h"
-#define SHADING_STEPS 256
-static void _DrawAxialShading(CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pObject2Bitmap,
- CPDF_Dictionary* pDict, CPDF_Function** pFuncs, int nFuncs,
- CPDF_ColorSpace* pCS, int alpha)
-{
- ASSERT(pBitmap->GetFormat() == FXDIB_Argb);
- CPDF_Array* pCoords = pDict->GetArray(FX_BSTRC("Coords"));
- if (pCoords == NULL) {
- return;
- }
- FX_FLOAT start_x = pCoords->GetNumber(0);
- FX_FLOAT start_y = pCoords->GetNumber(1);
- FX_FLOAT end_x = pCoords->GetNumber(2);
- FX_FLOAT end_y = pCoords->GetNumber(3);
- FX_FLOAT t_min = 0, t_max = 1.0f;
- CPDF_Array* pArray = pDict->GetArray(FX_BSTRC("Domain"));
- if (pArray) {
- t_min = pArray->GetNumber(0);
- t_max = pArray->GetNumber(1);
- }
- FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE;
- pArray = pDict->GetArray(FX_BSTRC("Extend"));
- if (pArray) {
- bStartExtend = pArray->GetInteger(0);
- bEndExtend = pArray->GetInteger(1);
- }
- int width = pBitmap->GetWidth();
- int height = pBitmap->GetHeight();
- FX_FLOAT x_span = end_x - start_x;
- FX_FLOAT y_span = end_y - start_y;
- FX_FLOAT axis_len_square = FXSYS_Mul(x_span, x_span) + FXSYS_Mul(y_span, y_span);
- CFX_AffineMatrix matrix;
- matrix.SetReverse(*pObject2Bitmap);
- int total_results = 0;
- for (int j = 0; j < nFuncs; j ++) {
- if (pFuncs[j]) {
- total_results += pFuncs[j]->CountOutputs();
- }
- }
- if (pCS->CountComponents() > total_results) {
- total_results = pCS->CountComponents();
- }
- CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results);
- FX_FLOAT* pResults = result_array;
- FXSYS_memset32(pResults, 0, total_results * sizeof(FX_FLOAT));
- FX_DWORD rgb_array[SHADING_STEPS];
- for (int i = 0; i < SHADING_STEPS; i ++) {
- FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min;
- int offset = 0;
- for (int j = 0; j < nFuncs; j ++) {
- if (pFuncs[j]) {
- int nresults = 0;
- if (pFuncs[j]->Call(&input, 1, pResults + offset, nresults)) {
- offset += nresults;
- }
- }
- }
- FX_FLOAT R, G, B;
- pCS->GetRGB(pResults, R, G, B);
- rgb_array[i] = FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255)));
- }
- int pitch = pBitmap->GetPitch();
- int Bpp = pBitmap->GetBPP() / 8;
- for (int row = 0; row < height; row ++) {
- FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch);
- for (int column = 0; column < width; column ++) {
- FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row;
- matrix.Transform(x, y);
- FX_FLOAT scale = FXSYS_Div(FXSYS_Mul(x - start_x, x_span) + FXSYS_Mul(y - start_y, y_span), axis_len_square);
- int index = (FX_INT32)(scale * (SHADING_STEPS - 1));
- if (index < 0) {
- if (!bStartExtend) {
- continue;
- }
- index = 0;
- } else if (index >= SHADING_STEPS) {
- if (!bEndExtend) {
- continue;
- }
- index = SHADING_STEPS - 1;
- }
- dib_buf[column] = rgb_array[index];
- }
- }
-}
-static void _DrawRadialShading(CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pObject2Bitmap,
- CPDF_Dictionary* pDict, CPDF_Function** pFuncs, int nFuncs,
- CPDF_ColorSpace* pCS, int alpha)
-{
- ASSERT(pBitmap->GetFormat() == FXDIB_Argb);
- CPDF_Array* pCoords = pDict->GetArray(FX_BSTRC("Coords"));
- if (pCoords == NULL) {
- return;
- }
- FX_FLOAT start_x = pCoords->GetNumber(0);
- FX_FLOAT start_y = pCoords->GetNumber(1);
- FX_FLOAT start_r = pCoords->GetNumber(2);
- FX_FLOAT end_x = pCoords->GetNumber(3);
- FX_FLOAT end_y = pCoords->GetNumber(4);
- FX_FLOAT end_r = pCoords->GetNumber(5);
- CFX_AffineMatrix matrix;
- matrix.SetReverse(*pObject2Bitmap);
- FX_FLOAT t_min = 0, t_max = 1.0f;
- CPDF_Array* pArray = pDict->GetArray(FX_BSTRC("Domain"));
- if (pArray) {
- t_min = pArray->GetNumber(0);
- t_max = pArray->GetNumber(1);
- }
- FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE;
- pArray = pDict->GetArray(FX_BSTRC("Extend"));
- if (pArray) {
- bStartExtend = pArray->GetInteger(0);
- bEndExtend = pArray->GetInteger(1);
- }
- int total_results = 0;
- for (int j = 0; j < nFuncs; j ++) {
- if (pFuncs[j]) {
- total_results += pFuncs[j]->CountOutputs();
- }
- }
- if (pCS->CountComponents() > total_results) {
- total_results = pCS->CountComponents();
- }
- CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results);
- FX_FLOAT* pResults = result_array;
- FXSYS_memset32(pResults, 0, total_results * sizeof(FX_FLOAT));
- FX_DWORD rgb_array[SHADING_STEPS];
- for (int i = 0; i < SHADING_STEPS; i ++) {
- FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min;
- int offset = 0;
- for (int j = 0; j < nFuncs; j ++) {
- if (pFuncs[j]) {
- int nresults;
- if (pFuncs[j]->Call(&input, 1, pResults + offset, nresults)) {
- offset += nresults;
- }
- }
- }
- FX_FLOAT R, G, B;
- pCS->GetRGB(pResults, R, G, B);
- rgb_array[i] = FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255)));
- }
- FX_FLOAT a = FXSYS_Mul(start_x - end_x, start_x - end_x) +
- FXSYS_Mul(start_y - end_y, start_y - end_y) - FXSYS_Mul(start_r - end_r, start_r - end_r);
- int width = pBitmap->GetWidth();
- int height = pBitmap->GetHeight();
- int pitch = pBitmap->GetPitch();
- int Bpp = pBitmap->GetBPP() / 8;
- FX_BOOL bDecreasing = FALSE;
- if (start_r > end_r) {
- int length = (int)FXSYS_sqrt((FXSYS_Mul(start_x - end_x, start_x - end_x) + FXSYS_Mul(start_y - end_y, start_y - end_y)));
- if (length < start_r - end_r) {
- bDecreasing = TRUE;
- }
- }
- for (int row = 0; row < height; row ++) {
- FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch);
- for (int column = 0; column < width; column ++) {
- FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row;
- matrix.Transform(x, y);
- FX_FLOAT b = -2 * (FXSYS_Mul(x - start_x, end_x - start_x) + FXSYS_Mul(y - start_y, end_y - start_y) +
- FXSYS_Mul(start_r, end_r - start_r));
- FX_FLOAT c = FXSYS_Mul(x - start_x, x - start_x) + FXSYS_Mul(y - start_y, y - start_y) -
- FXSYS_Mul(start_r, start_r);
- FX_FLOAT s;
- if (a == 0) {
- s = FXSYS_Div(-c, b);
- } else {
- FX_FLOAT b2_4ac = FXSYS_Mul(b, b) - 4 * FXSYS_Mul(a, c);
- if (b2_4ac < 0) {
- continue;
- }
- FX_FLOAT root = FXSYS_sqrt(b2_4ac);
- FX_FLOAT s1, s2;
- if (a > 0) {
- s1 = FXSYS_Div(-b - root, 2 * a);
- s2 = FXSYS_Div(-b + root, 2 * a);
- } else {
- s2 = FXSYS_Div(-b - root, 2 * a);
- s1 = FXSYS_Div(-b + root, 2 * a);
- }
- if (bDecreasing) {
- if (s1 >= 0 || bStartExtend) {
- s = s1;
- } else {
- s = s2;
- }
- } else {
- if (s2 <= 1.0f || bEndExtend) {
- s = s2;
- } else {
- s = s1;
- }
- }
- if ((start_r + s * (end_r - start_r)) < 0) {
- continue;
- }
- }
- int index = (FX_INT32)(s * (SHADING_STEPS - 1));
- if (index < 0) {
- if (!bStartExtend) {
- continue;
- }
- index = 0;
- }
- if (index >= SHADING_STEPS) {
- if (!bEndExtend) {
- continue;
- }
- index = SHADING_STEPS - 1;
- }
- dib_buf[column] = rgb_array[index];
- }
- }
-}
-static void _DrawFuncShading(CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pObject2Bitmap,
- CPDF_Dictionary* pDict, CPDF_Function** pFuncs, int nFuncs,
- CPDF_ColorSpace* pCS, int alpha)
-{
- ASSERT(pBitmap->GetFormat() == FXDIB_Argb);
- CPDF_Array* pDomain = pDict->GetArray(FX_BSTRC("Domain"));
- FX_FLOAT xmin = 0, ymin = 0, xmax = 1.0f, ymax = 1.0f;
- if (pDomain) {
- xmin = pDomain->GetNumber(0);
- xmax = pDomain->GetNumber(1);
- ymin = pDomain->GetNumber(2);
- ymax = pDomain->GetNumber(3);
- }
- CFX_AffineMatrix mtDomain2Target = pDict->GetMatrix(FX_BSTRC("Matrix"));
- CFX_AffineMatrix matrix, reverse_matrix;
- matrix.SetReverse(*pObject2Bitmap);
- reverse_matrix.SetReverse(mtDomain2Target);
- matrix.Concat(reverse_matrix);
- int width = pBitmap->GetWidth();
- int height = pBitmap->GetHeight();
- int pitch = pBitmap->GetPitch();
- int Bpp = pBitmap->GetBPP() / 8;
- int total_results = 0;
- for (int j = 0; j < nFuncs; j ++) {
- if (pFuncs[j]) {
- total_results += pFuncs[j]->CountOutputs();
- }
- }
- if (pCS->CountComponents() > total_results) {
- total_results = pCS->CountComponents();
- }
- CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results);
- FX_FLOAT* pResults = result_array;
- FXSYS_memset32(pResults, 0, total_results * sizeof(FX_FLOAT));
- for (int row = 0; row < height; row ++) {
- FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch);
- for (int column = 0; column < width; column ++) {
- FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row;
- matrix.Transform(x, y);
- if (x < xmin || x > xmax || y < ymin || y > ymax) {
- continue;
- }
- FX_FLOAT input[2];
- int offset = 0;
- input[0] = x;
- input[1] = y;
- for (int j = 0; j < nFuncs; j ++) {
- if (pFuncs[j]) {
- int nresults;
- if (pFuncs[j]->Call(input, 2, pResults + offset, nresults)) {
- offset += nresults;
- }
- }
- }
- FX_FLOAT R, G, B;
- pCS->GetRGB(pResults, R, G, B);
- dib_buf[column] = FXARGB_TODIB(FXARGB_MAKE(alpha, (FX_INT32)(R * 255), (FX_INT32)(G * 255), (FX_INT32)(B * 255)));
- }
- }
-}
-FX_BOOL _GetScanlineIntersect(int y, FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2, FX_FLOAT& x)
-{
- if (y1 == y2) {
- return FALSE;
- }
- if (y1 < y2) {
- if (y < y1 || y > y2) {
- return FALSE;
- }
- } else {
- if (y < y2 || y > y1) {
- return FALSE;
- }
- }
- x = x1 + FXSYS_MulDiv(x2 - x1, y - y1, y2 - y1);
- return TRUE;
-}
-static void _DrawGouraud(CFX_DIBitmap* pBitmap, int alpha, CPDF_MeshVertex triangle[3])
-{
- FX_FLOAT min_y = triangle[0].y, max_y = triangle[0].y;
- for (int i = 1; i < 3; i ++) {
- if (min_y > triangle[i].y) {
- min_y = triangle[i].y;
- }
- if (max_y < triangle[i].y) {
- max_y = triangle[i].y;
- }
- }
- if (min_y == max_y) {
- return;
- }
- int min_yi = (int)FXSYS_floor(min_y), max_yi = (int)FXSYS_ceil(max_y);
- if (min_yi < 0) {
- min_yi = 0;
- }
- if (max_yi >= pBitmap->GetHeight()) {
- max_yi = pBitmap->GetHeight() - 1;
- }
- for (int y = min_yi; y <= max_yi; y ++) {
- int nIntersects = 0;
- FX_FLOAT inter_x[3], r[3], g[3], b[3];
- for (int i = 0; i < 3; i ++) {
- CPDF_MeshVertex& vertex1 = triangle[i];
- CPDF_MeshVertex& vertex2 = triangle[(i + 1) % 3];
- FX_BOOL bIntersect = _GetScanlineIntersect(y, vertex1.x, vertex1.y,
- vertex2.x, vertex2.y, inter_x[nIntersects]);
- if (!bIntersect) {
- continue;
- }
- r[nIntersects] = vertex1.r + FXSYS_MulDiv(vertex2.r - vertex1.r, y - vertex1.y, vertex2.y - vertex1.y);
- g[nIntersects] = vertex1.g + FXSYS_MulDiv(vertex2.g - vertex1.g, y - vertex1.y, vertex2.y - vertex1.y);
- b[nIntersects] = vertex1.b + FXSYS_MulDiv(vertex2.b - vertex1.b, y - vertex1.y, vertex2.y - vertex1.y);
- nIntersects ++;
- }
- if (nIntersects != 2) {
- continue;
- }
- int min_x, max_x, start_index, end_index;
- if (inter_x[0] < inter_x[1]) {
- min_x = (int)FXSYS_floor(inter_x[0]);
- max_x = (int)FXSYS_ceil(inter_x[1]);
- start_index = 0;
- end_index = 1;
- } else {
- min_x = (int)FXSYS_floor(inter_x[1]);
- max_x = (int)FXSYS_ceil(inter_x[0]);
- start_index = 1;
- end_index = 0;
- }
- int start_x = min_x, end_x = max_x;
- if (start_x < 0) {
- start_x = 0;
- }
- if (end_x > pBitmap->GetWidth()) {
- end_x = pBitmap->GetWidth();
- }
- FX_LPBYTE dib_buf = pBitmap->GetBuffer() + y * pBitmap->GetPitch() + start_x * 4;
- FX_FLOAT r_unit = (r[end_index] - r[start_index]) / (max_x - min_x);
- FX_FLOAT g_unit = (g[end_index] - g[start_index]) / (max_x - min_x);
- FX_FLOAT b_unit = (b[end_index] - b[start_index]) / (max_x - min_x);
- FX_FLOAT R = r[start_index] + (start_x - min_x) * r_unit;
- FX_FLOAT G = g[start_index] + (start_x - min_x) * g_unit;
- FX_FLOAT B = b[start_index] + (start_x - min_x) * b_unit;
- for (int x = start_x; x < end_x; x ++) {
- R += r_unit;
- G += g_unit;
- B += b_unit;
- FXARGB_SETDIB(dib_buf, FXARGB_MAKE(alpha, (FX_INT32)(R * 255), (FX_INT32)(G * 255), (FX_INT32)(B * 255)));
- dib_buf += 4;
- }
- }
-}
-static void _DrawFreeGouraudShading(CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pObject2Bitmap,
- CPDF_Stream* pShadingStream, CPDF_Function** pFuncs, int nFuncs,
- CPDF_ColorSpace* pCS, int alpha)
-{
- ASSERT(pBitmap->GetFormat() == FXDIB_Argb);
- if (pShadingStream->GetType() != PDFOBJ_STREAM) {
- return;
- }
- CPDF_MeshStream stream;
- if (!stream.Load(pShadingStream, pFuncs, nFuncs, pCS)) {
- return;
- }
- CPDF_MeshVertex triangle[3];
- while (!stream.m_BitStream.IsEOF()) {
- CPDF_MeshVertex vertex;
- FX_DWORD flag = stream.GetVertex(vertex, pObject2Bitmap);
- if (flag == 0) {
- triangle[0] = vertex;
- for (int j = 1; j < 3; j ++) {
- stream.GetVertex(triangle[j], pObject2Bitmap);
- }
- } else {
- if (flag == 1) {
- triangle[0] = triangle[1];
- }
- triangle[1] = triangle[2];
- triangle[2] = vertex;
- }
- _DrawGouraud(pBitmap, alpha, triangle);
- }
-}
-static void _DrawLatticeGouraudShading(CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pObject2Bitmap,
- CPDF_Stream* pShadingStream, CPDF_Function** pFuncs, int nFuncs,
- CPDF_ColorSpace* pCS, int alpha)
-{
- ASSERT(pBitmap->GetFormat() == FXDIB_Argb);
- if (pShadingStream->GetType() != PDFOBJ_STREAM) {
- return;
- }
- int row_verts = pShadingStream->GetDict()->GetInteger("VerticesPerRow");
- if (row_verts < 2) {
- return;
- }
- CPDF_MeshStream stream;
- if (!stream.Load(pShadingStream, pFuncs, nFuncs, pCS)) {
- return;
- }
- CPDF_MeshVertex* vertex = FX_Alloc(CPDF_MeshVertex, row_verts * 2);
- if (!stream.GetVertexRow(vertex, row_verts, pObject2Bitmap)) {
- FX_Free(vertex);
- return;
- }
- int last_index = 0;
- while (1) {
- CPDF_MeshVertex* last_row = vertex + last_index * row_verts;
- CPDF_MeshVertex* this_row = vertex + (1 - last_index) * row_verts;
- if (!stream.GetVertexRow(this_row, row_verts, pObject2Bitmap)) {
- FX_Free(vertex);
- return;
- }
- CPDF_MeshVertex triangle[3];
- for (int i = 1; i < row_verts; i ++) {
- triangle[0] = last_row[i];
- triangle[1] = this_row[i - 1];
- triangle[2] = last_row[i - 1];
- _DrawGouraud(pBitmap, alpha, triangle);
- triangle[2] = this_row[i];
- _DrawGouraud(pBitmap, alpha, triangle);
- }
- last_index = 1 - last_index;
- }
- FX_Free(vertex);
-}
-struct Coon_BezierCoeff {
- float a, b, c, d;
- void FromPoints(float p0, float p1, float p2, float p3)
- {
- a = -p0 + 3 * p1 - 3 * p2 + p3;
- b = 3 * p0 - 6 * p1 + 3 * p2;
- c = -3 * p0 + 3 * p1;
- d = p0;
- }
- Coon_BezierCoeff first_half()
- {
- Coon_BezierCoeff result;
- result.a = a / 8;
- result.b = b / 4;
- result.c = c / 2;
- result.d = d;
- return result;
- }
- Coon_BezierCoeff second_half()
- {
- Coon_BezierCoeff result;
- result.a = a / 8;
- result.b = 3 * a / 8 + b / 4;
- result.c = 3 * a / 8 + b / 2 + c / 2;
- result.d = a / 8 + b / 4 + c / 2 + d;
- return result;
- }
- void GetPoints(float p[4])
- {
- p[0] = d;
- p[1] = c / 3 + p[0];
- p[2] = b / 3 - p[0] + 2 * p[1];
- p[3] = a + p[0] - 3 * p[1] + 3 * p[2];
- }
- void GetPointsReverse(float p[4])
- {
- p[3] = d;
- p[2] = c / 3 + p[3];
- p[1] = b / 3 - p[3] + 2 * p[2];
- p[0] = a + p[3] - 3 * p[2] + 3 * p[1];
- }
- void BezierInterpol(Coon_BezierCoeff& C1, Coon_BezierCoeff& C2, Coon_BezierCoeff& D1, Coon_BezierCoeff& D2)
- {
- a = (D1.a + D2.a) / 2;
- b = (D1.b + D2.b) / 2;
- c = (D1.c + D2.c) / 2 - (C1.a / 8 + C1.b / 4 + C1.c / 2) + (C2.a / 8 + C2.b / 4) + (-C1.d + D2.d) / 2 - (C2.a + C2.b) / 2;
- d = C1.a / 8 + C1.b / 4 + C1.c / 2 + C1.d;
- }
- float Distance()
- {
- float dis = a + b + c;
- return dis < 0 ? -dis : dis;
- }
-};
-struct Coon_Bezier {
- Coon_BezierCoeff x, y;
- void FromPoints(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
- {
- x.FromPoints(x0, x1, x2, x3);
- y.FromPoints(y0, y1, y2, y3);
- }
- Coon_Bezier first_half()
- {
- Coon_Bezier result;
- result.x = x.first_half();
- result.y = y.first_half();
- return result;
- }
- Coon_Bezier second_half()
- {
- Coon_Bezier result;
- result.x = x.second_half();
- result.y = y.second_half();
- return result;
- }
- void BezierInterpol(Coon_Bezier& C1, Coon_Bezier& C2, Coon_Bezier& D1, Coon_Bezier& D2)
- {
- x.BezierInterpol(C1.x, C2.x, D1.x, D2.x);
- y.BezierInterpol(C1.y, C2.y, D1.y, D2.y);
- }
- void GetPoints(FX_PATHPOINT* pPoints)
- {
- float p[4];
- int i;
- x.GetPoints(p);
- for (i = 0; i < 4; i ++) {
- pPoints[i].m_PointX = p[i];
- }
- y.GetPoints(p);
- for (i = 0; i < 4; i ++) {
- pPoints[i].m_PointY = p[i];
- }
- }
- void GetPointsReverse(FX_PATHPOINT* pPoints)
- {
- float p[4];
- int i;
- x.GetPointsReverse(p);
- for (i = 0; i < 4; i ++) {
- pPoints[i].m_PointX = p[i];
- }
- y.GetPointsReverse(p);
- for (i = 0; i < 4; i ++) {
- pPoints[i].m_PointY = p[i];
- }
- }
- float Distance()
- {
- return x.Distance() + y.Distance();
- }
-};
-static int _BiInterpol(int c0, int c1, int c2, int c3, int x, int y, int x_scale, int y_scale)
-{
- int x1 = c0 + (c3 - c0) * x / x_scale;
- int x2 = c1 + (c2 - c1) * x / x_scale;
- return x1 + (x2 - x1) * y / y_scale;
-}
-struct Coon_Color {
- Coon_Color()
- {
- FXSYS_memset32(comp, 0, sizeof(int) * 3);
- }
- int comp[3];
- void BiInterpol(Coon_Color colors[4], int x, int y, int x_scale, int y_scale)
- {
- for (int i = 0; i < 3; i ++)
- comp[i] = _BiInterpol(colors[0].comp[i], colors[1].comp[i], colors[2].comp[i], colors[3].comp[i],
- x, y, x_scale, y_scale);
- }
- int Distance(Coon_Color& o)
- {
- int max, diff;
- max = FXSYS_abs(comp[0] - o.comp[0]);
- diff = FXSYS_abs(comp[1] - o.comp[1]);
- if (max < diff) {
- max = diff;
- }
- diff = FXSYS_abs(comp[2] - o.comp[2]);
- if (max < diff) {
- max = diff;
- }
- return max;
- }
-};
-struct CPDF_PatchDrawer {
- Coon_Color patch_colors[4];
- int max_delta;
- CFX_PathData path;
- CFX_RenderDevice* pDevice;
- int fill_mode;
- int alpha;
- void Draw(int x_scale, int y_scale, int left, int bottom, Coon_Bezier C1, Coon_Bezier C2, Coon_Bezier D1, Coon_Bezier D2)
- {
- FX_BOOL bSmall = C1.Distance() < 2 && C2.Distance() < 2 && D1.Distance() < 2 && D2.Distance() < 2;
- Coon_Color div_colors[4];
- int d_bottom, d_left, d_top, d_right;
- div_colors[0].BiInterpol(patch_colors, left, bottom, x_scale, y_scale);
- if (!bSmall) {
- div_colors[1].BiInterpol(patch_colors, left, bottom + 1, x_scale, y_scale);
- div_colors[2].BiInterpol(patch_colors, left + 1, bottom + 1, x_scale, y_scale);
- div_colors[3].BiInterpol(patch_colors, left + 1, bottom, x_scale, y_scale);
- d_bottom = div_colors[3].Distance(div_colors[0]);
- d_left = div_colors[1].Distance(div_colors[0]);
- d_top = div_colors[1].Distance(div_colors[2]);
- d_right = div_colors[2].Distance(div_colors[3]);
- }
-#define COONCOLOR_THRESHOLD 4
- if (bSmall || (d_bottom < COONCOLOR_THRESHOLD && d_left < COONCOLOR_THRESHOLD &&
- d_top < COONCOLOR_THRESHOLD && d_right < COONCOLOR_THRESHOLD)) {
- FX_PATHPOINT* pPoints = path.GetPoints();
- C1.GetPoints(pPoints);
- D2.GetPoints(pPoints + 3);
- C2.GetPointsReverse(pPoints + 6);
- D1.GetPointsReverse(pPoints + 9);
- int fillFlags = FXFILL_WINDING | FXFILL_FULLCOVER;
- if (fill_mode & RENDER_NOPATHSMOOTH) {
- fillFlags |= FXFILL_NOPATHSMOOTH;
- }
- pDevice->DrawPath(&path, NULL, NULL, FXARGB_MAKE(alpha, div_colors[0].comp[0], div_colors[0].comp[1], div_colors[0].comp[2]), 0, fillFlags);
- } else {
- if (d_bottom < COONCOLOR_THRESHOLD && d_top < COONCOLOR_THRESHOLD) {
- Coon_Bezier m1;
- m1.BezierInterpol(D1, D2, C1, C2);
- y_scale *= 2;
- bottom *= 2;
- Draw(x_scale, y_scale, left, bottom, C1, m1, D1.first_half(), D2.first_half());
- Draw(x_scale, y_scale, left, bottom + 1, m1, C2, D1.second_half(), D2.second_half());
- } else if (d_left < COONCOLOR_THRESHOLD && d_right < COONCOLOR_THRESHOLD) {
- Coon_Bezier m2;
- m2.BezierInterpol(C1, C2, D1, D2);
- x_scale *= 2;
- left *= 2;
- Draw(x_scale, y_scale, left, bottom, C1.first_half(), C2.first_half(), D1, m2);
- Draw(x_scale, y_scale, left + 1, bottom, C1.second_half(), C2.second_half(), m2, D2);
- } else {
- Coon_Bezier m1, m2;
- m1.BezierInterpol(D1, D2, C1, C2);
- m2.BezierInterpol(C1, C2, D1, D2);
- Coon_Bezier m1f = m1.first_half();
- Coon_Bezier m1s = m1.second_half();
- Coon_Bezier m2f = m2.first_half();
- Coon_Bezier m2s = m2.second_half();
- x_scale *= 2;
- y_scale *= 2;
- left *= 2;
- bottom *= 2;
- Draw(x_scale, y_scale, left, bottom, C1.first_half(), m1f, D1.first_half(), m2f);
- Draw(x_scale, y_scale, left, bottom + 1, m1f, C2.first_half(), D1.second_half(), m2s);
- Draw(x_scale, y_scale, left + 1, bottom, C1.second_half(), m1s, m2f, D2.first_half());
- Draw(x_scale, y_scale, left + 1, bottom + 1, m1s, C2.second_half(), m2s, D2.second_half());
- }
- }
- }
-};
-static void _DrawCoonPatchMeshes(FX_BOOL bTensor, CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pObject2Bitmap,
- CPDF_Stream* pShadingStream, CPDF_Function** pFuncs, int nFuncs,
- CPDF_ColorSpace* pCS, int fill_mode, int alpha)
-{
- ASSERT(pBitmap->GetFormat() == FXDIB_Argb);
- if (pShadingStream->GetType() != PDFOBJ_STREAM) {
- return;
- }
- CFX_FxgeDevice device;
- device.Attach(pBitmap);
- CPDF_MeshStream stream;
- if (!stream.Load(pShadingStream, pFuncs, nFuncs, pCS)) {
- return;
- }
- CPDF_PatchDrawer patch;
- patch.alpha = alpha;
- patch.pDevice = &device;
- patch.fill_mode = fill_mode;
- patch.path.SetPointCount(13);
- FX_PATHPOINT* pPoints = patch.path.GetPoints();
- pPoints[0].m_Flag = FXPT_MOVETO;
- for (int i = 1; i < 13; i ++) {
- pPoints[i].m_Flag = FXPT_BEZIERTO;
- }
- CFX_FloatPoint coords[16];
- int point_count = bTensor ? 16 : 12;
- while (!stream.m_BitStream.IsEOF()) {
- FX_DWORD flag = stream.GetFlag();
- int iStartPoint = 0, iStartColor = 0, i;
- if (flag) {
- iStartPoint = 4;
- iStartColor = 2;
- CFX_FloatPoint tempCoords[4];
- for (int i = 0; i < 4; i ++) {
- tempCoords[i] = coords[(flag * 3 + i) % 12];
- }
- FXSYS_memcpy32(coords, tempCoords, sizeof(CFX_FloatPoint) * 4);
- Coon_Color tempColors[2];
- tempColors[0] = patch.patch_colors[flag];
- tempColors[1] = patch.patch_colors[(flag + 1) % 4];
- FXSYS_memcpy32(patch.patch_colors, tempColors, sizeof(Coon_Color) * 2);
- }
- for (i = iStartPoint; i < point_count; i ++) {
- stream.GetCoords(coords[i].x, coords[i].y);
- pObject2Bitmap->Transform(coords[i].x, coords[i].y);
- }
- for (i = iStartColor; i < 4; i ++) {
- FX_FLOAT r, g, b;
- stream.GetColor(r, g, b);
- patch.patch_colors[i].comp[0] = (FX_INT32)(r * 255);
- patch.patch_colors[i].comp[1] = (FX_INT32)(g * 255);
- patch.patch_colors[i].comp[2] = (FX_INT32)(b * 255);
- }
- CFX_FloatRect bbox = CFX_FloatRect::GetBBox(coords, point_count);
- if (bbox.right <= 0 || bbox.left >= (FX_FLOAT)pBitmap->GetWidth() || bbox.top <= 0 ||
- bbox.bottom >= (FX_FLOAT)pBitmap->GetHeight()) {
- continue;
- }
- Coon_Bezier C1, C2, D1, D2;
- C1.FromPoints(coords[0].x, coords[0].y, coords[11].x, coords[11].y, coords[10].x, coords[10].y,
- coords[9].x, coords[9].y);
- C2.FromPoints(coords[3].x, coords[3].y, coords[4].x, coords[4].y, coords[5].x, coords[5].y,
- coords[6].x, coords[6].y);
- D1.FromPoints(coords[0].x, coords[0].y, coords[1].x, coords[1].y, coords[2].x, coords[2].y,
- coords[3].x, coords[3].y);
- D2.FromPoints(coords[9].x, coords[9].y, coords[8].x, coords[8].y, coords[7].x, coords[7].y,
- coords[6].x, coords[6].y);
- patch.Draw(1, 1, 0, 0, C1, C2, D1, D2);
- }
-}
-void CPDF_RenderStatus::DrawShading(CPDF_ShadingPattern* pPattern, CFX_AffineMatrix* pMatrix,
- FX_RECT& clip_rect, int alpha, FX_BOOL bAlphaMode)
-{
- int width = clip_rect.Width();
- int height = clip_rect.Height();
- CPDF_Function** pFuncs = pPattern->m_pFunctions;
- int nFuncs = pPattern->m_nFuncs;
- CPDF_Dictionary* pDict = pPattern->m_pShadingObj->GetDict();
- CPDF_ColorSpace* pColorSpace = pPattern->m_pCS;
- if (pColorSpace == NULL) {
- return;
- }
- FX_ARGB background = 0;
- if (!pPattern->m_bShadingObj && pPattern->m_pShadingObj->GetDict()->KeyExist(FX_BSTRC("Background"))) {
- CPDF_Array* pBackColor = pPattern->m_pShadingObj->GetDict()->GetArray(FX_BSTRC("Background"));
- if (pBackColor && pBackColor->GetCount() >= (FX_DWORD)pColorSpace->CountComponents()) {
- CFX_FixedBufGrow<FX_FLOAT, 16> comps(pColorSpace->CountComponents());
- for (int i = 0; i < pColorSpace->CountComponents(); i ++) {
- comps[i] = pBackColor->GetNumber(i);
- }
- FX_FLOAT R, G, B;
- pColorSpace->GetRGB(comps, R, G, B);
- background = ArgbEncode(255, (FX_INT32)(R * 255), (FX_INT32)(G * 255), (FX_INT32)(B * 255));
- }
- }
- if (pDict->KeyExist(FX_BSTRC("BBox"))) {
- CFX_FloatRect rect = pDict->GetRect(FX_BSTRC("BBox"));
- rect.Transform(pMatrix);
- clip_rect.Intersect(rect.GetOutterRect());
- }
- CPDF_DeviceBuffer buffer;
- buffer.Initialize(m_pContext, m_pDevice, &clip_rect, m_pCurObj, 150);
- CFX_AffineMatrix FinalMatrix = *pMatrix;
- FinalMatrix.Concat(*buffer.GetMatrix());
- CFX_DIBitmap* pBitmap = buffer.GetBitmap();
- if (pBitmap->GetBuffer() == NULL) {
- return;
- }
- pBitmap->Clear(background);
- int fill_mode = m_Options.m_Flags;
- switch (pPattern->m_ShadingType) {
- case 1:
- _DrawFuncShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, pColorSpace, alpha);
- break;
- case 2:
- _DrawAxialShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, pColorSpace, alpha);
- break;
- case 3:
- _DrawRadialShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, pColorSpace, alpha);
- break;
- case 4: {
- _DrawFreeGouraudShading(pBitmap, &FinalMatrix, (CPDF_Stream*)pPattern->m_pShadingObj,
- pFuncs, nFuncs, pColorSpace, alpha);
- }
- break;
- case 5: {
- _DrawLatticeGouraudShading(pBitmap, &FinalMatrix, (CPDF_Stream*)pPattern->m_pShadingObj,
- pFuncs, nFuncs, pColorSpace, alpha);
- }
- break;
- case 6:
- case 7: {
- _DrawCoonPatchMeshes(pPattern->m_ShadingType - 6, pBitmap, &FinalMatrix, (CPDF_Stream*)pPattern->m_pShadingObj,
- pFuncs, nFuncs, pColorSpace, fill_mode, alpha);
- }
- break;
- }
- if (bAlphaMode) {
- pBitmap->LoadChannel(FXDIB_Red, pBitmap, FXDIB_Alpha);
- }
- if (m_Options.m_ColorMode == RENDER_COLOR_GRAY) {
- pBitmap->ConvertColorScale(m_Options.m_ForeColor, m_Options.m_BackColor);
- }
- buffer.OutputToDevice();
-}
-void CPDF_RenderStatus::DrawShadingPattern(CPDF_ShadingPattern* pattern, CPDF_PageObject* pPageObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke)
-{
- if (!pattern->Load()) {
- return;
- }
- m_pDevice->SaveState();
- if (pPageObj->m_Type == PDFPAGE_PATH) {
- if (!SelectClipPath((CPDF_PathObject*)pPageObj, pObj2Device, bStroke)) {
- m_pDevice->RestoreState();
- return;
- }
- } else if (pPageObj->m_Type == PDFPAGE_IMAGE) {
- FX_RECT rect = pPageObj->GetBBox(pObj2Device);
- m_pDevice->SetClip_Rect(&rect);
- } else {
- return;
- }
- FX_RECT rect;
- if (GetObjectClippedRect(pPageObj, pObj2Device, FALSE, rect)) {
- m_pDevice->RestoreState();
- return;
- }
- CFX_AffineMatrix matrix = pattern->m_Pattern2Form;
- matrix.Concat(*pObj2Device);
- GetScaledMatrix(matrix);
- int alpha = pPageObj->m_GeneralState.GetAlpha(bStroke);
- DrawShading(pattern, &matrix, rect, alpha, m_Options.m_ColorMode == RENDER_COLOR_ALPHA);
- m_pDevice->RestoreState();
-}
-FX_BOOL CPDF_RenderStatus::ProcessShading(CPDF_ShadingObject* pShadingObj, const CFX_AffineMatrix* pObj2Device)
-{
- FX_RECT rect = pShadingObj->GetBBox(pObj2Device);
- FX_RECT clip_box = m_pDevice->GetClipBox();
- rect.Intersect(clip_box);
- if (rect.IsEmpty()) {
- return TRUE;
- }
- CFX_AffineMatrix matrix = pShadingObj->m_Matrix;
- matrix.Concat(*pObj2Device);
- DrawShading(pShadingObj->m_pShading, &matrix, rect, pShadingObj->m_GeneralState.GetAlpha(FALSE),
- m_Options.m_ColorMode == RENDER_COLOR_ALPHA);
-#ifdef _FPDFAPI_MINI_
- if (m_DitherBits) {
- DitherObjectArea(pShadingObj, pObj2Device);
- }
-#endif
- return TRUE;
-}
-static CFX_DIBitmap* DrawPatternBitmap(CPDF_Document* pDoc, CPDF_PageRenderCache* pCache,
- CPDF_TilingPattern* pPattern, const CFX_AffineMatrix* pObject2Device,
- int width, int height, int flags)
-{
- CFX_DIBitmap* pBitmap = FX_NEW CFX_DIBitmap;
- if (!pBitmap->Create(width, height, pPattern->m_bColored ? FXDIB_Argb : FXDIB_8bppMask)) {
- delete pBitmap;
- return NULL;
- }
- CFX_FxgeDevice bitmap_device;
- bitmap_device.Attach(pBitmap);
- pBitmap->Clear(0);
- CFX_FloatRect cell_bbox = pPattern->m_BBox;
- pPattern->m_Pattern2Form.TransformRect(cell_bbox);
- pObject2Device->TransformRect(cell_bbox);
- CFX_FloatRect bitmap_rect(0.0f, 0.0f, (FX_FLOAT)width, (FX_FLOAT)height);
- CFX_AffineMatrix mtAdjust;
- mtAdjust.MatchRect(bitmap_rect, cell_bbox);
- CFX_AffineMatrix mtPattern2Bitmap = *pObject2Device;
- mtPattern2Bitmap.Concat(mtAdjust);
- CPDF_RenderOptions options;
- if (!pPattern->m_bColored) {
- options.m_ColorMode = RENDER_COLOR_ALPHA;
- }
- flags |= RENDER_FORCE_HALFTONE;
- options.m_Flags = flags;
- CPDF_RenderContext context;
- context.Create(pDoc, pCache, NULL);
- context.DrawObjectList(&bitmap_device, pPattern->m_pForm, &mtPattern2Bitmap, &options);
- return pBitmap;
-}
-void CPDF_RenderStatus::DrawTilingPattern(CPDF_TilingPattern* pPattern, CPDF_PageObject* pPageObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke)
-{
- if (!pPattern->Load()) {
- return;
- }
- m_pDevice->SaveState();
- if (pPageObj->m_Type == PDFPAGE_PATH) {
- if (!SelectClipPath((CPDF_PathObject*)pPageObj, pObj2Device, bStroke)) {
- m_pDevice->RestoreState();
- return;
- }
- } else if (pPageObj->m_Type == PDFPAGE_IMAGE) {
- FX_RECT rect = pPageObj->GetBBox(pObj2Device);
- m_pDevice->SetClip_Rect(&rect);
- } else {
- return;
- }
- FX_RECT clip_box = m_pDevice->GetClipBox();
- if (clip_box.IsEmpty()) {
- m_pDevice->RestoreState();
- return;
- }
- CFX_Matrix dCTM = m_pDevice->GetCTM();
- FX_FLOAT sa = FXSYS_fabs(dCTM.a);
- FX_FLOAT sd = FXSYS_fabs(dCTM.d);
- clip_box.right = clip_box.left + (FX_INT32)FXSYS_ceil(clip_box.Width() * sa);
- clip_box.bottom = clip_box.top + (FX_INT32)FXSYS_ceil(clip_box.Height() * sd);
- CFX_AffineMatrix mtPattern2Device = pPattern->m_Pattern2Form;
- mtPattern2Device.Concat(*pObj2Device);
- GetScaledMatrix(mtPattern2Device);
- FX_BOOL bAligned = FALSE;
- if (pPattern->m_BBox.left == 0 && pPattern->m_BBox.bottom == 0 &&
- pPattern->m_BBox.right == pPattern->m_XStep && pPattern->m_BBox.top == pPattern->m_YStep &&
- (mtPattern2Device.IsScaled() || mtPattern2Device.Is90Rotated())) {
- bAligned = TRUE;
- }
- CFX_FloatRect cell_bbox = pPattern->m_BBox;
- mtPattern2Device.TransformRect(cell_bbox);
- int width = (int)FXSYS_ceil(cell_bbox.Width());
- int height = (int)FXSYS_ceil(cell_bbox.Height());
- if (width == 0) {
- width = 1;
- }
- if (height == 0) {
- height = 1;
- }
- int min_col, max_col, min_row, max_row;
- CFX_AffineMatrix mtDevice2Pattern;
- mtDevice2Pattern.SetReverse(mtPattern2Device);
- CFX_FloatRect clip_box_p(clip_box);
- clip_box_p.Transform(&mtDevice2Pattern);
- min_col = (int)FXSYS_ceil(FXSYS_Div(clip_box_p.left - pPattern->m_BBox.right, pPattern->m_XStep));
- max_col = (int)FXSYS_floor(FXSYS_Div(clip_box_p.right - pPattern->m_BBox.left, pPattern->m_XStep));
- min_row = (int)FXSYS_ceil(FXSYS_Div(clip_box_p.bottom - pPattern->m_BBox.top, pPattern->m_YStep));
- max_row = (int)FXSYS_floor(FXSYS_Div(clip_box_p.top - pPattern->m_BBox.bottom, pPattern->m_YStep));
- if (width > clip_box.Width() || height > clip_box.Height() || width * height > clip_box.Width() * clip_box.Height()) {
- CPDF_GraphicStates* pStates = NULL;
- if (!pPattern->m_bColored) {
- pStates = CloneObjStates(pPageObj, bStroke);
- }
- CPDF_Dictionary* pFormResource = NULL;
- if (pPattern->m_pForm->m_pFormDict) {
- pFormResource = pPattern->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources"));
- }
- for (int col = min_col; col <= max_col; col ++)
- for (int row = min_row; row <= max_row; row ++) {
- FX_FLOAT orig_x, orig_y;
- orig_x = col * pPattern->m_XStep;
- orig_y = row * pPattern->m_YStep;
- mtPattern2Device.Transform(orig_x, orig_y);
- CFX_AffineMatrix matrix = *pObj2Device;
- matrix.Translate(orig_x - mtPattern2Device.e, orig_y - mtPattern2Device.f);
- m_pDevice->SaveState();
- CPDF_RenderStatus status;
- status.Initialize(m_Level + 1, m_pContext, m_pDevice, NULL, NULL, this, pStates, &m_Options,
- pPattern->m_pForm->m_Transparency, m_bDropObjects, pFormResource);
- status.RenderObjectList(pPattern->m_pForm, &matrix);
- m_pDevice->RestoreState();
- }
- m_pDevice->RestoreState();
- if (pStates) {
- delete pStates;
- }
- return;
- }
- if (bAligned) {
- int orig_x = FXSYS_round(mtPattern2Device.e);
- int orig_y = FXSYS_round(mtPattern2Device.f);
- min_col = (clip_box.left - orig_x) / width;
- if (clip_box.left < orig_x) {
- min_col --;
- }
- max_col = (clip_box.right - orig_x) / width;
- if (clip_box.right <= orig_x) {
- max_col --;
- }
- min_row = (clip_box.top - orig_y) / height;
- if (clip_box.top < orig_y) {
- min_row --;
- }
- max_row = (clip_box.bottom - orig_y) / height;
- if (clip_box.bottom <= orig_y) {
- max_row --;
- }
- }
- FX_FLOAT left_offset = cell_bbox.left - mtPattern2Device.e;
- FX_FLOAT top_offset = cell_bbox.bottom - mtPattern2Device.f;
- CFX_DIBitmap* pPatternBitmap = NULL;
- if (width * height < 16) {
- CFX_DIBitmap* pEnlargedBitmap = DrawPatternBitmap(m_pContext->m_pDocument, m_pContext->m_pPageCache, pPattern, pObj2Device, 8, 8, m_Options.m_Flags);
- pPatternBitmap = pEnlargedBitmap->StretchTo(width, height);
- delete pEnlargedBitmap;
- } else {
- pPatternBitmap = DrawPatternBitmap(m_pContext->m_pDocument, m_pContext->m_pPageCache, pPattern, pObj2Device, width, height, m_Options.m_Flags);
- }
- if (pPatternBitmap == NULL) {
- m_pDevice->RestoreState();
- return;
- }
- if (m_Options.m_ColorMode == RENDER_COLOR_GRAY) {
- pPatternBitmap->ConvertColorScale(m_Options.m_ForeColor, m_Options.m_BackColor);
- }
- FX_ARGB fill_argb = GetFillArgb(pPageObj);
- int clip_width = clip_box.right - clip_box.left;
- int clip_height = clip_box.bottom - clip_box.top;
- CFX_DIBitmap screen;
- if (!screen.Create(clip_width, clip_height, FXDIB_Argb)) {
- return;
- }
- screen.Clear(0);
- FX_DWORD* src_buf = (FX_DWORD*)pPatternBitmap->GetBuffer();
- for (int col = min_col; col <= max_col; col ++) {
- for (int row = min_row; row <= max_row; row ++) {
- int start_x, start_y;
- if (bAligned) {
- start_x = FXSYS_round(mtPattern2Device.e) + col * width - clip_box.left;
- start_y = FXSYS_round(mtPattern2Device.f) + row * height - clip_box.top;
- } else {
- FX_FLOAT orig_x = col * pPattern->m_XStep;
- FX_FLOAT orig_y = row * pPattern->m_YStep;
- mtPattern2Device.Transform(orig_x, orig_y);
- start_x = FXSYS_round(orig_x + left_offset) - clip_box.left;
- start_y = FXSYS_round(orig_y + top_offset) - clip_box.top;
- }
- if (width == 1 && height == 1) {
- if (start_x < 0 || start_x >= clip_box.Width() || start_y < 0 || start_y >= clip_box.Height()) {
- continue;
- }
- FX_DWORD* dest_buf = (FX_DWORD*)(screen.GetBuffer() + screen.GetPitch() * start_y + start_x * 4);
- if (pPattern->m_bColored) {
- *dest_buf = *src_buf;
- } else {
- *dest_buf = (*(FX_LPBYTE)src_buf << 24) | (fill_argb & 0xffffff);
- }
- } else {
- if (pPattern->m_bColored) {
- screen.CompositeBitmap(start_x, start_y, width, height, pPatternBitmap, 0, 0);
- } else {
- screen.CompositeMask(start_x, start_y, width, height, pPatternBitmap, fill_argb, 0, 0);
- }
- }
- }
- }
- CompositeDIBitmap(&screen, clip_box.left, clip_box.top, 0, 255, FXDIB_BLEND_NORMAL, FALSE);
- m_pDevice->RestoreState();
- delete pPatternBitmap;
-}
-void CPDF_RenderStatus::DrawPathWithPattern(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device, CPDF_Color* pColor, FX_BOOL bStroke)
-{
- CPDF_Pattern* pattern = pColor->GetPattern();
- if (pattern == NULL) {
- return;
- }
- if(pattern->m_PatternType == PATTERN_TILING) {
- DrawTilingPattern((CPDF_TilingPattern*)pattern, pPathObj, pObj2Device, bStroke);
- } else {
- DrawShadingPattern((CPDF_ShadingPattern*)pattern, pPathObj, pObj2Device, bStroke);
- }
-}
-void CPDF_RenderStatus::ProcessPathPattern(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device, int& filltype, FX_BOOL& bStroke)
-{
- FX_BOOL bPattern = FALSE;
- if(filltype) {
- CPDF_Color& FillColor = *pPathObj->m_ColorState.GetFillColor();
- if(FillColor.m_pCS && FillColor.m_pCS->GetFamily() == PDFCS_PATTERN) {
- DrawPathWithPattern(pPathObj, pObj2Device, &FillColor, FALSE);
- filltype = 0;
- bPattern = TRUE;
- }
- }
- if(bStroke) {
- CPDF_Color& StrokeColor = *pPathObj->m_ColorState.GetStrokeColor();
- if(StrokeColor.m_pCS && StrokeColor.m_pCS->GetFamily() == PDFCS_PATTERN) {
- DrawPathWithPattern(pPathObj, pObj2Device, &StrokeColor, TRUE);
- bStroke = FALSE;
- bPattern = TRUE;
- }
- }
-#ifdef _FPDFAPI_MINI_
- if (bPattern && m_DitherBits) {
- DitherObjectArea(pPathObj, pObj2Device);
- }
-#endif
-}
+// 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/fpdfapi/fpdf_render.h" +#include "../../../include/fpdfapi/fpdf_pageobj.h" +#include "../../../include/fxge/fx_ge.h" +#include "../fpdf_page/pageint.h" +#include "render_int.h" +#define SHADING_STEPS 256 +static void _DrawAxialShading(CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pObject2Bitmap, + CPDF_Dictionary* pDict, CPDF_Function** pFuncs, int nFuncs, + CPDF_ColorSpace* pCS, int alpha) +{ + ASSERT(pBitmap->GetFormat() == FXDIB_Argb); + CPDF_Array* pCoords = pDict->GetArray(FX_BSTRC("Coords")); + if (pCoords == NULL) { + return; + } + FX_FLOAT start_x = pCoords->GetNumber(0); + FX_FLOAT start_y = pCoords->GetNumber(1); + FX_FLOAT end_x = pCoords->GetNumber(2); + FX_FLOAT end_y = pCoords->GetNumber(3); + FX_FLOAT t_min = 0, t_max = 1.0f; + CPDF_Array* pArray = pDict->GetArray(FX_BSTRC("Domain")); + if (pArray) { + t_min = pArray->GetNumber(0); + t_max = pArray->GetNumber(1); + } + FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE; + pArray = pDict->GetArray(FX_BSTRC("Extend")); + if (pArray) { + bStartExtend = pArray->GetInteger(0); + bEndExtend = pArray->GetInteger(1); + } + int width = pBitmap->GetWidth(); + int height = pBitmap->GetHeight(); + FX_FLOAT x_span = end_x - start_x; + FX_FLOAT y_span = end_y - start_y; + FX_FLOAT axis_len_square = FXSYS_Mul(x_span, x_span) + FXSYS_Mul(y_span, y_span); + CFX_AffineMatrix matrix; + matrix.SetReverse(*pObject2Bitmap); + int total_results = 0; + for (int j = 0; j < nFuncs; j ++) { + if (pFuncs[j]) { + total_results += pFuncs[j]->CountOutputs(); + } + } + if (pCS->CountComponents() > total_results) { + total_results = pCS->CountComponents(); + } + CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results); + FX_FLOAT* pResults = result_array; + FXSYS_memset32(pResults, 0, total_results * sizeof(FX_FLOAT)); + FX_DWORD rgb_array[SHADING_STEPS]; + for (int i = 0; i < SHADING_STEPS; i ++) { + FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min; + int offset = 0; + for (int j = 0; j < nFuncs; j ++) { + if (pFuncs[j]) { + int nresults = 0; + if (pFuncs[j]->Call(&input, 1, pResults + offset, nresults)) { + offset += nresults; + } + } + } + FX_FLOAT R, G, B; + pCS->GetRGB(pResults, R, G, B); + rgb_array[i] = FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255))); + } + int pitch = pBitmap->GetPitch(); + int Bpp = pBitmap->GetBPP() / 8; + for (int row = 0; row < height; row ++) { + FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch); + for (int column = 0; column < width; column ++) { + FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row; + matrix.Transform(x, y); + FX_FLOAT scale = FXSYS_Div(FXSYS_Mul(x - start_x, x_span) + FXSYS_Mul(y - start_y, y_span), axis_len_square); + int index = (FX_INT32)(scale * (SHADING_STEPS - 1)); + if (index < 0) { + if (!bStartExtend) { + continue; + } + index = 0; + } else if (index >= SHADING_STEPS) { + if (!bEndExtend) { + continue; + } + index = SHADING_STEPS - 1; + } + dib_buf[column] = rgb_array[index]; + } + } +} +static void _DrawRadialShading(CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pObject2Bitmap, + CPDF_Dictionary* pDict, CPDF_Function** pFuncs, int nFuncs, + CPDF_ColorSpace* pCS, int alpha) +{ + ASSERT(pBitmap->GetFormat() == FXDIB_Argb); + CPDF_Array* pCoords = pDict->GetArray(FX_BSTRC("Coords")); + if (pCoords == NULL) { + return; + } + FX_FLOAT start_x = pCoords->GetNumber(0); + FX_FLOAT start_y = pCoords->GetNumber(1); + FX_FLOAT start_r = pCoords->GetNumber(2); + FX_FLOAT end_x = pCoords->GetNumber(3); + FX_FLOAT end_y = pCoords->GetNumber(4); + FX_FLOAT end_r = pCoords->GetNumber(5); + CFX_AffineMatrix matrix; + matrix.SetReverse(*pObject2Bitmap); + FX_FLOAT t_min = 0, t_max = 1.0f; + CPDF_Array* pArray = pDict->GetArray(FX_BSTRC("Domain")); + if (pArray) { + t_min = pArray->GetNumber(0); + t_max = pArray->GetNumber(1); + } + FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE; + pArray = pDict->GetArray(FX_BSTRC("Extend")); + if (pArray) { + bStartExtend = pArray->GetInteger(0); + bEndExtend = pArray->GetInteger(1); + } + int total_results = 0; + for (int j = 0; j < nFuncs; j ++) { + if (pFuncs[j]) { + total_results += pFuncs[j]->CountOutputs(); + } + } + if (pCS->CountComponents() > total_results) { + total_results = pCS->CountComponents(); + } + CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results); + FX_FLOAT* pResults = result_array; + FXSYS_memset32(pResults, 0, total_results * sizeof(FX_FLOAT)); + FX_DWORD rgb_array[SHADING_STEPS]; + for (int i = 0; i < SHADING_STEPS; i ++) { + FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min; + int offset = 0; + for (int j = 0; j < nFuncs; j ++) { + if (pFuncs[j]) { + int nresults; + if (pFuncs[j]->Call(&input, 1, pResults + offset, nresults)) { + offset += nresults; + } + } + } + FX_FLOAT R, G, B; + pCS->GetRGB(pResults, R, G, B); + rgb_array[i] = FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255))); + } + FX_FLOAT a = FXSYS_Mul(start_x - end_x, start_x - end_x) + + FXSYS_Mul(start_y - end_y, start_y - end_y) - FXSYS_Mul(start_r - end_r, start_r - end_r); + int width = pBitmap->GetWidth(); + int height = pBitmap->GetHeight(); + int pitch = pBitmap->GetPitch(); + int Bpp = pBitmap->GetBPP() / 8; + FX_BOOL bDecreasing = FALSE; + if (start_r > end_r) { + int length = (int)FXSYS_sqrt((FXSYS_Mul(start_x - end_x, start_x - end_x) + FXSYS_Mul(start_y - end_y, start_y - end_y))); + if (length < start_r - end_r) { + bDecreasing = TRUE; + } + } + for (int row = 0; row < height; row ++) { + FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch); + for (int column = 0; column < width; column ++) { + FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row; + matrix.Transform(x, y); + FX_FLOAT b = -2 * (FXSYS_Mul(x - start_x, end_x - start_x) + FXSYS_Mul(y - start_y, end_y - start_y) + + FXSYS_Mul(start_r, end_r - start_r)); + FX_FLOAT c = FXSYS_Mul(x - start_x, x - start_x) + FXSYS_Mul(y - start_y, y - start_y) - + FXSYS_Mul(start_r, start_r); + FX_FLOAT s; + if (a == 0) { + s = FXSYS_Div(-c, b); + } else { + FX_FLOAT b2_4ac = FXSYS_Mul(b, b) - 4 * FXSYS_Mul(a, c); + if (b2_4ac < 0) { + continue; + } + FX_FLOAT root = FXSYS_sqrt(b2_4ac); + FX_FLOAT s1, s2; + if (a > 0) { + s1 = FXSYS_Div(-b - root, 2 * a); + s2 = FXSYS_Div(-b + root, 2 * a); + } else { + s2 = FXSYS_Div(-b - root, 2 * a); + s1 = FXSYS_Div(-b + root, 2 * a); + } + if (bDecreasing) { + if (s1 >= 0 || bStartExtend) { + s = s1; + } else { + s = s2; + } + } else { + if (s2 <= 1.0f || bEndExtend) { + s = s2; + } else { + s = s1; + } + } + if ((start_r + s * (end_r - start_r)) < 0) { + continue; + } + } + int index = (FX_INT32)(s * (SHADING_STEPS - 1)); + if (index < 0) { + if (!bStartExtend) { + continue; + } + index = 0; + } + if (index >= SHADING_STEPS) { + if (!bEndExtend) { + continue; + } + index = SHADING_STEPS - 1; + } + dib_buf[column] = rgb_array[index]; + } + } +} +static void _DrawFuncShading(CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pObject2Bitmap, + CPDF_Dictionary* pDict, CPDF_Function** pFuncs, int nFuncs, + CPDF_ColorSpace* pCS, int alpha) +{ + ASSERT(pBitmap->GetFormat() == FXDIB_Argb); + CPDF_Array* pDomain = pDict->GetArray(FX_BSTRC("Domain")); + FX_FLOAT xmin = 0, ymin = 0, xmax = 1.0f, ymax = 1.0f; + if (pDomain) { + xmin = pDomain->GetNumber(0); + xmax = pDomain->GetNumber(1); + ymin = pDomain->GetNumber(2); + ymax = pDomain->GetNumber(3); + } + CFX_AffineMatrix mtDomain2Target = pDict->GetMatrix(FX_BSTRC("Matrix")); + CFX_AffineMatrix matrix, reverse_matrix; + matrix.SetReverse(*pObject2Bitmap); + reverse_matrix.SetReverse(mtDomain2Target); + matrix.Concat(reverse_matrix); + int width = pBitmap->GetWidth(); + int height = pBitmap->GetHeight(); + int pitch = pBitmap->GetPitch(); + int Bpp = pBitmap->GetBPP() / 8; + int total_results = 0; + for (int j = 0; j < nFuncs; j ++) { + if (pFuncs[j]) { + total_results += pFuncs[j]->CountOutputs(); + } + } + if (pCS->CountComponents() > total_results) { + total_results = pCS->CountComponents(); + } + CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results); + FX_FLOAT* pResults = result_array; + FXSYS_memset32(pResults, 0, total_results * sizeof(FX_FLOAT)); + for (int row = 0; row < height; row ++) { + FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch); + for (int column = 0; column < width; column ++) { + FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row; + matrix.Transform(x, y); + if (x < xmin || x > xmax || y < ymin || y > ymax) { + continue; + } + FX_FLOAT input[2]; + int offset = 0; + input[0] = x; + input[1] = y; + for (int j = 0; j < nFuncs; j ++) { + if (pFuncs[j]) { + int nresults; + if (pFuncs[j]->Call(input, 2, pResults + offset, nresults)) { + offset += nresults; + } + } + } + FX_FLOAT R, G, B; + pCS->GetRGB(pResults, R, G, B); + dib_buf[column] = FXARGB_TODIB(FXARGB_MAKE(alpha, (FX_INT32)(R * 255), (FX_INT32)(G * 255), (FX_INT32)(B * 255))); + } + } +} +FX_BOOL _GetScanlineIntersect(int y, FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2, FX_FLOAT& x) +{ + if (y1 == y2) { + return FALSE; + } + if (y1 < y2) { + if (y < y1 || y > y2) { + return FALSE; + } + } else { + if (y < y2 || y > y1) { + return FALSE; + } + } + x = x1 + FXSYS_MulDiv(x2 - x1, y - y1, y2 - y1); + return TRUE; +} +static void _DrawGouraud(CFX_DIBitmap* pBitmap, int alpha, CPDF_MeshVertex triangle[3]) +{ + FX_FLOAT min_y = triangle[0].y, max_y = triangle[0].y; + for (int i = 1; i < 3; i ++) { + if (min_y > triangle[i].y) { + min_y = triangle[i].y; + } + if (max_y < triangle[i].y) { + max_y = triangle[i].y; + } + } + if (min_y == max_y) { + return; + } + int min_yi = (int)FXSYS_floor(min_y), max_yi = (int)FXSYS_ceil(max_y); + if (min_yi < 0) { + min_yi = 0; + } + if (max_yi >= pBitmap->GetHeight()) { + max_yi = pBitmap->GetHeight() - 1; + } + for (int y = min_yi; y <= max_yi; y ++) { + int nIntersects = 0; + FX_FLOAT inter_x[3], r[3], g[3], b[3]; + for (int i = 0; i < 3; i ++) { + CPDF_MeshVertex& vertex1 = triangle[i]; + CPDF_MeshVertex& vertex2 = triangle[(i + 1) % 3]; + FX_BOOL bIntersect = _GetScanlineIntersect(y, vertex1.x, vertex1.y, + vertex2.x, vertex2.y, inter_x[nIntersects]); + if (!bIntersect) { + continue; + } + r[nIntersects] = vertex1.r + FXSYS_MulDiv(vertex2.r - vertex1.r, y - vertex1.y, vertex2.y - vertex1.y); + g[nIntersects] = vertex1.g + FXSYS_MulDiv(vertex2.g - vertex1.g, y - vertex1.y, vertex2.y - vertex1.y); + b[nIntersects] = vertex1.b + FXSYS_MulDiv(vertex2.b - vertex1.b, y - vertex1.y, vertex2.y - vertex1.y); + nIntersects ++; + } + if (nIntersects != 2) { + continue; + } + int min_x, max_x, start_index, end_index; + if (inter_x[0] < inter_x[1]) { + min_x = (int)FXSYS_floor(inter_x[0]); + max_x = (int)FXSYS_ceil(inter_x[1]); + start_index = 0; + end_index = 1; + } else { + min_x = (int)FXSYS_floor(inter_x[1]); + max_x = (int)FXSYS_ceil(inter_x[0]); + start_index = 1; + end_index = 0; + } + int start_x = min_x, end_x = max_x; + if (start_x < 0) { + start_x = 0; + } + if (end_x > pBitmap->GetWidth()) { + end_x = pBitmap->GetWidth(); + } + FX_LPBYTE dib_buf = pBitmap->GetBuffer() + y * pBitmap->GetPitch() + start_x * 4; + FX_FLOAT r_unit = (r[end_index] - r[start_index]) / (max_x - min_x); + FX_FLOAT g_unit = (g[end_index] - g[start_index]) / (max_x - min_x); + FX_FLOAT b_unit = (b[end_index] - b[start_index]) / (max_x - min_x); + FX_FLOAT R = r[start_index] + (start_x - min_x) * r_unit; + FX_FLOAT G = g[start_index] + (start_x - min_x) * g_unit; + FX_FLOAT B = b[start_index] + (start_x - min_x) * b_unit; + for (int x = start_x; x < end_x; x ++) { + R += r_unit; + G += g_unit; + B += b_unit; + FXARGB_SETDIB(dib_buf, FXARGB_MAKE(alpha, (FX_INT32)(R * 255), (FX_INT32)(G * 255), (FX_INT32)(B * 255))); + dib_buf += 4; + } + } +} +static void _DrawFreeGouraudShading(CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pObject2Bitmap, + CPDF_Stream* pShadingStream, CPDF_Function** pFuncs, int nFuncs, + CPDF_ColorSpace* pCS, int alpha) +{ + ASSERT(pBitmap->GetFormat() == FXDIB_Argb); + if (pShadingStream->GetType() != PDFOBJ_STREAM) { + return; + } + CPDF_MeshStream stream; + if (!stream.Load(pShadingStream, pFuncs, nFuncs, pCS)) { + return; + } + CPDF_MeshVertex triangle[3]; + while (!stream.m_BitStream.IsEOF()) { + CPDF_MeshVertex vertex; + FX_DWORD flag = stream.GetVertex(vertex, pObject2Bitmap); + if (flag == 0) { + triangle[0] = vertex; + for (int j = 1; j < 3; j ++) { + stream.GetVertex(triangle[j], pObject2Bitmap); + } + } else { + if (flag == 1) { + triangle[0] = triangle[1]; + } + triangle[1] = triangle[2]; + triangle[2] = vertex; + } + _DrawGouraud(pBitmap, alpha, triangle); + } +} +static void _DrawLatticeGouraudShading(CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pObject2Bitmap, + CPDF_Stream* pShadingStream, CPDF_Function** pFuncs, int nFuncs, + CPDF_ColorSpace* pCS, int alpha) +{ + ASSERT(pBitmap->GetFormat() == FXDIB_Argb); + if (pShadingStream->GetType() != PDFOBJ_STREAM) { + return; + } + int row_verts = pShadingStream->GetDict()->GetInteger("VerticesPerRow"); + if (row_verts < 2) { + return; + } + CPDF_MeshStream stream; + if (!stream.Load(pShadingStream, pFuncs, nFuncs, pCS)) { + return; + } + CPDF_MeshVertex* vertex = FX_Alloc(CPDF_MeshVertex, row_verts * 2); + if (!stream.GetVertexRow(vertex, row_verts, pObject2Bitmap)) { + FX_Free(vertex); + return; + } + int last_index = 0; + while (1) { + CPDF_MeshVertex* last_row = vertex + last_index * row_verts; + CPDF_MeshVertex* this_row = vertex + (1 - last_index) * row_verts; + if (!stream.GetVertexRow(this_row, row_verts, pObject2Bitmap)) { + FX_Free(vertex); + return; + } + CPDF_MeshVertex triangle[3]; + for (int i = 1; i < row_verts; i ++) { + triangle[0] = last_row[i]; + triangle[1] = this_row[i - 1]; + triangle[2] = last_row[i - 1]; + _DrawGouraud(pBitmap, alpha, triangle); + triangle[2] = this_row[i]; + _DrawGouraud(pBitmap, alpha, triangle); + } + last_index = 1 - last_index; + } + FX_Free(vertex); +} +struct Coon_BezierCoeff { + float a, b, c, d; + void FromPoints(float p0, float p1, float p2, float p3) + { + a = -p0 + 3 * p1 - 3 * p2 + p3; + b = 3 * p0 - 6 * p1 + 3 * p2; + c = -3 * p0 + 3 * p1; + d = p0; + } + Coon_BezierCoeff first_half() + { + Coon_BezierCoeff result; + result.a = a / 8; + result.b = b / 4; + result.c = c / 2; + result.d = d; + return result; + } + Coon_BezierCoeff second_half() + { + Coon_BezierCoeff result; + result.a = a / 8; + result.b = 3 * a / 8 + b / 4; + result.c = 3 * a / 8 + b / 2 + c / 2; + result.d = a / 8 + b / 4 + c / 2 + d; + return result; + } + void GetPoints(float p[4]) + { + p[0] = d; + p[1] = c / 3 + p[0]; + p[2] = b / 3 - p[0] + 2 * p[1]; + p[3] = a + p[0] - 3 * p[1] + 3 * p[2]; + } + void GetPointsReverse(float p[4]) + { + p[3] = d; + p[2] = c / 3 + p[3]; + p[1] = b / 3 - p[3] + 2 * p[2]; + p[0] = a + p[3] - 3 * p[2] + 3 * p[1]; + } + void BezierInterpol(Coon_BezierCoeff& C1, Coon_BezierCoeff& C2, Coon_BezierCoeff& D1, Coon_BezierCoeff& D2) + { + a = (D1.a + D2.a) / 2; + b = (D1.b + D2.b) / 2; + c = (D1.c + D2.c) / 2 - (C1.a / 8 + C1.b / 4 + C1.c / 2) + (C2.a / 8 + C2.b / 4) + (-C1.d + D2.d) / 2 - (C2.a + C2.b) / 2; + d = C1.a / 8 + C1.b / 4 + C1.c / 2 + C1.d; + } + float Distance() + { + float dis = a + b + c; + return dis < 0 ? -dis : dis; + } +}; +struct Coon_Bezier { + Coon_BezierCoeff x, y; + void FromPoints(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) + { + x.FromPoints(x0, x1, x2, x3); + y.FromPoints(y0, y1, y2, y3); + } + Coon_Bezier first_half() + { + Coon_Bezier result; + result.x = x.first_half(); + result.y = y.first_half(); + return result; + } + Coon_Bezier second_half() + { + Coon_Bezier result; + result.x = x.second_half(); + result.y = y.second_half(); + return result; + } + void BezierInterpol(Coon_Bezier& C1, Coon_Bezier& C2, Coon_Bezier& D1, Coon_Bezier& D2) + { + x.BezierInterpol(C1.x, C2.x, D1.x, D2.x); + y.BezierInterpol(C1.y, C2.y, D1.y, D2.y); + } + void GetPoints(FX_PATHPOINT* pPoints) + { + float p[4]; + int i; + x.GetPoints(p); + for (i = 0; i < 4; i ++) { + pPoints[i].m_PointX = p[i]; + } + y.GetPoints(p); + for (i = 0; i < 4; i ++) { + pPoints[i].m_PointY = p[i]; + } + } + void GetPointsReverse(FX_PATHPOINT* pPoints) + { + float p[4]; + int i; + x.GetPointsReverse(p); + for (i = 0; i < 4; i ++) { + pPoints[i].m_PointX = p[i]; + } + y.GetPointsReverse(p); + for (i = 0; i < 4; i ++) { + pPoints[i].m_PointY = p[i]; + } + } + float Distance() + { + return x.Distance() + y.Distance(); + } +}; +static int _BiInterpol(int c0, int c1, int c2, int c3, int x, int y, int x_scale, int y_scale) +{ + int x1 = c0 + (c3 - c0) * x / x_scale; + int x2 = c1 + (c2 - c1) * x / x_scale; + return x1 + (x2 - x1) * y / y_scale; +} +struct Coon_Color { + Coon_Color() + { + FXSYS_memset32(comp, 0, sizeof(int) * 3); + } + int comp[3]; + void BiInterpol(Coon_Color colors[4], int x, int y, int x_scale, int y_scale) + { + for (int i = 0; i < 3; i ++) + comp[i] = _BiInterpol(colors[0].comp[i], colors[1].comp[i], colors[2].comp[i], colors[3].comp[i], + x, y, x_scale, y_scale); + } + int Distance(Coon_Color& o) + { + int max, diff; + max = FXSYS_abs(comp[0] - o.comp[0]); + diff = FXSYS_abs(comp[1] - o.comp[1]); + if (max < diff) { + max = diff; + } + diff = FXSYS_abs(comp[2] - o.comp[2]); + if (max < diff) { + max = diff; + } + return max; + } +}; +struct CPDF_PatchDrawer { + Coon_Color patch_colors[4]; + int max_delta; + CFX_PathData path; + CFX_RenderDevice* pDevice; + int fill_mode; + int alpha; + void Draw(int x_scale, int y_scale, int left, int bottom, Coon_Bezier C1, Coon_Bezier C2, Coon_Bezier D1, Coon_Bezier D2) + { + FX_BOOL bSmall = C1.Distance() < 2 && C2.Distance() < 2 && D1.Distance() < 2 && D2.Distance() < 2; + Coon_Color div_colors[4]; + int d_bottom, d_left, d_top, d_right; + div_colors[0].BiInterpol(patch_colors, left, bottom, x_scale, y_scale); + if (!bSmall) { + div_colors[1].BiInterpol(patch_colors, left, bottom + 1, x_scale, y_scale); + div_colors[2].BiInterpol(patch_colors, left + 1, bottom + 1, x_scale, y_scale); + div_colors[3].BiInterpol(patch_colors, left + 1, bottom, x_scale, y_scale); + d_bottom = div_colors[3].Distance(div_colors[0]); + d_left = div_colors[1].Distance(div_colors[0]); + d_top = div_colors[1].Distance(div_colors[2]); + d_right = div_colors[2].Distance(div_colors[3]); + } +#define COONCOLOR_THRESHOLD 4 + if (bSmall || (d_bottom < COONCOLOR_THRESHOLD && d_left < COONCOLOR_THRESHOLD && + d_top < COONCOLOR_THRESHOLD && d_right < COONCOLOR_THRESHOLD)) { + FX_PATHPOINT* pPoints = path.GetPoints(); + C1.GetPoints(pPoints); + D2.GetPoints(pPoints + 3); + C2.GetPointsReverse(pPoints + 6); + D1.GetPointsReverse(pPoints + 9); + int fillFlags = FXFILL_WINDING | FXFILL_FULLCOVER; + if (fill_mode & RENDER_NOPATHSMOOTH) { + fillFlags |= FXFILL_NOPATHSMOOTH; + } + pDevice->DrawPath(&path, NULL, NULL, FXARGB_MAKE(alpha, div_colors[0].comp[0], div_colors[0].comp[1], div_colors[0].comp[2]), 0, fillFlags); + } else { + if (d_bottom < COONCOLOR_THRESHOLD && d_top < COONCOLOR_THRESHOLD) { + Coon_Bezier m1; + m1.BezierInterpol(D1, D2, C1, C2); + y_scale *= 2; + bottom *= 2; + Draw(x_scale, y_scale, left, bottom, C1, m1, D1.first_half(), D2.first_half()); + Draw(x_scale, y_scale, left, bottom + 1, m1, C2, D1.second_half(), D2.second_half()); + } else if (d_left < COONCOLOR_THRESHOLD && d_right < COONCOLOR_THRESHOLD) { + Coon_Bezier m2; + m2.BezierInterpol(C1, C2, D1, D2); + x_scale *= 2; + left *= 2; + Draw(x_scale, y_scale, left, bottom, C1.first_half(), C2.first_half(), D1, m2); + Draw(x_scale, y_scale, left + 1, bottom, C1.second_half(), C2.second_half(), m2, D2); + } else { + Coon_Bezier m1, m2; + m1.BezierInterpol(D1, D2, C1, C2); + m2.BezierInterpol(C1, C2, D1, D2); + Coon_Bezier m1f = m1.first_half(); + Coon_Bezier m1s = m1.second_half(); + Coon_Bezier m2f = m2.first_half(); + Coon_Bezier m2s = m2.second_half(); + x_scale *= 2; + y_scale *= 2; + left *= 2; + bottom *= 2; + Draw(x_scale, y_scale, left, bottom, C1.first_half(), m1f, D1.first_half(), m2f); + Draw(x_scale, y_scale, left, bottom + 1, m1f, C2.first_half(), D1.second_half(), m2s); + Draw(x_scale, y_scale, left + 1, bottom, C1.second_half(), m1s, m2f, D2.first_half()); + Draw(x_scale, y_scale, left + 1, bottom + 1, m1s, C2.second_half(), m2s, D2.second_half()); + } + } + } +}; +static void _DrawCoonPatchMeshes(FX_BOOL bTensor, CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pObject2Bitmap, + CPDF_Stream* pShadingStream, CPDF_Function** pFuncs, int nFuncs, + CPDF_ColorSpace* pCS, int fill_mode, int alpha) +{ + ASSERT(pBitmap->GetFormat() == FXDIB_Argb); + if (pShadingStream->GetType() != PDFOBJ_STREAM) { + return; + } + CFX_FxgeDevice device; + device.Attach(pBitmap); + CPDF_MeshStream stream; + if (!stream.Load(pShadingStream, pFuncs, nFuncs, pCS)) { + return; + } + CPDF_PatchDrawer patch; + patch.alpha = alpha; + patch.pDevice = &device; + patch.fill_mode = fill_mode; + patch.path.SetPointCount(13); + FX_PATHPOINT* pPoints = patch.path.GetPoints(); + pPoints[0].m_Flag = FXPT_MOVETO; + for (int i = 1; i < 13; i ++) { + pPoints[i].m_Flag = FXPT_BEZIERTO; + } + CFX_FloatPoint coords[16]; + int point_count = bTensor ? 16 : 12; + while (!stream.m_BitStream.IsEOF()) { + FX_DWORD flag = stream.GetFlag(); + int iStartPoint = 0, iStartColor = 0, i; + if (flag) { + iStartPoint = 4; + iStartColor = 2; + CFX_FloatPoint tempCoords[4]; + for (int i = 0; i < 4; i ++) { + tempCoords[i] = coords[(flag * 3 + i) % 12]; + } + FXSYS_memcpy32(coords, tempCoords, sizeof(CFX_FloatPoint) * 4); + Coon_Color tempColors[2]; + tempColors[0] = patch.patch_colors[flag]; + tempColors[1] = patch.patch_colors[(flag + 1) % 4]; + FXSYS_memcpy32(patch.patch_colors, tempColors, sizeof(Coon_Color) * 2); + } + for (i = iStartPoint; i < point_count; i ++) { + stream.GetCoords(coords[i].x, coords[i].y); + pObject2Bitmap->Transform(coords[i].x, coords[i].y); + } + for (i = iStartColor; i < 4; i ++) { + FX_FLOAT r, g, b; + stream.GetColor(r, g, b); + patch.patch_colors[i].comp[0] = (FX_INT32)(r * 255); + patch.patch_colors[i].comp[1] = (FX_INT32)(g * 255); + patch.patch_colors[i].comp[2] = (FX_INT32)(b * 255); + } + CFX_FloatRect bbox = CFX_FloatRect::GetBBox(coords, point_count); + if (bbox.right <= 0 || bbox.left >= (FX_FLOAT)pBitmap->GetWidth() || bbox.top <= 0 || + bbox.bottom >= (FX_FLOAT)pBitmap->GetHeight()) { + continue; + } + Coon_Bezier C1, C2, D1, D2; + C1.FromPoints(coords[0].x, coords[0].y, coords[11].x, coords[11].y, coords[10].x, coords[10].y, + coords[9].x, coords[9].y); + C2.FromPoints(coords[3].x, coords[3].y, coords[4].x, coords[4].y, coords[5].x, coords[5].y, + coords[6].x, coords[6].y); + D1.FromPoints(coords[0].x, coords[0].y, coords[1].x, coords[1].y, coords[2].x, coords[2].y, + coords[3].x, coords[3].y); + D2.FromPoints(coords[9].x, coords[9].y, coords[8].x, coords[8].y, coords[7].x, coords[7].y, + coords[6].x, coords[6].y); + patch.Draw(1, 1, 0, 0, C1, C2, D1, D2); + } +} +void CPDF_RenderStatus::DrawShading(CPDF_ShadingPattern* pPattern, CFX_AffineMatrix* pMatrix, + FX_RECT& clip_rect, int alpha, FX_BOOL bAlphaMode) +{ + int width = clip_rect.Width(); + int height = clip_rect.Height(); + CPDF_Function** pFuncs = pPattern->m_pFunctions; + int nFuncs = pPattern->m_nFuncs; + CPDF_Dictionary* pDict = pPattern->m_pShadingObj->GetDict(); + CPDF_ColorSpace* pColorSpace = pPattern->m_pCS; + if (pColorSpace == NULL) { + return; + } + FX_ARGB background = 0; + if (!pPattern->m_bShadingObj && pPattern->m_pShadingObj->GetDict()->KeyExist(FX_BSTRC("Background"))) { + CPDF_Array* pBackColor = pPattern->m_pShadingObj->GetDict()->GetArray(FX_BSTRC("Background")); + if (pBackColor && pBackColor->GetCount() >= (FX_DWORD)pColorSpace->CountComponents()) { + CFX_FixedBufGrow<FX_FLOAT, 16> comps(pColorSpace->CountComponents()); + for (int i = 0; i < pColorSpace->CountComponents(); i ++) { + comps[i] = pBackColor->GetNumber(i); + } + FX_FLOAT R, G, B; + pColorSpace->GetRGB(comps, R, G, B); + background = ArgbEncode(255, (FX_INT32)(R * 255), (FX_INT32)(G * 255), (FX_INT32)(B * 255)); + } + } + if (pDict->KeyExist(FX_BSTRC("BBox"))) { + CFX_FloatRect rect = pDict->GetRect(FX_BSTRC("BBox")); + rect.Transform(pMatrix); + clip_rect.Intersect(rect.GetOutterRect()); + } + CPDF_DeviceBuffer buffer; + buffer.Initialize(m_pContext, m_pDevice, &clip_rect, m_pCurObj, 150); + CFX_AffineMatrix FinalMatrix = *pMatrix; + FinalMatrix.Concat(*buffer.GetMatrix()); + CFX_DIBitmap* pBitmap = buffer.GetBitmap(); + if (pBitmap->GetBuffer() == NULL) { + return; + } + pBitmap->Clear(background); + int fill_mode = m_Options.m_Flags; + switch (pPattern->m_ShadingType) { + case 1: + _DrawFuncShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, pColorSpace, alpha); + break; + case 2: + _DrawAxialShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, pColorSpace, alpha); + break; + case 3: + _DrawRadialShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, pColorSpace, alpha); + break; + case 4: { + _DrawFreeGouraudShading(pBitmap, &FinalMatrix, (CPDF_Stream*)pPattern->m_pShadingObj, + pFuncs, nFuncs, pColorSpace, alpha); + } + break; + case 5: { + _DrawLatticeGouraudShading(pBitmap, &FinalMatrix, (CPDF_Stream*)pPattern->m_pShadingObj, + pFuncs, nFuncs, pColorSpace, alpha); + } + break; + case 6: + case 7: { + _DrawCoonPatchMeshes(pPattern->m_ShadingType - 6, pBitmap, &FinalMatrix, (CPDF_Stream*)pPattern->m_pShadingObj, + pFuncs, nFuncs, pColorSpace, fill_mode, alpha); + } + break; + } + if (bAlphaMode) { + pBitmap->LoadChannel(FXDIB_Red, pBitmap, FXDIB_Alpha); + } + if (m_Options.m_ColorMode == RENDER_COLOR_GRAY) { + pBitmap->ConvertColorScale(m_Options.m_ForeColor, m_Options.m_BackColor); + } + buffer.OutputToDevice(); +} +void CPDF_RenderStatus::DrawShadingPattern(CPDF_ShadingPattern* pattern, CPDF_PageObject* pPageObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke) +{ + if (!pattern->Load()) { + return; + } + m_pDevice->SaveState(); + if (pPageObj->m_Type == PDFPAGE_PATH) { + if (!SelectClipPath((CPDF_PathObject*)pPageObj, pObj2Device, bStroke)) { + m_pDevice->RestoreState(); + return; + } + } else if (pPageObj->m_Type == PDFPAGE_IMAGE) { + FX_RECT rect = pPageObj->GetBBox(pObj2Device); + m_pDevice->SetClip_Rect(&rect); + } else { + return; + } + FX_RECT rect; + if (GetObjectClippedRect(pPageObj, pObj2Device, FALSE, rect)) { + m_pDevice->RestoreState(); + return; + } + CFX_AffineMatrix matrix = pattern->m_Pattern2Form; + matrix.Concat(*pObj2Device); + GetScaledMatrix(matrix); + int alpha = pPageObj->m_GeneralState.GetAlpha(bStroke); + DrawShading(pattern, &matrix, rect, alpha, m_Options.m_ColorMode == RENDER_COLOR_ALPHA); + m_pDevice->RestoreState(); +} +FX_BOOL CPDF_RenderStatus::ProcessShading(CPDF_ShadingObject* pShadingObj, const CFX_AffineMatrix* pObj2Device) +{ + FX_RECT rect = pShadingObj->GetBBox(pObj2Device); + FX_RECT clip_box = m_pDevice->GetClipBox(); + rect.Intersect(clip_box); + if (rect.IsEmpty()) { + return TRUE; + } + CFX_AffineMatrix matrix = pShadingObj->m_Matrix; + matrix.Concat(*pObj2Device); + DrawShading(pShadingObj->m_pShading, &matrix, rect, pShadingObj->m_GeneralState.GetAlpha(FALSE), + m_Options.m_ColorMode == RENDER_COLOR_ALPHA); +#ifdef _FPDFAPI_MINI_ + if (m_DitherBits) { + DitherObjectArea(pShadingObj, pObj2Device); + } +#endif + return TRUE; +} +static CFX_DIBitmap* DrawPatternBitmap(CPDF_Document* pDoc, CPDF_PageRenderCache* pCache, + CPDF_TilingPattern* pPattern, const CFX_AffineMatrix* pObject2Device, + int width, int height, int flags) +{ + CFX_DIBitmap* pBitmap = FX_NEW CFX_DIBitmap; + if (!pBitmap->Create(width, height, pPattern->m_bColored ? FXDIB_Argb : FXDIB_8bppMask)) { + delete pBitmap; + return NULL; + } + CFX_FxgeDevice bitmap_device; + bitmap_device.Attach(pBitmap); + pBitmap->Clear(0); + CFX_FloatRect cell_bbox = pPattern->m_BBox; + pPattern->m_Pattern2Form.TransformRect(cell_bbox); + pObject2Device->TransformRect(cell_bbox); + CFX_FloatRect bitmap_rect(0.0f, 0.0f, (FX_FLOAT)width, (FX_FLOAT)height); + CFX_AffineMatrix mtAdjust; + mtAdjust.MatchRect(bitmap_rect, cell_bbox); + CFX_AffineMatrix mtPattern2Bitmap = *pObject2Device; + mtPattern2Bitmap.Concat(mtAdjust); + CPDF_RenderOptions options; + if (!pPattern->m_bColored) { + options.m_ColorMode = RENDER_COLOR_ALPHA; + } + flags |= RENDER_FORCE_HALFTONE; + options.m_Flags = flags; + CPDF_RenderContext context; + context.Create(pDoc, pCache, NULL); + context.DrawObjectList(&bitmap_device, pPattern->m_pForm, &mtPattern2Bitmap, &options); + return pBitmap; +} +void CPDF_RenderStatus::DrawTilingPattern(CPDF_TilingPattern* pPattern, CPDF_PageObject* pPageObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke) +{ + if (!pPattern->Load()) { + return; + } + m_pDevice->SaveState(); + if (pPageObj->m_Type == PDFPAGE_PATH) { + if (!SelectClipPath((CPDF_PathObject*)pPageObj, pObj2Device, bStroke)) { + m_pDevice->RestoreState(); + return; + } + } else if (pPageObj->m_Type == PDFPAGE_IMAGE) { + FX_RECT rect = pPageObj->GetBBox(pObj2Device); + m_pDevice->SetClip_Rect(&rect); + } else { + return; + } + FX_RECT clip_box = m_pDevice->GetClipBox(); + if (clip_box.IsEmpty()) { + m_pDevice->RestoreState(); + return; + } + CFX_Matrix dCTM = m_pDevice->GetCTM(); + FX_FLOAT sa = FXSYS_fabs(dCTM.a); + FX_FLOAT sd = FXSYS_fabs(dCTM.d); + clip_box.right = clip_box.left + (FX_INT32)FXSYS_ceil(clip_box.Width() * sa); + clip_box.bottom = clip_box.top + (FX_INT32)FXSYS_ceil(clip_box.Height() * sd); + CFX_AffineMatrix mtPattern2Device = pPattern->m_Pattern2Form; + mtPattern2Device.Concat(*pObj2Device); + GetScaledMatrix(mtPattern2Device); + FX_BOOL bAligned = FALSE; + if (pPattern->m_BBox.left == 0 && pPattern->m_BBox.bottom == 0 && + pPattern->m_BBox.right == pPattern->m_XStep && pPattern->m_BBox.top == pPattern->m_YStep && + (mtPattern2Device.IsScaled() || mtPattern2Device.Is90Rotated())) { + bAligned = TRUE; + } + CFX_FloatRect cell_bbox = pPattern->m_BBox; + mtPattern2Device.TransformRect(cell_bbox); + int width = (int)FXSYS_ceil(cell_bbox.Width()); + int height = (int)FXSYS_ceil(cell_bbox.Height()); + if (width == 0) { + width = 1; + } + if (height == 0) { + height = 1; + } + int min_col, max_col, min_row, max_row; + CFX_AffineMatrix mtDevice2Pattern; + mtDevice2Pattern.SetReverse(mtPattern2Device); + CFX_FloatRect clip_box_p(clip_box); + clip_box_p.Transform(&mtDevice2Pattern); + min_col = (int)FXSYS_ceil(FXSYS_Div(clip_box_p.left - pPattern->m_BBox.right, pPattern->m_XStep)); + max_col = (int)FXSYS_floor(FXSYS_Div(clip_box_p.right - pPattern->m_BBox.left, pPattern->m_XStep)); + min_row = (int)FXSYS_ceil(FXSYS_Div(clip_box_p.bottom - pPattern->m_BBox.top, pPattern->m_YStep)); + max_row = (int)FXSYS_floor(FXSYS_Div(clip_box_p.top - pPattern->m_BBox.bottom, pPattern->m_YStep)); + if (width > clip_box.Width() || height > clip_box.Height() || width * height > clip_box.Width() * clip_box.Height()) { + CPDF_GraphicStates* pStates = NULL; + if (!pPattern->m_bColored) { + pStates = CloneObjStates(pPageObj, bStroke); + } + CPDF_Dictionary* pFormResource = NULL; + if (pPattern->m_pForm->m_pFormDict) { + pFormResource = pPattern->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources")); + } + for (int col = min_col; col <= max_col; col ++) + for (int row = min_row; row <= max_row; row ++) { + FX_FLOAT orig_x, orig_y; + orig_x = col * pPattern->m_XStep; + orig_y = row * pPattern->m_YStep; + mtPattern2Device.Transform(orig_x, orig_y); + CFX_AffineMatrix matrix = *pObj2Device; + matrix.Translate(orig_x - mtPattern2Device.e, orig_y - mtPattern2Device.f); + m_pDevice->SaveState(); + CPDF_RenderStatus status; + status.Initialize(m_Level + 1, m_pContext, m_pDevice, NULL, NULL, this, pStates, &m_Options, + pPattern->m_pForm->m_Transparency, m_bDropObjects, pFormResource); + status.RenderObjectList(pPattern->m_pForm, &matrix); + m_pDevice->RestoreState(); + } + m_pDevice->RestoreState(); + if (pStates) { + delete pStates; + } + return; + } + if (bAligned) { + int orig_x = FXSYS_round(mtPattern2Device.e); + int orig_y = FXSYS_round(mtPattern2Device.f); + min_col = (clip_box.left - orig_x) / width; + if (clip_box.left < orig_x) { + min_col --; + } + max_col = (clip_box.right - orig_x) / width; + if (clip_box.right <= orig_x) { + max_col --; + } + min_row = (clip_box.top - orig_y) / height; + if (clip_box.top < orig_y) { + min_row --; + } + max_row = (clip_box.bottom - orig_y) / height; + if (clip_box.bottom <= orig_y) { + max_row --; + } + } + FX_FLOAT left_offset = cell_bbox.left - mtPattern2Device.e; + FX_FLOAT top_offset = cell_bbox.bottom - mtPattern2Device.f; + CFX_DIBitmap* pPatternBitmap = NULL; + if (width * height < 16) { + CFX_DIBitmap* pEnlargedBitmap = DrawPatternBitmap(m_pContext->m_pDocument, m_pContext->m_pPageCache, pPattern, pObj2Device, 8, 8, m_Options.m_Flags); + pPatternBitmap = pEnlargedBitmap->StretchTo(width, height); + delete pEnlargedBitmap; + } else { + pPatternBitmap = DrawPatternBitmap(m_pContext->m_pDocument, m_pContext->m_pPageCache, pPattern, pObj2Device, width, height, m_Options.m_Flags); + } + if (pPatternBitmap == NULL) { + m_pDevice->RestoreState(); + return; + } + if (m_Options.m_ColorMode == RENDER_COLOR_GRAY) { + pPatternBitmap->ConvertColorScale(m_Options.m_ForeColor, m_Options.m_BackColor); + } + FX_ARGB fill_argb = GetFillArgb(pPageObj); + int clip_width = clip_box.right - clip_box.left; + int clip_height = clip_box.bottom - clip_box.top; + CFX_DIBitmap screen; + if (!screen.Create(clip_width, clip_height, FXDIB_Argb)) { + return; + } + screen.Clear(0); + FX_DWORD* src_buf = (FX_DWORD*)pPatternBitmap->GetBuffer(); + for (int col = min_col; col <= max_col; col ++) { + for (int row = min_row; row <= max_row; row ++) { + int start_x, start_y; + if (bAligned) { + start_x = FXSYS_round(mtPattern2Device.e) + col * width - clip_box.left; + start_y = FXSYS_round(mtPattern2Device.f) + row * height - clip_box.top; + } else { + FX_FLOAT orig_x = col * pPattern->m_XStep; + FX_FLOAT orig_y = row * pPattern->m_YStep; + mtPattern2Device.Transform(orig_x, orig_y); + start_x = FXSYS_round(orig_x + left_offset) - clip_box.left; + start_y = FXSYS_round(orig_y + top_offset) - clip_box.top; + } + if (width == 1 && height == 1) { + if (start_x < 0 || start_x >= clip_box.Width() || start_y < 0 || start_y >= clip_box.Height()) { + continue; + } + FX_DWORD* dest_buf = (FX_DWORD*)(screen.GetBuffer() + screen.GetPitch() * start_y + start_x * 4); + if (pPattern->m_bColored) { + *dest_buf = *src_buf; + } else { + *dest_buf = (*(FX_LPBYTE)src_buf << 24) | (fill_argb & 0xffffff); + } + } else { + if (pPattern->m_bColored) { + screen.CompositeBitmap(start_x, start_y, width, height, pPatternBitmap, 0, 0); + } else { + screen.CompositeMask(start_x, start_y, width, height, pPatternBitmap, fill_argb, 0, 0); + } + } + } + } + CompositeDIBitmap(&screen, clip_box.left, clip_box.top, 0, 255, FXDIB_BLEND_NORMAL, FALSE); + m_pDevice->RestoreState(); + delete pPatternBitmap; +} +void CPDF_RenderStatus::DrawPathWithPattern(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device, CPDF_Color* pColor, FX_BOOL bStroke) +{ + CPDF_Pattern* pattern = pColor->GetPattern(); + if (pattern == NULL) { + return; + } + if(pattern->m_PatternType == PATTERN_TILING) { + DrawTilingPattern((CPDF_TilingPattern*)pattern, pPathObj, pObj2Device, bStroke); + } else { + DrawShadingPattern((CPDF_ShadingPattern*)pattern, pPathObj, pObj2Device, bStroke); + } +} +void CPDF_RenderStatus::ProcessPathPattern(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device, int& filltype, FX_BOOL& bStroke) +{ + FX_BOOL bPattern = FALSE; + if(filltype) { + CPDF_Color& FillColor = *pPathObj->m_ColorState.GetFillColor(); + if(FillColor.m_pCS && FillColor.m_pCS->GetFamily() == PDFCS_PATTERN) { + DrawPathWithPattern(pPathObj, pObj2Device, &FillColor, FALSE); + filltype = 0; + bPattern = TRUE; + } + } + if(bStroke) { + CPDF_Color& StrokeColor = *pPathObj->m_ColorState.GetStrokeColor(); + if(StrokeColor.m_pCS && StrokeColor.m_pCS->GetFamily() == PDFCS_PATTERN) { + DrawPathWithPattern(pPathObj, pObj2Device, &StrokeColor, TRUE); + bStroke = FALSE; + bPattern = TRUE; + } + } +#ifdef _FPDFAPI_MINI_ + if (bPattern && m_DitherBits) { + DitherObjectArea(pPathObj, pObj2Device); + } +#endif +} diff --git a/core/src/fpdfapi/fpdf_render/fpdf_render_text.cpp b/core/src/fpdfapi/fpdf_render/fpdf_render_text.cpp index 91ff982935..a26d619565 100644 --- a/core/src/fpdfapi/fpdf_render/fpdf_render_text.cpp +++ b/core/src/fpdfapi/fpdf_render/fpdf_render_text.cpp @@ -1,760 +1,760 @@ -// 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/fpdfapi/fpdf_render.h"
-#include "../../../include/fpdfapi/fpdf_pageobj.h"
-#include "../fpdf_page/pageint.h"
-#include "render_int.h"
-extern FX_BOOL IsAvailableMatrix(const CFX_AffineMatrix& matrix);
-CPDF_Type3Cache::~CPDF_Type3Cache()
-{
- FX_POSITION pos = m_SizeMap.GetStartPosition();
- CFX_ByteString Key;
- CPDF_Type3Glyphs* pSizeCache = NULL;
- while(pos) {
- pSizeCache = (CPDF_Type3Glyphs*)m_SizeMap.GetNextValue(pos);
- delete pSizeCache;
- }
- m_SizeMap.RemoveAll();
-}
-CFX_GlyphBitmap* CPDF_Type3Cache::LoadGlyph(FX_DWORD charcode, const CFX_AffineMatrix* pMatrix, FX_FLOAT retinaScaleX, FX_FLOAT retinaScaleY)
-{
- _CPDF_UniqueKeyGen keygen;
- keygen.Generate(4, FXSYS_round(pMatrix->a * 10000), FXSYS_round(pMatrix->b * 10000),
- FXSYS_round(pMatrix->c * 10000), FXSYS_round(pMatrix->d * 10000));
- CFX_ByteStringC FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen);
- CPDF_Type3Glyphs* pSizeCache = NULL;
- if(!m_SizeMap.Lookup(FaceGlyphsKey, (void*&)pSizeCache)) {
- pSizeCache = FX_NEW CPDF_Type3Glyphs;
- m_SizeMap.SetAt(FaceGlyphsKey, pSizeCache);
- }
- CFX_GlyphBitmap* pGlyphBitmap;
- if(pSizeCache->m_GlyphMap.Lookup((FX_LPVOID)(FX_UINTPTR)charcode, (void*&)pGlyphBitmap)) {
- return pGlyphBitmap;
- }
- pGlyphBitmap = RenderGlyph(pSizeCache, charcode, pMatrix, retinaScaleX, retinaScaleY);
- pSizeCache->m_GlyphMap.SetAt((FX_LPVOID)(FX_UINTPTR)charcode, pGlyphBitmap);
- return pGlyphBitmap;
-}
-CPDF_Type3Glyphs::~CPDF_Type3Glyphs()
-{
- FX_POSITION pos = m_GlyphMap.GetStartPosition();
- FX_LPVOID Key;
- CFX_GlyphBitmap* pGlyphBitmap;
- while(pos) {
- m_GlyphMap.GetNextAssoc(pos, Key, (void*&)pGlyphBitmap);
- delete pGlyphBitmap;
- }
-}
-static int _AdjustBlue(FX_FLOAT pos, int& count, int blues[])
-{
- FX_FLOAT min_distance = 1000000.0f * 1.0f;
- int closest_pos = -1;
- for (int i = 0; i < count; i ++) {
- FX_FLOAT distance = (FX_FLOAT)FXSYS_fabs(pos - (FX_FLOAT)blues[i]);
- if (distance < 1.0f * 80.0f / 100.0f && distance < min_distance) {
- min_distance = distance;
- closest_pos = i;
- }
- }
- if (closest_pos >= 0) {
- return blues[closest_pos];
- }
- int new_pos = FXSYS_round(pos);
- if (count == TYPE3_MAX_BLUES) {
- return new_pos;
- }
- blues[count++] = new_pos;
- return new_pos;
-}
-void CPDF_Type3Glyphs::AdjustBlue(FX_FLOAT top, FX_FLOAT bottom, int& top_line, int& bottom_line)
-{
- top_line = _AdjustBlue(top, m_TopBlueCount, m_TopBlue);
- bottom_line = _AdjustBlue(bottom, m_BottomBlueCount, m_BottomBlue);
-}
-static FX_BOOL _IsScanLine1bpp(FX_LPBYTE pBuf, int width)
-{
- int size = width / 8;
- for (int i = 0; i < size; i ++)
- if (pBuf[i]) {
- return TRUE;
- }
- if (width % 8)
- if (pBuf[width / 8] & (0xff << (8 - width % 8))) {
- return TRUE;
- }
- return FALSE;
-}
-static FX_BOOL _IsScanLine8bpp(FX_LPBYTE pBuf, int width)
-{
- for (int i = 0; i < width; i ++)
- if (pBuf[i] > 0x40) {
- return TRUE;
- }
- return FALSE;
-}
-static int _DetectFirstLastScan(const CFX_DIBitmap* pBitmap, FX_BOOL bFirst)
-{
- int height = pBitmap->GetHeight(), pitch = pBitmap->GetPitch(), width = pBitmap->GetWidth();
- int bpp = pBitmap->GetBPP();
- if (bpp > 8) {
- width *= bpp / 8;
- }
- FX_LPBYTE pBuf = pBitmap->GetBuffer();
- int line = bFirst ? 0 : height - 1;
- int line_step = bFirst ? 1 : -1;
- int line_end = bFirst ? height : -1;
- while (line != line_end) {
- if (bpp == 1) {
- if (_IsScanLine1bpp(pBuf + line * pitch, width)) {
- return line;
- }
- } else {
- if (_IsScanLine8bpp(pBuf + line * pitch, width)) {
- return line;
- }
- }
- line += line_step;
- }
- return -1;
-}
-CFX_GlyphBitmap* CPDF_Type3Cache::RenderGlyph(CPDF_Type3Glyphs* pSize, FX_DWORD charcode, const CFX_AffineMatrix* pMatrix, FX_FLOAT retinaScaleX, FX_FLOAT retinaScaleY)
-{
- CPDF_Type3Char* pChar = m_pFont->LoadChar(charcode);
- if (pChar == NULL || pChar->m_pBitmap == NULL) {
- return NULL;
- }
- CFX_DIBitmap* pBitmap = pChar->m_pBitmap;
- CFX_AffineMatrix image_matrix, text_matrix;
- image_matrix = pChar->m_ImageMatrix;
- text_matrix.Set(pMatrix->a, pMatrix->b, pMatrix->c, pMatrix->d, 0, 0);
- image_matrix.Concat(text_matrix);
- CFX_DIBitmap* pResBitmap = NULL;
- int left, top;
- if (FXSYS_fabs(image_matrix.b) < FXSYS_fabs(image_matrix.a) / 100 && FXSYS_fabs(image_matrix.c) < FXSYS_fabs(image_matrix.d) / 100) {
- int top_line, bottom_line;
- top_line = _DetectFirstLastScan(pBitmap, TRUE);
- bottom_line = _DetectFirstLastScan(pBitmap, FALSE);
- if (top_line == 0 && bottom_line == pBitmap->GetHeight() - 1) {
- FX_FLOAT top_y = image_matrix.d + image_matrix.f;
- FX_FLOAT bottom_y = image_matrix.f;
- FX_BOOL bFlipped = top_y > bottom_y;
- if (bFlipped) {
- FX_FLOAT temp = top_y;
- top_y = bottom_y;
- bottom_y = temp;
- }
- pSize->AdjustBlue(top_y, bottom_y, top_line, bottom_line);
- pResBitmap = pBitmap->StretchTo((int)(FXSYS_round(image_matrix.a) * retinaScaleX), (int)((bFlipped ? top_line - bottom_line : bottom_line - top_line) * retinaScaleY));
- top = top_line;
- if (image_matrix.a < 0) {
- image_matrix.Scale(retinaScaleX, retinaScaleY);
- left = FXSYS_round(image_matrix.e + image_matrix.a);
- } else {
- left = FXSYS_round(image_matrix.e);
- }
- } else {
- }
- }
- if (pResBitmap == NULL) {
- image_matrix.Scale(retinaScaleX, retinaScaleY);
- pResBitmap = pBitmap->TransformTo(&image_matrix, left, top);
- }
- if (pResBitmap == NULL) {
- return NULL;
- }
- CFX_GlyphBitmap* pGlyph = FX_NEW CFX_GlyphBitmap;
- pGlyph->m_Left = left;
- pGlyph->m_Top = -top;
- pGlyph->m_Bitmap.TakeOver(pResBitmap);
- delete pResBitmap;
- return pGlyph;
-}
-void _CPDF_UniqueKeyGen::Generate(int count, ...)
-{
- va_list argList;
- va_start(argList, count);
- for (int i = 0; i < count; i ++) {
- int p = va_arg(argList, int);
- ((FX_DWORD*)m_Key)[i] = p;
- }
- va_end(argList);
- m_KeyLen = count * sizeof(FX_DWORD);
-}
-FX_BOOL CPDF_RenderStatus::ProcessText(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device, CFX_PathData* pClippingPath)
-{
- if(textobj->m_nChars == 0) {
- return TRUE;
- }
- int text_render_mode = textobj->m_TextState.GetObject()->m_TextMode;
- if (text_render_mode == 3) {
- return TRUE;
- }
- CPDF_Font* pFont = textobj->m_TextState.GetFont();
- if (pFont->GetFontType() == PDFFONT_TYPE3) {
- return ProcessType3Text(textobj, pObj2Device);
- }
- FX_BOOL bFill = FALSE, bStroke = FALSE, bClip = FALSE;
- if (pClippingPath) {
- bClip = TRUE;
- } else {
- switch (text_render_mode) {
- case 0:
- case 4:
- bFill = TRUE;
- break;
- case 1:
- case 5:
- if (pFont->GetFace() == NULL && !(pFont->GetSubstFont()->m_SubstFlags & FXFONT_SUBST_GLYPHPATH)) {
- bFill = TRUE;
- } else {
- bStroke = TRUE;
- }
- break;
- case 2:
- case 6:
- if (pFont->GetFace() == NULL && !(pFont->GetSubstFont()->m_SubstFlags & FXFONT_SUBST_GLYPHPATH)) {
- bFill = TRUE;
- } else {
- bFill = bStroke = TRUE;
- }
- break;
- case 3:
- case 7:
- return TRUE;
- default:
- bFill = TRUE;
- }
- }
- FX_ARGB stroke_argb = 0, fill_argb = 0;
- FX_BOOL bPattern = FALSE;
- if (bStroke) {
- if (textobj->m_ColorState.GetStrokeColor()->IsPattern()) {
- bPattern = TRUE;
- } else {
- stroke_argb = GetStrokeArgb(textobj);
- }
- }
- if (bFill) {
- if (textobj->m_ColorState.GetFillColor()->IsPattern()) {
- bPattern = TRUE;
- } else {
- fill_argb = GetFillArgb(textobj);
- }
- }
- CFX_AffineMatrix text_matrix;
- textobj->GetTextMatrix(&text_matrix);
- if(IsAvailableMatrix(text_matrix) == FALSE) {
- return TRUE;
- }
- FX_FLOAT font_size = textobj->m_TextState.GetFontSize();
- if (bPattern) {
- DrawTextPathWithPattern(textobj, pObj2Device, pFont, font_size, &text_matrix, bFill, bStroke);
- return TRUE;
- }
-#if defined(_FPDFAPI_MINI_)
- if (bFill) {
- bStroke = FALSE;
- }
- if (bStroke) {
- if (font_size * text_matrix.GetXUnit() * pObj2Device->GetXUnit() < 6) {
- bStroke = FALSE;
- }
- }
-#endif
- if (bClip || bStroke) {
- const CFX_AffineMatrix* pDeviceMatrix = pObj2Device;
- CFX_AffineMatrix device_matrix;
- if (bStroke) {
- const FX_FLOAT* pCTM = textobj->m_TextState.GetObject()->m_CTM;
- if (pCTM[0] != 1.0f || pCTM[3] != 1.0f) {
- CFX_AffineMatrix ctm(pCTM[0], pCTM[1], pCTM[2], pCTM[3], 0, 0);
- text_matrix.ConcatInverse(ctm);
- device_matrix.Copy(ctm);
- device_matrix.Concat(*pObj2Device);
- pDeviceMatrix = &device_matrix;
- }
- }
- int flag = 0;
- if (bStroke && bFill) {
- flag |= FX_FILL_STROKE;
- flag |= FX_STROKE_TEXT_MODE;
- }
-#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_)
- const CPDF_GeneralStateData* pGeneralData = ((CPDF_PageObject*)textobj)->m_GeneralState;
- if (pGeneralData && pGeneralData->m_StrokeAdjust) {
- flag |= FX_STROKE_ADJUST;
- }
-#endif
- if (m_Options.m_Flags & RENDER_NOTEXTSMOOTH) {
- flag |= FXFILL_NOPATHSMOOTH;
- }
- return CPDF_TextRenderer::DrawTextPath(m_pDevice, textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos, pFont, font_size,
- &text_matrix, pDeviceMatrix, textobj->m_GraphState, fill_argb, stroke_argb, pClippingPath, flag);
- }
- text_matrix.Concat(*pObj2Device);
- return CPDF_TextRenderer::DrawNormalText(m_pDevice, textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos, pFont, font_size,
- &text_matrix, fill_argb, &m_Options);
-}
-CPDF_Type3Cache* CPDF_RenderStatus::GetCachedType3(CPDF_Type3Font* pFont)
-{
- if (pFont->m_pDocument == NULL) {
- return NULL;
- }
- pFont->m_pDocument->GetPageData()->GetFont(pFont->GetFontDict(), FALSE);
- return pFont->m_pDocument->GetRenderData()->GetCachedType3(pFont);
-}
-static void ReleaseCachedType3(CPDF_Type3Font* pFont)
-{
- if (pFont->m_pDocument == NULL) {
- return;
- }
- pFont->m_pDocument->GetRenderData()->ReleaseCachedType3(pFont);
- pFont->m_pDocument->GetPageData()->ReleaseFont(pFont->GetFontDict());
-}
-FX_BOOL CPDF_Type3Char::LoadBitmap(CPDF_RenderContext* pContext)
-{
- if (m_pBitmap != NULL || m_pForm == NULL) {
- return TRUE;
- }
- if (m_pForm->CountObjects() == 1 && !m_bColored) {
- CPDF_PageObject *pPageObj = m_pForm->GetObjectAt(m_pForm->GetFirstObjectPosition());
- if (pPageObj->m_Type == PDFPAGE_IMAGE) {
- CPDF_ImageObject* pImage = (CPDF_ImageObject*)pPageObj;
- m_ImageMatrix = pImage->m_Matrix;
- const CFX_DIBSource* pSource = pImage->m_pImage->LoadDIBSource();
- if (pSource) {
- m_pBitmap = pSource->Clone();
- delete pSource;
- }
- delete m_pForm;
- m_pForm = NULL;
- return TRUE;
- }
- if (pPageObj->m_Type == PDFPAGE_INLINES) {
- CPDF_InlineImages *pInlines = (CPDF_InlineImages *)pPageObj;
- if (pInlines->m_pStream) {
- m_ImageMatrix = pInlines->m_Matrices[0];
- CPDF_DIBSource dibsrc;
- if (!dibsrc.Load(pContext->m_pDocument, pInlines->m_pStream, NULL, NULL, NULL, NULL)) {
- return FALSE;
- }
- m_pBitmap = dibsrc.Clone();
- delete m_pForm;
- m_pForm = NULL;
- return TRUE;
- }
- }
- }
- return FALSE;
-}
-class CPDF_RefType3Cache
-{
-public:
- CPDF_RefType3Cache(CPDF_Type3Font* pType3Font)
- {
- m_dwCount = 0;
- m_pType3Font = pType3Font;
- }
- ~CPDF_RefType3Cache()
- {
- while(m_dwCount--) {
- ReleaseCachedType3(m_pType3Font);
- }
- }
- FX_DWORD m_dwCount;
- CPDF_Type3Font* m_pType3Font;
-};
-FX_BOOL CPDF_RenderStatus::ProcessType3Text(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device)
-{
- CPDF_Type3Font* pType3Font = textobj->m_TextState.GetFont()->GetType3Font();
- for (int j = 0; j < m_Type3FontCache.GetSize(); j++)
- if ((CPDF_Type3Font*)m_Type3FontCache.GetAt(j) == pType3Font) {
- return TRUE;
- }
- CFX_Matrix dCTM = m_pDevice->GetCTM();
- FX_FLOAT sa = FXSYS_fabs(dCTM.a);
- FX_FLOAT sd = FXSYS_fabs(dCTM.d);
- CFX_AffineMatrix text_matrix;
- textobj->GetTextMatrix(&text_matrix);
- CFX_AffineMatrix char_matrix = pType3Font->GetFontMatrix();
- FX_FLOAT font_size = textobj->m_TextState.GetFontSize();
- char_matrix.Scale(font_size, font_size);
- FX_ARGB fill_argb = GetFillArgb(textobj, TRUE);
- int fill_alpha = FXARGB_A(fill_argb);
- int device_class = m_pDevice->GetDeviceClass();
- FXTEXT_GLYPHPOS* pGlyphAndPos = NULL;
- if (device_class == FXDC_DISPLAY) {
- pGlyphAndPos = FX_Alloc(FXTEXT_GLYPHPOS, textobj->m_nChars);
- FXSYS_memset32(pGlyphAndPos, 0, sizeof(FXTEXT_GLYPHPOS) * textobj->m_nChars);
- } else if (fill_alpha < 255) {
- return FALSE;
- }
- CPDF_RefType3Cache refTypeCache(pType3Font);
- FX_DWORD *pChars = textobj->m_pCharCodes;
- if (textobj->m_nChars == 1) {
- pChars = (FX_DWORD*)(&textobj->m_pCharCodes);
- }
- for (int iChar = 0; iChar < textobj->m_nChars; iChar ++) {
- FX_DWORD charcode = pChars[iChar];
- if (charcode == (FX_DWORD) - 1) {
- continue;
- }
- CPDF_Type3Char* pType3Char = pType3Font->LoadChar(charcode);
- if (pType3Char == NULL) {
- continue;
- }
- CFX_AffineMatrix matrix = char_matrix;
- matrix.e += iChar ? textobj->m_pCharPos[iChar - 1] : 0;
- matrix.Concat(text_matrix);
- matrix.Concat(*pObj2Device);
- if (!pType3Char->LoadBitmap(m_pContext)) {
- if (pGlyphAndPos) {
- for (int i = 0; i < iChar; i ++) {
- FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[i];
- if (glyph.m_pGlyph == NULL) {
- continue;
- }
- m_pDevice->SetBitMask(&glyph.m_pGlyph->m_Bitmap,
- glyph.m_OriginX + glyph.m_pGlyph->m_Left,
- glyph.m_OriginY - glyph.m_pGlyph->m_Top, fill_argb);
- }
- FX_Free(pGlyphAndPos);
- pGlyphAndPos = NULL;
- }
- CPDF_GraphicStates* pStates = CloneObjStates(textobj, FALSE);
- CPDF_RenderOptions Options = m_Options;
- Options.m_Flags |= RENDER_FORCE_HALFTONE | RENDER_RECT_AA;
- Options.m_Flags &= ~RENDER_FORCE_DOWNSAMPLE;
- CPDF_Dictionary* pFormResource = NULL;
- if (pType3Char->m_pForm && pType3Char->m_pForm->m_pFormDict) {
- pFormResource = pType3Char->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources"));
- }
- if (fill_alpha == 255) {
- CPDF_RenderStatus status;
- status.Initialize(m_Level + 1, m_pContext, m_pDevice, NULL, NULL, this, pStates, &Options,
- pType3Char->m_pForm->m_Transparency, m_bDropObjects, pFormResource, FALSE, pType3Char, fill_argb);
- status.m_Type3FontCache.Append(m_Type3FontCache);
- status.m_Type3FontCache.Add(pType3Font);
- m_pDevice->SaveState();
- status.RenderObjectList(pType3Char->m_pForm, &matrix);
- m_pDevice->RestoreState();
- } else {
- CFX_FloatRect rect_f = pType3Char->m_pForm->CalcBoundingBox();
- rect_f.Transform(&matrix);
- FX_RECT rect = rect_f.GetOutterRect();
- CFX_FxgeDevice bitmap_device;
- if (!bitmap_device.Create((int)(rect.Width() * sa), (int)(rect.Height() * sd), FXDIB_Argb)) {
- return TRUE;
- }
- bitmap_device.GetBitmap()->Clear(0);
- CPDF_RenderStatus status;
- status.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL, NULL, this, pStates, &Options,
- pType3Char->m_pForm->m_Transparency, m_bDropObjects, pFormResource, FALSE, pType3Char, fill_argb);
- status.m_Type3FontCache.Append(m_Type3FontCache);
- status.m_Type3FontCache.Add(pType3Font);
- matrix.TranslateI(-rect.left, -rect.top);
- matrix.Scale(sa, sd);
- status.RenderObjectList(pType3Char->m_pForm, &matrix);
- m_pDevice->SetDIBits(bitmap_device.GetBitmap(), rect.left, rect.top);
- }
- delete pStates;
- } else if (pType3Char->m_pBitmap) {
- if (device_class == FXDC_DISPLAY) {
- CPDF_Type3Cache* pCache = GetCachedType3(pType3Font);
- refTypeCache.m_dwCount++;
- CFX_GlyphBitmap* pBitmap = pCache->LoadGlyph(charcode, &matrix, sa, sd);
- if (pBitmap == NULL) {
- continue;
- }
- int origin_x = FXSYS_round(matrix.e);
- int origin_y = FXSYS_round(matrix.f);
- if (pGlyphAndPos) {
- pGlyphAndPos[iChar].m_pGlyph = pBitmap;
- pGlyphAndPos[iChar].m_OriginX = origin_x;
- pGlyphAndPos[iChar].m_OriginY = origin_y;
- } else {
- m_pDevice->SetBitMask(&pBitmap->m_Bitmap, origin_x + pBitmap->m_Left, origin_y - pBitmap->m_Top, fill_argb);
- }
- } else {
- CFX_AffineMatrix image_matrix = pType3Char->m_ImageMatrix;
- image_matrix.Concat(matrix);
- CPDF_ImageRenderer renderer;
- if (renderer.Start(this, pType3Char->m_pBitmap, fill_argb, 255, &image_matrix, 0, FALSE)) {
- renderer.Continue(NULL);
- }
- if (!renderer.m_Result) {
- return FALSE;
- }
- }
- }
- }
- if (pGlyphAndPos) {
- FX_RECT rect = FXGE_GetGlyphsBBox(pGlyphAndPos, textobj->m_nChars, 0, sa, sd);
- CFX_DIBitmap bitmap;
- if (!bitmap.Create((int)(rect.Width() * sa), (int)(rect.Height() * sd), FXDIB_8bppMask)) {
- FX_Free(pGlyphAndPos);
- return TRUE;
- }
- bitmap.Clear(0);
- for (int iChar = 0; iChar < textobj->m_nChars; iChar ++) {
- FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar];
- if (glyph.m_pGlyph == NULL) {
- continue;
- }
- bitmap.TransferBitmap((int)((glyph.m_OriginX + glyph.m_pGlyph->m_Left - rect.left) * sa),
- (int)((glyph.m_OriginY - glyph.m_pGlyph->m_Top - rect.top) * sd),
- glyph.m_pGlyph->m_Bitmap.GetWidth(), glyph.m_pGlyph->m_Bitmap.GetHeight(),
- &glyph.m_pGlyph->m_Bitmap, 0, 0);
- }
- m_pDevice->SetBitMask(&bitmap, rect.left, rect.top, fill_argb);
- FX_Free(pGlyphAndPos);
- }
- return TRUE;
-}
-class CPDF_CharPosList
-{
-public:
- CPDF_CharPosList();
- ~CPDF_CharPosList();
- void Load(int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pCharPos, CPDF_Font* pFont, FX_FLOAT font_size);
- FXTEXT_CHARPOS* m_pCharPos;
- FX_DWORD m_nChars;
-};
-FX_FLOAT _CIDTransformToFloat(FX_BYTE ch);
-CPDF_CharPosList::CPDF_CharPosList()
-{
- m_pCharPos = NULL;
-}
-CPDF_CharPosList::~CPDF_CharPosList()
-{
- if (m_pCharPos) {
- FX_Free(m_pCharPos);
- }
-}
-void CPDF_CharPosList::Load(int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pCharPos, CPDF_Font* pFont,
- FX_FLOAT FontSize)
-{
- m_pCharPos = FX_Alloc(FXTEXT_CHARPOS, nChars);
- FXSYS_memset32(m_pCharPos, 0, sizeof(FXTEXT_CHARPOS) * nChars);
- m_nChars = 0;
- CPDF_CIDFont* pCIDFont = pFont->GetCIDFont();
- FX_BOOL bVertWriting = pCIDFont && pCIDFont->IsVertWriting();
- for (int iChar = 0; iChar < nChars; iChar ++) {
- FX_DWORD CharCode = nChars == 1 ? (FX_DWORD)(FX_UINTPTR)pCharCodes : pCharCodes[iChar];
- if (CharCode == (FX_DWORD) - 1) {
- continue;
- }
- FX_BOOL bVert = FALSE;
- FXTEXT_CHARPOS& charpos = m_pCharPos[m_nChars++];
- if (pCIDFont) {
- charpos.m_bFontStyle = pCIDFont->IsFontStyleFromCharCode(CharCode);
- }
- charpos.m_GlyphIndex = pFont->GlyphFromCharCode(CharCode, &bVert);
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
- charpos.m_ExtGID = pFont->GlyphFromCharCodeExt(CharCode);
-#endif
- if (!pFont->IsEmbedded() && pFont->GetFontType() != PDFFONT_CIDFONT) {
- charpos.m_FontCharWidth = pFont->GetCharWidthF(CharCode);
- } else {
- charpos.m_FontCharWidth = 0;
- }
- charpos.m_OriginX = iChar ? pCharPos[iChar - 1] : 0;
- charpos.m_OriginY = 0;
- charpos.m_bGlyphAdjust = FALSE;
- if (pCIDFont == NULL) {
- continue;
- }
- FX_WORD CID = pCIDFont->CIDFromCharCode(CharCode);
- if (bVertWriting) {
- charpos.m_OriginY = charpos.m_OriginX;
- charpos.m_OriginX = 0;
- short vx, vy;
- pCIDFont->GetVertOrigin(CID, vx, vy);
- charpos.m_OriginX -= FontSize * vx / 1000;
- charpos.m_OriginY -= FontSize * vy / 1000;
- }
- FX_LPCBYTE pTransform = pCIDFont->GetCIDTransform(CID);
- if (pTransform && !bVert) {
- charpos.m_AdjustMatrix[0] = _CIDTransformToFloat(pTransform[0]);
- charpos.m_AdjustMatrix[2] = _CIDTransformToFloat(pTransform[2]);
- charpos.m_AdjustMatrix[1] = _CIDTransformToFloat(pTransform[1]);
- charpos.m_AdjustMatrix[3] = _CIDTransformToFloat(pTransform[3]);
- charpos.m_OriginX += _CIDTransformToFloat(pTransform[4]) * FontSize;
- charpos.m_OriginY += _CIDTransformToFloat(pTransform[5]) * FontSize;
- charpos.m_bGlyphAdjust = TRUE;
- }
- }
-}
-FX_BOOL CPDF_TextRenderer::DrawTextPath(CFX_RenderDevice* pDevice, int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pCharPos,
- CPDF_Font* pFont, FX_FLOAT font_size,
- const CFX_AffineMatrix* pText2User, const CFX_AffineMatrix* pUser2Device,
- const CFX_GraphStateData* pGraphState,
- FX_ARGB fill_argb, FX_ARGB stroke_argb, CFX_PathData* pClippingPath, int nFlag)
-{
- CFX_FontCache* pCache = pFont->m_pDocument ? pFont->m_pDocument->GetRenderData()->GetFontCache() : NULL;
- CPDF_CharPosList CharPosList;
- CharPosList.Load(nChars, pCharCodes, pCharPos, pFont, font_size);
- return pDevice->DrawTextPath(CharPosList.m_nChars, CharPosList.m_pCharPos,
- &pFont->m_Font, pCache, font_size, pText2User, pUser2Device,
- pGraphState, fill_argb, stroke_argb, pClippingPath, nFlag);
-}
-void CPDF_TextRenderer::DrawTextString(CFX_RenderDevice* pDevice, int left, int top, CPDF_Font* pFont, int height,
- const CFX_ByteString& str, FX_ARGB argb)
-{
- FX_RECT font_bbox;
- pFont->GetFontBBox(font_bbox);
- FX_FLOAT font_size = (FX_FLOAT)height * 1000.0f / (FX_FLOAT)(font_bbox.top - font_bbox.bottom);
- FX_FLOAT origin_x = (FX_FLOAT)left;
- FX_FLOAT origin_y = (FX_FLOAT)top + font_size * (FX_FLOAT)font_bbox.top / 1000.0f;
- CFX_AffineMatrix matrix(1.0f, 0, 0, -1.0f, 0, 0);
- DrawTextString(pDevice, origin_x, origin_y, pFont, font_size, &matrix, str, argb);
-}
-void CPDF_TextRenderer::DrawTextString(CFX_RenderDevice* pDevice, FX_FLOAT origin_x, FX_FLOAT origin_y, CPDF_Font* pFont, FX_FLOAT font_size,
- const CFX_AffineMatrix* pMatrix, const CFX_ByteString& str, FX_ARGB fill_argb,
- FX_ARGB stroke_argb, const CFX_GraphStateData* pGraphState, const CPDF_RenderOptions* pOptions)
-{
- int nChars = pFont->CountChar(str, str.GetLength());
- if (nChars == 0) {
- return;
- }
- FX_DWORD charcode;
- int offset = 0;
- FX_DWORD* pCharCodes;
- FX_FLOAT* pCharPos;
- if (nChars == 1) {
- charcode = pFont->GetNextChar(str, offset);
- pCharCodes = (FX_DWORD*)(FX_UINTPTR)charcode;
- pCharPos = NULL;
- } else {
- pCharCodes = FX_Alloc(FX_DWORD, nChars);
- pCharPos = FX_Alloc(FX_FLOAT, nChars - 1);
- FX_FLOAT cur_pos = 0;
- for (int i = 0; i < nChars; i ++) {
- pCharCodes[i] = pFont->GetNextChar(str, offset);
- if (i) {
- pCharPos[i - 1] = cur_pos;
- }
- cur_pos += pFont->GetCharWidthF(pCharCodes[i]) * font_size / 1000;
- }
- }
- CFX_AffineMatrix matrix;
- if (pMatrix) {
- matrix = *pMatrix;
- }
- matrix.e = origin_x;
- matrix.f = origin_y;
- if (pFont->GetFontType() == PDFFONT_TYPE3)
- ;
- else if (stroke_argb == 0) {
- DrawNormalText(pDevice, nChars, pCharCodes, pCharPos, pFont, font_size, &matrix, fill_argb, pOptions);
- } else
- DrawTextPath(pDevice, nChars, pCharCodes, pCharPos, pFont, font_size, &matrix, NULL, pGraphState,
- fill_argb, stroke_argb, NULL);
- if (nChars > 1) {
- FX_Free(pCharCodes);
- FX_Free(pCharPos);
- }
-}
-FX_BOOL CPDF_TextRenderer::DrawNormalText(CFX_RenderDevice* pDevice, int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pCharPos,
- CPDF_Font* pFont, FX_FLOAT font_size,
- const CFX_AffineMatrix* pText2Device,
- FX_ARGB fill_argb, const CPDF_RenderOptions* pOptions)
-{
- CFX_FontCache* pCache = pFont->m_pDocument ? pFont->m_pDocument->GetRenderData()->GetFontCache() : NULL;
- CPDF_CharPosList CharPosList;
- CharPosList.Load(nChars, pCharCodes, pCharPos, pFont, font_size);
- int FXGE_flags = 0;
- if (pOptions) {
- FX_DWORD dwFlags = pOptions->m_Flags;
- if (dwFlags & RENDER_CLEARTYPE) {
- FXGE_flags |= FXTEXT_CLEARTYPE;
- if (dwFlags & RENDER_BGR_STRIPE) {
- FXGE_flags |= FXTEXT_BGR_STRIPE;
- }
- }
- if (dwFlags & RENDER_NOTEXTSMOOTH) {
- FXGE_flags |= FXTEXT_NOSMOOTH;
- }
- if (dwFlags & RENDER_PRINTGRAPHICTEXT) {
- FXGE_flags |= FXTEXT_PRINTGRAPHICTEXT;
- }
- if (dwFlags & RENDER_NO_NATIVETEXT) {
- FXGE_flags |= FXTEXT_NO_NATIVETEXT;
- }
- if (dwFlags & RENDER_PRINTIMAGETEXT) {
- FXGE_flags |= FXTEXT_PRINTIMAGETEXT;
- }
- } else {
- FXGE_flags = FXTEXT_CLEARTYPE;
- }
- if (pFont->GetFontType() & PDFFONT_CIDFONT) {
- FXGE_flags |= FXFONT_CIDFONT;
- }
- return pDevice->DrawNormalText(CharPosList.m_nChars, CharPosList.m_pCharPos, &pFont->m_Font, pCache, font_size, pText2Device, fill_argb, FXGE_flags);
-}
-void CPDF_RenderStatus::DrawTextPathWithPattern(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device,
- CPDF_Font* pFont, FX_FLOAT font_size,
- const CFX_AffineMatrix* pTextMatrix, FX_BOOL bFill, FX_BOOL bStroke)
-{
- if (!bStroke) {
- CPDF_PathObject path;
- CPDF_TextObject* pCopy = FX_NEW CPDF_TextObject;
- pCopy->Copy(textobj);
- path.m_bStroke = FALSE;
- path.m_FillType = FXFILL_WINDING;
- path.m_ClipPath.AppendTexts(&pCopy, 1);
- path.m_ColorState = textobj->m_ColorState;
- path.m_Path.New()->AppendRect(textobj->m_Left, textobj->m_Bottom, textobj->m_Right, textobj->m_Top);
- path.m_Left = textobj->m_Left;
- path.m_Bottom = textobj->m_Bottom;
- path.m_Right = textobj->m_Right;
- path.m_Top = textobj->m_Top;
- RenderSingleObject(&path, pObj2Device);
- return;
- }
- CFX_FontCache* pCache;
- if (pFont->m_pDocument) {
- pCache = pFont->m_pDocument->GetRenderData()->GetFontCache();
- } else {
- pCache = CFX_GEModule::Get()->GetFontCache();
- }
- CFX_FaceCache* pFaceCache = pCache->GetCachedFace(&pFont->m_Font);
- FX_FONTCACHE_DEFINE(pCache, &pFont->m_Font);
- CPDF_CharPosList CharPosList;
- CharPosList.Load(textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos, pFont, font_size);
- for (FX_DWORD i = 0; i < CharPosList.m_nChars; i ++) {
- FXTEXT_CHARPOS& charpos = CharPosList.m_pCharPos[i];
- const CFX_PathData* pPath = pFaceCache->LoadGlyphPath(&pFont->m_Font, charpos.m_GlyphIndex,
- charpos.m_FontCharWidth);
- if (pPath == NULL) {
- continue;
- }
- CPDF_PathObject path;
- path.m_GraphState = textobj->m_GraphState;
- path.m_ColorState = textobj->m_ColorState;
- CFX_AffineMatrix matrix;
- if (charpos.m_bGlyphAdjust)
- matrix.Set(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1],
- charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0);
- matrix.Concat(font_size, 0, 0, font_size, charpos.m_OriginX, charpos.m_OriginY);
- path.m_Path.New()->Append(pPath, &matrix);
- path.m_Matrix = *pTextMatrix;
- path.m_bStroke = bStroke;
- path.m_FillType = bFill ? FXFILL_WINDING : 0;
- path.CalcBoundingBox();
- ProcessPath(&path, pObj2Device);
- }
-}
-CFX_PathData* CPDF_Font::LoadGlyphPath(FX_DWORD charcode, int dest_width)
-{
- int glyph_index = GlyphFromCharCode(charcode);
- if (m_Font.m_Face == NULL) {
- return NULL;
- }
- return m_Font.LoadGlyphPath(glyph_index, dest_width);
-}
+// 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/fpdfapi/fpdf_render.h" +#include "../../../include/fpdfapi/fpdf_pageobj.h" +#include "../fpdf_page/pageint.h" +#include "render_int.h" +extern FX_BOOL IsAvailableMatrix(const CFX_AffineMatrix& matrix); +CPDF_Type3Cache::~CPDF_Type3Cache() +{ + FX_POSITION pos = m_SizeMap.GetStartPosition(); + CFX_ByteString Key; + CPDF_Type3Glyphs* pSizeCache = NULL; + while(pos) { + pSizeCache = (CPDF_Type3Glyphs*)m_SizeMap.GetNextValue(pos); + delete pSizeCache; + } + m_SizeMap.RemoveAll(); +} +CFX_GlyphBitmap* CPDF_Type3Cache::LoadGlyph(FX_DWORD charcode, const CFX_AffineMatrix* pMatrix, FX_FLOAT retinaScaleX, FX_FLOAT retinaScaleY) +{ + _CPDF_UniqueKeyGen keygen; + keygen.Generate(4, FXSYS_round(pMatrix->a * 10000), FXSYS_round(pMatrix->b * 10000), + FXSYS_round(pMatrix->c * 10000), FXSYS_round(pMatrix->d * 10000)); + CFX_ByteStringC FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen); + CPDF_Type3Glyphs* pSizeCache = NULL; + if(!m_SizeMap.Lookup(FaceGlyphsKey, (void*&)pSizeCache)) { + pSizeCache = FX_NEW CPDF_Type3Glyphs; + m_SizeMap.SetAt(FaceGlyphsKey, pSizeCache); + } + CFX_GlyphBitmap* pGlyphBitmap; + if(pSizeCache->m_GlyphMap.Lookup((FX_LPVOID)(FX_UINTPTR)charcode, (void*&)pGlyphBitmap)) { + return pGlyphBitmap; + } + pGlyphBitmap = RenderGlyph(pSizeCache, charcode, pMatrix, retinaScaleX, retinaScaleY); + pSizeCache->m_GlyphMap.SetAt((FX_LPVOID)(FX_UINTPTR)charcode, pGlyphBitmap); + return pGlyphBitmap; +} +CPDF_Type3Glyphs::~CPDF_Type3Glyphs() +{ + FX_POSITION pos = m_GlyphMap.GetStartPosition(); + FX_LPVOID Key; + CFX_GlyphBitmap* pGlyphBitmap; + while(pos) { + m_GlyphMap.GetNextAssoc(pos, Key, (void*&)pGlyphBitmap); + delete pGlyphBitmap; + } +} +static int _AdjustBlue(FX_FLOAT pos, int& count, int blues[]) +{ + FX_FLOAT min_distance = 1000000.0f * 1.0f; + int closest_pos = -1; + for (int i = 0; i < count; i ++) { + FX_FLOAT distance = (FX_FLOAT)FXSYS_fabs(pos - (FX_FLOAT)blues[i]); + if (distance < 1.0f * 80.0f / 100.0f && distance < min_distance) { + min_distance = distance; + closest_pos = i; + } + } + if (closest_pos >= 0) { + return blues[closest_pos]; + } + int new_pos = FXSYS_round(pos); + if (count == TYPE3_MAX_BLUES) { + return new_pos; + } + blues[count++] = new_pos; + return new_pos; +} +void CPDF_Type3Glyphs::AdjustBlue(FX_FLOAT top, FX_FLOAT bottom, int& top_line, int& bottom_line) +{ + top_line = _AdjustBlue(top, m_TopBlueCount, m_TopBlue); + bottom_line = _AdjustBlue(bottom, m_BottomBlueCount, m_BottomBlue); +} +static FX_BOOL _IsScanLine1bpp(FX_LPBYTE pBuf, int width) +{ + int size = width / 8; + for (int i = 0; i < size; i ++) + if (pBuf[i]) { + return TRUE; + } + if (width % 8) + if (pBuf[width / 8] & (0xff << (8 - width % 8))) { + return TRUE; + } + return FALSE; +} +static FX_BOOL _IsScanLine8bpp(FX_LPBYTE pBuf, int width) +{ + for (int i = 0; i < width; i ++) + if (pBuf[i] > 0x40) { + return TRUE; + } + return FALSE; +} +static int _DetectFirstLastScan(const CFX_DIBitmap* pBitmap, FX_BOOL bFirst) +{ + int height = pBitmap->GetHeight(), pitch = pBitmap->GetPitch(), width = pBitmap->GetWidth(); + int bpp = pBitmap->GetBPP(); + if (bpp > 8) { + width *= bpp / 8; + } + FX_LPBYTE pBuf = pBitmap->GetBuffer(); + int line = bFirst ? 0 : height - 1; + int line_step = bFirst ? 1 : -1; + int line_end = bFirst ? height : -1; + while (line != line_end) { + if (bpp == 1) { + if (_IsScanLine1bpp(pBuf + line * pitch, width)) { + return line; + } + } else { + if (_IsScanLine8bpp(pBuf + line * pitch, width)) { + return line; + } + } + line += line_step; + } + return -1; +} +CFX_GlyphBitmap* CPDF_Type3Cache::RenderGlyph(CPDF_Type3Glyphs* pSize, FX_DWORD charcode, const CFX_AffineMatrix* pMatrix, FX_FLOAT retinaScaleX, FX_FLOAT retinaScaleY) +{ + CPDF_Type3Char* pChar = m_pFont->LoadChar(charcode); + if (pChar == NULL || pChar->m_pBitmap == NULL) { + return NULL; + } + CFX_DIBitmap* pBitmap = pChar->m_pBitmap; + CFX_AffineMatrix image_matrix, text_matrix; + image_matrix = pChar->m_ImageMatrix; + text_matrix.Set(pMatrix->a, pMatrix->b, pMatrix->c, pMatrix->d, 0, 0); + image_matrix.Concat(text_matrix); + CFX_DIBitmap* pResBitmap = NULL; + int left, top; + if (FXSYS_fabs(image_matrix.b) < FXSYS_fabs(image_matrix.a) / 100 && FXSYS_fabs(image_matrix.c) < FXSYS_fabs(image_matrix.d) / 100) { + int top_line, bottom_line; + top_line = _DetectFirstLastScan(pBitmap, TRUE); + bottom_line = _DetectFirstLastScan(pBitmap, FALSE); + if (top_line == 0 && bottom_line == pBitmap->GetHeight() - 1) { + FX_FLOAT top_y = image_matrix.d + image_matrix.f; + FX_FLOAT bottom_y = image_matrix.f; + FX_BOOL bFlipped = top_y > bottom_y; + if (bFlipped) { + FX_FLOAT temp = top_y; + top_y = bottom_y; + bottom_y = temp; + } + pSize->AdjustBlue(top_y, bottom_y, top_line, bottom_line); + pResBitmap = pBitmap->StretchTo((int)(FXSYS_round(image_matrix.a) * retinaScaleX), (int)((bFlipped ? top_line - bottom_line : bottom_line - top_line) * retinaScaleY)); + top = top_line; + if (image_matrix.a < 0) { + image_matrix.Scale(retinaScaleX, retinaScaleY); + left = FXSYS_round(image_matrix.e + image_matrix.a); + } else { + left = FXSYS_round(image_matrix.e); + } + } else { + } + } + if (pResBitmap == NULL) { + image_matrix.Scale(retinaScaleX, retinaScaleY); + pResBitmap = pBitmap->TransformTo(&image_matrix, left, top); + } + if (pResBitmap == NULL) { + return NULL; + } + CFX_GlyphBitmap* pGlyph = FX_NEW CFX_GlyphBitmap; + pGlyph->m_Left = left; + pGlyph->m_Top = -top; + pGlyph->m_Bitmap.TakeOver(pResBitmap); + delete pResBitmap; + return pGlyph; +} +void _CPDF_UniqueKeyGen::Generate(int count, ...) +{ + va_list argList; + va_start(argList, count); + for (int i = 0; i < count; i ++) { + int p = va_arg(argList, int); + ((FX_DWORD*)m_Key)[i] = p; + } + va_end(argList); + m_KeyLen = count * sizeof(FX_DWORD); +} +FX_BOOL CPDF_RenderStatus::ProcessText(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device, CFX_PathData* pClippingPath) +{ + if(textobj->m_nChars == 0) { + return TRUE; + } + int text_render_mode = textobj->m_TextState.GetObject()->m_TextMode; + if (text_render_mode == 3) { + return TRUE; + } + CPDF_Font* pFont = textobj->m_TextState.GetFont(); + if (pFont->GetFontType() == PDFFONT_TYPE3) { + return ProcessType3Text(textobj, pObj2Device); + } + FX_BOOL bFill = FALSE, bStroke = FALSE, bClip = FALSE; + if (pClippingPath) { + bClip = TRUE; + } else { + switch (text_render_mode) { + case 0: + case 4: + bFill = TRUE; + break; + case 1: + case 5: + if (pFont->GetFace() == NULL && !(pFont->GetSubstFont()->m_SubstFlags & FXFONT_SUBST_GLYPHPATH)) { + bFill = TRUE; + } else { + bStroke = TRUE; + } + break; + case 2: + case 6: + if (pFont->GetFace() == NULL && !(pFont->GetSubstFont()->m_SubstFlags & FXFONT_SUBST_GLYPHPATH)) { + bFill = TRUE; + } else { + bFill = bStroke = TRUE; + } + break; + case 3: + case 7: + return TRUE; + default: + bFill = TRUE; + } + } + FX_ARGB stroke_argb = 0, fill_argb = 0; + FX_BOOL bPattern = FALSE; + if (bStroke) { + if (textobj->m_ColorState.GetStrokeColor()->IsPattern()) { + bPattern = TRUE; + } else { + stroke_argb = GetStrokeArgb(textobj); + } + } + if (bFill) { + if (textobj->m_ColorState.GetFillColor()->IsPattern()) { + bPattern = TRUE; + } else { + fill_argb = GetFillArgb(textobj); + } + } + CFX_AffineMatrix text_matrix; + textobj->GetTextMatrix(&text_matrix); + if(IsAvailableMatrix(text_matrix) == FALSE) { + return TRUE; + } + FX_FLOAT font_size = textobj->m_TextState.GetFontSize(); + if (bPattern) { + DrawTextPathWithPattern(textobj, pObj2Device, pFont, font_size, &text_matrix, bFill, bStroke); + return TRUE; + } +#if defined(_FPDFAPI_MINI_) + if (bFill) { + bStroke = FALSE; + } + if (bStroke) { + if (font_size * text_matrix.GetXUnit() * pObj2Device->GetXUnit() < 6) { + bStroke = FALSE; + } + } +#endif + if (bClip || bStroke) { + const CFX_AffineMatrix* pDeviceMatrix = pObj2Device; + CFX_AffineMatrix device_matrix; + if (bStroke) { + const FX_FLOAT* pCTM = textobj->m_TextState.GetObject()->m_CTM; + if (pCTM[0] != 1.0f || pCTM[3] != 1.0f) { + CFX_AffineMatrix ctm(pCTM[0], pCTM[1], pCTM[2], pCTM[3], 0, 0); + text_matrix.ConcatInverse(ctm); + device_matrix.Copy(ctm); + device_matrix.Concat(*pObj2Device); + pDeviceMatrix = &device_matrix; + } + } + int flag = 0; + if (bStroke && bFill) { + flag |= FX_FILL_STROKE; + flag |= FX_STROKE_TEXT_MODE; + } +#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_) + const CPDF_GeneralStateData* pGeneralData = ((CPDF_PageObject*)textobj)->m_GeneralState; + if (pGeneralData && pGeneralData->m_StrokeAdjust) { + flag |= FX_STROKE_ADJUST; + } +#endif + if (m_Options.m_Flags & RENDER_NOTEXTSMOOTH) { + flag |= FXFILL_NOPATHSMOOTH; + } + return CPDF_TextRenderer::DrawTextPath(m_pDevice, textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos, pFont, font_size, + &text_matrix, pDeviceMatrix, textobj->m_GraphState, fill_argb, stroke_argb, pClippingPath, flag); + } + text_matrix.Concat(*pObj2Device); + return CPDF_TextRenderer::DrawNormalText(m_pDevice, textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos, pFont, font_size, + &text_matrix, fill_argb, &m_Options); +} +CPDF_Type3Cache* CPDF_RenderStatus::GetCachedType3(CPDF_Type3Font* pFont) +{ + if (pFont->m_pDocument == NULL) { + return NULL; + } + pFont->m_pDocument->GetPageData()->GetFont(pFont->GetFontDict(), FALSE); + return pFont->m_pDocument->GetRenderData()->GetCachedType3(pFont); +} +static void ReleaseCachedType3(CPDF_Type3Font* pFont) +{ + if (pFont->m_pDocument == NULL) { + return; + } + pFont->m_pDocument->GetRenderData()->ReleaseCachedType3(pFont); + pFont->m_pDocument->GetPageData()->ReleaseFont(pFont->GetFontDict()); +} +FX_BOOL CPDF_Type3Char::LoadBitmap(CPDF_RenderContext* pContext) +{ + if (m_pBitmap != NULL || m_pForm == NULL) { + return TRUE; + } + if (m_pForm->CountObjects() == 1 && !m_bColored) { + CPDF_PageObject *pPageObj = m_pForm->GetObjectAt(m_pForm->GetFirstObjectPosition()); + if (pPageObj->m_Type == PDFPAGE_IMAGE) { + CPDF_ImageObject* pImage = (CPDF_ImageObject*)pPageObj; + m_ImageMatrix = pImage->m_Matrix; + const CFX_DIBSource* pSource = pImage->m_pImage->LoadDIBSource(); + if (pSource) { + m_pBitmap = pSource->Clone(); + delete pSource; + } + delete m_pForm; + m_pForm = NULL; + return TRUE; + } + if (pPageObj->m_Type == PDFPAGE_INLINES) { + CPDF_InlineImages *pInlines = (CPDF_InlineImages *)pPageObj; + if (pInlines->m_pStream) { + m_ImageMatrix = pInlines->m_Matrices[0]; + CPDF_DIBSource dibsrc; + if (!dibsrc.Load(pContext->m_pDocument, pInlines->m_pStream, NULL, NULL, NULL, NULL)) { + return FALSE; + } + m_pBitmap = dibsrc.Clone(); + delete m_pForm; + m_pForm = NULL; + return TRUE; + } + } + } + return FALSE; +} +class CPDF_RefType3Cache +{ +public: + CPDF_RefType3Cache(CPDF_Type3Font* pType3Font) + { + m_dwCount = 0; + m_pType3Font = pType3Font; + } + ~CPDF_RefType3Cache() + { + while(m_dwCount--) { + ReleaseCachedType3(m_pType3Font); + } + } + FX_DWORD m_dwCount; + CPDF_Type3Font* m_pType3Font; +}; +FX_BOOL CPDF_RenderStatus::ProcessType3Text(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device) +{ + CPDF_Type3Font* pType3Font = textobj->m_TextState.GetFont()->GetType3Font(); + for (int j = 0; j < m_Type3FontCache.GetSize(); j++) + if ((CPDF_Type3Font*)m_Type3FontCache.GetAt(j) == pType3Font) { + return TRUE; + } + CFX_Matrix dCTM = m_pDevice->GetCTM(); + FX_FLOAT sa = FXSYS_fabs(dCTM.a); + FX_FLOAT sd = FXSYS_fabs(dCTM.d); + CFX_AffineMatrix text_matrix; + textobj->GetTextMatrix(&text_matrix); + CFX_AffineMatrix char_matrix = pType3Font->GetFontMatrix(); + FX_FLOAT font_size = textobj->m_TextState.GetFontSize(); + char_matrix.Scale(font_size, font_size); + FX_ARGB fill_argb = GetFillArgb(textobj, TRUE); + int fill_alpha = FXARGB_A(fill_argb); + int device_class = m_pDevice->GetDeviceClass(); + FXTEXT_GLYPHPOS* pGlyphAndPos = NULL; + if (device_class == FXDC_DISPLAY) { + pGlyphAndPos = FX_Alloc(FXTEXT_GLYPHPOS, textobj->m_nChars); + FXSYS_memset32(pGlyphAndPos, 0, sizeof(FXTEXT_GLYPHPOS) * textobj->m_nChars); + } else if (fill_alpha < 255) { + return FALSE; + } + CPDF_RefType3Cache refTypeCache(pType3Font); + FX_DWORD *pChars = textobj->m_pCharCodes; + if (textobj->m_nChars == 1) { + pChars = (FX_DWORD*)(&textobj->m_pCharCodes); + } + for (int iChar = 0; iChar < textobj->m_nChars; iChar ++) { + FX_DWORD charcode = pChars[iChar]; + if (charcode == (FX_DWORD) - 1) { + continue; + } + CPDF_Type3Char* pType3Char = pType3Font->LoadChar(charcode); + if (pType3Char == NULL) { + continue; + } + CFX_AffineMatrix matrix = char_matrix; + matrix.e += iChar ? textobj->m_pCharPos[iChar - 1] : 0; + matrix.Concat(text_matrix); + matrix.Concat(*pObj2Device); + if (!pType3Char->LoadBitmap(m_pContext)) { + if (pGlyphAndPos) { + for (int i = 0; i < iChar; i ++) { + FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[i]; + if (glyph.m_pGlyph == NULL) { + continue; + } + m_pDevice->SetBitMask(&glyph.m_pGlyph->m_Bitmap, + glyph.m_OriginX + glyph.m_pGlyph->m_Left, + glyph.m_OriginY - glyph.m_pGlyph->m_Top, fill_argb); + } + FX_Free(pGlyphAndPos); + pGlyphAndPos = NULL; + } + CPDF_GraphicStates* pStates = CloneObjStates(textobj, FALSE); + CPDF_RenderOptions Options = m_Options; + Options.m_Flags |= RENDER_FORCE_HALFTONE | RENDER_RECT_AA; + Options.m_Flags &= ~RENDER_FORCE_DOWNSAMPLE; + CPDF_Dictionary* pFormResource = NULL; + if (pType3Char->m_pForm && pType3Char->m_pForm->m_pFormDict) { + pFormResource = pType3Char->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources")); + } + if (fill_alpha == 255) { + CPDF_RenderStatus status; + status.Initialize(m_Level + 1, m_pContext, m_pDevice, NULL, NULL, this, pStates, &Options, + pType3Char->m_pForm->m_Transparency, m_bDropObjects, pFormResource, FALSE, pType3Char, fill_argb); + status.m_Type3FontCache.Append(m_Type3FontCache); + status.m_Type3FontCache.Add(pType3Font); + m_pDevice->SaveState(); + status.RenderObjectList(pType3Char->m_pForm, &matrix); + m_pDevice->RestoreState(); + } else { + CFX_FloatRect rect_f = pType3Char->m_pForm->CalcBoundingBox(); + rect_f.Transform(&matrix); + FX_RECT rect = rect_f.GetOutterRect(); + CFX_FxgeDevice bitmap_device; + if (!bitmap_device.Create((int)(rect.Width() * sa), (int)(rect.Height() * sd), FXDIB_Argb)) { + return TRUE; + } + bitmap_device.GetBitmap()->Clear(0); + CPDF_RenderStatus status; + status.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL, NULL, this, pStates, &Options, + pType3Char->m_pForm->m_Transparency, m_bDropObjects, pFormResource, FALSE, pType3Char, fill_argb); + status.m_Type3FontCache.Append(m_Type3FontCache); + status.m_Type3FontCache.Add(pType3Font); + matrix.TranslateI(-rect.left, -rect.top); + matrix.Scale(sa, sd); + status.RenderObjectList(pType3Char->m_pForm, &matrix); + m_pDevice->SetDIBits(bitmap_device.GetBitmap(), rect.left, rect.top); + } + delete pStates; + } else if (pType3Char->m_pBitmap) { + if (device_class == FXDC_DISPLAY) { + CPDF_Type3Cache* pCache = GetCachedType3(pType3Font); + refTypeCache.m_dwCount++; + CFX_GlyphBitmap* pBitmap = pCache->LoadGlyph(charcode, &matrix, sa, sd); + if (pBitmap == NULL) { + continue; + } + int origin_x = FXSYS_round(matrix.e); + int origin_y = FXSYS_round(matrix.f); + if (pGlyphAndPos) { + pGlyphAndPos[iChar].m_pGlyph = pBitmap; + pGlyphAndPos[iChar].m_OriginX = origin_x; + pGlyphAndPos[iChar].m_OriginY = origin_y; + } else { + m_pDevice->SetBitMask(&pBitmap->m_Bitmap, origin_x + pBitmap->m_Left, origin_y - pBitmap->m_Top, fill_argb); + } + } else { + CFX_AffineMatrix image_matrix = pType3Char->m_ImageMatrix; + image_matrix.Concat(matrix); + CPDF_ImageRenderer renderer; + if (renderer.Start(this, pType3Char->m_pBitmap, fill_argb, 255, &image_matrix, 0, FALSE)) { + renderer.Continue(NULL); + } + if (!renderer.m_Result) { + return FALSE; + } + } + } + } + if (pGlyphAndPos) { + FX_RECT rect = FXGE_GetGlyphsBBox(pGlyphAndPos, textobj->m_nChars, 0, sa, sd); + CFX_DIBitmap bitmap; + if (!bitmap.Create((int)(rect.Width() * sa), (int)(rect.Height() * sd), FXDIB_8bppMask)) { + FX_Free(pGlyphAndPos); + return TRUE; + } + bitmap.Clear(0); + for (int iChar = 0; iChar < textobj->m_nChars; iChar ++) { + FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar]; + if (glyph.m_pGlyph == NULL) { + continue; + } + bitmap.TransferBitmap((int)((glyph.m_OriginX + glyph.m_pGlyph->m_Left - rect.left) * sa), + (int)((glyph.m_OriginY - glyph.m_pGlyph->m_Top - rect.top) * sd), + glyph.m_pGlyph->m_Bitmap.GetWidth(), glyph.m_pGlyph->m_Bitmap.GetHeight(), + &glyph.m_pGlyph->m_Bitmap, 0, 0); + } + m_pDevice->SetBitMask(&bitmap, rect.left, rect.top, fill_argb); + FX_Free(pGlyphAndPos); + } + return TRUE; +} +class CPDF_CharPosList +{ +public: + CPDF_CharPosList(); + ~CPDF_CharPosList(); + void Load(int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pCharPos, CPDF_Font* pFont, FX_FLOAT font_size); + FXTEXT_CHARPOS* m_pCharPos; + FX_DWORD m_nChars; +}; +FX_FLOAT _CIDTransformToFloat(FX_BYTE ch); +CPDF_CharPosList::CPDF_CharPosList() +{ + m_pCharPos = NULL; +} +CPDF_CharPosList::~CPDF_CharPosList() +{ + if (m_pCharPos) { + FX_Free(m_pCharPos); + } +} +void CPDF_CharPosList::Load(int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pCharPos, CPDF_Font* pFont, + FX_FLOAT FontSize) +{ + m_pCharPos = FX_Alloc(FXTEXT_CHARPOS, nChars); + FXSYS_memset32(m_pCharPos, 0, sizeof(FXTEXT_CHARPOS) * nChars); + m_nChars = 0; + CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); + FX_BOOL bVertWriting = pCIDFont && pCIDFont->IsVertWriting(); + for (int iChar = 0; iChar < nChars; iChar ++) { + FX_DWORD CharCode = nChars == 1 ? (FX_DWORD)(FX_UINTPTR)pCharCodes : pCharCodes[iChar]; + if (CharCode == (FX_DWORD) - 1) { + continue; + } + FX_BOOL bVert = FALSE; + FXTEXT_CHARPOS& charpos = m_pCharPos[m_nChars++]; + if (pCIDFont) { + charpos.m_bFontStyle = pCIDFont->IsFontStyleFromCharCode(CharCode); + } + charpos.m_GlyphIndex = pFont->GlyphFromCharCode(CharCode, &bVert); +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + charpos.m_ExtGID = pFont->GlyphFromCharCodeExt(CharCode); +#endif + if (!pFont->IsEmbedded() && pFont->GetFontType() != PDFFONT_CIDFONT) { + charpos.m_FontCharWidth = pFont->GetCharWidthF(CharCode); + } else { + charpos.m_FontCharWidth = 0; + } + charpos.m_OriginX = iChar ? pCharPos[iChar - 1] : 0; + charpos.m_OriginY = 0; + charpos.m_bGlyphAdjust = FALSE; + if (pCIDFont == NULL) { + continue; + } + FX_WORD CID = pCIDFont->CIDFromCharCode(CharCode); + if (bVertWriting) { + charpos.m_OriginY = charpos.m_OriginX; + charpos.m_OriginX = 0; + short vx, vy; + pCIDFont->GetVertOrigin(CID, vx, vy); + charpos.m_OriginX -= FontSize * vx / 1000; + charpos.m_OriginY -= FontSize * vy / 1000; + } + FX_LPCBYTE pTransform = pCIDFont->GetCIDTransform(CID); + if (pTransform && !bVert) { + charpos.m_AdjustMatrix[0] = _CIDTransformToFloat(pTransform[0]); + charpos.m_AdjustMatrix[2] = _CIDTransformToFloat(pTransform[2]); + charpos.m_AdjustMatrix[1] = _CIDTransformToFloat(pTransform[1]); + charpos.m_AdjustMatrix[3] = _CIDTransformToFloat(pTransform[3]); + charpos.m_OriginX += _CIDTransformToFloat(pTransform[4]) * FontSize; + charpos.m_OriginY += _CIDTransformToFloat(pTransform[5]) * FontSize; + charpos.m_bGlyphAdjust = TRUE; + } + } +} +FX_BOOL CPDF_TextRenderer::DrawTextPath(CFX_RenderDevice* pDevice, int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pCharPos, + CPDF_Font* pFont, FX_FLOAT font_size, + const CFX_AffineMatrix* pText2User, const CFX_AffineMatrix* pUser2Device, + const CFX_GraphStateData* pGraphState, + FX_ARGB fill_argb, FX_ARGB stroke_argb, CFX_PathData* pClippingPath, int nFlag) +{ + CFX_FontCache* pCache = pFont->m_pDocument ? pFont->m_pDocument->GetRenderData()->GetFontCache() : NULL; + CPDF_CharPosList CharPosList; + CharPosList.Load(nChars, pCharCodes, pCharPos, pFont, font_size); + return pDevice->DrawTextPath(CharPosList.m_nChars, CharPosList.m_pCharPos, + &pFont->m_Font, pCache, font_size, pText2User, pUser2Device, + pGraphState, fill_argb, stroke_argb, pClippingPath, nFlag); +} +void CPDF_TextRenderer::DrawTextString(CFX_RenderDevice* pDevice, int left, int top, CPDF_Font* pFont, int height, + const CFX_ByteString& str, FX_ARGB argb) +{ + FX_RECT font_bbox; + pFont->GetFontBBox(font_bbox); + FX_FLOAT font_size = (FX_FLOAT)height * 1000.0f / (FX_FLOAT)(font_bbox.top - font_bbox.bottom); + FX_FLOAT origin_x = (FX_FLOAT)left; + FX_FLOAT origin_y = (FX_FLOAT)top + font_size * (FX_FLOAT)font_bbox.top / 1000.0f; + CFX_AffineMatrix matrix(1.0f, 0, 0, -1.0f, 0, 0); + DrawTextString(pDevice, origin_x, origin_y, pFont, font_size, &matrix, str, argb); +} +void CPDF_TextRenderer::DrawTextString(CFX_RenderDevice* pDevice, FX_FLOAT origin_x, FX_FLOAT origin_y, CPDF_Font* pFont, FX_FLOAT font_size, + const CFX_AffineMatrix* pMatrix, const CFX_ByteString& str, FX_ARGB fill_argb, + FX_ARGB stroke_argb, const CFX_GraphStateData* pGraphState, const CPDF_RenderOptions* pOptions) +{ + int nChars = pFont->CountChar(str, str.GetLength()); + if (nChars == 0) { + return; + } + FX_DWORD charcode; + int offset = 0; + FX_DWORD* pCharCodes; + FX_FLOAT* pCharPos; + if (nChars == 1) { + charcode = pFont->GetNextChar(str, offset); + pCharCodes = (FX_DWORD*)(FX_UINTPTR)charcode; + pCharPos = NULL; + } else { + pCharCodes = FX_Alloc(FX_DWORD, nChars); + pCharPos = FX_Alloc(FX_FLOAT, nChars - 1); + FX_FLOAT cur_pos = 0; + for (int i = 0; i < nChars; i ++) { + pCharCodes[i] = pFont->GetNextChar(str, offset); + if (i) { + pCharPos[i - 1] = cur_pos; + } + cur_pos += pFont->GetCharWidthF(pCharCodes[i]) * font_size / 1000; + } + } + CFX_AffineMatrix matrix; + if (pMatrix) { + matrix = *pMatrix; + } + matrix.e = origin_x; + matrix.f = origin_y; + if (pFont->GetFontType() == PDFFONT_TYPE3) + ; + else if (stroke_argb == 0) { + DrawNormalText(pDevice, nChars, pCharCodes, pCharPos, pFont, font_size, &matrix, fill_argb, pOptions); + } else + DrawTextPath(pDevice, nChars, pCharCodes, pCharPos, pFont, font_size, &matrix, NULL, pGraphState, + fill_argb, stroke_argb, NULL); + if (nChars > 1) { + FX_Free(pCharCodes); + FX_Free(pCharPos); + } +} +FX_BOOL CPDF_TextRenderer::DrawNormalText(CFX_RenderDevice* pDevice, int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pCharPos, + CPDF_Font* pFont, FX_FLOAT font_size, + const CFX_AffineMatrix* pText2Device, + FX_ARGB fill_argb, const CPDF_RenderOptions* pOptions) +{ + CFX_FontCache* pCache = pFont->m_pDocument ? pFont->m_pDocument->GetRenderData()->GetFontCache() : NULL; + CPDF_CharPosList CharPosList; + CharPosList.Load(nChars, pCharCodes, pCharPos, pFont, font_size); + int FXGE_flags = 0; + if (pOptions) { + FX_DWORD dwFlags = pOptions->m_Flags; + if (dwFlags & RENDER_CLEARTYPE) { + FXGE_flags |= FXTEXT_CLEARTYPE; + if (dwFlags & RENDER_BGR_STRIPE) { + FXGE_flags |= FXTEXT_BGR_STRIPE; + } + } + if (dwFlags & RENDER_NOTEXTSMOOTH) { + FXGE_flags |= FXTEXT_NOSMOOTH; + } + if (dwFlags & RENDER_PRINTGRAPHICTEXT) { + FXGE_flags |= FXTEXT_PRINTGRAPHICTEXT; + } + if (dwFlags & RENDER_NO_NATIVETEXT) { + FXGE_flags |= FXTEXT_NO_NATIVETEXT; + } + if (dwFlags & RENDER_PRINTIMAGETEXT) { + FXGE_flags |= FXTEXT_PRINTIMAGETEXT; + } + } else { + FXGE_flags = FXTEXT_CLEARTYPE; + } + if (pFont->GetFontType() & PDFFONT_CIDFONT) { + FXGE_flags |= FXFONT_CIDFONT; + } + return pDevice->DrawNormalText(CharPosList.m_nChars, CharPosList.m_pCharPos, &pFont->m_Font, pCache, font_size, pText2Device, fill_argb, FXGE_flags); +} +void CPDF_RenderStatus::DrawTextPathWithPattern(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device, + CPDF_Font* pFont, FX_FLOAT font_size, + const CFX_AffineMatrix* pTextMatrix, FX_BOOL bFill, FX_BOOL bStroke) +{ + if (!bStroke) { + CPDF_PathObject path; + CPDF_TextObject* pCopy = FX_NEW CPDF_TextObject; + pCopy->Copy(textobj); + path.m_bStroke = FALSE; + path.m_FillType = FXFILL_WINDING; + path.m_ClipPath.AppendTexts(&pCopy, 1); + path.m_ColorState = textobj->m_ColorState; + path.m_Path.New()->AppendRect(textobj->m_Left, textobj->m_Bottom, textobj->m_Right, textobj->m_Top); + path.m_Left = textobj->m_Left; + path.m_Bottom = textobj->m_Bottom; + path.m_Right = textobj->m_Right; + path.m_Top = textobj->m_Top; + RenderSingleObject(&path, pObj2Device); + return; + } + CFX_FontCache* pCache; + if (pFont->m_pDocument) { + pCache = pFont->m_pDocument->GetRenderData()->GetFontCache(); + } else { + pCache = CFX_GEModule::Get()->GetFontCache(); + } + CFX_FaceCache* pFaceCache = pCache->GetCachedFace(&pFont->m_Font); + FX_FONTCACHE_DEFINE(pCache, &pFont->m_Font); + CPDF_CharPosList CharPosList; + CharPosList.Load(textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos, pFont, font_size); + for (FX_DWORD i = 0; i < CharPosList.m_nChars; i ++) { + FXTEXT_CHARPOS& charpos = CharPosList.m_pCharPos[i]; + const CFX_PathData* pPath = pFaceCache->LoadGlyphPath(&pFont->m_Font, charpos.m_GlyphIndex, + charpos.m_FontCharWidth); + if (pPath == NULL) { + continue; + } + CPDF_PathObject path; + path.m_GraphState = textobj->m_GraphState; + path.m_ColorState = textobj->m_ColorState; + CFX_AffineMatrix matrix; + if (charpos.m_bGlyphAdjust) + matrix.Set(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], + charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); + matrix.Concat(font_size, 0, 0, font_size, charpos.m_OriginX, charpos.m_OriginY); + path.m_Path.New()->Append(pPath, &matrix); + path.m_Matrix = *pTextMatrix; + path.m_bStroke = bStroke; + path.m_FillType = bFill ? FXFILL_WINDING : 0; + path.CalcBoundingBox(); + ProcessPath(&path, pObj2Device); + } +} +CFX_PathData* CPDF_Font::LoadGlyphPath(FX_DWORD charcode, int dest_width) +{ + int glyph_index = GlyphFromCharCode(charcode); + if (m_Font.m_Face == NULL) { + return NULL; + } + return m_Font.LoadGlyphPath(glyph_index, dest_width); +} diff --git a/core/src/fpdfapi/fpdf_render/render_int.h b/core/src/fpdfapi/fpdf_render/render_int.h index 3acde0ec43..9bde4be877 100644 --- a/core/src/fpdfapi/fpdf_render/render_int.h +++ b/core/src/fpdfapi/fpdf_render/render_int.h @@ -1,462 +1,462 @@ -// 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
-
-#ifndef _FPDF_PAGEOBJ_H_
-#include "../../../include/fpdfapi/fpdf_pageobj.h"
-#endif
-class CPDF_QuickStretcher;
-#define TYPE3_MAX_BLUES 16
-class CPDF_Type3Glyphs : public CFX_Object
-{
-public:
- CPDF_Type3Glyphs()
- {
- m_GlyphMap.InitHashTable(253);
- m_TopBlueCount = m_BottomBlueCount = 0;
- }
- ~CPDF_Type3Glyphs();
- CFX_MapPtrToPtr m_GlyphMap;
- void AdjustBlue(FX_FLOAT top, FX_FLOAT bottom, int& top_line, int& bottom_line);
-
- int m_TopBlue[TYPE3_MAX_BLUES], m_BottomBlue[TYPE3_MAX_BLUES];
- int m_TopBlueCount, m_BottomBlueCount;
-};
-class CFX_GlyphBitmap;
-class CPDF_Type3Cache : public CFX_Object
-{
-public:
- CPDF_Type3Cache(CPDF_Type3Font* pFont)
- {
- m_pFont = pFont;
- }
- ~CPDF_Type3Cache();
- CFX_GlyphBitmap* LoadGlyph(FX_DWORD charcode, const CFX_AffineMatrix* pMatrix, FX_FLOAT retinaScaleX = 1.0f, FX_FLOAT retinaScaleY = 1.0f);
-protected:
- CFX_GlyphBitmap* RenderGlyph(CPDF_Type3Glyphs* pSize, FX_DWORD charcode, const CFX_AffineMatrix* pMatrix, FX_FLOAT retinaScaleX = 1.0f, FX_FLOAT retinaScaleY = 1.0f);
- CPDF_Type3Font* m_pFont;
- CFX_MapByteStringToPtr m_SizeMap;
-};
-class CPDF_TransferFunc : public CFX_Object
-{
-public:
- CPDF_Document* m_pPDFDoc;
- FX_BYTE m_Samples[256 * 3];
- FX_BOOL m_bIdentity;
-
- CFX_DIBSource* TranslateImage(const CFX_DIBSource* pSrc, FX_BOOL bAutoDropSrc);
- FX_COLORREF TranslateColor(FX_COLORREF src);
-};
-typedef CFX_MapPtrTemplate<CPDF_Font*, CPDF_CountedObject<CPDF_Type3Cache*>*> CPDF_Type3CacheMap;
-typedef CFX_MapPtrTemplate<CPDF_Object*, CPDF_CountedObject<CPDF_TransferFunc*>*> CPDF_TransferFuncMap;
-class CPDF_DocRenderData : public CFX_Object
-{
-public:
- CPDF_DocRenderData(CPDF_Document* pPDFDoc = NULL);
- ~CPDF_DocRenderData();
- FX_BOOL Initialize();
- CPDF_Type3Cache* GetCachedType3(CPDF_Type3Font* pFont);
- CPDF_TransferFunc* GetTransferFunc(CPDF_Object* pObj);
- CFX_FontCache* GetFontCache()
- {
- return m_pFontCache;
- }
- void Clear(FX_BOOL bRelease = FALSE);
- void ReleaseCachedType3(CPDF_Type3Font* pFont);
- void ReleaseTransferFunc(CPDF_Object* pObj);
-private:
- CPDF_Document* m_pPDFDoc;
- CFX_FontCache* m_pFontCache;
- CPDF_Type3CacheMap m_Type3FaceMap;
- CPDF_TransferFuncMap m_TransferFuncMap;
-};
-struct _PDF_RenderItem {
-public:
- CPDF_PageObjects* m_pObjectList;
- CFX_AffineMatrix m_Matrix;
-};
-typedef CFX_ArrayTemplate<_PDF_RenderItem> CPDF_RenderLayer;
-class IPDF_ObjectRenderer : public CFX_Object
-{
-public:
- static IPDF_ObjectRenderer* Create(int type);
- virtual ~IPDF_ObjectRenderer() {}
- virtual FX_BOOL Start(CPDF_RenderStatus* pRenderStatus, const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStdCS, int blendType = FXDIB_BLEND_NORMAL) = 0;
- virtual FX_BOOL Continue(IFX_Pause* pPause) = 0;
- FX_BOOL m_Result;
-};
-class CPDF_RenderStatus : public CFX_Object
-{
-public:
- CPDF_RenderStatus();
- ~CPDF_RenderStatus();
- FX_BOOL Initialize(int level, class CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, const CFX_AffineMatrix* pDeviceMatrix,
- const CPDF_PageObject* pStopObj, const CPDF_RenderStatus* pParentStatus,
- const CPDF_GraphicStates* pInitialStates, const CPDF_RenderOptions* pOptions,
- int transparency, FX_BOOL bDropObjects, CPDF_Dictionary* pFormResource = NULL,
- FX_BOOL bStdCS = FALSE, CPDF_Type3Char* pType3Char = NULL, FX_ARGB fill_color = 0,
- FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE);
- void RenderObjectList(const CPDF_PageObjects* pObjs, const CFX_AffineMatrix* pObj2Device);
- void RenderSingleObject(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device);
- FX_BOOL ContinueSingleObject(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, IFX_Pause* pPause);
- CPDF_RenderOptions m_Options;
- CPDF_Dictionary* m_pFormResource;
- CPDF_Dictionary* m_pPageResource;
- CFX_PtrArray m_Type3FontCache;
- CPDF_RenderContext* GetContext()
- {
- return m_pContext;
- }
-protected:
- friend class CPDF_ImageRenderer;
- friend class CPDF_RenderContext;
- void ProcessClipPath(CPDF_ClipPath ClipPath, const CFX_AffineMatrix* pObj2Device);
- void DrawClipPath(CPDF_ClipPath ClipPath, const CFX_AffineMatrix* pObj2Device);
- FX_BOOL ProcessTransparency(const CPDF_PageObject* PageObj, const CFX_AffineMatrix* pObj2Device);
- void ProcessObjectNoClip(const CPDF_PageObject* PageObj, const CFX_AffineMatrix* pObj2Device);
- void DrawObjWithBackground(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device);
- FX_BOOL DrawObjWithBlend(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device);
- FX_BOOL ProcessPath(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device);
- void ProcessPathPattern(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device, int& filltype, FX_BOOL& bStroke);
- void DrawPathWithPattern(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device, CPDF_Color* pColor, FX_BOOL bStroke);
- void DrawTilingPattern(CPDF_TilingPattern* pPattern, CPDF_PageObject* pPageObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke);
- void DrawShadingPattern(CPDF_ShadingPattern* pPattern, CPDF_PageObject* pPageObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke);
- FX_BOOL SelectClipPath(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke);
- FX_BOOL ProcessImage(CPDF_ImageObject* pImageObj, const CFX_AffineMatrix* pObj2Device);
- FX_BOOL OutputBitmapAlpha(CPDF_ImageObject* pImageObj, const CFX_AffineMatrix* pImage2Device);
- FX_BOOL OutputImage(CPDF_ImageObject* pImageObj, const CFX_AffineMatrix* pImage2Device);
- FX_BOOL OutputDIBSource(const CFX_DIBSource* pOutputBitmap, FX_ARGB fill_argb, int bitmap_alpha,
- const CFX_AffineMatrix* pImage2Device, CPDF_ImageCache* pImageCache, FX_DWORD flags);
- void CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, int left, int top, FX_ARGB mask_argb,
- int bitmap_alpha, int blend_mode, int bIsolated);
- FX_BOOL ProcessInlines(CPDF_InlineImages* pInlines, const CFX_AffineMatrix* pObj2Device);
- FX_BOOL ProcessShading(CPDF_ShadingObject* pShadingObj, const CFX_AffineMatrix* pObj2Device);
- void DrawShading(CPDF_ShadingPattern* pPattern, CFX_AffineMatrix* pMatrix, FX_RECT& clip_rect,
- int alpha, FX_BOOL bAlphaMode);
- FX_BOOL ProcessType3Text(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device);
- FX_BOOL ProcessText(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device, CFX_PathData* pClippingPath);
- void DrawTextPathWithPattern(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device,
- CPDF_Font* pFont, FX_FLOAT font_size,
- const CFX_AffineMatrix* pTextMatrix, FX_BOOL bFill, FX_BOOL bStroke);
- FX_BOOL ProcessForm(CPDF_FormObject* pFormObj, const CFX_AffineMatrix* pObj2Device);
- CFX_DIBitmap* GetBackdrop(const CPDF_PageObject* pObj, const FX_RECT& rect, int& left, int& top,
- FX_BOOL bBackAlphaRequired);
- CFX_DIBitmap* LoadSMask(CPDF_Dictionary* pSMaskDict, FX_RECT* pClipRect, const CFX_AffineMatrix* pMatrix);
- void Init(CPDF_RenderContext* pParent);
- static class CPDF_Type3Cache* GetCachedType3(CPDF_Type3Font* pFont);
- static CPDF_GraphicStates* CloneObjStates(const CPDF_GraphicStates* pPathObj, FX_BOOL bStroke);
- CPDF_TransferFunc* GetTransferFunc(CPDF_Object* pObject) const;
- FX_ARGB GetFillArgb(const CPDF_PageObject* pObj, FX_BOOL bType3 = FALSE) const;
- FX_ARGB GetStrokeArgb(const CPDF_PageObject* pObj) const;
- CPDF_RenderContext* m_pContext;
- FX_BOOL m_bStopped;
- void DitherObjectArea(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device);
- FX_BOOL GetObjectClippedRect(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bLogical, FX_RECT &rect) const;
- void GetScaledMatrix(CFX_Matrix &matrix) const;
-protected:
- int m_Level;
- CFX_RenderDevice* m_pDevice;
- CFX_AffineMatrix m_DeviceMatrix;
- CPDF_ClipPath m_LastClipPath;
- const CPDF_PageObject* m_pCurObj;
- const CPDF_PageObject* m_pStopObj;
- CPDF_GraphicStates m_InitialStates;
- int m_HalftoneLimit;
- IPDF_ObjectRenderer* m_pObjectRenderer;
- FX_BOOL m_bPrint;
- int m_Transparency;
- int m_DitherBits;
- FX_BOOL m_bDropObjects;
- FX_BOOL m_bStdCS;
- FX_DWORD m_GroupFamily;
- FX_BOOL m_bLoadMask;
- CPDF_Type3Char * m_pType3Char;
- FX_ARGB m_T3FillColor;
- int m_curBlend;
-};
-class CPDF_ImageLoader : public CFX_Object
-{
-public:
- CPDF_ImageLoader()
- {
- m_pBitmap = NULL;
- m_pMask = NULL;
- m_MatteColor = 0;
- m_bCached = FALSE;
- m_nDownsampleWidth = 0;
- m_nDownsampleHeight = 0;
- }
-
- FX_BOOL Load(const CPDF_ImageObject* pImage, CPDF_PageRenderCache* pCache, FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE, CPDF_RenderStatus* pRenderStatus = NULL);
-
- FX_BOOL StartLoadImage(const CPDF_ImageObject* pImage, CPDF_PageRenderCache* pCache, FX_LPVOID& LoadHandle, FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE, CPDF_RenderStatus* pRenderStatus = NULL, FX_INT32 nDownsampleWidth = 0, FX_INT32 nDownsampleHeight = 0);
- FX_BOOL Continue(FX_LPVOID LoadHandle, IFX_Pause* pPause);
- ~CPDF_ImageLoader();
- CFX_DIBSource* m_pBitmap;
- CFX_DIBSource* m_pMask;
- FX_DWORD m_MatteColor;
- FX_BOOL m_bCached;
-protected:
- FX_INT32 m_nDownsampleWidth;
- FX_INT32 m_nDownsampleHeight;
-};
-class CPDF_ProgressiveImageLoaderHandle : public CFX_Object
-{
-public:
- CPDF_ProgressiveImageLoaderHandle();
- ~CPDF_ProgressiveImageLoaderHandle();
-
- FX_BOOL Start(CPDF_ImageLoader* pImageLoader, const CPDF_ImageObject* pImage, CPDF_PageRenderCache* pCache, FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE, CPDF_RenderStatus* pRenderStatus = NULL, FX_INT32 nDownsampleWidth = 0, FX_INT32 nDownsampleHeight = 0);
- FX_BOOL Continue(IFX_Pause* pPause);
-protected:
- CPDF_ImageLoader* m_pImageLoader;
- CPDF_PageRenderCache* m_pCache;
- CPDF_ImageObject* m_pImage;
- FX_INT32 m_nDownsampleWidth;
- FX_INT32 m_nDownsampleHeight;
-};
-class CFX_ImageTransformer;
-class CPDF_ImageRenderer : public IPDF_ObjectRenderer
-{
-public:
- CPDF_ImageRenderer();
- ~CPDF_ImageRenderer();
- FX_BOOL Start(CPDF_RenderStatus* pStatus, const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStdCS, int blendType = FXDIB_BLEND_NORMAL);
- FX_BOOL 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 = FXDIB_BLEND_NORMAL);
- FX_BOOL Continue(IFX_Pause* pPause);
-protected:
- CPDF_RenderStatus* m_pRenderStatus;
- CPDF_ImageObject* m_pImageObject;
- int m_Status;
- const CFX_AffineMatrix* m_pObj2Device;
- CFX_AffineMatrix m_ImageMatrix;
- CPDF_ImageLoader m_Loader;
- const CFX_DIBSource* m_pDIBSource;
- CFX_DIBitmap* m_pClone;
- int m_BitmapAlpha;
- FX_BOOL m_bPatternColor;
- CPDF_Pattern* m_pPattern;
- FX_ARGB m_FillArgb;
- FX_DWORD m_Flags;
- CPDF_QuickStretcher* m_pQuickStretcher;
- CFX_ImageTransformer* m_pTransformer;
- CPDF_ImageRenderer* m_pRenderer2;
- FX_LPVOID m_DeviceHandle;
- FX_LPVOID m_LoadHandle;
- FX_BOOL m_bStdCS;
- int m_BlendType;
- FX_BOOL StartBitmapAlpha();
- FX_BOOL StartDIBSource();
- FX_BOOL StartRenderDIBSource();
- FX_BOOL StartLoadDIBSource();
- FX_BOOL DrawMaskedImage();
- FX_BOOL DrawPatternImage(const CFX_Matrix* pObj2Device);
-};
-class CPDF_ScaledRenderBuffer : public CFX_Object
-{
-public:
- CPDF_ScaledRenderBuffer();
- ~CPDF_ScaledRenderBuffer();
- FX_BOOL Initialize(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, FX_RECT* pRect,
- const CPDF_PageObject* pObj, const CPDF_RenderOptions *pOptions = NULL, int max_dpi = 0);
- CFX_RenderDevice* GetDevice()
- {
- return m_pBitmapDevice ? m_pBitmapDevice : m_pDevice;
- }
- CFX_AffineMatrix* GetMatrix()
- {
- return &m_Matrix;
- }
- void OutputToDevice();
-private:
- CFX_RenderDevice* m_pDevice;
- CPDF_RenderContext* m_pContext;
- FX_RECT m_Rect;
- const CPDF_PageObject* m_pObject;
- CFX_FxgeDevice* m_pBitmapDevice;
- CFX_AffineMatrix m_Matrix;
-};
-class ICodec_ScanlineDecoder;
-class CPDF_QuickStretcher : public CFX_Object
-{
-public:
- CPDF_QuickStretcher();
- ~CPDF_QuickStretcher();
- FX_BOOL Start(CPDF_ImageObject* pImageObj, CFX_AffineMatrix* pImage2Device, const FX_RECT* pClipBox);
- FX_BOOL Continue(IFX_Pause* pPause);
- CFX_DIBitmap* m_pBitmap;
- int m_ResultLeft, m_ResultTop, m_ClipLeft, m_ClipTop;
- int m_DestWidth, m_DestHeight, m_ResultWidth, m_ResultHeight;
- int m_Bpp, m_SrcWidth, m_SrcHeight;
- FX_BOOL m_bFlipX, m_bFlipY;
- CPDF_ColorSpace* m_pCS;
- ICodec_ScanlineDecoder* m_pDecoder;
- CPDF_StreamAcc m_StreamAcc;
- int m_LineIndex;
-};
-class CPDF_DeviceBuffer : public CFX_Object
-{
-public:
- CPDF_DeviceBuffer();
- ~CPDF_DeviceBuffer();
- FX_BOOL Initialize(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, FX_RECT* pRect,
- const CPDF_PageObject* pObj, int max_dpi = 0);
- void OutputToDevice();
- CFX_DIBitmap* GetBitmap() const
- {
- return m_pBitmap;
- }
- const CFX_AffineMatrix* GetMatrix() const
- {
- return &m_Matrix;
- }
-private:
- CFX_RenderDevice* m_pDevice;
- CPDF_RenderContext* m_pContext;
- FX_RECT m_Rect;
- const CPDF_PageObject* m_pObject;
- CFX_DIBitmap* m_pBitmap;
- CFX_AffineMatrix m_Matrix;
-};
-class CPDF_ImageCache : public CFX_Object
-{
-public:
- CPDF_ImageCache(CPDF_Document* pDoc, CPDF_Stream* pStream);
- ~CPDF_ImageCache();
- void ClearImageData();
- void Reset(const CFX_DIBitmap* pBitmap);
- FX_BOOL GetCachedBitmap(CFX_DIBSource*& pBitmap, CFX_DIBSource*& pMask, FX_DWORD& MatteColor, CPDF_Dictionary* pPageResources,
- FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE,
- CPDF_RenderStatus* pRenderStatus = NULL, FX_INT32 downsampleWidth = 0, FX_INT32 downsampleHeight = 0);
- FX_DWORD EstimateSize() const
- {
- return m_dwCacheSize;
- }
- FX_DWORD GetTimeCount() const
- {
- return m_dwTimeCount;
- }
- CPDF_Stream* GetStream() const
- {
- return m_pStream;
- }
- void SetTimeCount(FX_DWORD dwTimeCount)
- {
- m_dwTimeCount = dwTimeCount;
- }
- int m_dwTimeCount;
-public:
- int StartGetCachedBitmap(CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources,
- FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0,
- FX_BOOL bLoadMask = FALSE, CPDF_RenderStatus* pRenderStatus = NULL, FX_INT32 downsampleWidth = 0, FX_INT32 downsampleHeight = 0);
- int Continue(IFX_Pause* pPause);
- int ContinueGetCachedBitmap();
- CFX_DIBSource* DetachBitmap();
- CFX_DIBSource* DetachMask();
- CFX_DIBSource* m_pCurBitmap;
- CFX_DIBSource* m_pCurMask;
- FX_DWORD m_MatteColor;
- CPDF_RenderStatus* m_pRenderStatus;
-protected:
- CPDF_Document* m_pDocument;
- CPDF_Stream* m_pStream;
- CFX_DIBSource* m_pCachedBitmap;
- CFX_DIBSource* m_pCachedMask;
- FX_DWORD m_dwCacheSize;
- void CalcSize();
-};
-typedef struct {
- FX_FLOAT m_DecodeMin;
- FX_FLOAT m_DecodeStep;
- int m_ColorKeyMin;
- int m_ColorKeyMax;
-} DIB_COMP_DATA;
-class CPDF_DIBSource : public CFX_DIBSource
-{
-public:
- CPDF_DIBSource();
- virtual ~CPDF_DIBSource();
- FX_BOOL Load(CPDF_Document* pDoc, const CPDF_Stream* pStream,
- CPDF_DIBSource** ppMask, FX_DWORD* pMatteColor,
- CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources,
- FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE);
- virtual FX_BOOL SkipToScanline(int line, IFX_Pause* pPause) const;
- virtual FX_LPBYTE GetBuffer() const;
- virtual FX_LPCBYTE GetScanline(int line) const;
- virtual void DownSampleScanline(int line, FX_LPBYTE dest_scan, int dest_bpp,
- int dest_width, FX_BOOL bFlipX, int clip_left, int clip_width) const;
- virtual void SetDownSampleSize(int dest_width, int dest_height) const;
- CFX_DIBitmap* GetBitmap() const;
- void ReleaseBitmap(CFX_DIBitmap*) const;
- void ClearImageData();
-public:
- int StartLoadDIBSource(CPDF_Document* pDoc, const CPDF_Stream* pStream, FX_BOOL bHasMask,
- CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources,
- FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE);
- int ContinueLoadDIBSource(IFX_Pause* pPause);
- int StratLoadMask();
- int StartLoadMaskDIB();
- int ContinueLoadMaskDIB(IFX_Pause* pPause);
- int ContinueToLoadMask();
- CPDF_DIBSource* DetachMask();
- CPDF_DIBSource* m_pMask;
- FX_DWORD m_MatteColor;
- FX_LPVOID m_pJbig2Context;
- CPDF_StreamAcc* m_pGlobalStream;
- FX_BOOL m_bStdCS;
- int m_Status;
- CPDF_Object* m_pMaskStream;
- FX_BOOL m_bHasMask;
-protected:
- FX_BOOL LoadColorInfo(CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources);
- CPDF_DIBSource* LoadMask(FX_DWORD& MatteColor);
- CPDF_DIBSource* LoadMaskDIB(CPDF_Stream* pMask);
- void LoadJpxBitmap();
- void LoadJbig2Bitmap();
- void LoadPalette();
- FX_BOOL CreateDecoder();
- void TranslateScanline24bpp(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan) const;
- FX_DWORD GetValidBpp() const;
-
- CPDF_Document* m_pDocument;
- const CPDF_Stream* m_pStream;
- CPDF_StreamAcc* m_pStreamAcc;
- const CPDF_Dictionary* m_pDict;
- CPDF_ColorSpace* m_pColorSpace;
- FX_DWORD m_Family, m_bpc, m_nComponents, m_GroupFamily;
- FX_BOOL m_bLoadMask;
- FX_BOOL m_bDefaultDecode, m_bImageMask, m_bColorKey;
- DIB_COMP_DATA* m_pCompData;
- FX_LPBYTE m_pLineBuf;
- FX_LPBYTE m_pMaskedLine;
- CFX_DIBitmap* m_pCachedBitmap;
- ICodec_ScanlineDecoder* m_pDecoder;
-};
-#ifdef _FPDFAPI_MINI_
-#define FPDF_HUGE_IMAGE_SIZE 3000000
-#else
-#define FPDF_HUGE_IMAGE_SIZE 60000000
-#endif
-class CPDF_DIBTransferFunc : public CFX_FilteredDIB
-{
-public:
- CPDF_DIBTransferFunc(const CPDF_TransferFunc* pTransferFunc);
- virtual FXDIB_Format GetDestFormat();
- virtual FX_ARGB* GetDestPalette()
- {
- return NULL;
- }
- virtual void TranslateScanline(FX_LPBYTE dest_buf, FX_LPCBYTE src_buf) const;
- virtual void TranslateDownSamples(FX_LPBYTE dest_buf, FX_LPCBYTE src_buf, int pixels, int Bpp) const;
- FX_LPCBYTE m_RampR;
- FX_LPCBYTE m_RampG;
- FX_LPCBYTE m_RampB;
-};
-struct _CPDF_UniqueKeyGen {
- void Generate(int count, ...);
- FX_CHAR m_Key[128];
- int m_KeyLen;
-};
+// 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 + +#ifndef _FPDF_PAGEOBJ_H_ +#include "../../../include/fpdfapi/fpdf_pageobj.h" +#endif +class CPDF_QuickStretcher; +#define TYPE3_MAX_BLUES 16 +class CPDF_Type3Glyphs : public CFX_Object +{ +public: + CPDF_Type3Glyphs() + { + m_GlyphMap.InitHashTable(253); + m_TopBlueCount = m_BottomBlueCount = 0; + } + ~CPDF_Type3Glyphs(); + CFX_MapPtrToPtr m_GlyphMap; + void AdjustBlue(FX_FLOAT top, FX_FLOAT bottom, int& top_line, int& bottom_line); + + int m_TopBlue[TYPE3_MAX_BLUES], m_BottomBlue[TYPE3_MAX_BLUES]; + int m_TopBlueCount, m_BottomBlueCount; +}; +class CFX_GlyphBitmap; +class CPDF_Type3Cache : public CFX_Object +{ +public: + CPDF_Type3Cache(CPDF_Type3Font* pFont) + { + m_pFont = pFont; + } + ~CPDF_Type3Cache(); + CFX_GlyphBitmap* LoadGlyph(FX_DWORD charcode, const CFX_AffineMatrix* pMatrix, FX_FLOAT retinaScaleX = 1.0f, FX_FLOAT retinaScaleY = 1.0f); +protected: + CFX_GlyphBitmap* RenderGlyph(CPDF_Type3Glyphs* pSize, FX_DWORD charcode, const CFX_AffineMatrix* pMatrix, FX_FLOAT retinaScaleX = 1.0f, FX_FLOAT retinaScaleY = 1.0f); + CPDF_Type3Font* m_pFont; + CFX_MapByteStringToPtr m_SizeMap; +}; +class CPDF_TransferFunc : public CFX_Object +{ +public: + CPDF_Document* m_pPDFDoc; + FX_BYTE m_Samples[256 * 3]; + FX_BOOL m_bIdentity; + + CFX_DIBSource* TranslateImage(const CFX_DIBSource* pSrc, FX_BOOL bAutoDropSrc); + FX_COLORREF TranslateColor(FX_COLORREF src); +}; +typedef CFX_MapPtrTemplate<CPDF_Font*, CPDF_CountedObject<CPDF_Type3Cache*>*> CPDF_Type3CacheMap; +typedef CFX_MapPtrTemplate<CPDF_Object*, CPDF_CountedObject<CPDF_TransferFunc*>*> CPDF_TransferFuncMap; +class CPDF_DocRenderData : public CFX_Object +{ +public: + CPDF_DocRenderData(CPDF_Document* pPDFDoc = NULL); + ~CPDF_DocRenderData(); + FX_BOOL Initialize(); + CPDF_Type3Cache* GetCachedType3(CPDF_Type3Font* pFont); + CPDF_TransferFunc* GetTransferFunc(CPDF_Object* pObj); + CFX_FontCache* GetFontCache() + { + return m_pFontCache; + } + void Clear(FX_BOOL bRelease = FALSE); + void ReleaseCachedType3(CPDF_Type3Font* pFont); + void ReleaseTransferFunc(CPDF_Object* pObj); +private: + CPDF_Document* m_pPDFDoc; + CFX_FontCache* m_pFontCache; + CPDF_Type3CacheMap m_Type3FaceMap; + CPDF_TransferFuncMap m_TransferFuncMap; +}; +struct _PDF_RenderItem { +public: + CPDF_PageObjects* m_pObjectList; + CFX_AffineMatrix m_Matrix; +}; +typedef CFX_ArrayTemplate<_PDF_RenderItem> CPDF_RenderLayer; +class IPDF_ObjectRenderer : public CFX_Object +{ +public: + static IPDF_ObjectRenderer* Create(int type); + virtual ~IPDF_ObjectRenderer() {} + virtual FX_BOOL Start(CPDF_RenderStatus* pRenderStatus, const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStdCS, int blendType = FXDIB_BLEND_NORMAL) = 0; + virtual FX_BOOL Continue(IFX_Pause* pPause) = 0; + FX_BOOL m_Result; +}; +class CPDF_RenderStatus : public CFX_Object +{ +public: + CPDF_RenderStatus(); + ~CPDF_RenderStatus(); + FX_BOOL Initialize(int level, class CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, const CFX_AffineMatrix* pDeviceMatrix, + const CPDF_PageObject* pStopObj, const CPDF_RenderStatus* pParentStatus, + const CPDF_GraphicStates* pInitialStates, const CPDF_RenderOptions* pOptions, + int transparency, FX_BOOL bDropObjects, CPDF_Dictionary* pFormResource = NULL, + FX_BOOL bStdCS = FALSE, CPDF_Type3Char* pType3Char = NULL, FX_ARGB fill_color = 0, + FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE); + void RenderObjectList(const CPDF_PageObjects* pObjs, const CFX_AffineMatrix* pObj2Device); + void RenderSingleObject(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device); + FX_BOOL ContinueSingleObject(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, IFX_Pause* pPause); + CPDF_RenderOptions m_Options; + CPDF_Dictionary* m_pFormResource; + CPDF_Dictionary* m_pPageResource; + CFX_PtrArray m_Type3FontCache; + CPDF_RenderContext* GetContext() + { + return m_pContext; + } +protected: + friend class CPDF_ImageRenderer; + friend class CPDF_RenderContext; + void ProcessClipPath(CPDF_ClipPath ClipPath, const CFX_AffineMatrix* pObj2Device); + void DrawClipPath(CPDF_ClipPath ClipPath, const CFX_AffineMatrix* pObj2Device); + FX_BOOL ProcessTransparency(const CPDF_PageObject* PageObj, const CFX_AffineMatrix* pObj2Device); + void ProcessObjectNoClip(const CPDF_PageObject* PageObj, const CFX_AffineMatrix* pObj2Device); + void DrawObjWithBackground(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device); + FX_BOOL DrawObjWithBlend(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device); + FX_BOOL ProcessPath(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device); + void ProcessPathPattern(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device, int& filltype, FX_BOOL& bStroke); + void DrawPathWithPattern(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device, CPDF_Color* pColor, FX_BOOL bStroke); + void DrawTilingPattern(CPDF_TilingPattern* pPattern, CPDF_PageObject* pPageObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke); + void DrawShadingPattern(CPDF_ShadingPattern* pPattern, CPDF_PageObject* pPageObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke); + FX_BOOL SelectClipPath(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke); + FX_BOOL ProcessImage(CPDF_ImageObject* pImageObj, const CFX_AffineMatrix* pObj2Device); + FX_BOOL OutputBitmapAlpha(CPDF_ImageObject* pImageObj, const CFX_AffineMatrix* pImage2Device); + FX_BOOL OutputImage(CPDF_ImageObject* pImageObj, const CFX_AffineMatrix* pImage2Device); + FX_BOOL OutputDIBSource(const CFX_DIBSource* pOutputBitmap, FX_ARGB fill_argb, int bitmap_alpha, + const CFX_AffineMatrix* pImage2Device, CPDF_ImageCache* pImageCache, FX_DWORD flags); + void CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, int left, int top, FX_ARGB mask_argb, + int bitmap_alpha, int blend_mode, int bIsolated); + FX_BOOL ProcessInlines(CPDF_InlineImages* pInlines, const CFX_AffineMatrix* pObj2Device); + FX_BOOL ProcessShading(CPDF_ShadingObject* pShadingObj, const CFX_AffineMatrix* pObj2Device); + void DrawShading(CPDF_ShadingPattern* pPattern, CFX_AffineMatrix* pMatrix, FX_RECT& clip_rect, + int alpha, FX_BOOL bAlphaMode); + FX_BOOL ProcessType3Text(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device); + FX_BOOL ProcessText(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device, CFX_PathData* pClippingPath); + void DrawTextPathWithPattern(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device, + CPDF_Font* pFont, FX_FLOAT font_size, + const CFX_AffineMatrix* pTextMatrix, FX_BOOL bFill, FX_BOOL bStroke); + FX_BOOL ProcessForm(CPDF_FormObject* pFormObj, const CFX_AffineMatrix* pObj2Device); + CFX_DIBitmap* GetBackdrop(const CPDF_PageObject* pObj, const FX_RECT& rect, int& left, int& top, + FX_BOOL bBackAlphaRequired); + CFX_DIBitmap* LoadSMask(CPDF_Dictionary* pSMaskDict, FX_RECT* pClipRect, const CFX_AffineMatrix* pMatrix); + void Init(CPDF_RenderContext* pParent); + static class CPDF_Type3Cache* GetCachedType3(CPDF_Type3Font* pFont); + static CPDF_GraphicStates* CloneObjStates(const CPDF_GraphicStates* pPathObj, FX_BOOL bStroke); + CPDF_TransferFunc* GetTransferFunc(CPDF_Object* pObject) const; + FX_ARGB GetFillArgb(const CPDF_PageObject* pObj, FX_BOOL bType3 = FALSE) const; + FX_ARGB GetStrokeArgb(const CPDF_PageObject* pObj) const; + CPDF_RenderContext* m_pContext; + FX_BOOL m_bStopped; + void DitherObjectArea(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device); + FX_BOOL GetObjectClippedRect(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bLogical, FX_RECT &rect) const; + void GetScaledMatrix(CFX_Matrix &matrix) const; +protected: + int m_Level; + CFX_RenderDevice* m_pDevice; + CFX_AffineMatrix m_DeviceMatrix; + CPDF_ClipPath m_LastClipPath; + const CPDF_PageObject* m_pCurObj; + const CPDF_PageObject* m_pStopObj; + CPDF_GraphicStates m_InitialStates; + int m_HalftoneLimit; + IPDF_ObjectRenderer* m_pObjectRenderer; + FX_BOOL m_bPrint; + int m_Transparency; + int m_DitherBits; + FX_BOOL m_bDropObjects; + FX_BOOL m_bStdCS; + FX_DWORD m_GroupFamily; + FX_BOOL m_bLoadMask; + CPDF_Type3Char * m_pType3Char; + FX_ARGB m_T3FillColor; + int m_curBlend; +}; +class CPDF_ImageLoader : public CFX_Object +{ +public: + CPDF_ImageLoader() + { + m_pBitmap = NULL; + m_pMask = NULL; + m_MatteColor = 0; + m_bCached = FALSE; + m_nDownsampleWidth = 0; + m_nDownsampleHeight = 0; + } + + FX_BOOL Load(const CPDF_ImageObject* pImage, CPDF_PageRenderCache* pCache, FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE, CPDF_RenderStatus* pRenderStatus = NULL); + + FX_BOOL StartLoadImage(const CPDF_ImageObject* pImage, CPDF_PageRenderCache* pCache, FX_LPVOID& LoadHandle, FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE, CPDF_RenderStatus* pRenderStatus = NULL, FX_INT32 nDownsampleWidth = 0, FX_INT32 nDownsampleHeight = 0); + FX_BOOL Continue(FX_LPVOID LoadHandle, IFX_Pause* pPause); + ~CPDF_ImageLoader(); + CFX_DIBSource* m_pBitmap; + CFX_DIBSource* m_pMask; + FX_DWORD m_MatteColor; + FX_BOOL m_bCached; +protected: + FX_INT32 m_nDownsampleWidth; + FX_INT32 m_nDownsampleHeight; +}; +class CPDF_ProgressiveImageLoaderHandle : public CFX_Object +{ +public: + CPDF_ProgressiveImageLoaderHandle(); + ~CPDF_ProgressiveImageLoaderHandle(); + + FX_BOOL Start(CPDF_ImageLoader* pImageLoader, const CPDF_ImageObject* pImage, CPDF_PageRenderCache* pCache, FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE, CPDF_RenderStatus* pRenderStatus = NULL, FX_INT32 nDownsampleWidth = 0, FX_INT32 nDownsampleHeight = 0); + FX_BOOL Continue(IFX_Pause* pPause); +protected: + CPDF_ImageLoader* m_pImageLoader; + CPDF_PageRenderCache* m_pCache; + CPDF_ImageObject* m_pImage; + FX_INT32 m_nDownsampleWidth; + FX_INT32 m_nDownsampleHeight; +}; +class CFX_ImageTransformer; +class CPDF_ImageRenderer : public IPDF_ObjectRenderer +{ +public: + CPDF_ImageRenderer(); + ~CPDF_ImageRenderer(); + FX_BOOL Start(CPDF_RenderStatus* pStatus, const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStdCS, int blendType = FXDIB_BLEND_NORMAL); + FX_BOOL 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 = FXDIB_BLEND_NORMAL); + FX_BOOL Continue(IFX_Pause* pPause); +protected: + CPDF_RenderStatus* m_pRenderStatus; + CPDF_ImageObject* m_pImageObject; + int m_Status; + const CFX_AffineMatrix* m_pObj2Device; + CFX_AffineMatrix m_ImageMatrix; + CPDF_ImageLoader m_Loader; + const CFX_DIBSource* m_pDIBSource; + CFX_DIBitmap* m_pClone; + int m_BitmapAlpha; + FX_BOOL m_bPatternColor; + CPDF_Pattern* m_pPattern; + FX_ARGB m_FillArgb; + FX_DWORD m_Flags; + CPDF_QuickStretcher* m_pQuickStretcher; + CFX_ImageTransformer* m_pTransformer; + CPDF_ImageRenderer* m_pRenderer2; + FX_LPVOID m_DeviceHandle; + FX_LPVOID m_LoadHandle; + FX_BOOL m_bStdCS; + int m_BlendType; + FX_BOOL StartBitmapAlpha(); + FX_BOOL StartDIBSource(); + FX_BOOL StartRenderDIBSource(); + FX_BOOL StartLoadDIBSource(); + FX_BOOL DrawMaskedImage(); + FX_BOOL DrawPatternImage(const CFX_Matrix* pObj2Device); +}; +class CPDF_ScaledRenderBuffer : public CFX_Object +{ +public: + CPDF_ScaledRenderBuffer(); + ~CPDF_ScaledRenderBuffer(); + FX_BOOL Initialize(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, FX_RECT* pRect, + const CPDF_PageObject* pObj, const CPDF_RenderOptions *pOptions = NULL, int max_dpi = 0); + CFX_RenderDevice* GetDevice() + { + return m_pBitmapDevice ? m_pBitmapDevice : m_pDevice; + } + CFX_AffineMatrix* GetMatrix() + { + return &m_Matrix; + } + void OutputToDevice(); +private: + CFX_RenderDevice* m_pDevice; + CPDF_RenderContext* m_pContext; + FX_RECT m_Rect; + const CPDF_PageObject* m_pObject; + CFX_FxgeDevice* m_pBitmapDevice; + CFX_AffineMatrix m_Matrix; +}; +class ICodec_ScanlineDecoder; +class CPDF_QuickStretcher : public CFX_Object +{ +public: + CPDF_QuickStretcher(); + ~CPDF_QuickStretcher(); + FX_BOOL Start(CPDF_ImageObject* pImageObj, CFX_AffineMatrix* pImage2Device, const FX_RECT* pClipBox); + FX_BOOL Continue(IFX_Pause* pPause); + CFX_DIBitmap* m_pBitmap; + int m_ResultLeft, m_ResultTop, m_ClipLeft, m_ClipTop; + int m_DestWidth, m_DestHeight, m_ResultWidth, m_ResultHeight; + int m_Bpp, m_SrcWidth, m_SrcHeight; + FX_BOOL m_bFlipX, m_bFlipY; + CPDF_ColorSpace* m_pCS; + ICodec_ScanlineDecoder* m_pDecoder; + CPDF_StreamAcc m_StreamAcc; + int m_LineIndex; +}; +class CPDF_DeviceBuffer : public CFX_Object +{ +public: + CPDF_DeviceBuffer(); + ~CPDF_DeviceBuffer(); + FX_BOOL Initialize(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, FX_RECT* pRect, + const CPDF_PageObject* pObj, int max_dpi = 0); + void OutputToDevice(); + CFX_DIBitmap* GetBitmap() const + { + return m_pBitmap; + } + const CFX_AffineMatrix* GetMatrix() const + { + return &m_Matrix; + } +private: + CFX_RenderDevice* m_pDevice; + CPDF_RenderContext* m_pContext; + FX_RECT m_Rect; + const CPDF_PageObject* m_pObject; + CFX_DIBitmap* m_pBitmap; + CFX_AffineMatrix m_Matrix; +}; +class CPDF_ImageCache : public CFX_Object +{ +public: + CPDF_ImageCache(CPDF_Document* pDoc, CPDF_Stream* pStream); + ~CPDF_ImageCache(); + void ClearImageData(); + void Reset(const CFX_DIBitmap* pBitmap); + FX_BOOL GetCachedBitmap(CFX_DIBSource*& pBitmap, CFX_DIBSource*& pMask, FX_DWORD& MatteColor, CPDF_Dictionary* pPageResources, + FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE, + CPDF_RenderStatus* pRenderStatus = NULL, FX_INT32 downsampleWidth = 0, FX_INT32 downsampleHeight = 0); + FX_DWORD EstimateSize() const + { + return m_dwCacheSize; + } + FX_DWORD GetTimeCount() const + { + return m_dwTimeCount; + } + CPDF_Stream* GetStream() const + { + return m_pStream; + } + void SetTimeCount(FX_DWORD dwTimeCount) + { + m_dwTimeCount = dwTimeCount; + } + int m_dwTimeCount; +public: + int StartGetCachedBitmap(CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources, + FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0, + FX_BOOL bLoadMask = FALSE, CPDF_RenderStatus* pRenderStatus = NULL, FX_INT32 downsampleWidth = 0, FX_INT32 downsampleHeight = 0); + int Continue(IFX_Pause* pPause); + int ContinueGetCachedBitmap(); + CFX_DIBSource* DetachBitmap(); + CFX_DIBSource* DetachMask(); + CFX_DIBSource* m_pCurBitmap; + CFX_DIBSource* m_pCurMask; + FX_DWORD m_MatteColor; + CPDF_RenderStatus* m_pRenderStatus; +protected: + CPDF_Document* m_pDocument; + CPDF_Stream* m_pStream; + CFX_DIBSource* m_pCachedBitmap; + CFX_DIBSource* m_pCachedMask; + FX_DWORD m_dwCacheSize; + void CalcSize(); +}; +typedef struct { + FX_FLOAT m_DecodeMin; + FX_FLOAT m_DecodeStep; + int m_ColorKeyMin; + int m_ColorKeyMax; +} DIB_COMP_DATA; +class CPDF_DIBSource : public CFX_DIBSource +{ +public: + CPDF_DIBSource(); + virtual ~CPDF_DIBSource(); + FX_BOOL Load(CPDF_Document* pDoc, const CPDF_Stream* pStream, + CPDF_DIBSource** ppMask, FX_DWORD* pMatteColor, + CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources, + FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE); + virtual FX_BOOL SkipToScanline(int line, IFX_Pause* pPause) const; + virtual FX_LPBYTE GetBuffer() const; + virtual FX_LPCBYTE GetScanline(int line) const; + virtual void DownSampleScanline(int line, FX_LPBYTE dest_scan, int dest_bpp, + int dest_width, FX_BOOL bFlipX, int clip_left, int clip_width) const; + virtual void SetDownSampleSize(int dest_width, int dest_height) const; + CFX_DIBitmap* GetBitmap() const; + void ReleaseBitmap(CFX_DIBitmap*) const; + void ClearImageData(); +public: + int StartLoadDIBSource(CPDF_Document* pDoc, const CPDF_Stream* pStream, FX_BOOL bHasMask, + CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources, + FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE); + int ContinueLoadDIBSource(IFX_Pause* pPause); + int StratLoadMask(); + int StartLoadMaskDIB(); + int ContinueLoadMaskDIB(IFX_Pause* pPause); + int ContinueToLoadMask(); + CPDF_DIBSource* DetachMask(); + CPDF_DIBSource* m_pMask; + FX_DWORD m_MatteColor; + FX_LPVOID m_pJbig2Context; + CPDF_StreamAcc* m_pGlobalStream; + FX_BOOL m_bStdCS; + int m_Status; + CPDF_Object* m_pMaskStream; + FX_BOOL m_bHasMask; +protected: + FX_BOOL LoadColorInfo(CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources); + CPDF_DIBSource* LoadMask(FX_DWORD& MatteColor); + CPDF_DIBSource* LoadMaskDIB(CPDF_Stream* pMask); + void LoadJpxBitmap(); + void LoadJbig2Bitmap(); + void LoadPalette(); + FX_BOOL CreateDecoder(); + void TranslateScanline24bpp(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan) const; + FX_DWORD GetValidBpp() const; + + CPDF_Document* m_pDocument; + const CPDF_Stream* m_pStream; + CPDF_StreamAcc* m_pStreamAcc; + const CPDF_Dictionary* m_pDict; + CPDF_ColorSpace* m_pColorSpace; + FX_DWORD m_Family, m_bpc, m_nComponents, m_GroupFamily; + FX_BOOL m_bLoadMask; + FX_BOOL m_bDefaultDecode, m_bImageMask, m_bColorKey; + DIB_COMP_DATA* m_pCompData; + FX_LPBYTE m_pLineBuf; + FX_LPBYTE m_pMaskedLine; + CFX_DIBitmap* m_pCachedBitmap; + ICodec_ScanlineDecoder* m_pDecoder; +}; +#ifdef _FPDFAPI_MINI_ +#define FPDF_HUGE_IMAGE_SIZE 3000000 +#else +#define FPDF_HUGE_IMAGE_SIZE 60000000 +#endif +class CPDF_DIBTransferFunc : public CFX_FilteredDIB +{ +public: + CPDF_DIBTransferFunc(const CPDF_TransferFunc* pTransferFunc); + virtual FXDIB_Format GetDestFormat(); + virtual FX_ARGB* GetDestPalette() + { + return NULL; + } + virtual void TranslateScanline(FX_LPBYTE dest_buf, FX_LPCBYTE src_buf) const; + virtual void TranslateDownSamples(FX_LPBYTE dest_buf, FX_LPCBYTE src_buf, int pixels, int Bpp) const; + FX_LPCBYTE m_RampR; + FX_LPCBYTE m_RampG; + FX_LPCBYTE m_RampB; +}; +struct _CPDF_UniqueKeyGen { + void Generate(int count, ...); + FX_CHAR m_Key[128]; + int m_KeyLen; +}; |