text: /******************************************************************************
   * $Id: pdfobject.h 27331 2014-05-14 16:25:25Z rouault $
   *
   * Project:  PDF driver
   * Purpose:  GDALDataset driver for PDF dataset.
   * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
   *
   ******************************************************************************
   * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
   *
   * Permission is hereby granted, free of charge, to any person obtaining a
   * copy of this software and associated documentation files (the "Software"),
   * to deal in the Software without restriction, including without limitation
   * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   * and/or sell copies of the Software, and to permit persons to whom the
   * Software is furnished to do so, subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included
   * in all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   * DEALINGS IN THE SOFTWARE.
   ****************************************************************************/
  
  #ifndef PDFOBJECT_H_INCLUDED
  #define PDFOBJECT_H_INCLUDED
  
  #include "cpl_string.h"
  #include <map>
  #include <vector>
  
  #define DEFAULT_DPI         (72.0)
  #define USER_UNIT_IN_INCH   (1.0 / DEFAULT_DPI)
  
  #ifdef HAVE_POPPLER
  
  /* begin of poppler xpdf includes */
  #include <poppler/Object.h>
  
  #define private public /* Ugly! Page::pageObj is private but we need it... */
  #include <poppler/Page.h>
  #undef private
  
  #include <poppler/Dict.h>
  
  #define private public /* Ugly! Catalog::optContent is private but we need it... */
  #include <poppler/Catalog.h>
  #undef private
  
  #define private public  /* Ugly! PDFDoc::str is private but we need it... */
  #include <poppler/PDFDoc.h>
  #undef private
  
  #include <poppler/splash/SplashBitmap.h>
  #include <poppler/splash/Splash.h>
  #include <poppler/SplashOutputDev.h>
  #include <poppler/GlobalParams.h>
  #include <poppler/ErrorCodes.h>
  /* end of poppler xpdf includes */
  
  #endif // HAVE_POPPLER
  
  #ifdef HAVE_PODOFO
  /*
   * Some Windows header defines a GetObject macro that
   * shadows a GetObject() method in PoDoFo. This
   * workaround is documented in the PoDoFo source.
   */ 
  #ifdef GetObject
  #undef GetObject
  #endif
  
  #include "podofo.h"
  #endif // HAVE_PODOFO
  
  
  double ROUND_TO_INT_IF_CLOSE(double x, double eps = 0);
  
  typedef enum
  {
      PDFObjectType_Unknown,
      PDFObjectType_Null,
      PDFObjectType_Bool,
      PDFObjectType_Int,
      PDFObjectType_Real,
      PDFObjectType_String,
      PDFObjectType_Name,
      PDFObjectType_Array,
      PDFObjectType_Dictionary
  } GDALPDFObjectType;
  
  class GDALPDFDictionary;
  class GDALPDFArray;
  class GDALPDFStream;
  
  class GDALPDFObjectRW;
  class GDALPDFDictionaryRW;
  class GDALPDFArrayRW;
  
  class GDALPDFObject
  {
      protected:
          virtual const char*       GetTypeNameNative() = 0;
  
      public:
          virtual ~GDALPDFObject();
  
          virtual GDALPDFObjectType GetType() = 0;
          virtual const char*       GetTypeName();
          virtual int               GetBool() = 0;
          virtual int               GetInt() = 0;
          virtual double            GetReal() = 0;
          virtual int               CanRepresentRealAsString() { return FALSE; }
          virtual const CPLString&  GetString() = 0;
          virtual const CPLString&  GetName() = 0;
          virtual GDALPDFDictionary*  GetDictionary() = 0;
          virtual GDALPDFArray*       GetArray() = 0;
          virtual GDALPDFStream*      GetStream() = 0;
          virtual int                 GetRefNum() = 0;
          virtual int                 GetRefGen() = 0;
  
          GDALPDFObject*              LookupObject(const char* pszPath);
  
          void                        Serialize(CPLString& osStr);
          CPLString                   Serialize() { CPLString osStr; Serialize(osStr); return osStr; }
          GDALPDFObjectRW*            Clone();
  };
  
  class GDALPDFDictionary
  {
      public:
          virtual ~GDALPDFDictionary();
  
          virtual GDALPDFObject* Get(const char* pszKey) = 0;
          virtual std::map<CPLString, GDALPDFObject*>& GetValues() = 0;
  
          GDALPDFObject*              LookupObject(const char* pszPath);
  
          void                        Serialize(CPLString& osStr);
          CPLString                   Serialize() { CPLString osStr; Serialize(osStr); return osStr; }
          GDALPDFDictionaryRW*        Clone();
  };
  
  class GDALPDFArray
  {
      public:
          virtual ~GDALPDFArray();
  
          virtual int GetLength() = 0;
          virtual GDALPDFObject* Get(int nIndex) = 0;
  
          void                        Serialize(CPLString& osStr);
          CPLString                   Serialize() { CPLString osStr; Serialize(osStr); return osStr; }
          GDALPDFArrayRW*             Clone();
  };
  
  class GDALPDFStream
  {
      public:
          virtual ~GDALPDFStream();
  
          virtual int GetLength() = 0;
          virtual char* GetBytes() = 0;
  };
  
  class GDALPDFObjectRW : public GDALPDFObject
  {
      private:
          GDALPDFObjectType     m_eType;
          int                   m_nVal;
          double                m_dfVal;
          CPLString             m_osVal;
          GDALPDFDictionaryRW  *m_poDict;
          GDALPDFArrayRW       *m_poArray;
          int                   m_nNum;
          int                   m_nGen;
          int                   m_bCanRepresentRealAsString;
  
                                GDALPDFObjectRW(GDALPDFObjectType eType);
  
      protected:
          virtual const char*       GetTypeNameNative();
  
      public:
  
          static GDALPDFObjectRW* CreateIndirect(int nNum, int nGen);
          static GDALPDFObjectRW* CreateNull();
          static GDALPDFObjectRW* CreateBool(int bVal);
          static GDALPDFObjectRW* CreateInt(int nVal);
          static GDALPDFObjectRW* CreateReal(double dfVal, int bCanRepresentRealAsString = FALSE);
          static GDALPDFObjectRW* CreateString(const char* pszStr);
          static GDALPDFObjectRW* CreateName(const char* pszName);
          static GDALPDFObjectRW* CreateDictionary(GDALPDFDictionaryRW* poDict);
          static GDALPDFObjectRW* CreateArray(GDALPDFArrayRW* poArray);
          virtual ~GDALPDFObjectRW();
  
          virtual GDALPDFObjectType GetType();
          virtual int               GetBool();
          virtual int               GetInt();
          virtual double            GetReal();
          virtual int               CanRepresentRealAsString() { return m_bCanRepresentRealAsString; }
          virtual const CPLString&  GetString();
          virtual const CPLString&  GetName();
          virtual GDALPDFDictionary*  GetDictionary();
          virtual GDALPDFArray*       GetArray();
          virtual GDALPDFStream*      GetStream();
          virtual int                 GetRefNum();
          virtual int                 GetRefGen();
  };
  
  class GDALPDFDictionaryRW : public GDALPDFDictionary
  {
      private:
          std::map<CPLString, GDALPDFObject*> m_map;
  
      public:
                                 GDALPDFDictionaryRW();
          virtual               ~GDALPDFDictionaryRW();
  
          virtual GDALPDFObject*                       Get(const char* pszKey);
          virtual std::map<CPLString, GDALPDFObject*>& GetValues();
  
          GDALPDFDictionaryRW&   Add(const char* pszKey, GDALPDFObject* poVal);
          GDALPDFDictionaryRW&   Remove(const char* pszKey);
  
          GDALPDFDictionaryRW&   Add(const char* pszKey, GDALPDFArrayRW* poArray) { return Add(pszKey, GDALPDFObjectRW::CreateArray(poArray)); }
          GDALPDFDictionaryRW&   Add(const char* pszKey, GDALPDFDictionaryRW* poDict) { return Add(pszKey, GDALPDFObjectRW::CreateDictionary(poDict)); }
          GDALPDFDictionaryRW&   Add(const char* pszKey, const char* pszVal) { return Add(pszKey, GDALPDFObjectRW::CreateString(pszVal)); }
          GDALPDFDictionaryRW&   Add(const char* pszKey, int nVal) { return Add(pszKey, GDALPDFObjectRW::CreateInt(nVal)); }
          GDALPDFDictionaryRW&   Add(const char* pszKey, double dfVal, int bCanRepresentRealAsString = FALSE) { return Add(pszKey, GDALPDFObjectRW::CreateReal(dfVal, bCanRepresentRealAsString)); }
          GDALPDFDictionaryRW&   Add(const char* pszKey, int nNum, int nGen) { return Add(pszKey, GDALPDFObjectRW::CreateIndirect(nNum, nGen)); }
  };
  
  class GDALPDFArrayRW : public GDALPDFArray
  {
      private:
          std::vector<GDALPDFObject*> m_array;
  
      public:
                                 GDALPDFArrayRW();
          virtual               ~GDALPDFArrayRW();
  
          virtual int            GetLength();
          virtual GDALPDFObject* Get(int nIndex);
  
          GDALPDFArrayRW&        Add(GDALPDFObject* poObj);
  
          GDALPDFArrayRW&        Add(GDALPDFArrayRW* poArray) { return Add(GDALPDFObjectRW::CreateArray(poArray)); }
          GDALPDFArrayRW&        Add(GDALPDFDictionaryRW* poDict) { return Add(GDALPDFObjectRW::CreateDictionary(poDict)); }
          GDALPDFArrayRW&        Add(const char* pszVal) { return Add(GDALPDFObjectRW::CreateString(pszVal)); }
          GDALPDFArrayRW&        Add(int nVal) { return Add(GDALPDFObjectRW::CreateInt(nVal)); }
          GDALPDFArrayRW&        Add(double dfVal, int bCanRepresentRealAsString = FALSE) { return Add(GDALPDFObjectRW::CreateReal(dfVal, bCanRepresentRealAsString)); }
          GDALPDFArrayRW&        Add(double* padfVal, int nCount, int bCanRepresentRealAsString = FALSE);
          GDALPDFArrayRW&        Add(int nNum, int nGen) { return Add(GDALPDFObjectRW::CreateIndirect(nNum, nGen)); }
  };
  
  #ifdef HAVE_POPPLER
  
  class GDALPDFObjectPoppler : public GDALPDFObject
  {
      private:
          Object* m_po;
          int     m_bDestroy;
          GDALPDFDictionary* m_poDict;
          GDALPDFArray* m_poArray;
          GDALPDFStream* m_poStream;
          CPLString osStr;
          int m_nRefNum;
          int m_nRefGen;
  
      protected:
          virtual const char*       GetTypeNameNative();
  
      public:
          GDALPDFObjectPoppler(Object* po, int bDestroy) :
                  m_po(po), m_bDestroy(bDestroy),
                  m_poDict(NULL), m_poArray(NULL), m_poStream(NULL),
                  m_nRefNum(0), m_nRefGen(0) {}
  
          void SetRefNumAndGen(int nNum, int nGen);
  
          virtual ~GDALPDFObjectPoppler();
  
          virtual GDALPDFObjectType GetType();
          virtual int               GetBool();
          virtual int               GetInt();
          virtual double            GetReal();
          virtual const CPLString&  GetString();
          virtual const CPLString&  GetName();
          virtual GDALPDFDictionary*  GetDictionary();
          virtual GDALPDFArray*       GetArray();
          virtual GDALPDFStream*      GetStream();
          virtual int                 GetRefNum();
          virtual int                 GetRefGen();
  };
  
  GDALPDFArray* GDALPDFCreateArray(Array* array);
  
  #endif // HAVE_POPPLER
  
  #ifdef HAVE_PODOFO
  
  class GDALPDFObjectPodofo : public GDALPDFObject
  {
      private:
          PoDoFo::PdfObject* m_po;
          PoDoFo::PdfVecObjects& m_poObjects;
          GDALPDFDictionary* m_poDict;
          GDALPDFArray* m_poArray;
          GDALPDFStream* m_poStream;
          CPLString osStr;
  
      protected:
          virtual const char*       GetTypeNameNative();
  
      public:
          GDALPDFObjectPodofo(PoDoFo::PdfObject* po, PoDoFo::PdfVecObjects& poObjects);
  
          virtual ~GDALPDFObjectPodofo();
  
          virtual GDALPDFObjectType GetType();
          virtual int               GetBool();
          virtual int               GetInt();
          virtual double            GetReal();
          virtual const CPLString&  GetString();
          virtual const CPLString&  GetName();
          virtual GDALPDFDictionary*  GetDictionary();
          virtual GDALPDFArray*       GetArray();
          virtual GDALPDFStream*      GetStream();
          virtual int                 GetRefNum();
          virtual int                 GetRefGen();
  };
  
  #endif // HAVE_PODOFO
  
  #endif // PDFOBJECT_H_INCLUDED
  