// 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_module.h"
#include "pageint.h"
CPDF_PageObject* CPDF_PageObject::Create(int type)
{
    switch (type) {
        case PDFPAGE_TEXT:
            return new CPDF_TextObject;
        case PDFPAGE_IMAGE:
            return new CPDF_ImageObject;
        case PDFPAGE_PATH:
            return new CPDF_PathObject;
        case PDFPAGE_SHADING:
            return new CPDF_ShadingObject;
        case PDFPAGE_FORM:
            return new CPDF_FormObject;
    }
    return NULL;
}
CPDF_PageObject::~CPDF_PageObject()
{
}
CPDF_PageObject* CPDF_PageObject::Clone() const
{
    CPDF_PageObject* pObj = Create(m_Type);
    pObj->Copy(this);
    return pObj;
}
void CPDF_PageObject::Copy(const CPDF_PageObject* pSrc)
{
    if (m_Type != pSrc->m_Type) {
        return;
    }
    CopyData(pSrc);
    CopyStates(*pSrc);
    m_Left = pSrc->m_Left;
    m_Right = pSrc->m_Right;
    m_Top = pSrc->m_Top;
    m_Bottom = pSrc->m_Bottom;
}
void CPDF_PageObject::AppendClipPath(CPDF_Path path, int type, bool bAutoMerge)
{
    m_ClipPath.AppendPath(path, type, bAutoMerge);
}
void CPDF_PageObject::CopyClipPath(CPDF_PageObject* pObj)
{
    m_ClipPath = pObj->m_ClipPath;
}
void CPDF_PageObject::RemoveClipPath()
{
    m_ClipPath.SetNull();
}
void CPDF_PageObject::RecalcBBox()
{
    switch (m_Type) {
        case PDFPAGE_TEXT:
            ((CPDF_TextObject*)this)->RecalcPositionData();
            break;
        case PDFPAGE_PATH:
            ((CPDF_PathObject*)this)->CalcBoundingBox();
            break;
        case PDFPAGE_SHADING:
            ((CPDF_ShadingObject*)this)->CalcBoundingBox();
            break;
    }
}
void CPDF_PageObject::TransformClipPath(CFX_AffineMatrix& matrix)
{
    if (m_ClipPath.IsNull()) {
        return;
    }
    m_ClipPath.GetModify();
    m_ClipPath.Transform(matrix);
}
void CPDF_PageObject::TransformGeneralState(CFX_AffineMatrix& matrix)
{
    if(m_GeneralState.IsNull()) {
        return;
    }
    CPDF_GeneralStateData* pGS = m_GeneralState.GetModify();
    pGS->m_Matrix.Concat(matrix);
}
FX_RECT CPDF_PageObject::GetBBox(const CFX_AffineMatrix* pMatrix) const
{
    CFX_FloatRect rect(m_Left, m_Bottom, m_Right, m_Top);
    if (pMatrix) {
        pMatrix->TransformRect(rect);
    }
    return rect.GetOutterRect();
}

CPDF_TextObject::CPDF_TextObject()
    : m_PosX(0),
      m_PosY(0),
      m_nChars(0),
      m_pCharCodes(nullptr),
      m_pCharPos(nullptr)
{
    m_Type = PDFPAGE_TEXT;
}

CPDF_TextObject::~CPDF_TextObject()
{
    if (m_nChars > 1 && m_pCharCodes) {
        FX_Free(m_pCharCodes);
    }
    if (m_pCharPos) {
        FX_Free(m_pCharPos);
    }
}

void CPDF_TextObject::GetItemInfo(int index, CPDF_TextObjectItem* pInfo) const
{
    pInfo->m_CharCode =
        m_nChars == 1 ? (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[index];
    pInfo->m_OriginX = index ? m_pCharPos[index - 1] : 0;
    pInfo->m_OriginY = 0;
    if (pInfo->m_CharCode == -1) {
        return;
    }
    CPDF_Font* pFont = m_TextState.GetFont();
    if (pFont->GetFontType() != PDFFONT_CIDFONT) {
        return;
    }
    if (!((CPDF_CIDFont*)pFont)->IsVertWriting()) {
        return;
    }
    FX_WORD CID = ((CPDF_CIDFont*)pFont)->CIDFromCharCode(pInfo->m_CharCode);
    pInfo->m_OriginY = pInfo->m_OriginX;
    pInfo->m_OriginX = 0;
    short vx, vy;
    ((CPDF_CIDFont*)pFont)->GetVertOrigin(CID, vx, vy);
    FX_FLOAT fontsize = m_TextState.GetFontSize();
    pInfo->m_OriginX -= fontsize * vx / 1000;
    pInfo->m_OriginY -= fontsize * vy / 1000;
}

int CPDF_TextObject::CountChars() const
{
    if (m_nChars == 1) {
        return 1;
    }
    int count = 0;
    for (int i = 0; i < m_nChars; ++i)
        if (m_pCharCodes[i] != (FX_DWORD) - 1) {
            ++count;
        }
    return count;
}

void CPDF_TextObject::GetCharInfo(int index,
                                  FX_DWORD& charcode,
                                  FX_FLOAT& kerning) const
{
    if (m_nChars == 1) {
        charcode = (FX_DWORD)(uintptr_t)m_pCharCodes;
        kerning = 0;
        return;
    }
    int count = 0;
    for (int i = 0; i < m_nChars; ++i) {
        if (m_pCharCodes[i] != (FX_DWORD) - 1) {
            if (count == index) {
                charcode = m_pCharCodes[i];
                if (i == m_nChars - 1 ||
                    m_pCharCodes[i + 1] != (FX_DWORD) - 1) {
                    kerning = 0;
                } else {
                    kerning = m_pCharPos[i];
                }
                return;
            }
            ++count;
        }
    }
}

void CPDF_TextObject::GetCharInfo(int index, CPDF_TextObjectItem* pInfo) const
{
    if (m_nChars == 1) {
        GetItemInfo(0, pInfo);
        return;
    }
    int count = 0;
    for (int i = 0; i < m_nChars; ++i) {
        FX_DWORD charcode = m_pCharCodes[i];
        if (charcode == (FX_DWORD) - 1) {
            continue;
        }
        if (count == index) {
            GetItemInfo(i, pInfo);
            break;
        }
        ++count;
    }
}

void CPDF_TextObject::CopyData(const CPDF_PageObject* pSrc)
{
    const CPDF_TextObject* pSrcObj = (const CPDF_TextObject*)pSrc;
    if (m_nChars > 1 && m_pCharCodes) {
        FX_Free(m_pCharCodes);
        m_pCharCodes = nullptr;
    }
    if (m_pCharPos) {
        FX_Free(m_pCharPos);
        m_pCharPos = nullptr;
    }
    m_nChars = pSrcObj->m_nChars;
    if (m_nChars > 1) {
        m_pCharCodes = FX_Alloc(FX_DWORD, m_nChars);
        m_pCharPos = FX_Alloc(FX_FLOAT, m_nChars - 1);
        for (int i = 0; i < m_nChars; ++i) {
            m_pCharCodes[i] = pSrcObj->m_pCharCodes[i];
        }
        for (int i = 0; i < m_nChars - 1; ++i) {
            m_pCharPos[i] = pSrcObj->m_pCharPos[i];
        }
    } else {
        m_pCharCodes = pSrcObj->m_pCharCodes;
    }
    m_PosX = pSrcObj->m_PosX;
    m_PosY = pSrcObj->m_PosY;
}

void CPDF_TextObject::GetTextMatrix(CFX_AffineMatrix* pMatrix) const
{
    FX_FLOAT* pTextMatrix = m_TextState.GetMatrix();
    pMatrix->Set(pTextMatrix[0],
                 pTextMatrix[2],
                 pTextMatrix[1],
                 pTextMatrix[3],
                 m_PosX,
                 m_PosY);
}

void CPDF_TextObject::SetSegments(const CFX_ByteString* pStrs,
                                  FX_FLOAT* pKerning,
                                  int nsegs)
{
    if (m_nChars > 1 && m_pCharCodes) {
        FX_Free(m_pCharCodes);
        m_pCharCodes = nullptr;
    }
    if (m_pCharPos) {
        FX_Free(m_pCharPos);
        m_pCharPos = nullptr;
    }
    CPDF_Font* pFont = m_TextState.GetFont();
    m_nChars = 0;
    for (int i = 0; i < nsegs; ++i) {
        m_nChars += pFont->CountChar(pStrs[i], pStrs[i].GetLength());
    }
    m_nChars += nsegs - 1;
    if (m_nChars > 1) {
        m_pCharCodes = FX_Alloc(FX_DWORD, m_nChars);
        m_pCharPos = FX_Alloc(FX_FLOAT, m_nChars - 1);
        int index = 0;
        for (int i = 0; i < nsegs; ++i) {
            const FX_CHAR* segment = pStrs[i];
            int offset = 0, len = pStrs[i].GetLength();
            while (offset < len) {
                m_pCharCodes[index++] =
                    pFont->GetNextChar(segment, len, offset);
            }
            if (i != nsegs - 1) {
                m_pCharPos[index - 1] = pKerning[i];
                m_pCharCodes[index++] = (FX_DWORD) - 1;
            }
        }
    } else {
        int offset = 0;
        m_pCharCodes =
            (FX_DWORD*)(uintptr_t)pFont->GetNextChar(pStrs[0],
                                                     pStrs[0].GetLength(),
                                                     offset);
    }
}

void CPDF_TextObject::SetText(const CFX_ByteString& str)
{
    SetSegments(&str, nullptr, 1);
    RecalcPositionData();
}

void CPDF_TextObject::SetEmpty()
{
    if (m_nChars > 1 && m_pCharCodes) {
        FX_Free(m_pCharCodes);
    }
    if (m_nChars > 1 && m_pCharPos) {
        FX_Free(m_pCharPos);
    }
    m_nChars = 0;
    m_pCharCodes = nullptr;
    m_pCharPos = nullptr;
    m_Left = m_Right = m_PosX;
    m_Top = m_Bottom = m_PosY;
}

void CPDF_TextObject::SetText(CFX_ByteString* pStrs,
                              FX_FLOAT* pKerning,
                              int nSegs)
{
    SetSegments(pStrs, pKerning, nSegs);
    RecalcPositionData();
}

void CPDF_TextObject::SetText(int nChars,
                              FX_DWORD* pCharCodes,
                              FX_FLOAT* pKernings)
{
    if (m_nChars > 1 && m_pCharCodes) {
        FX_Free(m_pCharCodes);
        m_pCharCodes = nullptr;
    }
    if (m_pCharPos) {
        FX_Free(m_pCharPos);
        m_pCharPos = nullptr;
    }
    int nKernings = 0;
    int i;
    for (i = 0; i < nChars - 1; ++i) {
        if (pKernings[i] != 0) {
            ++nKernings;
        }
    }
    m_nChars = nChars + nKernings;
    if (m_nChars > 1) {
        m_pCharCodes = FX_Alloc(FX_DWORD, m_nChars);
        m_pCharPos = FX_Alloc(FX_FLOAT, m_nChars - 1);
        for (int i = 0, index = 0; i < nChars; ++i) {
            m_pCharCodes[index++] = pCharCodes[i];
            if (pKernings[i] != 0 && i != nChars - 1) {
                m_pCharCodes[index] = (FX_DWORD) - 1;
                m_pCharPos[index - 1] = pKernings[i];
                ++index;
            }
        }
    } else {
        m_pCharCodes = (FX_DWORD*)(uintptr_t)pCharCodes[0];
    }
    RecalcPositionData();
}

FX_FLOAT CPDF_TextObject::GetCharWidth(FX_DWORD charcode) const
{
    FX_FLOAT fontsize = m_TextState.GetFontSize() / 1000;
    CPDF_Font* pFont = m_TextState.GetFont();
    bool bVertWriting = false;
    CPDF_CIDFont* pCIDFont = pFont->GetCIDFont();
    if (pCIDFont) {
        bVertWriting = pCIDFont->IsVertWriting();
    }
    if (!bVertWriting)
        return pFont->GetCharWidthF(charcode, 0) * fontsize;

    FX_WORD CID = pCIDFont->CIDFromCharCode(charcode);
    return pCIDFont->GetVertWidth(CID) * fontsize;
}

FX_FLOAT CPDF_TextObject::GetSpaceCharWidth() const
{
    CPDF_Font* pFont = m_TextState.GetFont();
    FX_DWORD charCode = m_TextState.GetFont()->CharCodeFromUnicode(32);
    if (charCode != (FX_DWORD) - 1) {
        return GetCharWidth(charCode);
    }
    FX_FLOAT fontSize = m_TextState.GetFontSize() / 4000.0f;
    bool bVertWriting = false;
    CPDF_CIDFont* pCIDFont = pFont->GetCIDFont();
    if (pCIDFont) {
        bVertWriting = pCIDFont->IsVertWriting();
    }
    FX_RECT fontRect;
    pFont->GetFontBBox(fontRect);
    fontSize *= bVertWriting ?
        (FX_FLOAT)fontRect.Height() : (FX_FLOAT)fontRect.Width();
    return fontSize;
}

void CPDF_TextObject::GetCharRect(int index, CFX_FloatRect& rect) const
{
    CPDF_Font* pFont = m_TextState.GetFont();
    bool bVertWriting = false;
    CPDF_CIDFont* pCIDFont = pFont->GetCIDFont();
    if (pCIDFont) {
        bVertWriting = pCIDFont->IsVertWriting();
    }
    FX_FLOAT fontsize = m_TextState.GetFontSize() / 1000;
    int count = 0;
    for (int i = 0; i < m_nChars; ++i) {
        FX_DWORD charcode = m_nChars == 1 ?
            (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[i];
        if (charcode == (FX_DWORD) - 1) {
            continue;
        }
        if (count != index) {
            ++count;
            continue;
        }
        FX_FLOAT curpos = i > 0 ? m_pCharPos[i - 1] : 0;
        FX_RECT char_rect;
        pFont->GetCharBBox(charcode, char_rect, 0);
        if (!bVertWriting) {
            rect.left = curpos + char_rect.left * fontsize;
            rect.right = curpos + char_rect.right * fontsize;
            rect.top = char_rect.top * fontsize;
            rect.bottom = char_rect.bottom * fontsize;
        } else {
            FX_WORD CID = pCIDFont->CIDFromCharCode(charcode);
            short vx, vy;
            pCIDFont->GetVertOrigin(CID, vx, vy);
            char_rect.left -= vx;
            char_rect.right -= vx;
            char_rect.top -= vy;
            char_rect.bottom -= vy;
            rect.left = char_rect.left * fontsize;
            rect.right = char_rect.right * fontsize;
            rect.top = curpos + char_rect.top * fontsize;
            rect.bottom = curpos + char_rect.bottom * fontsize;
        }
        return;
    }
}

void CPDF_TextObject::CalcPositionData(FX_FLOAT* pTextAdvanceX,
                                       FX_FLOAT* pTextAdvanceY,
                                       FX_FLOAT horz_scale,
                                       int level)
{
    FX_FLOAT curpos = 0;
    FX_FLOAT min_x = 10000 * 1.0f;
    FX_FLOAT max_x = -10000 * 1.0f;
    FX_FLOAT min_y = 10000 * 1.0f;
    FX_FLOAT max_y = -10000 * 1.0f;
    CPDF_Font* pFont = m_TextState.GetFont();
    bool bVertWriting = false;
    CPDF_CIDFont* pCIDFont = pFont->GetCIDFont();
    if (pCIDFont) {
        bVertWriting = pCIDFont->IsVertWriting();
    }
    FX_FLOAT fontsize = m_TextState.GetFontSize();
    for (int i = 0; i < m_nChars; ++i) {
        FX_DWORD charcode = m_nChars == 1 ?
            (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[i];
        if (charcode == (FX_DWORD) - 1) {
            curpos -= FXSYS_Mul(m_pCharPos[i - 1], fontsize) / 1000;
            continue;
        }
        if (i) {
            m_pCharPos[i - 1] = curpos;
        }
        FX_RECT char_rect;
        pFont->GetCharBBox(charcode, char_rect, level);
        FX_FLOAT charwidth;
        if (!bVertWriting) {
            if (min_y > char_rect.top) {
                min_y = (FX_FLOAT)char_rect.top;
            }
            if (max_y < char_rect.top) {
                max_y = (FX_FLOAT)char_rect.top;
            }
            if (min_y > char_rect.bottom) {
                min_y = (FX_FLOAT)char_rect.bottom;
            }
            if (max_y < char_rect.bottom) {
                max_y = (FX_FLOAT)char_rect.bottom;
            }
            FX_FLOAT char_left = curpos + char_rect.left * fontsize / 1000;
            FX_FLOAT char_right = curpos + char_rect.right * fontsize / 1000;
            if (min_x > char_left) {
                min_x = char_left;
            }
            if (max_x < char_left) {
                max_x = char_left;
            }
            if (min_x > char_right) {
                min_x = char_right;
            }
            if (max_x < char_right) {
                max_x = char_right;
            }
            charwidth = pFont->GetCharWidthF(charcode, level) * fontsize / 1000;
        } else {
            FX_WORD CID = pCIDFont->CIDFromCharCode(charcode);
            short vx;
            short vy;
            pCIDFont->GetVertOrigin(CID, vx, vy);
            char_rect.left -= vx;
            char_rect.right -= vx;
            char_rect.top -= vy;
            char_rect.bottom -= vy;
            if (min_x > char_rect.left) {
                min_x = (FX_FLOAT)char_rect.left;
            }
            if (max_x < char_rect.left) {
                max_x = (FX_FLOAT)char_rect.left;
            }
            if (min_x > char_rect.right) {
                min_x = (FX_FLOAT)char_rect.right;
            }
            if (max_x < char_rect.right) {
                max_x = (FX_FLOAT)char_rect.right;
            }
            FX_FLOAT char_top = curpos + char_rect.top * fontsize / 1000;
            FX_FLOAT char_bottom = curpos + char_rect.bottom * fontsize / 1000;
            if (min_y > char_top) {
                min_y = char_top;
            }
            if (max_y < char_top) {
                max_y = char_top;
            }
            if (min_y > char_bottom) {
                min_y = char_bottom;
            }
            if (max_y < char_bottom) {
                max_y = char_bottom;
            }
            charwidth = pCIDFont->GetVertWidth(CID) * fontsize / 1000;
        }
        curpos += charwidth;
        if (charcode == ' ' && (!pCIDFont || pCIDFont->GetCharSize(32) == 1)) {
            curpos += m_TextState.GetObject()->m_WordSpace;
        }
        curpos += m_TextState.GetObject()->m_CharSpace;
    }
    if (bVertWriting) {
        if (pTextAdvanceX) {
            *pTextAdvanceX = 0;
        }
        if (pTextAdvanceY) {
            *pTextAdvanceY = curpos;
        }
        min_x = min_x * fontsize / 1000;
        max_x = max_x * fontsize / 1000;
    } else {
        if (pTextAdvanceX) {
            *pTextAdvanceX = FXSYS_Mul(curpos, horz_scale);
        }
        if (pTextAdvanceY) {
            *pTextAdvanceY = 0;
        }
        min_y = min_y * fontsize / 1000;
        max_y = max_y * fontsize / 1000;
    }
    CFX_AffineMatrix matrix;
    GetTextMatrix(&matrix);
    m_Left = min_x;
    m_Right = max_x;
    m_Bottom = min_y;
    m_Top = max_y;
    matrix.TransformRect(m_Left, m_Right, m_Top, m_Bottom);
    int textmode = m_TextState.GetObject()->m_TextMode;
    if (textmode == 1 || textmode == 2 || textmode == 5 || textmode == 6) {
        FX_FLOAT half_width = m_GraphState.GetObject()->m_LineWidth / 2;
        m_Left -= half_width;
        m_Right += half_width;
        m_Top += half_width;
        m_Bottom -= half_width;
    }
}

void CPDF_TextObject::CalcCharPos(FX_FLOAT* pPosArray) const
{
    CPDF_Font* pFont = m_TextState.GetFont();
    bool bVertWriting = false;
    CPDF_CIDFont* pCIDFont = pFont->GetCIDFont();
    if (pCIDFont) {
        bVertWriting = pCIDFont->IsVertWriting();
    }
    FX_FLOAT fontsize = m_TextState.GetFontSize();
    for (int i = 0, index = 0; i < m_nChars; ++i) {
        FX_DWORD charcode = m_nChars == 1 ?
            (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[i];
        if (charcode == (FX_DWORD) - 1) {
            continue;
        }
        pPosArray[index++] = i ? m_pCharPos[i - 1] : 0;
        FX_FLOAT charwidth;
        if (bVertWriting) {
            FX_WORD CID = pCIDFont->CIDFromCharCode(charcode);
            charwidth = pCIDFont->GetVertWidth(CID) * fontsize / 1000;
        } else {
            charwidth = pFont->GetCharWidthF(charcode) * fontsize / 1000;
        }
        pPosArray[index] = pPosArray[index - 1] + charwidth;
        index++;
    }
}

void CPDF_TextObject::Transform(const CFX_AffineMatrix& matrix)
{
    m_TextState.GetModify();
    CFX_AffineMatrix text_matrix;
    GetTextMatrix(&text_matrix);
    text_matrix.Concat(matrix);
    FX_FLOAT* pTextMatrix = m_TextState.GetMatrix();
    pTextMatrix[0] = text_matrix.GetA();
    pTextMatrix[1] = text_matrix.GetC();
    pTextMatrix[2] = text_matrix.GetB();
    pTextMatrix[3] = text_matrix.GetD();
    m_PosX = text_matrix.GetE();
    m_PosY = text_matrix.GetF();
    CalcPositionData(nullptr, nullptr, 0);
}

void CPDF_TextObject::SetPosition(FX_FLOAT x, FX_FLOAT y)
{
    FX_FLOAT dx = x - m_PosX;
    FX_FLOAT dy = y - m_PosY;
    m_PosX = x;
    m_PosY = y;
    m_Left += dx;
    m_Right += dx;
    m_Top += dy;
    m_Bottom += dy;
}

void CPDF_TextObject::SetData(int nChars,
                              FX_DWORD* pCharCodes,
                              FX_FLOAT* pCharPos,
                              FX_FLOAT x,
                              FX_FLOAT y)
{
    ASSERT(m_nChars == 0);
    m_nChars = nChars;
    m_PosX = x;
    m_PosY = y;
    if (nChars == 0) {
        return;
    }
    if (nChars == 1) {
        m_pCharCodes = (FX_DWORD*)(uintptr_t) * pCharCodes;
    } else {
        m_pCharCodes = FX_Alloc(FX_DWORD, nChars);
        FXSYS_memcpy(m_pCharCodes, pCharCodes, sizeof(FX_DWORD)*nChars);
        m_pCharPos = FX_Alloc(FX_FLOAT, nChars - 1);
        FXSYS_memcpy(m_pCharPos, pCharPos, sizeof(FX_FLOAT) * (nChars - 1));
    }
    RecalcPositionData();
}

void CPDF_TextObject::SetTextState(CPDF_TextState TextState)
{
    m_TextState = TextState;
    CalcPositionData(nullptr, nullptr, 0);
}

CPDF_ShadingObject::CPDF_ShadingObject()
{
    m_pShading = NULL;
    m_Type = PDFPAGE_SHADING;
}
CPDF_ShadingObject::~CPDF_ShadingObject()
{
}
void CPDF_ShadingObject::CopyData(const CPDF_PageObject* pSrc)
{
    CPDF_ShadingObject* pSrcObj = (CPDF_ShadingObject*)pSrc;
    m_pShading = pSrcObj->m_pShading;
    if (m_pShading && m_pShading->m_pDocument) {
        CPDF_DocPageData* pDocPageData = m_pShading->m_pDocument->GetPageData();
        m_pShading = (CPDF_ShadingPattern*)pDocPageData->GetPattern(m_pShading->m_pShadingObj, m_pShading->m_bShadingObj, &m_pShading->m_ParentMatrix);
    }
    m_Matrix = pSrcObj->m_Matrix;
}
void CPDF_ShadingObject::Transform(const CFX_AffineMatrix& matrix)
{
    if (!m_ClipPath.IsNull()) {
        m_ClipPath.GetModify();
        m_ClipPath.Transform(matrix);
    }
    m_Matrix.Concat(matrix);
    if (!m_ClipPath.IsNull()) {
        CalcBoundingBox();
    } else {
        matrix.TransformRect(m_Left, m_Right, m_Top, m_Bottom);
    }
}
void CPDF_ShadingObject::CalcBoundingBox()
{
    if (m_ClipPath.IsNull()) {
        return;
    }
    CFX_FloatRect rect = m_ClipPath.GetClipBox();
    m_Left = rect.left;
    m_Bottom = rect.bottom;
    m_Right = rect.right;
    m_Top = rect.top;
}
CPDF_FormObject::~CPDF_FormObject()
{
    delete m_pForm;
}
void CPDF_FormObject::Transform(const CFX_AffineMatrix& matrix)
{
    m_FormMatrix.Concat(matrix);
    CalcBoundingBox();
}
void CPDF_FormObject::CopyData(const CPDF_PageObject* pSrc)
{
    const CPDF_FormObject* pSrcObj = (const CPDF_FormObject*)pSrc;
    delete m_pForm;
    m_pForm = pSrcObj->m_pForm->Clone();
    m_FormMatrix = pSrcObj->m_FormMatrix;
}
void CPDF_FormObject::CalcBoundingBox()
{
    CFX_FloatRect form_rect = m_pForm->CalcBoundingBox();
    form_rect.Transform(&m_FormMatrix);
    m_Left = form_rect.left;
    m_Bottom = form_rect.bottom;
    m_Right = form_rect.right;
    m_Top = form_rect.top;
}
CPDF_PageObjects::CPDF_PageObjects(bool bReleaseMembers) : m_ObjectList(128)
{
    m_bBackgroundAlphaNeeded = false;
    m_bReleaseMembers = bReleaseMembers;
    m_ParseState = PDF_CONTENT_NOT_PARSED;
    m_pParser = NULL;
    m_pFormStream = NULL;
    m_pResources = NULL;
}
CPDF_PageObjects::~CPDF_PageObjects()
{
    delete m_pParser;
    if (!m_bReleaseMembers) {
        return;
    }
    FX_POSITION pos = m_ObjectList.GetHeadPosition();
    while (pos) {
        delete (CPDF_PageObject*)m_ObjectList.GetNext(pos);
    }
}
void CPDF_PageObjects::ContinueParse(IFX_Pause* pPause)
{
    if (m_pParser == NULL) {
        return;
    }
    m_pParser->Continue(pPause);
    if (m_pParser->GetStatus() == CPDF_ContentParser::Done) {
        m_ParseState = PDF_CONTENT_PARSED;
        delete m_pParser;
        m_pParser = NULL;
    }
}
int CPDF_PageObjects::EstimateParseProgress() const
{
    if (!m_pParser) {
        return m_ParseState == PDF_CONTENT_PARSED ? 100 : 0;
    }
    return m_pParser->EstimateProgress();
}
FX_POSITION CPDF_PageObjects::InsertObject(FX_POSITION posInsertAfter, CPDF_PageObject* pNewObject)
{
    if (!posInsertAfter) {
        return m_ObjectList.AddHead(pNewObject);
    }
    return m_ObjectList.InsertAfter(posInsertAfter, pNewObject);
}
int CPDF_PageObjects::GetObjectIndex(CPDF_PageObject* pObj) const
{
    int index = 0;
    FX_POSITION pos = m_ObjectList.GetHeadPosition();
    while (pos) {
        CPDF_PageObject* pThisObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos);
        if (pThisObj == pObj) {
            return index;
        }
        index ++;
    }
    return -1;
}
CPDF_PageObject* CPDF_PageObjects::GetObjectByIndex(int index) const
{
    FX_POSITION pos = m_ObjectList.FindIndex(index);
    if (pos == NULL) {
        return NULL;
    }
    return (CPDF_PageObject*)m_ObjectList.GetAt(pos);
}
void CPDF_PageObjects::Transform(const CFX_AffineMatrix& matrix)
{
    FX_POSITION pos = m_ObjectList.GetHeadPosition();
    while (pos) {
        CPDF_PageObject* pObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos);
        pObj->Transform(matrix);
    }
}
CFX_FloatRect CPDF_PageObjects::CalcBoundingBox() const
{
    if (m_ObjectList.GetCount() == 0) {
        return CFX_FloatRect(0, 0, 0, 0);
    }
    FX_FLOAT left, right, top, bottom;
    left = bottom = 1000000 * 1.0f;
    right = top = -1000000 * 1.0f;
    FX_POSITION pos = m_ObjectList.GetHeadPosition();
    while (pos) {
        CPDF_PageObject* pObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos);
        if (left > pObj->m_Left) {
            left = pObj->m_Left;
        }
        if (right < pObj->m_Right) {
            right = pObj->m_Right;
        }
        if (top < pObj->m_Top) {
            top = pObj->m_Top;
        }
        if (bottom > pObj->m_Bottom) {
            bottom = pObj->m_Bottom;
        }
    }
    return CFX_FloatRect(left, bottom, right, top);
}
void CPDF_PageObjects::LoadTransInfo()
{
    if (m_pFormDict == NULL) {
        return;
    }
    CPDF_Dictionary* pGroup = m_pFormDict->GetDict(FX_BSTRC("Group"));
    if (pGroup == NULL) {
        return;
    }
    if (pGroup->GetString(FX_BSTRC("S")) != FX_BSTRC("Transparency")) {
        return;
    }
    m_Transparency |= PDFTRANS_GROUP;
    if (pGroup->GetInteger(FX_BSTRC("I"))) {
        m_Transparency |= PDFTRANS_ISOLATED;
    }
    if (pGroup->GetInteger(FX_BSTRC("K"))) {
        m_Transparency |= PDFTRANS_KNOCKOUT;
    }
}
void CPDF_PageObjects::ClearCacheObjects()
{
    m_ParseState = PDF_CONTENT_NOT_PARSED;
    delete m_pParser;
    m_pParser = NULL;
    if (m_bReleaseMembers) {
        FX_POSITION pos = m_ObjectList.GetHeadPosition();
        while (pos) {
            delete (CPDF_PageObject*)m_ObjectList.GetNext(pos);
        }
    }
    m_ObjectList.RemoveAll();
}
CPDF_Page::CPDF_Page()
{
    m_pPageRender = NULL;
}
void CPDF_Page::Load(CPDF_Document* pDocument, CPDF_Dictionary* pPageDict, bool bPageCache)
{
    m_pDocument = (CPDF_Document*)pDocument;
    m_pFormDict = pPageDict;
    if (bPageCache) {
        m_pPageRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreatePageCache(this);
    }
    if (pPageDict == NULL) {
        m_PageWidth = m_PageHeight = 100 * 1.0f;
        m_pPageResources = m_pResources = NULL;
        return;
    }
    CPDF_Object* pageAttr = GetPageAttr(FX_BSTRC("Resources"));
    m_pResources = pageAttr ? pageAttr->GetDict() : NULL;
    m_pPageResources = m_pResources;
    CPDF_Object* pRotate = GetPageAttr(FX_BSTRC("Rotate"));
    int rotate = 0;
    if (pRotate) {
        rotate = pRotate->GetInteger() / 90 % 4;
    }
    if (rotate < 0) {
        rotate += 4;
    }
    CPDF_Array* pMediaBox, *pCropBox;
    pMediaBox = (CPDF_Array*)GetPageAttr(FX_BSTRC("MediaBox"));
    CFX_FloatRect mediabox;
    if (pMediaBox) {
        mediabox = pMediaBox->GetRect();
        mediabox.Normalize();
    }
    if (mediabox.IsEmpty()) {
        mediabox = CFX_FloatRect(0, 0, 612, 792);
    }
    pCropBox = (CPDF_Array*)GetPageAttr(FX_BSTRC("CropBox"));
    if (pCropBox) {
        m_BBox = pCropBox->GetRect();
        m_BBox.Normalize();
    }
    if (m_BBox.IsEmpty()) {
        m_BBox = mediabox;
    } else {
        m_BBox.Intersect(mediabox);
    }
    if (rotate % 2) {
        m_PageHeight = m_BBox.right - m_BBox.left;
        m_PageWidth = m_BBox.top - m_BBox.bottom;
    } else {
        m_PageWidth = m_BBox.right - m_BBox.left;
        m_PageHeight = m_BBox.top - m_BBox.bottom;
    }
    switch (rotate) {
        case 0:
            m_PageMatrix.Set(1.0f, 0, 0, 1.0f, -m_BBox.left, -m_BBox.bottom);
            break;
        case 1:
            m_PageMatrix.Set(0, -1.0f, 1.0f, 0, -m_BBox.bottom, m_BBox.right);
            break;
        case 2:
            m_PageMatrix.Set(-1.0f, 0, 0, -1.0f, m_BBox.right, m_BBox.top);
            break;
        case 3:
            m_PageMatrix.Set(0, 1.0f, -1.0f, 0, m_BBox.top, -m_BBox.left);
            break;
    }
    m_Transparency = PDFTRANS_ISOLATED;
    LoadTransInfo();
}
void CPDF_Page::StartParse(CPDF_ParseOptions* pOptions, bool bReParse)
{
    if (bReParse) {
        ClearCacheObjects();
    }
    if (m_ParseState == PDF_CONTENT_PARSED || m_ParseState == PDF_CONTENT_PARSING) {
        return;
    }
    m_pParser = new CPDF_ContentParser;
    m_pParser->Start(this, pOptions);
    m_ParseState = PDF_CONTENT_PARSING;
}
void CPDF_Page::ParseContent(CPDF_ParseOptions* pOptions, bool bReParse)
{
    StartParse(pOptions, bReParse);
    ContinueParse(NULL);
}
CPDF_Page::~CPDF_Page()
{
    if (m_pPageRender) {
        IPDF_RenderModule* pModule = CPDF_ModuleMgr::Get()->GetRenderModule();
        pModule->DestroyPageCache(m_pPageRender);
    }
}
CPDF_Object* FPDFAPI_GetPageAttr(CPDF_Dictionary* pPageDict, const CFX_ByteStringC& name)
{
    int level = 0;
    while (1) {
        CPDF_Object* pObj = pPageDict->GetElementValue(name);
        if (pObj) {
            return pObj;
        }
        CPDF_Dictionary* pParent = pPageDict->GetDict(FX_BSTRC("Parent"));
        if (!pParent || pParent == pPageDict) {
            return NULL;
        }
        pPageDict = pParent;
        level ++;
        if (level == 1000) {
            return NULL;
        }
    }
}
CPDF_Object* CPDF_Page::GetPageAttr(const CFX_ByteStringC& name) const
{
    return FPDFAPI_GetPageAttr(m_pFormDict, name);
}
CPDF_Form::CPDF_Form(CPDF_Document* pDoc, CPDF_Dictionary* pPageResources, CPDF_Stream* pFormStream, CPDF_Dictionary* pParentResources)
{
    m_pDocument = pDoc;
    m_pFormStream = pFormStream;
    m_pFormDict = pFormStream ? pFormStream->GetDict() : NULL;
    m_pResources = m_pFormDict->GetDict(FX_BSTRC("Resources"));
    m_pPageResources = pPageResources;
    if (m_pResources == NULL) {
        m_pResources = pParentResources;
    }
    if (m_pResources == NULL) {
        m_pResources = pPageResources;
    }
    m_Transparency = 0;
    LoadTransInfo();
}
CPDF_Form::~CPDF_Form()
{
}
void CPDF_Form::StartParse(CPDF_AllStates* pGraphicStates, CFX_AffineMatrix* pParentMatrix,
                           CPDF_Type3Char* pType3Char, CPDF_ParseOptions* pOptions, int level)
{
    if (m_ParseState == PDF_CONTENT_PARSED || m_ParseState == PDF_CONTENT_PARSING) {
        return;
    }
    m_pParser = new CPDF_ContentParser;
    m_pParser->Start(this, pGraphicStates, pParentMatrix, pType3Char, pOptions, level);
    m_ParseState = PDF_CONTENT_PARSING;
}
void CPDF_Form::ParseContent(CPDF_AllStates* pGraphicStates, CFX_AffineMatrix* pParentMatrix,
                             CPDF_Type3Char* pType3Char, CPDF_ParseOptions* pOptions, int level)
{
    StartParse(pGraphicStates, pParentMatrix, pType3Char, pOptions, level);
    ContinueParse(NULL);
}
CPDF_Form* CPDF_Form::Clone() const
{
    CPDF_Form* pClone = new CPDF_Form(m_pDocument, m_pPageResources, m_pFormStream, m_pResources);
    FX_POSITION pos = m_ObjectList.GetHeadPosition();
    while (pos) {
        CPDF_PageObject* pObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos);
        pClone->m_ObjectList.AddTail(pObj->Clone());
    }
    return pClone;
}
void CPDF_Page::GetDisplayMatrix(CFX_AffineMatrix& matrix, int xPos, int yPos,
                                 int xSize, int ySize, int iRotate) const
{
    if (m_PageWidth == 0 || m_PageHeight == 0) {
        return;
    }
    CFX_AffineMatrix display_matrix;
    int x0, y0, x1, y1, x2, y2;
    iRotate %= 4;
    switch (iRotate) {
        case 0:
            x0 = xPos;
            y0 = yPos + ySize;
            x1 = xPos;
            y1 = yPos;
            x2 = xPos + xSize;
            y2 = yPos + ySize;
            break;
        case 1:
            x0 = xPos;
            y0 = yPos;
            x1 = xPos + xSize;
            y1 = yPos;
            x2 = xPos;
            y2 = yPos + ySize;
            break;
        case 2:
            x0 = xPos + xSize;
            y0 = yPos;
            x1 = xPos + xSize;
            y1 = yPos + ySize;
            x2 = xPos;
            y2 = yPos;
            break;
        case 3:
            x0 = xPos + xSize;
            y0 = yPos + ySize;
            x1 = xPos;
            y1 = yPos + ySize;
            x2 = xPos + xSize;
            y2 = yPos;
            break;
    }
    display_matrix.Set(FXSYS_Div((FX_FLOAT)(x2 - x0), m_PageWidth),
                       FXSYS_Div((FX_FLOAT)(y2 - y0), m_PageWidth),
                       FXSYS_Div((FX_FLOAT)(x1 - x0), m_PageHeight),
                       FXSYS_Div((FX_FLOAT)(y1 - y0), m_PageHeight),
                       (FX_FLOAT)x0, (FX_FLOAT)y0);
    matrix = m_PageMatrix;
    matrix.Concat(display_matrix);
}
CPDF_ParseOptions::CPDF_ParseOptions()
{
    m_bTextOnly = false;
    m_bMarkedContent = true;
    m_bSeparateForm = true;
    m_bDecodeInlineImage = false;
}
