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 4 #include <map>
5 5 #include <string.h>
6 6 #include <memory.h>
7   -#include <assert.h>
8 7  
9 8 #include <qpdf/QTC.hh>
10 9 #include <qpdf/QUtil.hh>
... ... @@ -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 43 libqpdf/QPDF_encryption.cc \
44 44 libqpdf/QPDF_linearization.cc \
45 45 libqpdf/QPDF_optimization.cc \
  46 + libqpdf/QPDF_pages.cc \
46 47 libqpdf/QTC.cc \
47 48 libqpdf/QUtil.cc \
48 49 libqpdf/RC4.cc \
... ...