// 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_serial.h"
#include "../../../include/fpdfapi/fpdf_module.h"
#include "../fpdf_page/pageint.h"

CFX_ByteTextBuf& operator << (CFX_ByteTextBuf& ar, CFX_AffineMatrix& matrix)
{
    ar << matrix.a << " " << matrix.b << " " << matrix.c << " " << matrix.d << " " << matrix.e << " " << matrix.f;
    return ar;
}
CPDF_PageContentGenerate::CPDF_PageContentGenerate(CPDF_Page* pPage) : m_pPage(pPage)
{
    m_pDocument = NULL;
    if (m_pPage) {
        m_pDocument = m_pPage->m_pDocument;
    }
    FX_POSITION pos = pPage->GetFirstObjectPosition();
    while (pos) {
        InsertPageObject(pPage->GetNextObject(pos));
    }
}
CPDF_PageContentGenerate::~CPDF_PageContentGenerate()
{
}
bool CPDF_PageContentGenerate::InsertPageObject(CPDF_PageObject* pPageObject)
{
    if (!pPageObject) {
        return false;
    }
    return m_pageObjects.Add(pPageObject);
}
void CPDF_PageContentGenerate::GenerateContent()
{
    CFX_ByteTextBuf buf;
    CPDF_Dictionary* pPageDict = m_pPage->m_pFormDict;
    for (int i = 0; i < m_pageObjects.GetSize(); ++i) {
        CPDF_PageObject* pPageObj = (CPDF_PageObject*)m_pageObjects[i];
        if (!pPageObj || pPageObj->m_Type != PDFPAGE_IMAGE) {
            continue;
        }
        ProcessImage(buf, (CPDF_ImageObject*)pPageObj);
    }
    CPDF_Object* pContent = pPageDict ? pPageDict->GetElementValue("Contents") : NULL;
    if (pContent != NULL) {
        pPageDict->RemoveAt("Contents");
    }
    CPDF_Stream* pStream = new CPDF_Stream(NULL, 0, NULL);
    pStream->SetData(buf.GetBuffer(), buf.GetLength(), false, false);
    m_pDocument->AddIndirectObject(pStream);
    pPageDict->SetAtReference("Contents", m_pDocument, pStream->GetObjNum());
}
CFX_ByteString CPDF_PageContentGenerate::RealizeResource(CPDF_Object* pResourceObj, const FX_CHAR* szType)
{
    if (m_pPage->m_pResources == NULL) {
        m_pPage->m_pResources = new CPDF_Dictionary;
        int objnum = m_pDocument->AddIndirectObject(m_pPage->m_pResources);
        m_pPage->m_pFormDict->SetAtReference("Resources", m_pDocument, objnum);
    }
    CPDF_Dictionary* pResList = m_pPage->m_pResources->GetDict(szType);
    if (pResList == NULL) {
        pResList = new CPDF_Dictionary;
        m_pPage->m_pResources->SetAt(szType, pResList);
    }
    m_pDocument->AddIndirectObject(pResourceObj);
    CFX_ByteString name;
    int idnum = 1;
    while (1) {
        name.Format("FX%c%d", szType[0], idnum);
        if (!pResList->KeyExist(name)) {
            break;
        }
        idnum ++;
    }
    pResList->AddReference(name, m_pDocument, pResourceObj->GetObjNum());
    return name;
}
void CPDF_PageContentGenerate::ProcessImage(CFX_ByteTextBuf& buf, CPDF_ImageObject* pImageObj)
{
    if ((pImageObj->m_Matrix.a == 0 && pImageObj->m_Matrix.b == 0) ||
            (pImageObj->m_Matrix.c == 0 && pImageObj->m_Matrix.d == 0)) {
        return;
    }
    buf << "q " << pImageObj->m_Matrix << " cm ";
    if (!pImageObj->m_pImage->IsInline()) {
        CPDF_Stream* pStream = pImageObj->m_pImage->GetStream();
        FX_DWORD dwSavedObjNum = pStream->GetObjNum();
        CFX_ByteString name = RealizeResource(pStream, "XObject");
        if (dwSavedObjNum == 0) {
            if (pImageObj->m_pImage)
                pImageObj->m_pImage->Release();
            pImageObj->m_pImage = m_pDocument->GetPageData()->GetImage(pStream);
        }
        buf << "/" << PDF_NameEncode(name) << " Do Q\n";
    }
}
void CPDF_PageContentGenerate::ProcessForm(CFX_ByteTextBuf& buf, const uint8_t* data, FX_DWORD size, CFX_Matrix& matrix)
{
    if (!data || !size) {
        return;
    }
    CPDF_Stream* pStream = new CPDF_Stream(NULL, 0, NULL);
    CPDF_Dictionary* pFormDict = CPDF_Dictionary::Create();
    pFormDict->SetAtName("Type", "XObject");
    pFormDict->SetAtName("Subtype", "Form");
    CFX_FloatRect bbox = m_pPage->GetPageBBox();
    matrix.TransformRect(bbox);
    pFormDict->SetAtRect("BBox", bbox);
    pStream->InitStream((uint8_t*)data, size, pFormDict);
    buf << "q " << matrix << " cm ";
    CFX_ByteString name = RealizeResource(pStream, "XObject");
    buf << "/" << PDF_NameEncode(name) << " Do Q\n";
}
void CPDF_PageContentGenerate::TransformContent(CFX_Matrix& matrix)
{
    CPDF_Dictionary* pDict = m_pPage->m_pFormDict;
    CPDF_Object* pContent = pDict ? pDict->GetElementValue("Contents") : NULL;
    if (!pContent) {
        return;
    }
    CFX_ByteTextBuf buf;
    int type = pContent->GetType();
    if (type == PDFOBJ_ARRAY) {
        CPDF_Array* pArray = (CPDF_Array*)pContent;
        int iCount = pArray->GetCount();
        CPDF_StreamAcc** pContentArray = (CPDF_StreamAcc**)FX_Alloc(CPDF_StreamAcc*, iCount);
        int size = 0;
        int i = 0;
        for (i = 0; i < iCount; ++i) {
            pContent = pArray->GetElement(i);
            if (!pContent || pContent->GetType() != PDFOBJ_STREAM) {
                continue;
            }
            CPDF_StreamAcc* pStream = new CPDF_StreamAcc();
            pStream->LoadAllData((CPDF_Stream*)pContent);
            pContentArray[i] = pStream;
            size += pContentArray[i]->GetSize() + 1;
        }
        int pos = 0;
        uint8_t* pBuf = FX_Alloc(uint8_t, size);
        for (i = 0; i < iCount; ++i) {
            FXSYS_memcpy(pBuf + pos, pContentArray[i]->GetData(), pContentArray[i]->GetSize());
            pos += pContentArray[i]->GetSize() + 1;
            pBuf[pos - 1] = ' ';
            delete pContentArray[i];
        }
        ProcessForm(buf, pBuf, size, matrix);
        FX_Free(pBuf);
        FX_Free(pContentArray);
    } else if (type == PDFOBJ_STREAM) {
        CPDF_StreamAcc contentStream;
        contentStream.LoadAllData((CPDF_Stream*)pContent);
        ProcessForm(buf, contentStream.GetData(), contentStream.GetSize(), matrix);
    }
    CPDF_Stream* pStream = new CPDF_Stream(NULL, 0, NULL);
    pStream->SetData(buf.GetBuffer(), buf.GetLength(), false, false);
    m_pDocument->AddIndirectObject(pStream);
    m_pPage->m_pFormDict->SetAtReference("Contents", m_pDocument, pStream->GetObjNum());
}
