Remove trailing whitespaces in fpdfsdk.
[pdfium.git] / fpdfsdk / src / fpdfppo.cpp
index e605484..21ae05d 100644 (file)
-// Copyright 2014 PDFium Authors. All rights reserved.\r
-// Use of this source code is governed by a BSD-style license that can be\r
-// found in the LICENSE file.\r
\r
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
-\r
-#include "../include/fpdfppo.h"\r
-#include "../include/fsdk_define.h"\r
-\r
-class CPDF_PageOrganizer\r
-{\r
-public:\r
-       CPDF_PageOrganizer();\r
-       ~CPDF_PageOrganizer();\r
-       \r
-public:\r
-       FX_BOOL                         PDFDocInit(CPDF_Document *pDestPDFDoc, CPDF_Document *pSrcPDFDoc);\r
-       FX_BOOL                         ExportPage(CPDF_Document *pSrcPDFDoc, CFX_WordArray* nPageNum, CPDF_Document *pDestPDFDoc, int nIndex);\r
-       CPDF_Object*            PageDictGetInheritableTag(CPDF_Dictionary *pDict, CFX_ByteString nSrctag);\r
-       FX_BOOL                         UpdateReference(CPDF_Object *pObj, CPDF_Document *pDoc, CFX_MapPtrToPtr* pMapPtrToPtr);\r
-       int                                     GetNewObjId(CPDF_Document *pDoc, CFX_MapPtrToPtr* pMapPtrToPtr, CPDF_Reference *pRef);\r
-       \r
-};\r
-\r
-\r
-CPDF_PageOrganizer::CPDF_PageOrganizer()\r
-{\r
-\r
-}\r
-\r
-CPDF_PageOrganizer::~CPDF_PageOrganizer()\r
-{\r
-\r
-}\r
-\r
-FX_BOOL CPDF_PageOrganizer::PDFDocInit(CPDF_Document *pDestPDFDoc, CPDF_Document *pSrcPDFDoc)\r
-{\r
-       if(!pDestPDFDoc || !pSrcPDFDoc)\r
-               return false;\r
-       \r
-       CPDF_Dictionary* pNewRoot = pDestPDFDoc->GetRoot();\r
-       if(!pNewRoot)   return FALSE;\r
-       \r
-       //Set the document information////////////////////////////////////////////\r
-       \r
-       CPDF_Dictionary* DInfoDict = pDestPDFDoc->GetInfo();\r
-       \r
-       if(!DInfoDict)\r
-               return FALSE;\r
-       \r
-       CFX_ByteString producerstr;\r
-       \r
-#ifdef FOXIT_CHROME_BUILD\r
-       producerstr.Format("Google");\r
-#else\r
-        producerstr.Format("Foxit PDF SDK %s - Foxit Corporation", "2.0");\r
-#endif\r
-       DInfoDict->SetAt("Producer", new CPDF_String(producerstr));\r
-\r
-       //Set type////////////////////////////////////////////////////////////////\r
-       CFX_ByteString cbRootType = pNewRoot->GetString("Type","");\r
-       if( cbRootType.Equal("") )\r
-       {\r
-               pNewRoot->SetAt("Type", new CPDF_Name("Catalog"));\r
-       }\r
-       \r
-       CPDF_Dictionary* pNewPages = (CPDF_Dictionary*)pNewRoot->GetElement("Pages")->GetDirect();\r
-       if(!pNewPages)\r
-       {\r
-               pNewPages = new CPDF_Dictionary;\r
-               FX_DWORD NewPagesON = pDestPDFDoc->AddIndirectObject(pNewPages);\r
-               pNewRoot->SetAt("Pages", new CPDF_Reference(pDestPDFDoc, NewPagesON));\r
-       }\r
-       \r
-       CFX_ByteString cbPageType = pNewPages->GetString("Type","");\r
-       if(cbPageType.Equal(""))\r
-       {\r
-               pNewPages->SetAt("Type", new CPDF_Name("Pages"));\r
-       }\r
-\r
-       CPDF_Array* pKeysArray = pNewPages->GetArray("Kids");\r
-       if(pKeysArray == NULL)\r
-       {\r
-               CPDF_Array* pNewKids = new CPDF_Array;\r
-               FX_DWORD Kidsobjnum = -1;\r
-               Kidsobjnum = pDestPDFDoc->AddIndirectObject(pNewKids);//, Kidsobjnum, Kidsgennum);\r
-               \r
-               pNewPages->SetAt("Kids", new CPDF_Reference(pDestPDFDoc, Kidsobjnum));//, Kidsgennum));\r
-               pNewPages->SetAt("Count", new CPDF_Number(0));          \r
-       }\r
-\r
-       return true;\r
-}\r
-\r
-FX_BOOL CPDF_PageOrganizer::ExportPage(CPDF_Document *pSrcPDFDoc, CFX_WordArray* nPageNum, \r
-                                                                                               CPDF_Document *pDestPDFDoc,int nIndex)\r
-{\r
-       int curpage =nIndex;\r
-\r
-       CFX_MapPtrToPtr* pMapPtrToPtr = new CFX_MapPtrToPtr;\r
-       pMapPtrToPtr->InitHashTable(1001);\r
-\r
-       for(int i=0; i<nPageNum->GetSize(); i++)\r
-       {\r
-               \r
-               CPDF_Dictionary* pCurPageDict = pDestPDFDoc->CreateNewPage(curpage);\r
-               CPDF_Dictionary* pSrcPageDict = pSrcPDFDoc->GetPage(nPageNum->GetAt(i)-1);\r
-               if(!pSrcPageDict || !pCurPageDict)\r
-               {\r
-                       delete pMapPtrToPtr;\r
-                       return FALSE;\r
-               }\r
-               \r
-               // Clone the page dictionary///////////\r
-               FX_POSITION     SrcPos = pSrcPageDict->GetStartPos();\r
-               while (SrcPos)\r
-               {\r
-                       CFX_ByteString cbSrcKeyStr;\r
-                       CPDF_Object* pObj = pSrcPageDict->GetNextElement(SrcPos, cbSrcKeyStr);\r
-                       if(cbSrcKeyStr.Compare(("Type")) && cbSrcKeyStr.Compare(("Parent")))\r
-                       {\r
-                               if(pCurPageDict->KeyExist(cbSrcKeyStr))\r
-                                       pCurPageDict->RemoveAt(cbSrcKeyStr);\r
-                               pCurPageDict->SetAt(cbSrcKeyStr, pObj->Clone());\r
-                       }\r
-               }\r
-               \r
-               //inheritable item///////////////////////\r
-               CPDF_Object* pInheritable = NULL;\r
-               //1     MediaBox  //required\r
-               if(!pCurPageDict->KeyExist("MediaBox"))\r
-               {\r
-                       \r
-                       pInheritable = PageDictGetInheritableTag(pSrcPageDict, "MediaBox");\r
-                       if(!pInheritable) \r
-                       {\r
-                               //Search the "CropBox" from source page dictionary, if not exists,we take the letter size.\r
-                               pInheritable = PageDictGetInheritableTag(pSrcPageDict, "CropBox");\r
-                               if(pInheritable)\r
-                                       pCurPageDict->SetAt("MediaBox", pInheritable->Clone());\r
-                               else\r
-                               {\r
-                                       //Make the default size to be letter size (8.5'x11')\r
-                                       CPDF_Array* pArray = new CPDF_Array;\r
-                                       pArray->AddNumber(0);\r
-                                       pArray->AddNumber(0);\r
-                                       pArray->AddNumber(612);\r
-                                       pArray->AddNumber(792);\r
-                                       pCurPageDict->SetAt("MediaBox", pArray);\r
-                               }\r
-                       }\r
-                       else\r
-                               pCurPageDict->SetAt("MediaBox", pInheritable->Clone());\r
-               }\r
-               //2 Resources //required\r
-               if(!pCurPageDict->KeyExist("Resources"))\r
-               {\r
-                       pInheritable = PageDictGetInheritableTag(pSrcPageDict, "Resources");\r
-                       if(!pInheritable) \r
-                       {\r
-                               delete pMapPtrToPtr;\r
-                               return FALSE;\r
-                       }\r
-                       pCurPageDict->SetAt("Resources", pInheritable->Clone());\r
-               }\r
-               //3 CropBox  //Optional\r
-               if(!pCurPageDict->KeyExist("CropBox"))\r
-               {\r
-                       pInheritable = PageDictGetInheritableTag(pSrcPageDict, "CropBox");\r
-                       if(pInheritable) \r
-                               pCurPageDict->SetAt("CropBox", pInheritable->Clone());\r
-               }\r
-               //4 Rotate  //Optional\r
-               if(!pCurPageDict->KeyExist("Rotate"))\r
-               {\r
-                       pInheritable = PageDictGetInheritableTag(pSrcPageDict, "Rotate");\r
-                       if(pInheritable) \r
-                               pCurPageDict->SetAt("Rotate", pInheritable->Clone());\r
-               }\r
-\r
-               /////////////////////////////////////////////\r
-               //Update the reference\r
-               FX_DWORD dwOldPageObj = pSrcPageDict->GetObjNum();\r
-               FX_DWORD dwNewPageObj = pCurPageDict->GetObjNum();\r
-               \r
-               pMapPtrToPtr->SetAt((FX_LPVOID)(FX_UINTPTR)dwOldPageObj, (FX_LPVOID)(FX_UINTPTR)dwNewPageObj);\r
-\r
-               this->UpdateReference(pCurPageDict, pDestPDFDoc, pMapPtrToPtr);\r
-               curpage++;\r
-       }\r
-\r
-       delete pMapPtrToPtr;\r
-       return TRUE;\r
-}\r
-\r
-CPDF_Object* CPDF_PageOrganizer::PageDictGetInheritableTag(CPDF_Dictionary *pDict, CFX_ByteString nSrctag)\r
-{\r
-       if(!pDict || !pDict->KeyExist("Type") || nSrctag.IsEmpty())     \r
-               return NULL;\r
-\r
-       CPDF_Object* pType = pDict->GetElement("Type")->GetDirect();\r
-       if(!pType || pType->GetType() != PDFOBJ_NAME)   return NULL;\r
-\r
-       if(pType->GetString().Compare("Page"))  return NULL;\r
-\r
-       if(!pDict->KeyExist("Parent"))  return NULL;\r
-       CPDF_Object* pParent = pDict->GetElement("Parent")->GetDirect();\r
-       if(!pParent || pParent->GetType() != PDFOBJ_DICTIONARY) return NULL;\r
-       \r
-       CPDF_Dictionary* pp = (CPDF_Dictionary*)pParent;\r
-       \r
-       if(pDict->KeyExist((const char*)nSrctag))       \r
-               return pDict->GetElement((const char*)nSrctag);\r
-       while (pp)\r
-       {\r
-               if(pp->KeyExist((const char*)nSrctag))  \r
-                       return pp->GetElement((const char*)nSrctag);\r
-               else if(pp->KeyExist("Parent"))\r
-                       pp = (CPDF_Dictionary*)pp->GetElement("Parent")->GetDirect();\r
-               else break;\r
-       }\r
-       \r
-       return NULL;\r
-}\r
-\r
-FX_BOOL CPDF_PageOrganizer::UpdateReference(CPDF_Object *pObj, CPDF_Document *pDoc, \r
-                                                                                CFX_MapPtrToPtr* pMapPtrToPtr)\r
-{\r
-       switch (pObj->GetType())\r
-       {\r
-       case PDFOBJ_REFERENCE:\r
-               {\r
-                       CPDF_Reference* pReference = (CPDF_Reference*)pObj;\r
-                       int newobjnum = GetNewObjId(pDoc, pMapPtrToPtr, pReference);\r
-                       if (newobjnum == 0) return FALSE;\r
-                       pReference->SetRef(pDoc, newobjnum);//, 0);\r
-                       break;\r
-               }\r
-       case PDFOBJ_DICTIONARY:\r
-               {\r
-                       CPDF_Dictionary* pDict = (CPDF_Dictionary*)pObj;\r
-                       \r
-                       FX_POSITION pos = pDict->GetStartPos();\r
-                       while(pos)\r
-                       {\r
-                               CFX_ByteString key("");\r
-                               CPDF_Object* pNextObj = pDict->GetNextElement(pos, key);\r
-                               if (!FXSYS_strcmp(key, "Parent") || !FXSYS_strcmp(key, "Prev") || !FXSYS_strcmp(key, "First"))\r
-                                       continue;\r
-                               if(pNextObj)\r
-                               {\r
-                                       if(!UpdateReference(pNextObj, pDoc, pMapPtrToPtr))\r
-                                               pDict->RemoveAt(key);\r
-                               }\r
-                               else\r
-                                       return FALSE;\r
-                       }\r
-                       break;\r
-               }\r
-       case    PDFOBJ_ARRAY:\r
-               {\r
-                       CPDF_Array* pArray = (CPDF_Array*)pObj;\r
-                       FX_DWORD count = pArray->GetCount();\r
-                       for(FX_DWORD i = 0; i < count; i ++)\r
-                       {\r
-                               CPDF_Object* pNextObj = pArray->GetElement(i);\r
-                               if(pNextObj)\r
-                               {\r
-                                       if(!UpdateReference(pNextObj, pDoc, pMapPtrToPtr))\r
-                                               return FALSE;\r
-                               }\r
-                               else\r
-                                       return FALSE;\r
-                       }\r
-                       break;\r
-               }\r
-       case    PDFOBJ_STREAM:\r
-               {\r
-                       CPDF_Stream* pStream = (CPDF_Stream*)pObj;\r
-                       CPDF_Dictionary* pDict = pStream->GetDict();\r
-                       if(pDict)\r
-                       {\r
-                               if(!UpdateReference(pDict, pDoc, pMapPtrToPtr))\r
-                                       return FALSE;\r
-                       }\r
-                       else\r
-                               return FALSE;\r
-                       break;\r
-               }\r
-       default:        break;\r
-       }\r
-\r
-       return TRUE;\r
-}\r
-\r
-int    CPDF_PageOrganizer::GetNewObjId(CPDF_Document *pDoc, CFX_MapPtrToPtr* pMapPtrToPtr,\r
-                                                                       CPDF_Reference *pRef)\r
-{\r
-       size_t dwObjnum = 0;\r
-       if(!pRef)\r
-               return 0;\r
-       dwObjnum = pRef->GetRefObjNum();\r
-       \r
-       size_t dwNewObjNum = 0;\r
-       \r
-       pMapPtrToPtr->Lookup((FX_LPVOID)dwObjnum, (FX_LPVOID&)dwNewObjNum);\r
-       if(dwNewObjNum)\r
-       {\r
-               return (int)dwNewObjNum;\r
-       }\r
-       else\r
-       {\r
-               CPDF_Object* pClone  = pRef->GetDirect()->Clone();\r
-               if(!pClone)                     return 0;\r
-               \r
-               if(pClone->GetType() == PDFOBJ_DICTIONARY)\r
-               {\r
-                       CPDF_Dictionary* pDictClone = (CPDF_Dictionary*)pClone;\r
-                       if(pDictClone->KeyExist("Type"))\r
-                       {\r
-                               CFX_ByteString strType = pDictClone->GetString("Type");\r
-                               if(!FXSYS_stricmp(strType, "Pages"))\r
-                               {\r
-                                       pDictClone->Release();\r
-                                       return 4;\r
-                               }\r
-                               else if(!FXSYS_stricmp(strType, "Page"))\r
-                               {\r
-                                       pDictClone->Release();\r
-                                       return  0;\r
-                               }\r
-                       }\r
-               }\r
-               dwNewObjNum = pDoc->AddIndirectObject(pClone);//, onum, gnum);\r
-               pMapPtrToPtr->SetAt((FX_LPVOID)dwObjnum, (FX_LPVOID)dwNewObjNum);\r
-               \r
-               if(!UpdateReference(pClone, pDoc, pMapPtrToPtr))\r
-               {\r
-                       pClone->Release();\r
-                       return 0;\r
-               }\r
-               return (int)dwNewObjNum;\r
-       }\r
-       return 0;\r
-}\r
-\r
-FPDF_BOOL ParserPageRangeString(CFX_ByteString rangstring, CFX_WordArray* pageArray,int nCount)\r
-{\r
-\r
-       if(rangstring.GetLength() != 0)\r
-       {\r
-               rangstring.Remove(' ');\r
-               int nLength = rangstring.GetLength();\r
-               CFX_ByteString cbCompareString("0123456789-,");\r
-               for(int i=0; i<nLength; i++)\r
-               {\r
-                       if(cbCompareString.Find(rangstring[i]) == -1)\r
-                               return FALSE;\r
-               }\r
-               CFX_ByteString cbMidRange;\r
-               int nStringFrom = 0;\r
-               int nStringTo=0;\r
-               while(nStringTo < nLength)\r
-               {\r
-                       nStringTo = rangstring.Find(',',nStringFrom);\r
-                       if(nStringTo == -1)\r
-                       {\r
-                               nStringTo = nLength;\r
-                       }\r
-                       cbMidRange = rangstring.Mid(nStringFrom,nStringTo-nStringFrom);\r
-                       \r
-                       int nMid = cbMidRange.Find('-');\r
-                       if(nMid == -1)\r
-                       {\r
-                               long lPageNum = atol(cbMidRange);\r
-                               if(lPageNum <= 0 || lPageNum > nCount)\r
-                                       return FALSE;\r
-                               pageArray->Add((FX_WORD)lPageNum);\r
-                       }\r
-                       else\r
-                       {\r
-                               int nStartPageNum = atol(cbMidRange.Mid(0,nMid));\r
-                               if (nStartPageNum ==0)\r
-                               {\r
-                                       return FALSE;\r
-                               }\r
-\r
-\r
-                               nMid = nMid+1;\r
-                               int nEnd = cbMidRange.GetLength()-nMid;\r
-\r
-                               if(nEnd ==0)return FALSE;\r
-                               \r
-                               //                              int nEndPageNum = (nEnd == 0)?nCount:atol(cbMidRange.Mid(nMid,nEnd));\r
-                               int nEndPageNum = atol(cbMidRange.Mid(nMid,nEnd));\r
-                               \r
-                               if(nStartPageNum < 0 ||nStartPageNum >nEndPageNum|| nEndPageNum > nCount)\r
-                               {\r
-                                       return FALSE;\r
-                               }\r
-                               else\r
-                               {\r
-                                       for(int nIndex=nStartPageNum; nIndex <= nEndPageNum; nIndex ++)\r
-                                               pageArray->Add(nIndex);\r
-                               }\r
-                       }\r
-                       nStringFrom = nStringTo +1;\r
-               }\r
-       }\r
-       return TRUE;\r
-}\r
-\r
-DLLEXPORT FPDF_BOOL STDCALL FPDF_ImportPages(FPDF_DOCUMENT dest_doc,FPDF_DOCUMENT src_doc, \r
-                                                                                        FPDF_BYTESTRING pagerange, int index)\r
-{\r
-       if(dest_doc == NULL || src_doc == NULL )\r
-               return FALSE;\r
-       CFX_WordArray pageArray;\r
-       CPDF_Document* pSrcDoc = (CPDF_Document*)src_doc;\r
-       int nCount = pSrcDoc->GetPageCount();\r
-       if(pagerange)\r
-       {\r
-               if(ParserPageRangeString(pagerange,&pageArray,nCount) == FALSE)\r
-                       return FALSE;\r
-       }\r
-       else\r
-       {\r
-               for(int i=1; i<=nCount; i++)\r
-               {\r
-                       pageArray.Add(i);\r
-               }\r
-       }\r
-       \r
-       CPDF_Document* pDestDoc = (CPDF_Document*)dest_doc;\r
-       CPDF_PageOrganizer pageOrg;\r
-\r
-       pageOrg.PDFDocInit(pDestDoc,pSrcDoc);\r
-\r
-       if(pageOrg.ExportPage(pSrcDoc,&pageArray,pDestDoc,index))\r
-               return TRUE;\r
-       return FALSE;\r
-}\r
-\r
-DLLEXPORT FPDF_BOOL STDCALL FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc)\r
-{\r
-       if(src_doc == NULL || dest_doc == NULL)\r
-               return false;\r
-       CPDF_Document* pSrcDoc = (CPDF_Document*)src_doc;\r
-       CPDF_Dictionary* pSrcDict = pSrcDoc->GetRoot();\r
-       pSrcDict = pSrcDict->GetDict(FX_BSTRC("ViewerPreferences"));;\r
-       if(!pSrcDict)\r
-               return FALSE;\r
-       CPDF_Document* pDstDoc = (CPDF_Document*)dest_doc;\r
-       CPDF_Dictionary* pDstDict = pDstDoc->GetRoot();\r
-       if(!pDstDict)\r
-               return FALSE;\r
-       pDstDict->SetAt(FX_BSTRC("ViewerPreferences"), pSrcDict->Clone(TRUE));\r
-       return TRUE;\r
-}\r
-\r
+// 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 "../../public/fpdf_ppo.h"
+#include "../include/fsdk_define.h"
+
+class CPDF_PageOrganizer
+{
+public:
+       CPDF_PageOrganizer();
+       ~CPDF_PageOrganizer();
+
+public:
+       FX_BOOL                         PDFDocInit(CPDF_Document *pDestPDFDoc, CPDF_Document *pSrcPDFDoc);
+       FX_BOOL                         ExportPage(CPDF_Document *pSrcPDFDoc, CFX_WordArray* nPageNum, CPDF_Document *pDestPDFDoc, int nIndex);
+       CPDF_Object*            PageDictGetInheritableTag(CPDF_Dictionary *pDict, CFX_ByteString nSrctag);
+       FX_BOOL                         UpdateReference(CPDF_Object *pObj, CPDF_Document *pDoc, CFX_MapPtrToPtr* pMapPtrToPtr);
+       int                                     GetNewObjId(CPDF_Document *pDoc, CFX_MapPtrToPtr* pMapPtrToPtr, CPDF_Reference *pRef);
+
+};
+
+
+CPDF_PageOrganizer::CPDF_PageOrganizer()
+{
+
+}
+
+CPDF_PageOrganizer::~CPDF_PageOrganizer()
+{
+
+}
+
+FX_BOOL CPDF_PageOrganizer::PDFDocInit(CPDF_Document *pDestPDFDoc, CPDF_Document *pSrcPDFDoc)
+{
+       if(!pDestPDFDoc || !pSrcPDFDoc)
+               return false;
+
+       CPDF_Dictionary* pNewRoot = pDestPDFDoc->GetRoot();
+       if(!pNewRoot)   return FALSE;
+
+       //Set the document information////////////////////////////////////////////
+
+       CPDF_Dictionary* DInfoDict = pDestPDFDoc->GetInfo();
+
+       if(!DInfoDict)
+               return FALSE;
+
+       CFX_ByteString producerstr;
+       producerstr.Format("PDFium");
+       DInfoDict->SetAt("Producer", new CPDF_String(producerstr));
+
+       //Set type////////////////////////////////////////////////////////////////
+       CFX_ByteString cbRootType = pNewRoot->GetString("Type","");
+       if( cbRootType.Equal("") )
+       {
+               pNewRoot->SetAt("Type", new CPDF_Name("Catalog"));
+       }
+
+       CPDF_Dictionary* pNewPages = (CPDF_Dictionary*)(pNewRoot->GetElement("Pages")? pNewRoot->GetElement("Pages")->GetDirect() : NULL);
+       if(!pNewPages)
+       {
+               pNewPages = new CPDF_Dictionary;
+               FX_DWORD NewPagesON = pDestPDFDoc->AddIndirectObject(pNewPages);
+               pNewRoot->SetAt("Pages", new CPDF_Reference(pDestPDFDoc, NewPagesON));
+       }
+
+       CFX_ByteString cbPageType = pNewPages->GetString("Type","");
+       if(cbPageType.Equal(""))
+       {
+               pNewPages->SetAt("Type", new CPDF_Name("Pages"));
+       }
+
+       CPDF_Array* pKeysArray = pNewPages->GetArray("Kids");
+       if(pKeysArray == NULL)
+       {
+               CPDF_Array* pNewKids = new CPDF_Array;
+               FX_DWORD Kidsobjnum = -1;
+               Kidsobjnum = pDestPDFDoc->AddIndirectObject(pNewKids);//, Kidsobjnum, Kidsgennum);
+
+               pNewPages->SetAt("Kids", new CPDF_Reference(pDestPDFDoc, Kidsobjnum));//, Kidsgennum));
+               pNewPages->SetAt("Count", new CPDF_Number(0));
+       }
+
+       return true;
+}
+
+FX_BOOL CPDF_PageOrganizer::ExportPage(CPDF_Document *pSrcPDFDoc, CFX_WordArray* nPageNum,
+                                                                                               CPDF_Document *pDestPDFDoc,int nIndex)
+{
+       int curpage =nIndex;
+
+       CFX_MapPtrToPtr* pMapPtrToPtr = new CFX_MapPtrToPtr;
+       pMapPtrToPtr->InitHashTable(1001);
+
+       for(int i=0; i<nPageNum->GetSize(); i++)
+       {
+
+               CPDF_Dictionary* pCurPageDict = pDestPDFDoc->CreateNewPage(curpage);
+               CPDF_Dictionary* pSrcPageDict = pSrcPDFDoc->GetPage(nPageNum->GetAt(i)-1);
+               if(!pSrcPageDict || !pCurPageDict)
+               {
+                       delete pMapPtrToPtr;
+                       return FALSE;
+               }
+
+               // Clone the page dictionary///////////
+               FX_POSITION     SrcPos = pSrcPageDict->GetStartPos();
+               while (SrcPos)
+               {
+                       CFX_ByteString cbSrcKeyStr;
+                       CPDF_Object* pObj = pSrcPageDict->GetNextElement(SrcPos, cbSrcKeyStr);
+                       if(cbSrcKeyStr.Compare(("Type")) && cbSrcKeyStr.Compare(("Parent")))
+                       {
+                               if(pCurPageDict->KeyExist(cbSrcKeyStr))
+                                       pCurPageDict->RemoveAt(cbSrcKeyStr);
+                               pCurPageDict->SetAt(cbSrcKeyStr, pObj->Clone());
+                       }
+               }
+
+               //inheritable item///////////////////////
+               CPDF_Object* pInheritable = NULL;
+               //1     MediaBox  //required
+               if(!pCurPageDict->KeyExist("MediaBox"))
+               {
+
+                       pInheritable = PageDictGetInheritableTag(pSrcPageDict, "MediaBox");
+                       if(!pInheritable)
+                       {
+                               //Search the "CropBox" from source page dictionary, if not exists,we take the letter size.
+                               pInheritable = PageDictGetInheritableTag(pSrcPageDict, "CropBox");
+                               if(pInheritable)
+                                       pCurPageDict->SetAt("MediaBox", pInheritable->Clone());
+                               else
+                               {
+                                       //Make the default size to be letter size (8.5'x11')
+                                       CPDF_Array* pArray = new CPDF_Array;
+                                       pArray->AddNumber(0);
+                                       pArray->AddNumber(0);
+                                       pArray->AddNumber(612);
+                                       pArray->AddNumber(792);
+                                       pCurPageDict->SetAt("MediaBox", pArray);
+                               }
+                       }
+                       else
+                               pCurPageDict->SetAt("MediaBox", pInheritable->Clone());
+               }
+               //2 Resources //required
+               if(!pCurPageDict->KeyExist("Resources"))
+               {
+                       pInheritable = PageDictGetInheritableTag(pSrcPageDict, "Resources");
+                       if(!pInheritable)
+                       {
+                               delete pMapPtrToPtr;
+                               return FALSE;
+                       }
+                       pCurPageDict->SetAt("Resources", pInheritable->Clone());
+               }
+               //3 CropBox  //Optional
+               if(!pCurPageDict->KeyExist("CropBox"))
+               {
+                       pInheritable = PageDictGetInheritableTag(pSrcPageDict, "CropBox");
+                       if(pInheritable)
+                               pCurPageDict->SetAt("CropBox", pInheritable->Clone());
+               }
+               //4 Rotate  //Optional
+               if(!pCurPageDict->KeyExist("Rotate"))
+               {
+                       pInheritable = PageDictGetInheritableTag(pSrcPageDict, "Rotate");
+                       if(pInheritable)
+                               pCurPageDict->SetAt("Rotate", pInheritable->Clone());
+               }
+
+               /////////////////////////////////////////////
+               //Update the reference
+               FX_DWORD dwOldPageObj = pSrcPageDict->GetObjNum();
+               FX_DWORD dwNewPageObj = pCurPageDict->GetObjNum();
+
+               pMapPtrToPtr->SetAt((void*)(uintptr_t)dwOldPageObj, (void*)(uintptr_t)dwNewPageObj);
+
+               UpdateReference(pCurPageDict, pDestPDFDoc, pMapPtrToPtr);
+               curpage++;
+       }
+
+       delete pMapPtrToPtr;
+       return TRUE;
+}
+
+CPDF_Object* CPDF_PageOrganizer::PageDictGetInheritableTag(CPDF_Dictionary *pDict, CFX_ByteString nSrctag)
+{
+       if(!pDict || !pDict->KeyExist("Type") || nSrctag.IsEmpty())
+               return NULL;
+
+       CPDF_Object* pType = pDict->GetElement("Type")->GetDirect();
+       if(!pType || pType->GetType() != PDFOBJ_NAME)   return NULL;
+
+       if(pType->GetString().Compare("Page"))  return NULL;
+
+       if(!pDict->KeyExist("Parent"))  return NULL;
+       CPDF_Object* pParent = pDict->GetElement("Parent")->GetDirect();
+       if(!pParent || pParent->GetType() != PDFOBJ_DICTIONARY) return NULL;
+
+       CPDF_Dictionary* pp = (CPDF_Dictionary*)pParent;
+
+       if(pDict->KeyExist((const char*)nSrctag))
+               return pDict->GetElement((const char*)nSrctag);
+       while (pp)
+       {
+               if(pp->KeyExist((const char*)nSrctag))
+                       return pp->GetElement((const char*)nSrctag);
+               else if (pp->KeyExist("Parent"))
+               {
+                       pp = (CPDF_Dictionary*)pp->GetElement("Parent")->GetDirect();
+                       if (pp->GetType() == PDFOBJ_NULL) break;
+               }
+               else break;
+       }
+
+       return NULL;
+}
+
+FX_BOOL CPDF_PageOrganizer::UpdateReference(CPDF_Object *pObj, CPDF_Document *pDoc,
+                                                                                CFX_MapPtrToPtr* pMapPtrToPtr)
+{
+       switch (pObj->GetType())
+       {
+       case PDFOBJ_REFERENCE:
+               {
+                       CPDF_Reference* pReference = (CPDF_Reference*)pObj;
+                       int newobjnum = GetNewObjId(pDoc, pMapPtrToPtr, pReference);
+                       if (newobjnum == 0) return FALSE;
+                       pReference->SetRef(pDoc, newobjnum);//, 0);
+                       break;
+               }
+       case PDFOBJ_DICTIONARY:
+               {
+                       CPDF_Dictionary* pDict = (CPDF_Dictionary*)pObj;
+
+                       FX_POSITION pos = pDict->GetStartPos();
+                       while(pos)
+                       {
+                               CFX_ByteString key("");
+                               CPDF_Object* pNextObj = pDict->GetNextElement(pos, key);
+                               if (!FXSYS_strcmp(key, "Parent") || !FXSYS_strcmp(key, "Prev") || !FXSYS_strcmp(key, "First"))
+                                       continue;
+                               if(pNextObj)
+                               {
+                                       if(!UpdateReference(pNextObj, pDoc, pMapPtrToPtr))
+                                               pDict->RemoveAt(key);
+                               }
+                               else
+                                       return FALSE;
+                       }
+                       break;
+               }
+       case    PDFOBJ_ARRAY:
+               {
+                       CPDF_Array* pArray = (CPDF_Array*)pObj;
+                       FX_DWORD count = pArray->GetCount();
+                       for(FX_DWORD i = 0; i < count; i ++)
+                       {
+                               CPDF_Object* pNextObj = pArray->GetElement(i);
+                               if(pNextObj)
+                               {
+                                       if(!UpdateReference(pNextObj, pDoc, pMapPtrToPtr))
+                                               return FALSE;
+                               }
+                               else
+                                       return FALSE;
+                       }
+                       break;
+               }
+       case    PDFOBJ_STREAM:
+               {
+                       CPDF_Stream* pStream = (CPDF_Stream*)pObj;
+                       CPDF_Dictionary* pDict = pStream->GetDict();
+                       if(pDict)
+                       {
+                               if(!UpdateReference(pDict, pDoc, pMapPtrToPtr))
+                                       return FALSE;
+                       }
+                       else
+                               return FALSE;
+                       break;
+               }
+       default:        break;
+       }
+
+       return TRUE;
+}
+
+int    CPDF_PageOrganizer::GetNewObjId(CPDF_Document *pDoc, CFX_MapPtrToPtr* pMapPtrToPtr,
+                                                                       CPDF_Reference *pRef)
+{
+       size_t dwObjnum = 0;
+       if(!pRef)
+               return 0;
+       dwObjnum = pRef->GetRefObjNum();
+
+       size_t dwNewObjNum = 0;
+
+       pMapPtrToPtr->Lookup((void*)dwObjnum, (void*&)dwNewObjNum);
+       if(dwNewObjNum)
+       {
+               return (int)dwNewObjNum;
+       }
+       else
+       {
+               CPDF_Object* pDirect = pRef->GetDirect();
+               if(!pDirect)
+               {
+                       return 0;
+               }
+
+               CPDF_Object* pClone = pDirect->Clone();
+               if(!pClone)
+               {
+                       return 0;
+               }
+
+               if(pClone->GetType() == PDFOBJ_DICTIONARY)
+               {
+                       CPDF_Dictionary* pDictClone = (CPDF_Dictionary*)pClone;
+                       if(pDictClone->KeyExist("Type"))
+                       {
+                               CFX_ByteString strType = pDictClone->GetString("Type");
+                               if(!FXSYS_stricmp(strType, "Pages"))
+                               {
+                                       pDictClone->Release();
+                                       return 4;
+                               }
+                               else if(!FXSYS_stricmp(strType, "Page"))
+                               {
+                                       pDictClone->Release();
+                                       return  0;
+                               }
+                       }
+               }
+               dwNewObjNum = pDoc->AddIndirectObject(pClone);//, onum, gnum);
+               pMapPtrToPtr->SetAt((void*)dwObjnum, (void*)dwNewObjNum);
+
+               if(!UpdateReference(pClone, pDoc, pMapPtrToPtr))
+               {
+                       pClone->Release();
+                       return 0;
+               }
+               return (int)dwNewObjNum;
+       }
+       return 0;
+}
+
+FPDF_BOOL ParserPageRangeString(CFX_ByteString rangstring, CFX_WordArray* pageArray,int nCount)
+{
+
+       if(rangstring.GetLength() != 0)
+       {
+               rangstring.Remove(' ');
+               int nLength = rangstring.GetLength();
+               CFX_ByteString cbCompareString("0123456789-,");
+               for(int i=0; i<nLength; i++)
+               {
+                       if(cbCompareString.Find(rangstring[i]) == -1)
+                               return FALSE;
+               }
+               CFX_ByteString cbMidRange;
+               int nStringFrom = 0;
+               int nStringTo=0;
+               while(nStringTo < nLength)
+               {
+                       nStringTo = rangstring.Find(',',nStringFrom);
+                       if(nStringTo == -1)
+                       {
+                               nStringTo = nLength;
+                       }
+                       cbMidRange = rangstring.Mid(nStringFrom,nStringTo-nStringFrom);
+
+                       int nMid = cbMidRange.Find('-');
+                       if(nMid == -1)
+                       {
+                               long lPageNum = atol(cbMidRange);
+                               if(lPageNum <= 0 || lPageNum > nCount)
+                                       return FALSE;
+                               pageArray->Add((FX_WORD)lPageNum);
+                       }
+                       else
+                       {
+                               int nStartPageNum = atol(cbMidRange.Mid(0,nMid));
+                               if (nStartPageNum ==0)
+                               {
+                                       return FALSE;
+                               }
+
+
+                               nMid = nMid+1;
+                               int nEnd = cbMidRange.GetLength()-nMid;
+
+                               if(nEnd ==0)return FALSE;
+
+                               //                              int nEndPageNum = (nEnd == 0)?nCount:atol(cbMidRange.Mid(nMid,nEnd));
+                               int nEndPageNum = atol(cbMidRange.Mid(nMid,nEnd));
+
+                               if(nStartPageNum < 0 ||nStartPageNum >nEndPageNum|| nEndPageNum > nCount)
+                               {
+                                       return FALSE;
+                               }
+                               else
+                               {
+                                       for(int nIndex=nStartPageNum; nIndex <= nEndPageNum; nIndex ++)
+                                               pageArray->Add(nIndex);
+                               }
+                       }
+                       nStringFrom = nStringTo +1;
+               }
+       }
+       return TRUE;
+}
+
+DLLEXPORT FPDF_BOOL STDCALL FPDF_ImportPages(FPDF_DOCUMENT dest_doc,FPDF_DOCUMENT src_doc,
+                                                                                        FPDF_BYTESTRING pagerange, int index)
+{
+       if(dest_doc == NULL || src_doc == NULL )
+               return FALSE;
+       CFX_WordArray pageArray;
+       CPDF_Document* pSrcDoc = (CPDF_Document*)src_doc;
+       int nCount = pSrcDoc->GetPageCount();
+       if(pagerange)
+       {
+               if(ParserPageRangeString(pagerange,&pageArray,nCount) == FALSE)
+                       return FALSE;
+       }
+       else
+       {
+               for(int i=1; i<=nCount; i++)
+               {
+                       pageArray.Add(i);
+               }
+       }
+
+       CPDF_Document* pDestDoc = (CPDF_Document*)dest_doc;
+       CPDF_PageOrganizer pageOrg;
+
+       pageOrg.PDFDocInit(pDestDoc,pSrcDoc);
+
+       if(pageOrg.ExportPage(pSrcDoc,&pageArray,pDestDoc,index))
+               return TRUE;
+       return FALSE;
+}
+
+DLLEXPORT FPDF_BOOL STDCALL FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc)
+{
+       if(src_doc == NULL || dest_doc == NULL)
+               return false;
+       CPDF_Document* pSrcDoc = (CPDF_Document*)src_doc;
+       CPDF_Dictionary* pSrcDict = pSrcDoc->GetRoot();
+       pSrcDict = pSrcDict->GetDict(FX_BSTRC("ViewerPreferences"));;
+       if(!pSrcDict)
+               return FALSE;
+       CPDF_Document* pDstDoc = (CPDF_Document*)dest_doc;
+       CPDF_Dictionary* pDstDict = pDstDoc->GetRoot();
+       if(!pDstDict)
+               return FALSE;
+       pDstDict->SetAt(FX_BSTRC("ViewerPreferences"), pSrcDict->Clone(TRUE));
+       return TRUE;
+}
+