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 |