Commit e01ae1968b79841797b2ae59eda00b867604e3f9

Authored by Jay Berkenbilt
1 parent df493c35

Split page handling APIs into a separate source file

libqpdf/QPDF.cc
@@ -4,7 +4,6 @@ @@ -4,7 +4,6 @@
4 #include <map> 4 #include <map>
5 #include <string.h> 5 #include <string.h>
6 #include <memory.h> 6 #include <memory.h>
7 -#include <assert.h>  
8 7
9 #include <qpdf/QTC.hh> 8 #include <qpdf/QTC.hh>
10 #include <qpdf/QUtil.hh> 9 #include <qpdf/QUtil.hh>
@@ -2165,191 +2164,3 @@ QPDF::decodeStreams() @@ -2165,191 +2164,3 @@ QPDF::decodeStreams()
2165 } 2164 }
2166 } 2165 }
2167 } 2166 }
2168 -  
2169 -std::vector<QPDFObjectHandle> const&  
2170 -QPDF::getAllPages()  
2171 -{  
2172 - if (this->all_pages.empty())  
2173 - {  
2174 - getAllPagesInternal(  
2175 - this->trailer.getKey("/Root").getKey("/Pages"), this->all_pages);  
2176 - }  
2177 - return this->all_pages;  
2178 -}  
2179 -  
2180 -void  
2181 -QPDF::getAllPagesInternal(QPDFObjectHandle cur_pages,  
2182 - std::vector<QPDFObjectHandle>& result)  
2183 -{  
2184 - std::string type = cur_pages.getKey("/Type").getName();  
2185 - if (type == "/Pages")  
2186 - {  
2187 - QPDFObjectHandle kids = cur_pages.getKey("/Kids");  
2188 - int n = kids.getArrayNItems();  
2189 - for (int i = 0; i < n; ++i)  
2190 - {  
2191 - getAllPagesInternal(kids.getArrayItem(i), result);  
2192 - }  
2193 - }  
2194 - else if (type == "/Page")  
2195 - {  
2196 - result.push_back(cur_pages);  
2197 - }  
2198 - else  
2199 - {  
2200 - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),  
2201 - this->last_object_description,  
2202 - this->file->getLastOffset(),  
2203 - ": invalid Type in page tree");  
2204 - }  
2205 -}  
2206 -  
2207 -// FIXXX here down  
2208 -  
2209 -void  
2210 -QPDF::clearPagesCache()  
2211 -{  
2212 - this->all_pages.clear();  
2213 - this->pageobj_to_pages_pos.clear();  
2214 -}  
2215 -  
2216 -void  
2217 -QPDF::flattenPagesTree()  
2218 -{  
2219 - clearPagesCache();  
2220 -  
2221 - // FIXME: more specific method, we don't want to generate the extra stuff.  
2222 - // We also need cheap fixup after addPage/removePage.  
2223 -  
2224 - // no compressed objects to be produced here...  
2225 - std::map<int, int> object_stream_data;  
2226 - optimize(object_stream_data); // push down inheritance  
2227 -  
2228 - std::vector<QPDFObjectHandle> kids = this->getAllPages();  
2229 - QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages");  
2230 -  
2231 - const int len = kids.size();  
2232 - for (int pos = 0; pos < len; ++pos)  
2233 - {  
2234 - // populate pageobj_to_pages_pos  
2235 - ObjGen og(kids[pos].getObjectID(), kids[pos].getGeneration());  
2236 - if (! this->pageobj_to_pages_pos.insert(std::make_pair(og, pos)).second)  
2237 - {  
2238 - // insert failed: duplicate entry found  
2239 - *out_stream << "WARNING: duplicate page reference found, "  
2240 - << "but currently not fully supported." << std::endl;  
2241 - }  
2242 -  
2243 - // fix parent links  
2244 - kids[pos].replaceKey("/Parent", pages);  
2245 - }  
2246 -  
2247 - pages.replaceKey("/Kids", QPDFObjectHandle::newArray(kids));  
2248 - // /Count has not changed  
2249 - assert(pages.getKey("/Count").getIntValue() == len);  
2250 -}  
2251 -  
2252 -int  
2253 -QPDF::findPage(int objid, int generation)  
2254 -{  
2255 - if (this->pageobj_to_pages_pos.empty())  
2256 - {  
2257 - flattenPagesTree();  
2258 - }  
2259 - std::map<ObjGen, int>::iterator it =  
2260 - this->pageobj_to_pages_pos.find(ObjGen(objid, generation));  
2261 - if (it != this->pageobj_to_pages_pos.end())  
2262 - {  
2263 - return (*it).second;  
2264 - }  
2265 - return -1; // throw?  
2266 -}  
2267 -  
2268 -int  
2269 -QPDF::findPage(QPDFObjectHandle const& pageoh)  
2270 -{  
2271 - if (!pageoh.isInitialized())  
2272 - {  
2273 - return -1;  
2274 - // TODO? throw  
2275 - }  
2276 - return findPage(pageoh.getObjectID(), pageoh.getGeneration());  
2277 -}  
2278 -  
2279 -void  
2280 -QPDF::addPage(QPDFObjectHandle newpage, bool first)  
2281 -{  
2282 - if (this->pageobj_to_pages_pos.empty())  
2283 - {  
2284 - flattenPagesTree();  
2285 - }  
2286 -  
2287 - newpage.assertPageObject(); // FIXME: currently private  
2288 -  
2289 - QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages");  
2290 - QPDFObjectHandle kids = pages.getKey("/Kids");  
2291 -  
2292 - newpage.replaceKey("/Parent", pages);  
2293 - if (first)  
2294 - {  
2295 - kids.insertItem(0, newpage);  
2296 - }  
2297 - else  
2298 - {  
2299 - kids.appendItem(newpage);  
2300 - }  
2301 - pages.replaceKey("/Count",  
2302 - QPDFObjectHandle::newInteger(kids.getArrayNItems()));  
2303 -  
2304 - // FIXME: this is overkill, but cache is now stale  
2305 - clearPagesCache();  
2306 -}  
2307 -  
2308 -void  
2309 -QPDF::addPageAt(QPDFObjectHandle newpage, bool before,  
2310 - QPDFObjectHandle const &refpage)  
2311 -{  
2312 - int refpos = findPage(refpage); // also ensures flat /Pages  
2313 - if (refpos == -1)  
2314 - {  
2315 - throw "Could not find refpage";  
2316 - }  
2317 -  
2318 - newpage.assertPageObject();  
2319 -  
2320 - QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages");  
2321 - QPDFObjectHandle kids = pages.getKey("/Kids");  
2322 -  
2323 - if (! before)  
2324 - {  
2325 - ++refpos;  
2326 - }  
2327 -  
2328 - newpage.replaceKey("/Parent", pages);  
2329 - kids.insertItem(refpos, newpage);  
2330 - pages.replaceKey("/Count",  
2331 - QPDFObjectHandle::newInteger(kids.getArrayNItems()));  
2332 -  
2333 - // FIXME: this is overkill, but cache is now stale  
2334 - clearPagesCache();  
2335 -}  
2336 -  
2337 -void  
2338 -QPDF::removePage(QPDFObjectHandle const& pageoh)  
2339 -{  
2340 - int pos = findPage(pageoh); // also ensures flat /Pages  
2341 - if (pos == -1)  
2342 - {  
2343 - throw "Can't remove non-existing page";  
2344 - }  
2345 -  
2346 - QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages");  
2347 - QPDFObjectHandle kids = pages.getKey("/Kids");  
2348 -  
2349 - kids.eraseItem(pos);  
2350 - pages.replaceKey("/Count",  
2351 - QPDFObjectHandle::newInteger(kids.getArrayNItems()));  
2352 -  
2353 - // FIXME: this is overkill, but cache is now stale  
2354 - clearPagesCache();  
2355 -}  
libqpdf/QPDF_pages.cc 0 โ†’ 100644
  1 +#include <qpdf/QPDF.hh>
  2 +
  3 +#include <assert.h>
  4 +
  5 +#include <qpdf/QTC.hh>
  6 +#include <qpdf/QUtil.hh>
  7 +#include <qpdf/QPDFExc.hh>
  8 +
  9 +std::vector<QPDFObjectHandle> const&
  10 +QPDF::getAllPages()
  11 +{
  12 + if (this->all_pages.empty())
  13 + {
  14 + getAllPagesInternal(
  15 + this->trailer.getKey("/Root").getKey("/Pages"), this->all_pages);
  16 + }
  17 + return this->all_pages;
  18 +}
  19 +
  20 +void
  21 +QPDF::getAllPagesInternal(QPDFObjectHandle cur_pages,
  22 + std::vector<QPDFObjectHandle>& result)
  23 +{
  24 + std::string type = cur_pages.getKey("/Type").getName();
  25 + if (type == "/Pages")
  26 + {
  27 + QPDFObjectHandle kids = cur_pages.getKey("/Kids");
  28 + int n = kids.getArrayNItems();
  29 + for (int i = 0; i < n; ++i)
  30 + {
  31 + getAllPagesInternal(kids.getArrayItem(i), result);
  32 + }
  33 + }
  34 + else if (type == "/Page")
  35 + {
  36 + result.push_back(cur_pages);
  37 + }
  38 + else
  39 + {
  40 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  41 + this->last_object_description,
  42 + this->file->getLastOffset(),
  43 + ": invalid Type in page tree");
  44 + }
  45 +}
  46 +
  47 +// FIXXX here down
  48 +
  49 +void
  50 +QPDF::clearPagesCache()
  51 +{
  52 + this->all_pages.clear();
  53 + this->pageobj_to_pages_pos.clear();
  54 +}
  55 +
  56 +void
  57 +QPDF::flattenPagesTree()
  58 +{
  59 + clearPagesCache();
  60 +
  61 + // FIXME: more specific method, we don't want to generate the extra stuff.
  62 + // We also need cheap fixup after addPage/removePage.
  63 +
  64 + // no compressed objects to be produced here...
  65 + std::map<int, int> object_stream_data;
  66 + optimize(object_stream_data); // push down inheritance
  67 +
  68 + std::vector<QPDFObjectHandle> kids = this->getAllPages();
  69 + QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages");
  70 +
  71 + const int len = kids.size();
  72 + for (int pos = 0; pos < len; ++pos)
  73 + {
  74 + // populate pageobj_to_pages_pos
  75 + ObjGen og(kids[pos].getObjectID(), kids[pos].getGeneration());
  76 + if (! this->pageobj_to_pages_pos.insert(std::make_pair(og, pos)).second)
  77 + {
  78 + // insert failed: duplicate entry found
  79 + *out_stream << "WARNING: duplicate page reference found, "
  80 + << "but currently not fully supported." << std::endl;
  81 + }
  82 +
  83 + // fix parent links
  84 + kids[pos].replaceKey("/Parent", pages);
  85 + }
  86 +
  87 + pages.replaceKey("/Kids", QPDFObjectHandle::newArray(kids));
  88 + // /Count has not changed
  89 + assert(pages.getKey("/Count").getIntValue() == len);
  90 +}
  91 +
  92 +int
  93 +QPDF::findPage(int objid, int generation)
  94 +{
  95 + if (this->pageobj_to_pages_pos.empty())
  96 + {
  97 + flattenPagesTree();
  98 + }
  99 + std::map<ObjGen, int>::iterator it =
  100 + this->pageobj_to_pages_pos.find(ObjGen(objid, generation));
  101 + if (it != this->pageobj_to_pages_pos.end())
  102 + {
  103 + return (*it).second;
  104 + }
  105 + return -1; // throw?
  106 +}
  107 +
  108 +int
  109 +QPDF::findPage(QPDFObjectHandle const& pageoh)
  110 +{
  111 + if (!pageoh.isInitialized())
  112 + {
  113 + return -1;
  114 + // TODO? throw
  115 + }
  116 + return findPage(pageoh.getObjectID(), pageoh.getGeneration());
  117 +}
  118 +
  119 +void
  120 +QPDF::addPage(QPDFObjectHandle newpage, bool first)
  121 +{
  122 + if (this->pageobj_to_pages_pos.empty())
  123 + {
  124 + flattenPagesTree();
  125 + }
  126 +
  127 + newpage.assertPageObject(); // FIXME: currently private
  128 +
  129 + QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages");
  130 + QPDFObjectHandle kids = pages.getKey("/Kids");
  131 +
  132 + newpage.replaceKey("/Parent", pages);
  133 + if (first)
  134 + {
  135 + kids.insertItem(0, newpage);
  136 + }
  137 + else
  138 + {
  139 + kids.appendItem(newpage);
  140 + }
  141 + pages.replaceKey("/Count",
  142 + QPDFObjectHandle::newInteger(kids.getArrayNItems()));
  143 +
  144 + // FIXME: this is overkill, but cache is now stale
  145 + clearPagesCache();
  146 +}
  147 +
  148 +void
  149 +QPDF::addPageAt(QPDFObjectHandle newpage, bool before,
  150 + QPDFObjectHandle const &refpage)
  151 +{
  152 + int refpos = findPage(refpage); // also ensures flat /Pages
  153 + if (refpos == -1)
  154 + {
  155 + throw "Could not find refpage";
  156 + }
  157 +
  158 + newpage.assertPageObject();
  159 +
  160 + QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages");
  161 + QPDFObjectHandle kids = pages.getKey("/Kids");
  162 +
  163 + if (! before)
  164 + {
  165 + ++refpos;
  166 + }
  167 +
  168 + newpage.replaceKey("/Parent", pages);
  169 + kids.insertItem(refpos, newpage);
  170 + pages.replaceKey("/Count",
  171 + QPDFObjectHandle::newInteger(kids.getArrayNItems()));
  172 +
  173 + // FIXME: this is overkill, but cache is now stale
  174 + clearPagesCache();
  175 +}
  176 +
  177 +void
  178 +QPDF::removePage(QPDFObjectHandle const& pageoh)
  179 +{
  180 + int pos = findPage(pageoh); // also ensures flat /Pages
  181 + if (pos == -1)
  182 + {
  183 + throw "Can't remove non-existing page";
  184 + }
  185 +
  186 + QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages");
  187 + QPDFObjectHandle kids = pages.getKey("/Kids");
  188 +
  189 + kids.eraseItem(pos);
  190 + pages.replaceKey("/Count",
  191 + QPDFObjectHandle::newInteger(kids.getArrayNItems()));
  192 +
  193 + // FIXME: this is overkill, but cache is now stale
  194 + clearPagesCache();
  195 +}
libqpdf/build.mk
@@ -43,6 +43,7 @@ SRCS_libqpdf = \ @@ -43,6 +43,7 @@ SRCS_libqpdf = \
43 libqpdf/QPDF_encryption.cc \ 43 libqpdf/QPDF_encryption.cc \
44 libqpdf/QPDF_linearization.cc \ 44 libqpdf/QPDF_linearization.cc \
45 libqpdf/QPDF_optimization.cc \ 45 libqpdf/QPDF_optimization.cc \
  46 + libqpdf/QPDF_pages.cc \
46 libqpdf/QTC.cc \ 47 libqpdf/QTC.cc \
47 libqpdf/QUtil.cc \ 48 libqpdf/QUtil.cc \
48 libqpdf/RC4.cc \ 49 libqpdf/RC4.cc \