| OLD | NEW |
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | 6 |
| 7 #include <limits.h> | 7 #include <limits.h> |
| 8 | 8 |
| 9 #include <set> |
| 9 #include <vector> | 10 #include <vector> |
| 10 | 11 |
| 11 #include "core/fpdfapi/fpdf_font/include/cpdf_font.h" | 12 #include "core/fpdfapi/fpdf_font/include/cpdf_font.h" |
| 12 #include "core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h" | 13 #include "core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h" |
| 13 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h" | 14 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h" |
| 14 #include "core/fpdfapi/fpdf_page/pageint.h" | 15 #include "core/fpdfapi/fpdf_page/pageint.h" |
| 15 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" | 16 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" |
| 16 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" | 17 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" |
| 17 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" | 18 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" |
| 18 #include "core/fpdfapi/fpdf_parser/include/cpdf_reference.h" | 19 #include "core/fpdfapi/fpdf_parser/include/cpdf_reference.h" |
| (...skipping 982 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1001 pFontDesc->SetAtInteger("StemV", nStemV); | 1002 pFontDesc->SetAtInteger("StemV", nStemV); |
| 1002 AddIndirectObject(pFontDesc); | 1003 AddIndirectObject(pFontDesc); |
| 1003 pFontDict->SetAtReference("FontDescriptor", this, pFontDesc); | 1004 pFontDict->SetAtReference("FontDescriptor", this, pFontDesc); |
| 1004 return LoadFont(pBaseDict); | 1005 return LoadFont(pBaseDict); |
| 1005 } | 1006 } |
| 1006 static int InsertDeletePDFPage(CPDF_Document* pDoc, | 1007 static int InsertDeletePDFPage(CPDF_Document* pDoc, |
| 1007 CPDF_Dictionary* pPages, | 1008 CPDF_Dictionary* pPages, |
| 1008 int nPagesToGo, | 1009 int nPagesToGo, |
| 1009 CPDF_Dictionary* pPage, | 1010 CPDF_Dictionary* pPage, |
| 1010 FX_BOOL bInsert, | 1011 FX_BOOL bInsert, |
| 1011 CFX_ArrayTemplate<CPDF_Dictionary*>& stackList) { | 1012 std::set<CPDF_Dictionary*>* pVisited) { |
| 1012 CPDF_Array* pKidList = pPages->GetArrayBy("Kids"); | 1013 CPDF_Array* pKidList = pPages->GetArrayBy("Kids"); |
| 1013 if (!pKidList) { | 1014 if (!pKidList) |
| 1014 return -1; | 1015 return -1; |
| 1015 } | 1016 |
| 1016 for (size_t i = 0; i < pKidList->GetCount(); i++) { | 1017 for (size_t i = 0; i < pKidList->GetCount(); i++) { |
| 1017 CPDF_Dictionary* pKid = pKidList->GetDictAt(i); | 1018 CPDF_Dictionary* pKid = pKidList->GetDictAt(i); |
| 1018 if (pKid->GetStringBy("Type") == "Page") { | 1019 if (pKid->GetStringBy("Type") == "Page") { |
| 1019 if (nPagesToGo == 0) { | 1020 if (nPagesToGo == 0) { |
| 1020 if (bInsert) { | 1021 if (bInsert) { |
| 1021 pKidList->InsertAt(i, new CPDF_Reference(pDoc, pPage->GetObjNum())); | 1022 pKidList->InsertAt(i, new CPDF_Reference(pDoc, pPage->GetObjNum())); |
| 1022 pPage->SetAtReference("Parent", pDoc, pPages->GetObjNum()); | 1023 pPage->SetAtReference("Parent", pDoc, pPages->GetObjNum()); |
| 1023 } else { | 1024 } else { |
| 1024 pKidList->RemoveAt(i); | 1025 pKidList->RemoveAt(i); |
| 1025 } | 1026 } |
| 1026 pPages->SetAtInteger( | 1027 pPages->SetAtInteger( |
| 1027 "Count", pPages->GetIntegerBy("Count") + (bInsert ? 1 : -1)); | 1028 "Count", pPages->GetIntegerBy("Count") + (bInsert ? 1 : -1)); |
| 1028 return 1; | 1029 return 1; |
| 1029 } | 1030 } |
| 1030 nPagesToGo--; | 1031 nPagesToGo--; |
| 1031 } else { | 1032 } else { |
| 1032 int nPages = pKid->GetIntegerBy("Count"); | 1033 int nPages = pKid->GetIntegerBy("Count"); |
| 1033 if (nPagesToGo < nPages) { | 1034 if (nPagesToGo < nPages) { |
| 1034 int stackCount = stackList.GetSize(); | 1035 if (pdfium::ContainsValue(*pVisited, pKid)) |
| 1035 for (int j = 0; j < stackCount; ++j) { | 1036 return -1; |
| 1036 if (pKid == stackList[j]) { | 1037 pdfium::ScopedSetInsertion<CPDF_Dictionary*>(pVisited, pKid); |
| 1037 return -1; | |
| 1038 } | |
| 1039 } | |
| 1040 stackList.Add(pKid); | |
| 1041 if (InsertDeletePDFPage(pDoc, pKid, nPagesToGo, pPage, bInsert, | 1038 if (InsertDeletePDFPage(pDoc, pKid, nPagesToGo, pPage, bInsert, |
| 1042 stackList) < 0) { | 1039 pVisited) < 0) { |
| 1043 return -1; | 1040 return -1; |
| 1044 } | 1041 } |
| 1045 stackList.RemoveAt(stackCount); | |
| 1046 pPages->SetAtInteger( | 1042 pPages->SetAtInteger( |
| 1047 "Count", pPages->GetIntegerBy("Count") + (bInsert ? 1 : -1)); | 1043 "Count", pPages->GetIntegerBy("Count") + (bInsert ? 1 : -1)); |
| 1048 return 1; | 1044 return 1; |
| 1049 } | 1045 } |
| 1050 nPagesToGo -= nPages; | 1046 nPagesToGo -= nPages; |
| 1051 } | 1047 } |
| 1052 } | 1048 } |
| 1053 return 0; | 1049 return 0; |
| 1054 } | 1050 } |
| 1055 static int InsertNewPage(CPDF_Document* pDoc, | 1051 static int InsertNewPage(CPDF_Document* pDoc, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1071 if (iPage == nPages) { | 1067 if (iPage == nPages) { |
| 1072 CPDF_Array* pPagesList = pPages->GetArrayBy("Kids"); | 1068 CPDF_Array* pPagesList = pPages->GetArrayBy("Kids"); |
| 1073 if (!pPagesList) { | 1069 if (!pPagesList) { |
| 1074 pPagesList = new CPDF_Array; | 1070 pPagesList = new CPDF_Array; |
| 1075 pPages->SetAt("Kids", pPagesList); | 1071 pPages->SetAt("Kids", pPagesList); |
| 1076 } | 1072 } |
| 1077 pPagesList->Add(pPageDict, pDoc); | 1073 pPagesList->Add(pPageDict, pDoc); |
| 1078 pPages->SetAtInteger("Count", nPages + 1); | 1074 pPages->SetAtInteger("Count", nPages + 1); |
| 1079 pPageDict->SetAtReference("Parent", pDoc, pPages->GetObjNum()); | 1075 pPageDict->SetAtReference("Parent", pDoc, pPages->GetObjNum()); |
| 1080 } else { | 1076 } else { |
| 1081 CFX_ArrayTemplate<CPDF_Dictionary*> stack; | 1077 std::set<CPDF_Dictionary*> stack = {pPages}; |
| 1082 stack.Add(pPages); | 1078 if (InsertDeletePDFPage(pDoc, pPages, iPage, pPageDict, TRUE, &stack) < 0) |
| 1083 if (InsertDeletePDFPage(pDoc, pPages, iPage, pPageDict, TRUE, stack) < 0) { | |
| 1084 return -1; | 1079 return -1; |
| 1085 } | |
| 1086 } | 1080 } |
| 1087 pageList.InsertAt(iPage, pPageDict->GetObjNum()); | 1081 pageList.InsertAt(iPage, pPageDict->GetObjNum()); |
| 1088 return iPage; | 1082 return iPage; |
| 1089 } | 1083 } |
| 1090 CPDF_Dictionary* CPDF_Document::CreateNewPage(int iPage) { | 1084 CPDF_Dictionary* CPDF_Document::CreateNewPage(int iPage) { |
| 1091 CPDF_Dictionary* pDict = new CPDF_Dictionary; | 1085 CPDF_Dictionary* pDict = new CPDF_Dictionary; |
| 1092 pDict->SetAtName("Type", "Page"); | 1086 pDict->SetAtName("Type", "Page"); |
| 1093 uint32_t dwObjNum = AddIndirectObject(pDict); | 1087 uint32_t dwObjNum = AddIndirectObject(pDict); |
| 1094 if (InsertNewPage(this, iPage, pDict, m_PageList) < 0) { | 1088 if (InsertNewPage(this, iPage, pDict, m_PageList) < 0) { |
| 1095 ReleaseIndirectObject(dwObjNum); | 1089 ReleaseIndirectObject(dwObjNum); |
| 1096 return NULL; | 1090 return NULL; |
| 1097 } | 1091 } |
| 1098 return pDict; | 1092 return pDict; |
| 1099 } | 1093 } |
| 1100 | 1094 |
| 1101 CPDF_Font* CPDF_Document::AddStandardFont(const FX_CHAR* font, | 1095 CPDF_Font* CPDF_Document::AddStandardFont(const FX_CHAR* font, |
| 1102 CPDF_FontEncoding* pEncoding) { | 1096 CPDF_FontEncoding* pEncoding) { |
| 1103 CFX_ByteString name(font); | 1097 CFX_ByteString name(font); |
| 1104 if (PDF_GetStandardFontName(&name) < 0) | 1098 if (PDF_GetStandardFontName(&name) < 0) |
| 1105 return nullptr; | 1099 return nullptr; |
| 1106 return GetPageData()->GetStandardFont(name.AsStringC(), pEncoding); | 1100 return GetPageData()->GetStandardFont(name.AsStringC(), pEncoding); |
| 1107 } | 1101 } |
| 1108 | 1102 |
| 1109 void CPDF_Document::DeletePage(int iPage) { | 1103 void CPDF_Document::DeletePage(int iPage) { |
| 1110 CPDF_Dictionary* pRoot = GetRoot(); | 1104 CPDF_Dictionary* pRoot = GetRoot(); |
| 1111 if (!pRoot) { | 1105 if (!pRoot) |
| 1112 return; | 1106 return; |
| 1113 } | 1107 |
| 1114 CPDF_Dictionary* pPages = pRoot->GetDictBy("Pages"); | 1108 CPDF_Dictionary* pPages = pRoot->GetDictBy("Pages"); |
| 1115 if (!pPages) { | 1109 if (!pPages) |
| 1116 return; | 1110 return; |
| 1117 } | 1111 |
| 1118 int nPages = pPages->GetIntegerBy("Count"); | 1112 int nPages = pPages->GetIntegerBy("Count"); |
| 1119 if (iPage < 0 || iPage >= nPages) { | 1113 if (iPage < 0 || iPage >= nPages) |
| 1120 return; | 1114 return; |
| 1121 } | 1115 |
| 1122 CFX_ArrayTemplate<CPDF_Dictionary*> stack; | 1116 std::set<CPDF_Dictionary*> stack = {pPages}; |
| 1123 stack.Add(pPages); | 1117 if (InsertDeletePDFPage(this, pPages, iPage, nullptr, FALSE, &stack) < 0) |
| 1124 if (InsertDeletePDFPage(this, pPages, iPage, NULL, FALSE, stack) < 0) { | |
| 1125 return; | 1118 return; |
| 1126 } | 1119 |
| 1127 m_PageList.RemoveAt(iPage); | 1120 m_PageList.RemoveAt(iPage); |
| 1128 } | 1121 } |
| 1129 | 1122 |
| 1130 void FPDFAPI_FlatPageAttr(CPDF_Dictionary* pPageDict, | 1123 void FPDFAPI_FlatPageAttr(CPDF_Dictionary* pPageDict, |
| 1131 const CFX_ByteStringC& name) { | 1124 const CFX_ByteStringC& name) { |
| 1132 if (pPageDict->KeyExist(name)) { | 1125 if (pPageDict->KeyExist(name)) { |
| 1133 return; | 1126 return; |
| 1134 } | 1127 } |
| 1135 CPDF_Object* pObj = FPDFAPI_GetPageAttr(pPageDict, name); | 1128 CPDF_Object* pObj = FPDFAPI_GetPageAttr(pPageDict, name); |
| 1136 if (pObj) { | 1129 if (pObj) { |
| 1137 pPageDict->SetAt(name, pObj->Clone()); | 1130 pPageDict->SetAt(name, pObj->Clone()); |
| 1138 } | 1131 } |
| 1139 } | 1132 } |
| OLD | NEW |