// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
#ifndef _FPDF_OBJECTS_
#define _FPDF_OBJECTS_
#ifndef _FXCRT_EXTENSION_
#include "../fxcrt/fx_ext.h"
#endif
class CPDF_Document;
class CPDF_IndirectObjects;
class CPDF_Null;
class CPDF_Boolean;
class CPDF_Number;
class CPDF_String;
class CPDF_Stream;
class CPDF_StreamAcc;
class CPDF_StreamFilter;
class CPDF_Array;
class CPDF_Dictionary;
class CPDF_Reference;
class IPDF_DocParser;
class IFX_FileRead;
class CPDF_CryptoHandler;
#define PDFOBJ_INVALID 0
#define PDFOBJ_BOOLEAN 1
#define PDFOBJ_NUMBER 2
#define PDFOBJ_STRING 3
#define PDFOBJ_NAME 4
#define PDFOBJ_ARRAY 5
#define PDFOBJ_DICTIONARY 6
#define PDFOBJ_STREAM 7
#define PDFOBJ_NULL 8
#define PDFOBJ_REFERENCE 9
typedef IFX_FileStream* (*FPDF_LPFCloneStreamCallback)(CPDF_Stream *pStream, FX_LPVOID pUserData);
class CPDF_Object : public CFX_Object
{
public:
int GetType() const
{
return m_Type;
}
FX_DWORD GetObjNum() const
{
return m_ObjNum;
}
FX_BOOL IsIdentical(CPDF_Object* pObj) const;
CPDF_Object* Clone(FX_BOOL bDirect = FALSE) const;
CPDF_Object* CloneRef(CPDF_IndirectObjects* pObjs) const;
CPDF_Object* GetDirect() const;
void Release();
CFX_ByteString GetString() const;
CFX_ByteStringC GetConstString() const;
CFX_WideString GetUnicodeText(CFX_CharMap* pCharMap = NULL) const;
FX_FLOAT GetNumber() const;
FX_FLOAT GetNumber16() const;
int GetInteger() const;
CPDF_Dictionary* GetDict() const;
CPDF_Array* GetArray() const;
void SetString(const CFX_ByteString& str);
void SetUnicodeText(FX_LPCWSTR pUnicodes, int len = -1);
int GetDirectType() const;
FX_BOOL IsModified() const
{
return FALSE;
}
protected:
FX_DWORD m_Type;
CPDF_Object()
{
m_ObjNum = 0;
}
FX_DWORD m_ObjNum;
void Destroy();
~CPDF_Object() {}
friend class CPDF_IndirectObjects;
friend class CPDF_Parser;
friend class CPDF_SyntaxParser;
private:
CPDF_Object(const CPDF_Object& src) {}
CPDF_Object* CloneInternal(FX_BOOL bDirect, CFX_MapPtrToPtr* visited) const;
};
class CPDF_Boolean : public CPDF_Object
{
public:
static CPDF_Boolean* Create(FX_BOOL value)
{
return FX_NEW CPDF_Boolean(value);
}
CPDF_Boolean()
{
m_Type = PDFOBJ_BOOLEAN;
}
CPDF_Boolean(FX_BOOL value)
{
m_Type = PDFOBJ_BOOLEAN;
m_bValue = value;
}
FX_BOOL Identical(CPDF_Boolean* pOther) const
{
return m_bValue == pOther->m_bValue;
}
protected:
FX_BOOL m_bValue;
friend class CPDF_Object;
};
class CPDF_Number : public CPDF_Object
{
public:
static CPDF_Number* Create(int value)
{
return FX_NEW CPDF_Number(value);
}
static CPDF_Number* Create(FX_FLOAT value)
{
return FX_NEW CPDF_Number(value);
}
static CPDF_Number* Create(FX_BSTR str)
{
return FX_NEW CPDF_Number(str);
}
static CPDF_Number* Create(FX_BOOL bInteger, void* pData)
{
return FX_NEW CPDF_Number(bInteger, pData);
}
CPDF_Number()
{
m_Type = PDFOBJ_NUMBER;
}
CPDF_Number(FX_BOOL bInteger, void* pData);
CPDF_Number(int value);
CPDF_Number(FX_FLOAT value);
CPDF_Number(FX_BSTR str);
FX_BOOL Identical(CPDF_Number* pOther) const;
CFX_ByteString GetString() const;
void SetString(FX_BSTR str);
FX_BOOL IsInteger() const
{
return m_bInteger;
}
int GetInteger() const
{
return m_bInteger ? m_Integer : (int)m_Float;
}
FX_FLOAT GetNumber() const
{
return m_bInteger ? (FX_FLOAT)m_Integer : m_Float;
}
void SetNumber(FX_FLOAT value);
FX_FLOAT GetNumber16() const
{
return GetNumber();
}
FX_FLOAT GetFloat() const
{
return m_bInteger ? (FX_FLOAT)m_Integer : m_Float;
}
protected:
FX_BOOL m_bInteger;
union {
int m_Integer;
FX_FLOAT m_Float;
};
friend class CPDF_Object;
};
class CPDF_String : public CPDF_Object
{
public:
static CPDF_String* Create(const CFX_ByteString& str, FX_BOOL bHex = FALSE)
{
return FX_NEW CPDF_String(str, bHex);
}
static CPDF_String* Create(const CFX_WideString& str)
{
return FX_NEW CPDF_String(str);
}
CPDF_String()
{
m_Type = PDFOBJ_STRING;
m_bHex = FALSE;
}
CPDF_String(const CFX_ByteString& str, FX_BOOL bHex = FALSE) : m_String(str)
{
m_Type = PDFOBJ_STRING;
m_bHex = bHex;
}
CPDF_String(const CFX_WideString& str);
CFX_ByteString& GetString()
{
return m_String;
}
FX_BOOL Identical(CPDF_String* pOther) const
{
return m_String == pOther->m_String;
}
FX_BOOL IsHex() const
{
return m_bHex;
}
protected:
CFX_ByteString m_String;
FX_BOOL m_bHex;
friend class CPDF_Object;
};
class CPDF_Name : public CPDF_Object
{
public:
static CPDF_Name* Create(const CFX_ByteString& str)
{
return FX_NEW CPDF_Name(str);
}
static CPDF_Name* Create(FX_BSTR str)
{
return FX_NEW CPDF_Name(str);
}
static CPDF_Name* Create(FX_LPCSTR str)
{
return FX_NEW CPDF_Name(str);
}
CPDF_Name(const CFX_ByteString& str) : m_Name(str)
{
m_Type = PDFOBJ_NAME;
}
CPDF_Name(FX_BSTR str) : m_Name(str)
{
m_Type = PDFOBJ_NAME;
}
CPDF_Name(FX_LPCSTR str) : m_Name(str)
{
m_Type = PDFOBJ_NAME;
}
CFX_ByteString& GetString()
{
return m_Name;
}
FX_BOOL Identical(CPDF_Name* pOther) const
{
return m_Name == pOther->m_Name;
}
protected:
CFX_ByteString m_Name;
friend class CPDF_Object;
};
class CPDF_Array : public CPDF_Object
{
public:
static CPDF_Array* Create()
{
return FX_NEW CPDF_Array();
}
CPDF_Array()
{
m_Type = PDFOBJ_ARRAY;
}
FX_DWORD GetCount() const
{
return m_Objects.GetSize();
}
CPDF_Object* GetElement(FX_DWORD index) const;
CPDF_Object* GetElementValue(FX_DWORD index) const;
CFX_AffineMatrix GetMatrix();
CFX_FloatRect GetRect();
CFX_ByteString GetString(FX_DWORD index) const;
CFX_ByteStringC GetConstString(FX_DWORD index) const;
int GetInteger(FX_DWORD index) const;
FX_FLOAT GetNumber(FX_DWORD index) const;
CPDF_Dictionary* GetDict(FX_DWORD index) const;
CPDF_Stream* GetStream(FX_DWORD index) const;
CPDF_Array* GetArray(FX_DWORD index) const;
FX_FLOAT GetFloat(FX_DWORD index) const
{
return GetNumber(index);
}
void SetAt(FX_DWORD index, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs = NULL);
void InsertAt(FX_DWORD index, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs = NULL);
void RemoveAt(FX_DWORD index);
void Add(CPDF_Object* pObj, CPDF_IndirectObjects* pObjs = NULL);
void AddNumber(FX_FLOAT f);
void AddInteger(int i);
void AddString(const CFX_ByteString& str);
void AddName(const CFX_ByteString& str);
void AddReference(CPDF_IndirectObjects* pDoc, FX_DWORD objnum);
void AddReference(CPDF_IndirectObjects* pDoc, CPDF_Object* obj)
{
AddReference(pDoc, obj->GetObjNum());
}
FX_FLOAT GetNumber16(FX_DWORD index) const
{
return GetNumber(index);
}
void AddNumber16(FX_FLOAT value)
{
AddNumber(value);
}
FX_BOOL Identical(CPDF_Array* pOther) const;
protected:
~CPDF_Array();
CFX_PtrArray m_Objects;
friend class CPDF_Object;
};
class CPDF_Dictionary : public CPDF_Object
{
public:
static CPDF_Dictionary* Create()
{
return FX_NEW CPDF_Dictionary();
}
CPDF_Dictionary()
{
m_Type = PDFOBJ_DICTIONARY;
}
CPDF_Object* GetElement(FX_BSTR key) const;
CPDF_Object* GetElementValue(FX_BSTR key) const;
CFX_ByteString GetString(FX_BSTR key) const;
CFX_ByteStringC GetConstString(FX_BSTR key) const;
CFX_ByteString GetString(FX_BSTR key, FX_BSTR default_str) const;
CFX_ByteStringC GetConstString(FX_BSTR key, FX_BSTR default_str) const;
CFX_WideString GetUnicodeText(FX_BSTR key, CFX_CharMap* pCharMap = NULL) const;
int GetInteger(FX_BSTR key) const;
int GetInteger(FX_BSTR key, int default_int) const;
FX_BOOL GetBoolean(FX_BSTR key, FX_BOOL bDefault = FALSE) const;
FX_FLOAT GetNumber(FX_BSTR key) const;
CPDF_Dictionary* GetDict(FX_BSTR key) const;
CPDF_Stream* GetStream(FX_BSTR key) const;
CPDF_Array* GetArray(FX_BSTR key) const;
CFX_FloatRect GetRect(FX_BSTR key) const;
CFX_AffineMatrix GetMatrix(FX_BSTR key) const;
FX_FLOAT GetFloat(FX_BSTR key) const
{
return GetNumber(key);
}
FX_BOOL KeyExist(FX_BSTR key) const;
FX_POSITION GetStartPos() const;
CPDF_Object* GetNextElement(FX_POSITION& pos, CFX_ByteString& key) const;
void SetAt(FX_BSTR key, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs = NULL);
void SetAtName(FX_BSTR key, const CFX_ByteString& name);
void SetAtString(FX_BSTR key, const CFX_ByteString& string);
void SetAtInteger(FX_BSTR key, int i);
void SetAtNumber(FX_BSTR key, FX_FLOAT f);
void SetAtReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, FX_DWORD objnum);
void SetAtReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, CPDF_Object* obj)
{
SetAtReference(key, pDoc, obj->GetObjNum());
}
void AddReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, FX_DWORD objnum);
void AddReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, CPDF_Object* obj)
{
AddReference(key, pDoc, obj->GetObjNum());
}
void SetAtRect(FX_BSTR key, const CFX_FloatRect& rect);
void SetAtMatrix(FX_BSTR key, const CFX_AffineMatrix& matrix);
void SetAtBoolean(FX_BSTR key, FX_BOOL bValue);
void RemoveAt(FX_BSTR key);
void ReplaceKey(FX_BSTR oldkey, FX_BSTR newkey);
FX_BOOL Identical(CPDF_Dictionary* pDict) const;
int GetCount() const
{
return m_Map.GetCount();
}
void AddValue(FX_BSTR key, CPDF_Object* pObj);
protected:
~CPDF_Dictionary();
CFX_CMapByteStringToPtr m_Map;
friend class CPDF_Object;
};
class CPDF_Stream : public CPDF_Object
{
public:
static CPDF_Stream* Create(FX_LPBYTE pData, FX_DWORD size, CPDF_Dictionary* pDict)
{
return FX_NEW CPDF_Stream(pData, size, pDict);
}
CPDF_Stream(FX_LPBYTE pData, FX_DWORD size, CPDF_Dictionary* pDict);
CPDF_Dictionary* GetDict() const
{
return m_pDict;
}
void SetData(FX_LPCBYTE pData, FX_DWORD size, FX_BOOL bCompressed, FX_BOOL bKeepBuf);
void InitStream(FX_BYTE* pData, FX_DWORD size, CPDF_Dictionary* pDict);
void InitStream(IFX_FileRead *pFile, CPDF_Dictionary* pDict);
FX_BOOL Identical(CPDF_Stream* pOther) const;
CPDF_StreamFilter* GetStreamFilter(FX_BOOL bRaw = FALSE) const;
FX_DWORD GetRawSize() const
{
return m_dwSize;
}
FX_BOOL ReadRawData(FX_FILESIZE start_pos, FX_LPBYTE pBuf, FX_DWORD buf_size) const;
FX_BOOL IsMemoryBased() const
{
return m_GenNum == (FX_DWORD) - 1;
}
CPDF_Stream* Clone(FX_BOOL bDirect, FPDF_LPFCloneStreamCallback lpfCallback, FX_LPVOID pUserData) const;
protected:
~CPDF_Stream();
CPDF_Dictionary* m_pDict;
FX_DWORD m_dwSize;
FX_DWORD m_GenNum;
union {
FX_LPBYTE m_pDataBuf;
IFX_FileRead* m_pFile;
};
FX_FILESIZE m_FileOffset;
CPDF_CryptoHandler* m_pCryptoHandler;
void InitStream(CPDF_Dictionary* pDict);
friend class CPDF_Object;
friend class CPDF_StreamAcc;
friend class CPDF_AttachmentAcc;
};
class CPDF_StreamAcc : public CFX_Object
{
public:
CPDF_StreamAcc();
~CPDF_StreamAcc();
void LoadAllData(const CPDF_Stream* pStream, FX_BOOL bRawAccess = FALSE,
FX_DWORD estimated_size = 0, FX_BOOL bImageAcc = FALSE);
const CPDF_Stream* GetStream() const
{
return m_pStream;
}
CPDF_Dictionary* GetDict() const
{
return m_pStream->GetDict();
}
FX_LPCBYTE GetData() const;
FX_DWORD GetSize() const;
FX_LPBYTE DetachData();
const CFX_ByteString& GetImageDecoder()
{
return m_ImageDecoder;
}
const CPDF_Dictionary* GetImageParam()
{
return m_pImageParam;
}
protected:
FX_LPBYTE m_pData;
FX_DWORD m_dwSize;
FX_BOOL m_bNewBuf;
CFX_ByteString m_ImageDecoder;
CPDF_Dictionary* m_pImageParam;
const CPDF_Stream* m_pStream;
FX_LPBYTE m_pSrcData;
};
CFX_DataFilter* FPDF_CreateFilter(FX_BSTR name, const CPDF_Dictionary* pParam, int width = 0, int height = 0);
#define FPDF_FILTER_BUFFER_SIZE 20480
class CPDF_StreamFilter : public CFX_Object
{
public:
~CPDF_StreamFilter();
FX_DWORD ReadBlock(FX_LPBYTE buffer, FX_DWORD size);
FX_DWORD GetSrcPos()
{
return m_SrcOffset;
}
const CPDF_Stream* GetStream()
{
return m_pStream;
}
protected:
CPDF_StreamFilter() {}
FX_DWORD ReadLeftOver(FX_LPBYTE buffer, FX_DWORD buf_size);
const CPDF_Stream* m_pStream;
CFX_DataFilter* m_pFilter;
CFX_BinaryBuf* m_pBuffer;
FX_DWORD m_BufOffset;
FX_DWORD m_SrcOffset;
FX_BYTE m_SrcBuffer[FPDF_FILTER_BUFFER_SIZE];
friend class CPDF_Stream;
};
class CPDF_Null : public CPDF_Object
{
public:
static CPDF_Null* Create()
{
return FX_NEW CPDF_Null();
}
CPDF_Null()
{
m_Type = PDFOBJ_NULL;
}
};
class CPDF_Reference : public CPDF_Object
{
public:
static CPDF_Reference* Create(CPDF_IndirectObjects* pDoc, int objnum)
{
return FX_NEW CPDF_Reference(pDoc, objnum);
}
CPDF_Reference(CPDF_IndirectObjects* pDoc, int objnum)
{
m_Type = PDFOBJ_REFERENCE;
m_pObjList = pDoc;
m_RefObjNum = objnum;
}
CPDF_IndirectObjects* GetObjList() const
{
return m_pObjList;
}
FX_DWORD GetRefObjNum() const
{
return m_RefObjNum;
}
void SetRef(CPDF_IndirectObjects* pDoc, FX_DWORD objnum);
FX_BOOL Identical(CPDF_Reference* pOther) const
{
return m_RefObjNum == pOther->m_RefObjNum;
}
protected:
CPDF_IndirectObjects* m_pObjList;
FX_DWORD m_RefObjNum;
friend class CPDF_Object;
};
class CPDF_IndirectObjects : public CFX_Object
{
public:
CPDF_IndirectObjects(IPDF_DocParser* pParser);
~CPDF_IndirectObjects();
CPDF_Object* GetIndirectObject(FX_DWORD objnum, struct PARSE_CONTEXT* pContext = NULL);
int GetIndirectType(FX_DWORD objnum);
FX_DWORD AddIndirectObject(CPDF_Object* pObj);
void ReleaseIndirectObject(FX_DWORD objnum);
void InsertIndirectObject(FX_DWORD objnum, CPDF_Object* pObj);
FX_DWORD GetLastObjNum() const;
FX_POSITION GetStartPosition() const
{
return m_IndirectObjs.GetStartPosition();
}
void GetNextAssoc(FX_POSITION& rPos, FX_DWORD& objnum, CPDF_Object*& pObject) const
{
m_IndirectObjs.GetNextAssoc(rPos, (void*&)objnum, (void*&)pObject);
}
protected:
CFX_MapPtrToPtr m_IndirectObjs;
IPDF_DocParser* m_pParser;
FX_DWORD m_LastObjNum;
};
#endif