// 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_module.h"
#include "../../../include/fpdfapi/fpdf_render.h"
#include "../../../include/fxge/fx_ge.h"
#include "../fpdf_page/pageint.h"
#include "render_int.h"

CPDF_DocRenderData::CPDF_DocRenderData(CPDF_Document* pPDFDoc)
    : m_pPDFDoc(pPDFDoc),
      m_pFontCache(new CFX_FontCache)
{
}

CPDF_DocRenderData::~CPDF_DocRenderData()
{
    Clear(TRUE);
}

void CPDF_DocRenderData::Clear(FX_BOOL bRelease)
{
    for (auto it = m_Type3FaceMap.begin(); it != m_Type3FaceMap.end();) {
        auto curr_it = it++;
        CPDF_CountedObject<CPDF_Type3Cache>* cache = curr_it->second;
        if (bRelease || cache->use_count() < 2) {
            delete cache->get();
            delete cache;
            m_Type3FaceMap.erase(curr_it);
        }
    }

    for (auto it = m_TransferFuncMap.begin(); it != m_TransferFuncMap.end();) {
        auto curr_it = it++;
        CPDF_CountedObject<CPDF_TransferFunc>* value = curr_it->second;
        if (bRelease || value->use_count() < 2) {
            delete value->get();
            delete value;
            m_TransferFuncMap.erase(curr_it);
        }
    }

    if (m_pFontCache) {
        if (bRelease) {
            delete m_pFontCache;
            m_pFontCache = NULL;
        } else {
            m_pFontCache->FreeCache(FALSE);
        }
    }
}

CPDF_Type3Cache* CPDF_DocRenderData::GetCachedType3(CPDF_Type3Font* pFont)
{
    CPDF_CountedObject<CPDF_Type3Cache>* pCache;
    auto it = m_Type3FaceMap.find(pFont);
    if (it == m_Type3FaceMap.end()) {
        CPDF_Type3Cache* pType3 = new CPDF_Type3Cache(pFont);
        pCache = new CPDF_CountedObject<CPDF_Type3Cache>(pType3);
        m_Type3FaceMap[pFont] = pCache;
    } else {
        pCache = it->second;
    }
    return pCache->AddRef();
}

void CPDF_DocRenderData::ReleaseCachedType3(CPDF_Type3Font* pFont)
{
    auto it = m_Type3FaceMap.find(pFont);
    if (it != m_Type3FaceMap.end())
        it->second->RemoveRef();
}

class CPDF_RenderModule : public IPDF_RenderModule
{
public:
   CPDF_RenderModule() {}

private:
    ~CPDF_RenderModule() override {}

    CPDF_DocRenderData* CreateDocData(CPDF_Document* pDoc) override;
    void DestroyDocData(CPDF_DocRenderData* p) override;
    void ClearDocData(CPDF_DocRenderData* p) override;

    CPDF_DocRenderData* GetRenderData() override
    {
        return &m_RenderData;
    }

    CPDF_PageRenderCache* CreatePageCache(CPDF_Page* pPage) override
    {
        return new CPDF_PageRenderCache(pPage);
    }

    void DestroyPageCache(CPDF_PageRenderCache* pCache) override;

    CPDF_RenderConfig* GetConfig() override
    {
        return &m_RenderConfig;
    }

    CPDF_DocRenderData m_RenderData;
    CPDF_RenderConfig m_RenderConfig;
};

CPDF_DocRenderData*	CPDF_RenderModule::CreateDocData(CPDF_Document* pDoc)
{
    return new CPDF_DocRenderData(pDoc);
}
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()
{
    m_pRenderModule.reset(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)
{
}
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);
}

// static
int CPDF_RenderStatus::s_CurrentRecursionDepth = 0;

CPDF_RenderStatus::CPDF_RenderStatus()
{
    m_pContext = NULL;
    m_bStopped = FALSE;
    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()
{
    delete m_pObjectRenderer;
}

FX_BOOL CPDF_RenderStatus::Initialize(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_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();
    }
    m_pObjectRenderer = NULL;
    m_Transparency = transparency;
    return TRUE;
}
void CPDF_RenderStatus::RenderObjectList(const CPDF_PageObjects* pObjs, const CFX_AffineMatrix* pObj2Device)
{
    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)
{
    CFX_AutoRestorer<int> restorer(&s_CurrentRecursionDepth);
    if (++s_CurrentRecursionDepth > kRenderMaxRecursionDepth) {
        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);
        }
        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);
            }
            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)
{
    if (type != PDFPAGE_IMAGE) {
        return NULL;
    }
    return new CPDF_ImageRenderer;
}
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 + (int32_t)FXSYS_ceil((FX_FLOAT)rect.Width() * a);
            rect.bottom = rect.top + (int32_t)FXSYS_ceil((FX_FLOAT)rect.Height() * d);
            rtClip.right = rtClip.left + (int32_t)FXSYS_ceil((FX_FLOAT)rtClip.Width() * a);
            rtClip.bottom = rtClip.top + (int32_t)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 (!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)
{
    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_pContext, buffer.GetDevice(), buffer.GetMatrix(), NULL, NULL, NULL, &m_Options, m_Transparency, m_bDropObjects, pFormResource);
    status.RenderSingleObject(pObj, &matrix);
    buffer.OutputToDevice();
}
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_pContext, m_pDevice, NULL, m_pStopObj,
                      this, pFormObj, &m_Options, m_Transparency, m_bDropObjects, pResources, FALSE);
    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;
    }
    const CPDF_GeneralStateData* pGeneralData = ((CPDF_PageObject*)pPathObj)->m_GeneralState;
    if (pGeneralData && pGeneralData->m_StrokeAdjust) {
        FillType |= FX_STROKE_ADJUST;
    }
    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 = (int32_t)(pGeneralData->m_FillAlpha * 255);
        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);
            }
        }
    } 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 = (int32_t)(pGeneralData->m_StrokeAlpha * 255);
        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);
            }
        }
    } 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 = new CFX_PathData;
            }
            ProcessText(pText, pObj2Device, 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 = 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 = 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_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_memcpy(&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((int32_t)(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);
    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 = 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);

    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 = new CPDF_GraphicStates;
    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_pDocument = pDoc;
    m_pPageResources = pPageResources;
    m_pPageCache = pPageCache;
    m_bFirstLayer = bFirstLayer;
}
void CPDF_RenderContext::Create(CPDF_Page* pPage, FX_BOOL bFirstLayer)
{
    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_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(this, pDevice, pLastMatrix, pStopObj, NULL, NULL, pOptions,
                              pItem->m_pObjectList->m_Transparency, FALSE, NULL);
            status.RenderObjectList(pItem->m_pObjectList, &FinalMatrix);
            if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
                m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize);
            }
            if (status.m_bStopped) {
                pDevice->RestoreState();
                break;
            }
        } else {
            CPDF_RenderStatus status;
            status.Initialize(this, pDevice, NULL, pStopObj, NULL, NULL, pOptions,
                              pItem->m_pObjectList->m_Transparency, FALSE, NULL);
            status.RenderObjectList(pItem->m_pObjectList, &pItem->m_Matrix);
            if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
                m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize);
            }
            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(
    CPDF_RenderContext* pContext,
    CFX_RenderDevice* pDevice,
    const CPDF_RenderOptions* pOptions) :
        m_Status(Ready),
        m_pContext(pContext),
        m_pDevice(pDevice),
        m_pOptions(pOptions),
        m_LayerIndex(0),
        m_ObjectIndex(0),
        m_ObjectPos(nullptr),
        m_PrevLastPos(nullptr)
{
}

CPDF_ProgressiveRenderer::~CPDF_ProgressiveRenderer()
{
    if (m_pRenderStatus)
        m_pDevice->RestoreState();
}

void CPDF_ProgressiveRenderer::Start(IFX_Pause* pPause)
{
    if (!m_pContext || !m_pDevice || m_Status != Ready) {
        m_Status = Failed;
        return;
    }
    m_Status = ToBeContinued;
    Continue(pPause);
}

#define RENDER_STEP_LIMIT 100
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_pRenderStatus) {
                    m_pRenderStatus.reset();
                    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_pRenderStatus) {
            m_ObjectPos = pItem->m_pObjectList->GetFirstObjectPosition();
            m_ObjectIndex = 0;
            m_pRenderStatus.reset(new CPDF_RenderStatus());
            m_pRenderStatus->Initialize(
                m_pContext, m_pDevice, NULL, NULL, NULL, NULL, m_pOptions,
                pItem->m_pObjectList->m_Transparency, FALSE, 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_pRenderStatus->ContinueSingleObject(pCurObj, &pItem->m_Matrix, pPause)) {
                    return;
                }
                if (pCurObj->m_Type == PDFPAGE_IMAGE && m_pRenderStatus->m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
                    m_pContext->GetPageCache()->CacheOptimization(m_pRenderStatus->m_Options.m_dwLimitCacheSize);
                }
                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;
        }
        m_pRenderStatus.reset();
        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)
        return nullptr;

    auto it = m_TransferFuncMap.find(pObj);
    if (it != m_TransferFuncMap.end()) {
        CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter = it->second;
        return pTransferCounter->AddRef();
    }

    CPDF_Function* pFuncs[3] = { nullptr, nullptr, nullptr };
    FX_BOOL bUniTransfer = TRUE;
    FX_BOOL bIdentity = TRUE;
    if (pObj->GetType() == PDFOBJ_ARRAY) {
        bUniTransfer = FALSE;
        CPDF_Array* pArray = (CPDF_Array*)pObj;
        if (pArray->GetCount() < 3)
            return nullptr;

        for (FX_DWORD i = 0; i < 3; ++i) {
            pFuncs[2 - i] = CPDF_Function::Load(pArray->GetElementValue(i));
            if (!pFuncs[2 - i]) {
                return nullptr;
            }
        }
    } else {
        pFuncs[0] = CPDF_Function::Load(pObj);
        if (!pFuncs[0]) {
            return nullptr;
        }
    }
    CPDF_TransferFunc* pTransfer = new CPDF_TransferFunc;
    pTransfer->m_pPDFDoc = m_pPDFDoc;
    CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter =
        new CPDF_CountedObject<CPDF_TransferFunc>(pTransfer);
    m_TransferFuncMap[pObj] = pTransferCounter;
    static const int kMaxOutputs = 16;
    FX_FLOAT output[kMaxOutputs];
    FXSYS_memset(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 (int i = 0; i < 3; ++i) {
                pTransfer->m_Samples[i * 256 + v] = o;
            }
        } else {
            for (int 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 (int i = 0; i < 3; ++i)
        delete pFuncs[i];

    pTransfer->m_bIdentity = bIdentity;
    return pTransferCounter->AddRef();
}

void CPDF_DocRenderData::ReleaseTransferFunc(CPDF_Object* pObj)
{
    auto it = m_TransferFuncMap.find(pObj);
    if (it != m_TransferFuncMap.end())
        it->second->RemoveRef();
}
CPDF_RenderConfig::CPDF_RenderConfig()
{
    m_HalftoneLimit = 0;
    m_RenderStepLimit = 100;
}
CPDF_RenderConfig::~CPDF_RenderConfig()
{
}
CPDF_DeviceBuffer::CPDF_DeviceBuffer()
{
    m_pBitmap = NULL;
    m_pDevice = NULL;
    m_pContext = NULL;
    m_pObject = NULL;
}
CPDF_DeviceBuffer::~CPDF_DeviceBuffer()
{
    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);
        }
    }
#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 = 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 {
        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());
    }
}
CPDF_ScaledRenderBuffer::CPDF_ScaledRenderBuffer()
{
    m_pBitmapDevice = NULL;
}
CPDF_ScaledRenderBuffer::~CPDF_ScaledRenderBuffer()
{
    delete m_pBitmapDevice;
}
#define _FPDFAPI_IMAGESIZE_LIMIT_	(30 * 1024 * 1024)
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 = new CFX_FxgeDevice;
    FXDIB_Format dibFormat = FXDIB_Rgb;
    int32_t bpp = 24;
    if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_ALPHA_OUTPUT) {
        dibFormat = FXDIB_Argb;
        bpp = 32;
    }
    CFX_FloatRect rect;
    int32_t 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);
    }
    m_pContext->GetBackground(m_pBitmapDevice->GetBitmap(), m_pObject, pOptions, &m_Matrix);
    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;
}
