Reduce usage of operator LPCWSTR from CFX_WideString().
[pdfium.git] / core / src / fpdfapi / fpdf_parser / fpdf_parser_document.cpp
index 068a606..c3e35d8 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/fpdfapi/fpdf_parser.h"\r
-#include "../../../include/fpdfapi/fpdf_module.h"\r
-extern FX_LPVOID PDFPreviewInitCache(CPDF_Document* pDoc);\r
-extern void PDFPreviewClearCache(FX_LPVOID pCache);\r
-CPDF_Document::CPDF_Document(IPDF_DocParser* pParser) : CPDF_IndirectObjects(pParser)\r
-{\r
-    ASSERT(pParser != NULL);\r
-    m_pRootDict = NULL;\r
-    m_pInfoDict = NULL;\r
-    m_bLinearized = FALSE;\r
-    m_dwFirstPageNo = 0;\r
-    m_dwFirstPageObjNum = 0;\r
-    m_pDocPage = CPDF_ModuleMgr::Get()->GetPageModule()->CreateDocData(this);\r
-    m_pDocRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreateDocData(this);\r
-}\r
-CPDF_DocPageData* CPDF_Document::GetValidatePageData()\r
-{\r
-    if (m_pDocPage) {\r
-        return m_pDocPage;\r
-    }\r
-    m_pDocPage = CPDF_ModuleMgr::Get()->GetPageModule()->CreateDocData(this);\r
-    return m_pDocPage;\r
-}\r
-CPDF_DocRenderData* CPDF_Document::GetValidateRenderData()\r
-{\r
-    if (m_pDocRender) {\r
-        return m_pDocRender;\r
-    }\r
-    m_pDocRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreateDocData(this);\r
-    return m_pDocRender;\r
-}\r
-void CPDF_Document::LoadDoc()\r
-{\r
-    m_LastObjNum = m_pParser->GetLastObjNum();\r
-    CPDF_Object* pRootObj = GetIndirectObject(m_pParser->GetRootObjNum());\r
-    if (pRootObj == NULL) {\r
-        return;\r
-    }\r
-    m_pRootDict = pRootObj->GetDict();\r
-    if (m_pRootDict == NULL) {\r
-        return;\r
-    }\r
-    CPDF_Object* pInfoObj = GetIndirectObject(m_pParser->GetInfoObjNum());\r
-    if (pInfoObj) {\r
-        m_pInfoDict = pInfoObj->GetDict();\r
-    }\r
-    CPDF_Array* pIDArray = m_pParser->GetIDArray();\r
-    if (pIDArray) {\r
-        m_ID1 = pIDArray->GetString(0);\r
-        m_ID2 = pIDArray->GetString(1);\r
-    }\r
-    m_PageList.SetSize(_GetPageCount());\r
-}\r
-void CPDF_Document::LoadAsynDoc(CPDF_Dictionary *pLinearized)\r
-{\r
-    m_bLinearized = TRUE;\r
-    m_LastObjNum = m_pParser->GetLastObjNum();\r
-    m_pRootDict = GetIndirectObject(m_pParser->GetRootObjNum())->GetDict();\r
-    if (m_pRootDict == NULL) {\r
-        return;\r
-    }\r
-    m_pInfoDict = GetIndirectObject(m_pParser->GetInfoObjNum())->GetDict();\r
-    CPDF_Array* pIDArray = m_pParser->GetIDArray();\r
-    if (pIDArray) {\r
-        m_ID1 = pIDArray->GetString(0);\r
-        m_ID2 = pIDArray->GetString(1);\r
-    }\r
-    FX_DWORD dwPageCount = 0;\r
-    CPDF_Object *pCount = pLinearized->GetElement(FX_BSTRC("N"));\r
-    if (pCount && pCount->GetType() == PDFOBJ_NUMBER) {\r
-        dwPageCount = pCount->GetInteger();\r
-    }\r
-    m_PageList.SetSize(dwPageCount);\r
-    CPDF_Object *pNo = pLinearized->GetElement(FX_BSTRC("P"));\r
-    if (pNo && pNo->GetType() == PDFOBJ_NUMBER) {\r
-        m_dwFirstPageNo = pNo->GetInteger();\r
-    }\r
-    CPDF_Object *pObjNum = pLinearized->GetElement(FX_BSTRC("O"));\r
-    if (pObjNum && pObjNum->GetType() == PDFOBJ_NUMBER) {\r
-        m_dwFirstPageObjNum = pObjNum->GetInteger();\r
-    }\r
-}\r
-void CPDF_Document::LoadPages()\r
-{\r
-    m_PageList.SetSize(_GetPageCount());\r
-}\r
-extern void FPDF_TTFaceMapper_ReleaseDoc(CPDF_Document*);\r
-CPDF_Document::~CPDF_Document()\r
-{\r
-    if (m_pDocRender) {\r
-        CPDF_ModuleMgr::Get()->GetRenderModule()->DestroyDocData(m_pDocRender);\r
-    }\r
-    if (m_pDocPage) {\r
-        CPDF_ModuleMgr::Get()->GetPageModule()->ReleaseDoc(this);\r
-        CPDF_ModuleMgr::Get()->GetPageModule()->ClearStockFont(this);\r
-    }\r
-}\r
-#define                FX_MAX_PAGE_LEVEL                       1024\r
-CPDF_Dictionary* CPDF_Document::_FindPDFPage(CPDF_Dictionary* pPages, int iPage, int nPagesToGo, int level)\r
-{\r
-    CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids"));\r
-    if (pKidList == NULL) {\r
-        if (nPagesToGo == 0) {\r
-            return pPages;\r
-        }\r
-        return NULL;\r
-    }\r
-    if (level >= FX_MAX_PAGE_LEVEL) {\r
-        return NULL;\r
-    }\r
-    int nKids = pKidList->GetCount();\r
-    for (int i = 0; i < nKids; i ++) {\r
-        CPDF_Dictionary* pKid = pKidList->GetDict(i);\r
-        if (pKid == NULL) {\r
-            nPagesToGo --;\r
-            continue;\r
-        }\r
-        if (pKid == pPages) {\r
-            continue;\r
-        }\r
-        if (!pKid->KeyExist(FX_BSTRC("Kids"))) {\r
-            if (nPagesToGo == 0) {\r
-                return pKid;\r
-            }\r
-            m_PageList.SetAt(iPage - nPagesToGo, pKid->GetObjNum());\r
-            nPagesToGo --;\r
-        } else {\r
-            int nPages = pKid->GetInteger(FX_BSTRC("Count"));\r
-            if (nPagesToGo < nPages) {\r
-                return _FindPDFPage(pKid, iPage, nPagesToGo, level + 1);\r
-            }\r
-            nPagesToGo -= nPages;\r
-        }\r
-    }\r
-    return NULL;\r
-}\r
-CPDF_Dictionary* CPDF_Document::GetPage(int iPage)\r
-{\r
-    if (iPage < 0 || iPage >= m_PageList.GetSize()) {\r
-        return NULL;\r
-    }\r
-    if (m_bLinearized && (iPage == (int)m_dwFirstPageNo)) {\r
-        CPDF_Object* pObj = GetIndirectObject(m_dwFirstPageObjNum);\r
-        if (pObj && pObj->GetType() == PDFOBJ_DICTIONARY) {\r
-            return (CPDF_Dictionary*)pObj;\r
-        }\r
-    }\r
-    int objnum = m_PageList.GetAt(iPage);\r
-    if (objnum) {\r
-        CPDF_Object* pObj = GetIndirectObject(objnum);\r
-        ASSERT(pObj->GetType() == PDFOBJ_DICTIONARY);\r
-        return (CPDF_Dictionary*)pObj;\r
-    }\r
-    CPDF_Dictionary* pRoot = GetRoot();\r
-    if (pRoot == NULL) {\r
-        return NULL;\r
-    }\r
-    CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages"));\r
-    if (pPages == NULL) {\r
-        return NULL;\r
-    }\r
-    CPDF_Dictionary* pPage = _FindPDFPage(pPages, iPage, iPage, 0);\r
-    if (pPage == NULL) {\r
-        return NULL;\r
-    }\r
-    m_PageList.SetAt(iPage, pPage->GetObjNum());\r
-    return pPage;\r
-}\r
-int CPDF_Document::_FindPageIndex(CPDF_Dictionary* pNode, FX_DWORD& skip_count, FX_DWORD objnum, int& index, int level)\r
-{\r
-    if (pNode->KeyExist(FX_BSTRC("Kids"))) {\r
-        CPDF_Array* pKidList = pNode->GetArray(FX_BSTRC("Kids"));\r
-        if (pKidList == NULL) {\r
-            return -1;\r
-        }\r
-        if (level >= FX_MAX_PAGE_LEVEL) {\r
-            return -1;\r
-        }\r
-        FX_DWORD count = pNode->GetInteger(FX_BSTRC("Count"));\r
-        if (count <= skip_count) {\r
-            skip_count -= count;\r
-            index += count;\r
-            return -1;\r
-        }\r
-        if (count && count == pKidList->GetCount()) {\r
-            for (FX_DWORD i = 0; i < count; i ++) {\r
-                CPDF_Reference* pKid = (CPDF_Reference*)pKidList->GetElement(i);\r
-                if (pKid && pKid->GetType() == PDFOBJ_REFERENCE) {\r
-                    if (pKid->GetRefObjNum() == objnum) {\r
-                        m_PageList.SetAt(index + i, objnum);\r
-                        return index + i;\r
-                    }\r
-                }\r
-            }\r
-        }\r
-        for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) {\r
-            CPDF_Dictionary* pKid = pKidList->GetDict(i);\r
-            if (pKid == NULL) {\r
-                continue;\r
-            }\r
-            if (pKid == pNode) {\r
-                continue;\r
-            }\r
-            int found_index = _FindPageIndex(pKid, skip_count, objnum, index, level + 1);\r
-            if (found_index >= 0) {\r
-                return found_index;\r
-            }\r
-        }\r
-    } else {\r
-        if (objnum == pNode->GetObjNum()) {\r
-            return index;\r
-        }\r
-        if (skip_count) {\r
-            skip_count--;\r
-        }\r
-        index ++;\r
-    }\r
-    return -1;\r
-}\r
-int CPDF_Document::GetPageIndex(FX_DWORD objnum)\r
-{\r
-    FX_DWORD nPages = m_PageList.GetSize();\r
-    FX_DWORD skip_count = 0;\r
-    FX_BOOL bSkipped = FALSE;\r
-    for (FX_DWORD i = 0; i < nPages; i ++) {\r
-        FX_DWORD objnum1 = m_PageList.GetAt(i);\r
-        if (objnum1 == objnum) {\r
-            return i;\r
-        }\r
-        if (!bSkipped && objnum1 == 0) {\r
-            skip_count = i;\r
-            bSkipped = TRUE;\r
-        }\r
-    }\r
-    CPDF_Dictionary* pRoot = GetRoot();\r
-    if (pRoot == NULL) {\r
-        return -1;\r
-    }\r
-    CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages"));\r
-    if (pPages == NULL) {\r
-        return -1;\r
-    }\r
-    int index = 0;\r
-    return _FindPageIndex(pPages, skip_count, objnum, index);\r
-}\r
-int CPDF_Document::GetPageCount() const\r
-{\r
-    return m_PageList.GetSize();\r
-}\r
-static int _CountPages(CPDF_Dictionary* pPages, int level)\r
-{\r
-    if (level > 128) {\r
-        return 0;\r
-    }\r
-    int count = pPages->GetInteger(FX_BSTRC("Count"));\r
-    if (count > 0 && count < FPDF_PAGE_MAX_NUM) {\r
-        return count;\r
-    }\r
-    CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids"));\r
-    if (pKidList == NULL) {\r
-        return 0;\r
-    }\r
-    count = 0;\r
-    for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) {\r
-        CPDF_Dictionary* pKid = pKidList->GetDict(i);\r
-        if (pKid == NULL) {\r
-            continue;\r
-        }\r
-        if (!pKid->KeyExist(FX_BSTRC("Kids"))) {\r
-            count ++;\r
-        } else {\r
-            count += _CountPages(pKid, level + 1);\r
-        }\r
-    }\r
-    pPages->SetAtInteger(FX_BSTRC("Count"), count);\r
-    return count;\r
-}\r
-int CPDF_Document::_GetPageCount() const\r
-{\r
-    CPDF_Dictionary* pRoot = GetRoot();\r
-    if (pRoot == NULL) {\r
-        return 0;\r
-    }\r
-    CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages"));\r
-    if (pPages == NULL) {\r
-        return 0;\r
-    }\r
-    if (!pPages->KeyExist(FX_BSTRC("Kids"))) {\r
-        return 1;\r
-    }\r
-    return _CountPages(pPages, 0);\r
-}\r
-static FX_BOOL _EnumPages(CPDF_Dictionary* pPages, IPDF_EnumPageHandler* pHandler)\r
-{\r
-    CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids"));\r
-    if (pKidList == NULL) {\r
-        return pHandler->EnumPage(pPages);\r
-    }\r
-    for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) {\r
-        CPDF_Dictionary* pKid = pKidList->GetDict(i);\r
-        if (pKid == NULL) {\r
-            continue;\r
-        }\r
-        if (!pKid->KeyExist(FX_BSTRC("Kids"))) {\r
-            if (!pHandler->EnumPage(pKid)) {\r
-                return FALSE;\r
-            }\r
-        } else {\r
-            return _EnumPages(pKid, pHandler);\r
-        }\r
-    }\r
-    return TRUE;\r
-}\r
-void CPDF_Document::EnumPages(IPDF_EnumPageHandler* pHandler)\r
-{\r
-    CPDF_Dictionary* pRoot = GetRoot();\r
-    if (pRoot == NULL) {\r
-        return;\r
-    }\r
-    CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages"));\r
-    if (pPages == NULL) {\r
-        return;\r
-    }\r
-    _EnumPages(pPages, pHandler);\r
-}\r
-FX_BOOL CPDF_Document::IsContentUsedElsewhere(FX_DWORD objnum, CPDF_Dictionary* pThisPageDict)\r
-{\r
-    for (int i = 0; i < m_PageList.GetSize(); i ++) {\r
-        CPDF_Dictionary* pPageDict = GetPage(i);\r
-        if (pPageDict == pThisPageDict) {\r
-            continue;\r
-        }\r
-        CPDF_Object* pContents = pPageDict->GetElement(FX_BSTRC("Contents"));\r
-        if (pContents == NULL) {\r
-            continue;\r
-        }\r
-        if (pContents->GetDirectType() == PDFOBJ_ARRAY) {\r
-            CPDF_Array* pArray = (CPDF_Array*)pContents->GetDirect();\r
-            for (FX_DWORD j = 0; j < pArray->GetCount(); j ++) {\r
-                CPDF_Reference* pRef = (CPDF_Reference*)pArray->GetElement(j);\r
-                if (pRef->GetRefObjNum() == objnum) {\r
-                    return TRUE;\r
-                }\r
-            }\r
-        } else if (pContents->GetObjNum() == objnum) {\r
-            return TRUE;\r
-        }\r
-    }\r
-    return FALSE;\r
-}\r
-FX_DWORD CPDF_Document::GetUserPermissions(FX_BOOL bCheckRevision) const\r
-{\r
-    if (m_pParser == NULL) {\r
-        return (FX_DWORD) - 1;\r
-    }\r
-    return m_pParser->GetPermissions(bCheckRevision);\r
-}\r
-FX_BOOL CPDF_Document::IsOwner() const\r
-{\r
-    if (m_pParser == NULL) {\r
-        return TRUE;\r
-    }\r
-    return m_pParser->IsOwner();\r
-}\r
-FX_BOOL CPDF_Document::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm) const\r
-{\r
-    {\r
-        CPDF_Object* pObj;\r
-        if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, (FX_LPVOID&)pObj)) {\r
-            bForm = pObj->GetType() == PDFOBJ_STREAM &&\r
-                    ((CPDF_Stream*)pObj)->GetDict()->GetString(FX_BSTRC("Subtype")) == FX_BSTRC("Form");\r
-            return TRUE;\r
-        }\r
-    }\r
-    if (m_pParser == NULL) {\r
-        bForm = FALSE;\r
-        return TRUE;\r
-    }\r
-    return m_pParser->IsFormStream(objnum, bForm);\r
-}\r
-void CPDF_Document::ClearPageData()\r
-{\r
-    if (m_pDocPage) {\r
-        CPDF_ModuleMgr::Get()->GetPageModule()->ClearDoc(this);\r
-    }\r
-}\r
-void CPDF_Document::ClearRenderData()\r
-{\r
-    if (m_pDocRender) {\r
-        CPDF_ModuleMgr::Get()->GetRenderModule()->ClearDocData(m_pDocRender);\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 "../../../include/fpdfapi/fpdf_parser.h"
+#include "../../../include/fpdfapi/fpdf_module.h"
+extern FX_LPVOID PDFPreviewInitCache(CPDF_Document* pDoc);
+extern void PDFPreviewClearCache(FX_LPVOID pCache);
+CPDF_Document::CPDF_Document(IPDF_DocParser* pParser) : CPDF_IndirectObjects(pParser)
+{
+    ASSERT(pParser != NULL);
+    m_pRootDict = NULL;
+    m_pInfoDict = NULL;
+    m_bLinearized = FALSE;
+    m_dwFirstPageNo = 0;
+    m_dwFirstPageObjNum = 0;
+    m_pDocPage = CPDF_ModuleMgr::Get()->GetPageModule()->CreateDocData(this);
+    m_pDocRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreateDocData(this);
+}
+CPDF_DocPageData* CPDF_Document::GetValidatePageData()
+{
+    if (m_pDocPage) {
+        return m_pDocPage;
+    }
+    m_pDocPage = CPDF_ModuleMgr::Get()->GetPageModule()->CreateDocData(this);
+    return m_pDocPage;
+}
+CPDF_DocRenderData* CPDF_Document::GetValidateRenderData()
+{
+    if (m_pDocRender) {
+        return m_pDocRender;
+    }
+    m_pDocRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreateDocData(this);
+    return m_pDocRender;
+}
+void CPDF_Document::LoadDoc()
+{
+    m_LastObjNum = m_pParser->GetLastObjNum();
+    CPDF_Object* pRootObj = GetIndirectObject(m_pParser->GetRootObjNum());
+    if (pRootObj == NULL) {
+        return;
+    }
+    m_pRootDict = pRootObj->GetDict();
+    if (m_pRootDict == NULL) {
+        return;
+    }
+    CPDF_Object* pInfoObj = GetIndirectObject(m_pParser->GetInfoObjNum());
+    if (pInfoObj) {
+        m_pInfoDict = pInfoObj->GetDict();
+    }
+    CPDF_Array* pIDArray = m_pParser->GetIDArray();
+    if (pIDArray) {
+        m_ID1 = pIDArray->GetString(0);
+        m_ID2 = pIDArray->GetString(1);
+    }
+    m_PageList.SetSize(_GetPageCount());
+}
+void CPDF_Document::LoadAsynDoc(CPDF_Dictionary *pLinearized)
+{
+    m_bLinearized = TRUE;
+    m_LastObjNum = m_pParser->GetLastObjNum();
+    CPDF_Object* indirectObj = GetIndirectObject(m_pParser->GetRootObjNum());
+    m_pRootDict = indirectObj ? indirectObj->GetDict() : NULL;
+    if (m_pRootDict == NULL) {
+        return;
+    }
+    indirectObj = GetIndirectObject(m_pParser->GetInfoObjNum());
+    m_pInfoDict = indirectObj ? indirectObj->GetDict() : NULL;
+    CPDF_Array* pIDArray = m_pParser->GetIDArray();
+    if (pIDArray) {
+        m_ID1 = pIDArray->GetString(0);
+        m_ID2 = pIDArray->GetString(1);
+    }
+    FX_DWORD dwPageCount = 0;
+    CPDF_Object *pCount = pLinearized->GetElement(FX_BSTRC("N"));
+    if (pCount && pCount->GetType() == PDFOBJ_NUMBER) {
+        dwPageCount = pCount->GetInteger();
+    }
+    m_PageList.SetSize(dwPageCount);
+    CPDF_Object *pNo = pLinearized->GetElement(FX_BSTRC("P"));
+    if (pNo && pNo->GetType() == PDFOBJ_NUMBER) {
+        m_dwFirstPageNo = pNo->GetInteger();
+    }
+    CPDF_Object *pObjNum = pLinearized->GetElement(FX_BSTRC("O"));
+    if (pObjNum && pObjNum->GetType() == PDFOBJ_NUMBER) {
+        m_dwFirstPageObjNum = pObjNum->GetInteger();
+    }
+}
+void CPDF_Document::LoadPages()
+{
+    m_PageList.SetSize(_GetPageCount());
+}
+extern void FPDF_TTFaceMapper_ReleaseDoc(CPDF_Document*);
+CPDF_Document::~CPDF_Document()
+{
+    if (m_pDocPage) {
+        CPDF_ModuleMgr::Get()->GetPageModule()->ReleaseDoc(this);
+        CPDF_ModuleMgr::Get()->GetPageModule()->ClearStockFont(this);
+    }
+    if (m_pDocRender) {
+        CPDF_ModuleMgr::Get()->GetRenderModule()->DestroyDocData(m_pDocRender);
+    }
+}
+#define                FX_MAX_PAGE_LEVEL                       1024
+CPDF_Dictionary* CPDF_Document::_FindPDFPage(CPDF_Dictionary* pPages, int iPage, int nPagesToGo, int level)
+{
+    CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids"));
+    if (pKidList == NULL) {
+        if (nPagesToGo == 0) {
+            return pPages;
+        }
+        return NULL;
+    }
+    if (level >= FX_MAX_PAGE_LEVEL) {
+        return NULL;
+    }
+    int nKids = pKidList->GetCount();
+    for (int i = 0; i < nKids; i ++) {
+        CPDF_Dictionary* pKid = pKidList->GetDict(i);
+        if (pKid == NULL) {
+            nPagesToGo --;
+            continue;
+        }
+        if (pKid == pPages) {
+            continue;
+        }
+        if (!pKid->KeyExist(FX_BSTRC("Kids"))) {
+            if (nPagesToGo == 0) {
+                return pKid;
+            }
+            m_PageList.SetAt(iPage - nPagesToGo, pKid->GetObjNum());
+            nPagesToGo --;
+        } else {
+            int nPages = pKid->GetInteger(FX_BSTRC("Count"));
+            if (nPagesToGo < nPages) {
+                return _FindPDFPage(pKid, iPage, nPagesToGo, level + 1);
+            }
+            nPagesToGo -= nPages;
+        }
+    }
+    return NULL;
+}
+CPDF_Dictionary* CPDF_Document::GetPage(int iPage)
+{
+    if (iPage < 0 || iPage >= m_PageList.GetSize()) {
+        return NULL;
+    }
+    if (m_bLinearized && (iPage == (int)m_dwFirstPageNo)) {
+        CPDF_Object* pObj = GetIndirectObject(m_dwFirstPageObjNum);
+        if (pObj && pObj->GetType() == PDFOBJ_DICTIONARY) {
+            return (CPDF_Dictionary*)pObj;
+        }
+    }
+    int objnum = m_PageList.GetAt(iPage);
+    if (objnum) {
+        CPDF_Object* pObj = GetIndirectObject(objnum);
+        ASSERT(pObj->GetType() == PDFOBJ_DICTIONARY);
+        return (CPDF_Dictionary*)pObj;
+    }
+    CPDF_Dictionary* pRoot = GetRoot();
+    if (pRoot == NULL) {
+        return NULL;
+    }
+    CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages"));
+    if (pPages == NULL) {
+        return NULL;
+    }
+    CPDF_Dictionary* pPage = _FindPDFPage(pPages, iPage, iPage, 0);
+    if (pPage == NULL) {
+        return NULL;
+    }
+    m_PageList.SetAt(iPage, pPage->GetObjNum());
+    return pPage;
+}
+int CPDF_Document::_FindPageIndex(CPDF_Dictionary* pNode, FX_DWORD& skip_count, FX_DWORD objnum, int& index, int level)
+{
+    if (pNode->KeyExist(FX_BSTRC("Kids"))) {
+        CPDF_Array* pKidList = pNode->GetArray(FX_BSTRC("Kids"));
+        if (pKidList == NULL) {
+            return -1;
+        }
+        if (level >= FX_MAX_PAGE_LEVEL) {
+            return -1;
+        }
+        FX_DWORD count = pNode->GetInteger(FX_BSTRC("Count"));
+        if (count <= skip_count) {
+            skip_count -= count;
+            index += count;
+            return -1;
+        }
+        if (count && count == pKidList->GetCount()) {
+            for (FX_DWORD i = 0; i < count; i ++) {
+                CPDF_Object* pKid = pKidList->GetElement(i);
+                if (pKid && pKid->GetType() == PDFOBJ_REFERENCE) {
+                    if (((CPDF_Reference*) pKid)->GetRefObjNum() == objnum) {
+                        m_PageList.SetAt(index + i, objnum);
+                        return index + i;
+                    }
+                }
+            }
+        }
+        for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) {
+            CPDF_Dictionary* pKid = pKidList->GetDict(i);
+            if (pKid == NULL) {
+                continue;
+            }
+            if (pKid == pNode) {
+                continue;
+            }
+            int found_index = _FindPageIndex(pKid, skip_count, objnum, index, level + 1);
+            if (found_index >= 0) {
+                return found_index;
+            }
+        }
+    } else {
+        if (objnum == pNode->GetObjNum()) {
+            return index;
+        }
+        if (skip_count) {
+            skip_count--;
+        }
+        index ++;
+    }
+    return -1;
+}
+int CPDF_Document::GetPageIndex(FX_DWORD objnum)
+{
+    FX_DWORD nPages = m_PageList.GetSize();
+    FX_DWORD skip_count = 0;
+    FX_BOOL bSkipped = FALSE;
+    for (FX_DWORD i = 0; i < nPages; i ++) {
+        FX_DWORD objnum1 = m_PageList.GetAt(i);
+        if (objnum1 == objnum) {
+            return i;
+        }
+        if (!bSkipped && objnum1 == 0) {
+            skip_count = i;
+            bSkipped = TRUE;
+        }
+    }
+    CPDF_Dictionary* pRoot = GetRoot();
+    if (pRoot == NULL) {
+        return -1;
+    }
+    CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages"));
+    if (pPages == NULL) {
+        return -1;
+    }
+    int index = 0;
+    return _FindPageIndex(pPages, skip_count, objnum, index);
+}
+int CPDF_Document::GetPageCount() const
+{
+    return m_PageList.GetSize();
+}
+static int _CountPages(CPDF_Dictionary* pPages, int level)
+{
+    if (level > 128) {
+        return 0;
+    }
+    int count = pPages->GetInteger(FX_BSTRC("Count"));
+    if (count > 0 && count < FPDF_PAGE_MAX_NUM) {
+        return count;
+    }
+    CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids"));
+    if (pKidList == NULL) {
+        return 0;
+    }
+    count = 0;
+    for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) {
+        CPDF_Dictionary* pKid = pKidList->GetDict(i);
+        if (pKid == NULL) {
+            continue;
+        }
+        if (!pKid->KeyExist(FX_BSTRC("Kids"))) {
+            count ++;
+        } else {
+            count += _CountPages(pKid, level + 1);
+        }
+    }
+    pPages->SetAtInteger(FX_BSTRC("Count"), count);
+    return count;
+}
+int CPDF_Document::_GetPageCount() const
+{
+    CPDF_Dictionary* pRoot = GetRoot();
+    if (pRoot == NULL) {
+        return 0;
+    }
+    CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages"));
+    if (pPages == NULL) {
+        return 0;
+    }
+    if (!pPages->KeyExist(FX_BSTRC("Kids"))) {
+        return 1;
+    }
+    return _CountPages(pPages, 0);
+}
+static FX_BOOL _EnumPages(CPDF_Dictionary* pPages, IPDF_EnumPageHandler* pHandler)
+{
+    CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids"));
+    if (pKidList == NULL) {
+        return pHandler->EnumPage(pPages);
+    }
+    for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) {
+        CPDF_Dictionary* pKid = pKidList->GetDict(i);
+        if (pKid == NULL) {
+            continue;
+        }
+        if (!pKid->KeyExist(FX_BSTRC("Kids"))) {
+            if (!pHandler->EnumPage(pKid)) {
+                return FALSE;
+            }
+        } else {
+            return _EnumPages(pKid, pHandler);
+        }
+    }
+    return TRUE;
+}
+void CPDF_Document::EnumPages(IPDF_EnumPageHandler* pHandler)
+{
+    CPDF_Dictionary* pRoot = GetRoot();
+    if (pRoot == NULL) {
+        return;
+    }
+    CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages"));
+    if (pPages == NULL) {
+        return;
+    }
+    _EnumPages(pPages, pHandler);
+}
+FX_BOOL CPDF_Document::IsContentUsedElsewhere(FX_DWORD objnum, CPDF_Dictionary* pThisPageDict)
+{
+    for (int i = 0; i < m_PageList.GetSize(); i ++) {
+        CPDF_Dictionary* pPageDict = GetPage(i);
+        if (pPageDict == pThisPageDict) {
+            continue;
+        }
+        CPDF_Object* pContents = pPageDict ? pPageDict->GetElement(FX_BSTRC("Contents")) : NULL;
+        if (pContents == NULL) {
+            continue;
+        }
+        if (pContents->GetDirectType() == PDFOBJ_ARRAY) {
+            CPDF_Array* pArray = (CPDF_Array*)pContents->GetDirect();
+            for (FX_DWORD j = 0; j < pArray->GetCount(); j ++) {
+                CPDF_Object* pRef = pArray->GetElement(j);
+                if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
+                    continue;
+                }
+                if (((CPDF_Reference*) pRef)->GetRefObjNum() == objnum) {
+                    return TRUE;
+                }
+            }
+        } else if (pContents->GetObjNum() == objnum) {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+FX_DWORD CPDF_Document::GetUserPermissions(FX_BOOL bCheckRevision) const
+{
+    if (m_pParser == NULL) {
+        return (FX_DWORD) - 1;
+    }
+    return m_pParser->GetPermissions(bCheckRevision);
+}
+FX_BOOL CPDF_Document::IsOwner() const
+{
+    if (m_pParser == NULL) {
+        return TRUE;
+    }
+    return m_pParser->IsOwner();
+}
+FX_BOOL CPDF_Document::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm) const
+{
+    {
+        CPDF_Object* pObj;
+        if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, (FX_LPVOID&)pObj)) {
+            bForm = pObj->GetType() == PDFOBJ_STREAM &&
+                    ((CPDF_Stream*)pObj)->GetDict()->GetString(FX_BSTRC("Subtype")) == FX_BSTRC("Form");
+            return TRUE;
+        }
+    }
+    if (m_pParser == NULL) {
+        bForm = FALSE;
+        return TRUE;
+    }
+    return m_pParser->IsFormStream(objnum, bForm);
+}
+void CPDF_Document::ClearPageData()
+{
+    if (m_pDocPage) {
+        CPDF_ModuleMgr::Get()->GetPageModule()->ClearDoc(this);
+    }
+}
+void CPDF_Document::ClearRenderData()
+{
+    if (m_pDocRender) {
+        CPDF_ModuleMgr::Get()->GetRenderModule()->ClearDocData(m_pDocRender);
+    }
+}