// 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_page.h"
#include "../../../include/fpdfapi/fpdf_pageobj.h"
#include "../../../include/fpdfapi/fpdf_module.h"
#include "../../../include/fpdfapi/fpdf_render.h"
#include "../fpdf_render/render_int.h"
#include "pageint.h"

void CPDF_GraphicStates::DefaultStates()
{
    m_ColorState.New()->Default();
}
void CPDF_GraphicStates::CopyStates(const CPDF_GraphicStates& src)
{
    m_ClipPath = src.m_ClipPath;
    m_GraphState = src.m_GraphState;
    m_ColorState = src.m_ColorState;
    m_TextState = src.m_TextState;
    m_GeneralState = src.m_GeneralState;
}
CPDF_ClipPathData::CPDF_ClipPathData()
{
    m_PathCount = 0;
    m_pPathList = NULL;
    m_pTypeList = NULL;
    m_TextCount = 0;
    m_pTextList = NULL;
}
CPDF_ClipPathData::~CPDF_ClipPathData()
{
    int i;
    delete[] m_pPathList;
    if (m_pTypeList) {
        FX_Free(m_pTypeList);
    }
    for (i = m_TextCount - 1; i > -1; i --)
        delete m_pTextList[i];
    if (m_pTextList) {
        FX_Free(m_pTextList);
    }
}
CPDF_ClipPathData::CPDF_ClipPathData(const CPDF_ClipPathData& src)
{
    m_pPathList = NULL;
    m_pPathList = NULL;
    m_pTextList = NULL;
    m_PathCount = src.m_PathCount;
    if (m_PathCount) {
        int alloc_size = m_PathCount;
        if (alloc_size % 8) {
            alloc_size += 8 - (alloc_size % 8);
        }
        m_pPathList = new CPDF_Path[alloc_size];
        for (int i = 0; i < m_PathCount; i ++) {
            m_pPathList[i] = src.m_pPathList[i];
        }
        m_pTypeList = FX_Alloc(uint8_t, alloc_size);
        FXSYS_memcpy(m_pTypeList, src.m_pTypeList, m_PathCount);
    } else {
        m_pPathList = NULL;
        m_pTypeList = NULL;
    }
    m_TextCount = src.m_TextCount;
    if (m_TextCount) {
        m_pTextList = FX_Alloc(CPDF_TextObject*, m_TextCount);
        for (int i = 0; i < m_TextCount; i ++) {
            if (src.m_pTextList[i]) {
                m_pTextList[i] = new CPDF_TextObject;
                m_pTextList[i]->Copy(src.m_pTextList[i]);
            } else {
                m_pTextList[i] = NULL;
            }
        }
    } else {
        m_pTextList = NULL;
    }
}
void CPDF_ClipPathData::SetCount(int path_count, int text_count)
{
    ASSERT(m_TextCount == 0 && m_PathCount == 0);
    if (path_count) {
        m_PathCount = path_count;
        int alloc_size = (path_count + 7) / 8 * 8;
        m_pPathList = new CPDF_Path[alloc_size];
        m_pTypeList = FX_Alloc(uint8_t, alloc_size);
    }
    if (text_count) {
        m_TextCount = text_count;
        m_pTextList = FX_Alloc(CPDF_TextObject*, text_count);
    }
}
CPDF_Rect CPDF_ClipPath::GetClipBox() const
{
    CPDF_Rect rect;
    bool bStarted = false;
    int count = GetPathCount();
    if (count) {
        rect = GetPath(0).GetBoundingBox();
        for (int i = 1; i < count; i ++) {
            CPDF_Rect path_rect = GetPath(i).GetBoundingBox();
            rect.Intersect(path_rect);
        }
        bStarted = true;
    }
    count = GetTextCount();
    if (count) {
        CPDF_Rect layer_rect;
        bool bLayerStarted = false;
        for (int i = 0; i < count; i ++) {
            CPDF_TextObject* pTextObj = GetText(i);
            if (pTextObj == NULL) {
                if (!bStarted) {
                    rect = layer_rect;
                    bStarted = true;
                } else {
                    rect.Intersect(layer_rect);
                }
                bLayerStarted = false;
            } else {
                if (!bLayerStarted) {
                    layer_rect = pTextObj->GetBBox(NULL);
                    bLayerStarted = true;
                } else {
                    layer_rect.Union(pTextObj->GetBBox(NULL));
                }
            }
        }
    }
    return rect;
}
void CPDF_ClipPath::AppendPath(CPDF_Path path, int type, bool bAutoMerge)
{
    CPDF_ClipPathData* pData = GetModify();
    if (pData->m_PathCount && bAutoMerge) {
        CPDF_Path old_path = pData->m_pPathList[pData->m_PathCount - 1];
        if (old_path.IsRect()) {
            CPDF_Rect old_rect(old_path.GetPointX(0), old_path.GetPointY(0),
                               old_path.GetPointX(2), old_path.GetPointY(2));
            CPDF_Rect new_rect = path.GetBoundingBox();
            if (old_rect.Contains(new_rect)) {
                pData->m_PathCount --;
                pData->m_pPathList[pData->m_PathCount].SetNull();
            }
        }
    }
    if (pData->m_PathCount % 8 == 0) {
        CPDF_Path* pNewPath = new CPDF_Path[pData->m_PathCount + 8];
        for (int i = 0; i < pData->m_PathCount; i ++) {
            pNewPath[i] = pData->m_pPathList[i];
        }
        delete[] pData->m_pPathList;
        uint8_t* pNewType = FX_Alloc(uint8_t, pData->m_PathCount + 8);
        FXSYS_memcpy(pNewType, pData->m_pTypeList, pData->m_PathCount);
        if (pData->m_pTypeList) {
            FX_Free(pData->m_pTypeList);
        }
        pData->m_pPathList = pNewPath;
        pData->m_pTypeList = pNewType;
    }
    pData->m_pPathList[pData->m_PathCount] = path;
    pData->m_pTypeList[pData->m_PathCount] = (uint8_t)type;
    pData->m_PathCount ++;
}
void CPDF_ClipPath::DeletePath(int index)
{
    CPDF_ClipPathData* pData = GetModify();
    if (index >= pData->m_PathCount) {
        return;
    }
    pData->m_pPathList[index].SetNull();
    for (int i = index; i < pData->m_PathCount - 1; i ++) {
        pData->m_pPathList[i] = pData->m_pPathList[i + 1];
    }
    pData->m_pPathList[pData->m_PathCount - 1].SetNull();
    FXSYS_memmove(pData->m_pTypeList + index, pData->m_pTypeList + index + 1, pData->m_PathCount - index - 1);
    pData->m_PathCount --;
}
#define FPDF_CLIPPATH_MAX_TEXTS 1024
void CPDF_ClipPath::AppendTexts(CPDF_TextObject** pTexts, int count)
{
    CPDF_ClipPathData* pData = GetModify();
    if (pData->m_TextCount + count > FPDF_CLIPPATH_MAX_TEXTS) {
        for (int i = 0; i < count; i ++) {
            delete pTexts[i];
        }
        return;
    }
    CPDF_TextObject** pNewList = FX_Alloc(CPDF_TextObject*, pData->m_TextCount + count + 1);
    if (pData->m_pTextList) {
        FXSYS_memcpy(pNewList, pData->m_pTextList, pData->m_TextCount * sizeof(CPDF_TextObject*));
        FX_Free(pData->m_pTextList);
    }
    pData->m_pTextList = pNewList;
    for (int i = 0; i < count; i ++) {
        pData->m_pTextList[pData->m_TextCount + i] = pTexts[i];
    }
    pData->m_pTextList[pData->m_TextCount + count] = NULL;
    pData->m_TextCount += count + 1;
}
void CPDF_ClipPath::Transform(const CPDF_Matrix& matrix)
{
    CPDF_ClipPathData* pData = GetModify();
    int i;
    for (i = 0; i < pData->m_PathCount; i ++) {
        pData->m_pPathList[i].Transform(&matrix);
    }
    for (i = 0; i < pData->m_TextCount; i ++)
        if (pData->m_pTextList[i]) {
            pData->m_pTextList[i]->Transform(matrix);
        }
}
CPDF_ColorStateData::CPDF_ColorStateData(const CPDF_ColorStateData& src)
{
    m_FillColor.Copy(&src.m_FillColor);
    m_FillRGB = src.m_FillRGB;
    m_StrokeColor.Copy(&src.m_StrokeColor);
    m_StrokeRGB = src.m_StrokeRGB;
}
void CPDF_ColorStateData::Default()
{
    m_FillRGB = m_StrokeRGB = 0;
    m_FillColor.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY));
    m_StrokeColor.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY));
}
void CPDF_ColorState::SetFillColor(CPDF_ColorSpace* pCS, FX_FLOAT* pValue, int nValues)
{
    CPDF_ColorStateData* pData = GetModify();
    SetColor(pData->m_FillColor, pData->m_FillRGB, pCS, pValue, nValues);
}
void CPDF_ColorState::SetStrokeColor(CPDF_ColorSpace* pCS, FX_FLOAT* pValue, int nValues)
{
    CPDF_ColorStateData* pData = GetModify();
    SetColor(pData->m_StrokeColor, pData->m_StrokeRGB, pCS, pValue, nValues);
}
void CPDF_ColorState::SetColor(CPDF_Color& color, FX_DWORD& rgb, CPDF_ColorSpace* pCS, FX_FLOAT* pValue, int nValues)
{
    if (pCS) {
        color.SetColorSpace(pCS);
    } else if (color.IsNull()) {
        color.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY));
    }
    if (color.m_pCS->CountComponents() > nValues) {
        return;
    }
    color.SetValue(pValue);
    int R, G, B;
    rgb = color.GetRGB(R, G, B) ? FXSYS_RGB(R, G, B) : (FX_DWORD) - 1;
}
void CPDF_ColorState::SetFillPattern(CPDF_Pattern* pPattern, FX_FLOAT* pValue, int nValues)
{
    CPDF_ColorStateData* pData = GetModify();
    pData->m_FillColor.SetValue(pPattern, pValue, nValues);
    int R, G, B;
    bool ret = pData->m_FillColor.GetRGB(R, G, B);
    if (pPattern->m_PatternType == 1 && ((CPDF_TilingPattern*)pPattern)->m_bColored && !ret) {
        pData->m_FillRGB = 0x00BFBFBF;
        return;
    }
    pData->m_FillRGB = ret ? FXSYS_RGB(R, G, B) : (FX_DWORD) - 1;
}
void CPDF_ColorState::SetStrokePattern(CPDF_Pattern* pPattern, FX_FLOAT* pValue, int nValues)
{
    CPDF_ColorStateData* pData = GetModify();
    pData->m_StrokeColor.SetValue(pPattern, pValue, nValues);
    int R, G, B;
    bool ret = pData->m_StrokeColor.GetRGB(R, G, B);
    if (pPattern->m_PatternType == 1 && ((CPDF_TilingPattern*)pPattern)->m_bColored && !ret) {
        pData->m_StrokeRGB = 0x00BFBFBF;
        return;
    }
    pData->m_StrokeRGB = pData->m_StrokeColor.GetRGB(R, G, B) ? FXSYS_RGB(R, G, B) : (FX_DWORD) - 1;
}
CPDF_TextStateData::CPDF_TextStateData()
{
    m_pFont = NULL;
    m_pDocument = NULL;
    m_FontSize = 1.0f;
    m_WordSpace = 0;
    m_CharSpace = 0;
    m_TextMode = 0;
    m_Matrix[0] = m_Matrix[3] = 1.0f;
    m_Matrix[1] = m_Matrix[2] = 0;
    m_CTM[0] = m_CTM[3] = 1.0f;
    m_CTM[1] = m_CTM[2] = 0;
}
CPDF_TextStateData::CPDF_TextStateData(const CPDF_TextStateData& src)
{
    if (this == &src) {
        return;
    }
    FXSYS_memcpy(this, &src, sizeof(CPDF_TextStateData));
    if (m_pDocument && m_pFont) {
        m_pFont = m_pDocument->GetPageData()->GetFont(m_pFont->GetFontDict(), false);
    }
}
CPDF_TextStateData::~CPDF_TextStateData()
{
    if (m_pDocument && m_pFont) {
        CPDF_DocPageData *pPageData = m_pDocument->GetPageData();
        if (pPageData && !pPageData->IsForceClear()) {
            pPageData->ReleaseFont(m_pFont->GetFontDict());
        }
    }
}
void CPDF_TextState::SetFont(CPDF_Font* pFont)
{
    CPDF_TextStateData* pStateData = GetModify();
    if (pStateData) {
        CPDF_Document* pDoc = pStateData->m_pDocument;
        CPDF_DocPageData *pPageData = pDoc ? pDoc->GetPageData() : NULL;
        if (pPageData && pStateData->m_pFont && !pPageData->IsForceClear()) {
            pPageData->ReleaseFont(pStateData->m_pFont->GetFontDict());
        }
        pStateData->m_pDocument = pFont ? pFont->m_pDocument : NULL;
        pStateData->m_pFont = pFont;
    }
}
FX_FLOAT CPDF_TextState::GetFontSizeV() const
{
    FX_FLOAT* pMatrix = GetMatrix();
    FX_FLOAT unit = FXSYS_sqrt2(pMatrix[1], pMatrix[3]);
    FX_FLOAT size = FXSYS_Mul(unit, GetFontSize());
    return (FX_FLOAT)FXSYS_fabs(size);
}
FX_FLOAT CPDF_TextState::GetFontSizeH() const
{
    FX_FLOAT* pMatrix = GetMatrix();
    FX_FLOAT unit = FXSYS_sqrt2(pMatrix[0], pMatrix[2]);
    FX_FLOAT size = FXSYS_Mul(unit, GetFontSize());
    return (FX_FLOAT)FXSYS_fabs(size);
}
FX_FLOAT CPDF_TextState::GetBaselineAngle() const
{
    FX_FLOAT* m_Matrix = GetMatrix();
    return FXSYS_atan2(m_Matrix[2], m_Matrix[0]);
}
FX_FLOAT CPDF_TextState::GetShearAngle() const
{
    FX_FLOAT* m_Matrix = GetMatrix();
    FX_FLOAT shear_angle = FXSYS_atan2(m_Matrix[1], m_Matrix[3]);
    return GetBaselineAngle() + shear_angle;
}
CPDF_GeneralStateData::CPDF_GeneralStateData()
{
    FXSYS_memset(this, 0, sizeof(CPDF_GeneralStateData));
    FXSYS_strcpy((FX_CHAR*)m_BlendMode, "Normal");
    m_StrokeAlpha = 1.0f;
    m_FillAlpha = 1.0f;
    m_Flatness = 1.0f;
    m_Matrix.SetIdentity();
}
CPDF_GeneralStateData::CPDF_GeneralStateData(const CPDF_GeneralStateData& src)
{
    FXSYS_memcpy(this, &src, sizeof(CPDF_GeneralStateData));
    if (src.m_pTransferFunc && src.m_pTransferFunc->m_pPDFDoc) {
        CPDF_DocRenderData* pDocCache = src.m_pTransferFunc->m_pPDFDoc->GetRenderData();
        if (!pDocCache) {
            return;
        }
        m_pTransferFunc = pDocCache->GetTransferFunc(m_pTR);
    }
}
CPDF_GeneralStateData::~CPDF_GeneralStateData()
{
    if (m_pTransferFunc && m_pTransferFunc->m_pPDFDoc) {
        CPDF_DocRenderData* pDocCache = m_pTransferFunc->m_pPDFDoc->GetRenderData();
        if (!pDocCache) {
            return;
        }
        pDocCache->ReleaseTransferFunc(m_pTR);
    }
}
static int GetBlendType(const CFX_ByteStringC& mode)
{
    switch (mode.GetID()) {
        case FXBSTR_ID('N', 'o', 'r', 'm'):
        case FXBSTR_ID('C', 'o', 'm', 'p'):
            return FXDIB_BLEND_NORMAL;
        case FXBSTR_ID('M', 'u', 'l', 't'):
            return FXDIB_BLEND_MULTIPLY;
        case FXBSTR_ID('S', 'c', 'r', 'e'):
            return FXDIB_BLEND_SCREEN;
        case FXBSTR_ID('O', 'v', 'e', 'r'):
            return FXDIB_BLEND_OVERLAY;
        case FXBSTR_ID('D', 'a', 'r', 'k'):
            return FXDIB_BLEND_DARKEN;
        case FXBSTR_ID('L', 'i', 'g', 'h'):
            return FXDIB_BLEND_LIGHTEN;
        case FXBSTR_ID('C', 'o', 'l', 'o'):
            if (mode.GetLength() == 10) {
                return FXDIB_BLEND_COLORDODGE;
            }
            if (mode.GetLength() == 9) {
                return FXDIB_BLEND_COLORBURN;
            }
            return FXDIB_BLEND_COLOR;
        case FXBSTR_ID('H', 'a', 'r', 'd'):
            return FXDIB_BLEND_HARDLIGHT;
        case FXBSTR_ID('S', 'o', 'f', 't'):
            return FXDIB_BLEND_SOFTLIGHT;
        case FXBSTR_ID('D', 'i', 'f', 'f'):
            return FXDIB_BLEND_DIFFERENCE;
        case FXBSTR_ID('E', 'x', 'c', 'l'):
            return FXDIB_BLEND_EXCLUSION;
        case FXBSTR_ID('H', 'u', 'e', 0):
            return FXDIB_BLEND_HUE;
        case FXBSTR_ID('S', 'a', 't', 'u'):
            return FXDIB_BLEND_SATURATION;
        case FXBSTR_ID('L', 'u', 'm', 'i'):
            return FXDIB_BLEND_LUMINOSITY;
    }
    return FXDIB_BLEND_NORMAL;
}
void CPDF_GeneralStateData::SetBlendMode(const CFX_ByteStringC& blend_mode)
{
    if (blend_mode.GetLength() > 15) {
        return;
    }
    FXSYS_memcpy(m_BlendMode, blend_mode.GetPtr(), blend_mode.GetLength());
    m_BlendMode[blend_mode.GetLength()] = 0;
    m_BlendType = ::GetBlendType(blend_mode);
}
int RI_StringToId(const CFX_ByteString& ri)
{
    FX_DWORD id = ri.GetID();
    if (id == FXBSTR_ID('A', 'b', 's', 'o')) {
        return 1;
    }
    if (id == FXBSTR_ID('S', 'a', 't', 'u')) {
        return 2;
    }
    if (id == FXBSTR_ID('P', 'e', 'r', 'c')) {
        return 3;
    }
    return 0;
}
void CPDF_GeneralState::SetRenderIntent(const CFX_ByteString& ri)
{
    GetModify()->m_RenderIntent = RI_StringToId(ri);
}
CPDF_AllStates::CPDF_AllStates()
{
    m_TextX = m_TextY = m_TextLineX = m_TextLineY = 0;
    m_TextLeading = 0;
    m_TextRise = 0;
    m_TextHorzScale = 1.0f;
}
CPDF_AllStates::~CPDF_AllStates()
{
}
void CPDF_AllStates::Copy(const CPDF_AllStates& src)
{
    CopyStates(src);
    m_TextMatrix.Copy(src.m_TextMatrix);
    m_ParentMatrix.Copy(src.m_ParentMatrix);
    m_CTM.Copy(src.m_CTM);
    m_TextX = src.m_TextX;
    m_TextY = src.m_TextY;
    m_TextLineX = src.m_TextLineX;
    m_TextLineY = src.m_TextLineY;
    m_TextLeading = src.m_TextLeading;
    m_TextRise = src.m_TextRise;
    m_TextHorzScale = src.m_TextHorzScale;
}
void CPDF_AllStates::SetLineDash(CPDF_Array* pArray, FX_FLOAT phase, FX_FLOAT scale)
{
    CFX_GraphStateData* pData = m_GraphState.GetModify();
    pData->m_DashPhase = FXSYS_Mul(phase, scale);
    pData->SetDashCount(pArray->GetCount());
    for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
        pData->m_DashArray[i] = FXSYS_Mul(pArray->GetNumber(i), scale);
    }
}
void CPDF_AllStates::ProcessExtGS(CPDF_Dictionary* pGS, CPDF_StreamContentParser* pParser)
{
    CPDF_GeneralStateData* pGeneralState = m_GeneralState.GetModify();
    FX_POSITION pos = pGS->GetStartPos();
    while (pos) {
        CFX_ByteString key_str;
        CPDF_Object* pElement = pGS->GetNextElement(pos, key_str);
        CPDF_Object* pObject = pElement ? pElement->GetDirect() : NULL;
        if (pObject == NULL) {
            continue;
        }
        FX_DWORD key = key_str.GetID();
        switch (key) {
            case FXBSTR_ID('L', 'W', 0, 0):
                m_GraphState.GetModify()->m_LineWidth = pObject->GetNumber();
                break;
            case FXBSTR_ID('L', 'C', 0, 0):
                m_GraphState.GetModify()->m_LineCap = (CFX_GraphStateData::LineCap)pObject->GetInteger();
                break;
            case FXBSTR_ID('L', 'J', 0, 0):
                m_GraphState.GetModify()->m_LineJoin = (CFX_GraphStateData::LineJoin)pObject->GetInteger();
                break;
            case FXBSTR_ID('M', 'L', 0, 0):
                m_GraphState.GetModify()->m_MiterLimit = pObject->GetNumber();
                break;
            case FXBSTR_ID('D', 0, 0, 0):	{
                    if (pObject->GetType() != PDFOBJ_ARRAY) {
                        break;
                    }
                    CPDF_Array* pDash = (CPDF_Array*)pObject;
                    CPDF_Array* pArray = pDash->GetArray(0);
                    if (pArray == NULL) {
                        break;
                    }
                    SetLineDash(pArray, pDash->GetNumber(1), 1.0f);
                    break;
                }
            case FXBSTR_ID('R', 'I', 0, 0):
                m_GeneralState.SetRenderIntent(pObject->GetString());
                break;
            case FXBSTR_ID('F', 'o', 'n', 't'):	{
                    if (pObject->GetType() != PDFOBJ_ARRAY) {
                        break;
                    }
                    CPDF_Array* pFont = (CPDF_Array*)pObject;
                    m_TextState.GetModify()->m_FontSize = pFont->GetNumber(1);
                    m_TextState.SetFont(pParser->FindFont(pFont->GetString(0)));
                    break;
                }
            case FXBSTR_ID('T', 'R', 0, 0):
                if (pGS->KeyExist(FX_BSTRC("TR2"))) {
                    continue;
                }
            case FXBSTR_ID('T', 'R', '2', 0):
                if (pObject && pObject->GetType() != PDFOBJ_NAME) {
                    pGeneralState->m_pTR = pObject;
                } else {
                    pGeneralState->m_pTR = NULL;
                }
                break;
            case FXBSTR_ID('B', 'M', 0, 0):	{
                    CFX_ByteString mode;
                    if (pObject->GetType() == PDFOBJ_ARRAY) {
                        mode = ((CPDF_Array*)pObject)->GetString(0);
                    } else {
                        mode = pObject->GetString();
                    }
                    pGeneralState->SetBlendMode(mode);
                    if (pGeneralState->m_BlendType > FXDIB_BLEND_MULTIPLY) {
                        pParser->GetObjectList()->m_bBackgroundAlphaNeeded = true;
                    }
                    break;
                }
            case FXBSTR_ID('S', 'M', 'a', 's'):
                if (pObject && pObject->GetType() == PDFOBJ_DICTIONARY) {
                    pGeneralState->m_pSoftMask = pObject;
                    FXSYS_memcpy(pGeneralState->m_SMaskMatrix, &pParser->GetCurStates()->m_CTM, sizeof(CPDF_Matrix));
                } else {
                    pGeneralState->m_pSoftMask = NULL;
                }
                break;
            case FXBSTR_ID('C', 'A', 0, 0):
                pGeneralState->m_StrokeAlpha = PDF_ClipFloat(pObject->GetNumber());
                break;
            case FXBSTR_ID('c', 'a', 0, 0):
                pGeneralState->m_FillAlpha = PDF_ClipFloat(pObject->GetNumber());
                break;
            case FXBSTR_ID('O', 'P', 0, 0):
                pGeneralState->m_StrokeOP = pObject->GetInteger();
                if (!pGS->KeyExist(FX_BSTRC("op"))) {
                    pGeneralState->m_FillOP = pObject->GetInteger();
                }
                break;
            case FXBSTR_ID('o', 'p', 0, 0):
                pGeneralState->m_FillOP = pObject->GetInteger();
                break;
            case FXBSTR_ID('O', 'P', 'M', 0):
                pGeneralState->m_OPMode = pObject->GetInteger();
                break;
            case FXBSTR_ID('B', 'G', 0, 0):
                if (pGS->KeyExist(FX_BSTRC("BG2"))) {
                    continue;
                }
            case FXBSTR_ID('B', 'G', '2', 0):
                pGeneralState->m_pBG = pObject;
                break;
            case FXBSTR_ID('U', 'C', 'R', 0):
                if (pGS->KeyExist(FX_BSTRC("UCR2"))) {
                    continue;
                }
            case FXBSTR_ID('U', 'C', 'R', '2'):
                pGeneralState->m_pUCR = pObject;
                break;
            case FXBSTR_ID('H', 'T', 0, 0):
                pGeneralState->m_pHT = pObject;
                break;
            case FXBSTR_ID('F', 'L', 0, 0):
                pGeneralState->m_Flatness = pObject->GetNumber();
                break;
            case FXBSTR_ID('S', 'M', 0, 0):
                pGeneralState->m_Smoothness = pObject->GetNumber();
                break;
            case FXBSTR_ID('S', 'A', 0, 0):
                pGeneralState->m_StrokeAdjust = pObject->GetInteger();
                break;
            case FXBSTR_ID('A', 'I', 'S', 0):
                pGeneralState->m_AlphaSource = pObject->GetInteger();
                break;
            case FXBSTR_ID('T', 'K', 0, 0):
                pGeneralState->m_TextKnockout = pObject->GetInteger();
                break;
        }
    }
    pGeneralState->m_Matrix = m_CTM;
}
CPDF_ContentMarkItem::CPDF_ContentMarkItem()
{
    m_ParamType = None;
}
CPDF_ContentMarkItem::CPDF_ContentMarkItem(const CPDF_ContentMarkItem& src)
{
    m_MarkName = src.m_MarkName;
    m_ParamType = src.m_ParamType;
    if (m_ParamType == DirectDict) {
        m_pParam = ((CPDF_Dictionary*)src.m_pParam)->Clone();
    } else {
        m_pParam = src.m_pParam;
    }
}
CPDF_ContentMarkItem::~CPDF_ContentMarkItem()
{
    if (m_ParamType == DirectDict && m_pParam) {
        ((CPDF_Dictionary*)m_pParam)->Release();
    }
}
bool	CPDF_ContentMarkItem::HasMCID() const
{
    if (m_pParam && (m_ParamType == DirectDict || m_ParamType == PropertiesDict)) {
        return ((CPDF_Dictionary *)m_pParam)->KeyExist(FX_BSTRC("MCID"));
    }
    return false;
}
CPDF_ContentMarkData::CPDF_ContentMarkData(const CPDF_ContentMarkData& src)
{
    for (int i = 0; i < src.m_Marks.GetSize(); i ++) {
        m_Marks.Add(src.m_Marks[i]);
    }
}
int CPDF_ContentMarkData::GetMCID() const
{
    CPDF_ContentMarkItem::ParamType type = CPDF_ContentMarkItem::None;
    for (int i = 0; i < m_Marks.GetSize(); i ++) {
        type = m_Marks[i].GetParamType();
        if (type == CPDF_ContentMarkItem::PropertiesDict || type == CPDF_ContentMarkItem::DirectDict) {
            CPDF_Dictionary *pDict = (CPDF_Dictionary *)m_Marks[i].GetParam();
            if (pDict->KeyExist(FX_BSTRC("MCID"))) {
                return pDict->GetInteger(FX_BSTRC("MCID"));
            }
        }
    }
    return -1;
}
void CPDF_ContentMarkData::AddMark(const CFX_ByteString& name, CPDF_Dictionary* pDict, bool bDirect)
{
    CPDF_ContentMarkItem& item = m_Marks.Add();
    item.SetName(name);
    if (pDict == NULL) {
        return;
    }
    item.SetParam(bDirect ? CPDF_ContentMarkItem::DirectDict : CPDF_ContentMarkItem::PropertiesDict,
                  bDirect ? pDict->Clone() : pDict);
}
void CPDF_ContentMarkData::DeleteLastMark()
{
    int size = m_Marks.GetSize();
    if (size == 0) {
        return;
    }
    m_Marks.RemoveAt(size - 1);
}
bool CPDF_ContentMark::HasMark(const CFX_ByteStringC& mark) const
{
    if (m_pObject == NULL) {
        return false;
    }
    for (int i = 0; i < m_pObject->CountItems(); i ++) {
        CPDF_ContentMarkItem& item = m_pObject->GetItem(i);
        if (item.GetName() == mark) {
            return true;
        }
    }
    return false;
}
bool CPDF_ContentMark::LookupMark(const CFX_ByteStringC& mark, CPDF_Dictionary*& pDict) const
{
    if (m_pObject == NULL) {
        return false;
    }
    for (int i = 0; i < m_pObject->CountItems(); i ++) {
        CPDF_ContentMarkItem& item = m_pObject->GetItem(i);
        if (item.GetName() == mark) {
            pDict = NULL;
            if (item.GetParamType() == CPDF_ContentMarkItem::PropertiesDict ||
                    item.GetParamType() == CPDF_ContentMarkItem::DirectDict) {
                pDict = (CPDF_Dictionary*)item.GetParam();
            }
            return true;
        }
    }
    return false;
}
