]> mj.ucw.cz Git - paperjam.git/blobdiff - paperjam.cc
Flip and switch parameters
[paperjam.git] / paperjam.cc
index 07ae6b4289d40f460bc054373c7bcd3c9d11ac7a..c8e107181d7ad97b1b1bdb195c20e45405a1b6eb 100644 (file)
 static QPDF in_pdf;
 static QPDF out_pdf;
 
-string page_out::new_resource(const string type)
+string out_context::new_resource(const string type)
 {
   return "/" + type + to_string(++res_cnt);
 }
 
 class in_page : public page {
   QPDFObjectHandle pdf_page;
+  QPDFObjectHandle xobject;
 public:
   BBox media_box;
-  void render(page_out *out, pdf_matrix xform);
+  void render(out_context *out, pdf_matrix xform);
   in_page(QPDFObjectHandle inpg, int idx);
 };
 
 in_page::in_page(QPDFObjectHandle inpg, int idx)
 {
   pdf_page = inpg;
+  xobject = QPDFObjectHandle::newNull();
   index = idx;
+
   media_box = BBox(inpg.getKey("/MediaBox"));
   width = media_box.width();
   height = media_box.height();
+
+  QPDFObjectHandle art_box = inpg.getKey("/ArtBox");
+  if (art_box.isNull())
+    art_box = inpg.getKey("/CropBox");
+  if (art_box.isNull())
+    bbox = BBox(width, height);
+  else
+    {
+      bbox = BBox(art_box);
+      bbox.x_min -= media_box.x_min;
+      bbox.x_max -= media_box.x_min;
+      bbox.y_min -= media_box.y_min;
+      bbox.y_max -= media_box.y_min;
+    }
 }
 
-void in_page::render(page_out *out, pdf_matrix xform)
+void in_page::render(out_context *out, pdf_matrix xform)
 {
   // Convert page to xobject
-  QPDFObjectHandle page_copy = page_to_xobject(&out_pdf, out_pdf.copyForeignObject(pdf_page));
+  if (xobject.isNull())
+    xobject = out_pdf.makeIndirectObject( page_to_xobject(&out_pdf, out_pdf.copyForeignObject(pdf_page)) );
   string xobj_res = out->new_resource("XO");
-  out->xobjects.replaceKey(xobj_res, out_pdf.makeIndirectObject(page_copy));
+  out->xobjects.replaceKey(xobj_res, xobject);
 
   pdf_matrix m;
   m.shift(-media_box.x_min, -media_box.y_min);
   m.concat(xform);
 
-  out->contents += "q " + m.to_string() + " cm " + xobj_res + " Do Q";
+  out->contents += "q " + m.to_string() + " cm " + xobj_res + " Do Q ";
 }
 
-static int run_indent;
-
 static void debug_pages(vector<page *> &pages)
 {
   if (!debug_mode)
     return;
 
   for (auto pg: pages)
-    debug("%*sPage #%d: w=%.3f h=%.3f", run_indent, "", pg->index, pg->width, pg->height);
+    debug("Page #%d: media[%.3f %.3f] bbox[%.3f %.3f %.3f %.3f]",
+      pg->index,
+      pg->width, pg->height,
+      pg->bbox.x_min, pg->bbox.y_min, pg->bbox.x_max, pg->bbox.y_max);
 }
 
 vector<page *> run_command_list(list<cmd *> &cmds, vector<page *> &pages)
 {
-  debug("%*s# Input", run_indent, "");
+  debug("# Input");
   debug_pages(pages);
 
   for (auto c: cmds)
     {
-      debug("%*s# Executing %s", run_indent, "", c->def->name);
-      run_indent += 4;
+      debug("# Executing %s", c->def->name);
+      debug_indent += 4;
       pages = c->exec->process(pages);
-      run_indent -= 4;
+      debug_indent -= 4;
       debug_pages(pages);
     }
 
   return pages;
 }
 
+static void find_bboxes(vector<page *> &pages, const char *in_name)
+{
+  vector<BBox> bboxes = gs_bboxes(in_name);
+  if (pages.size() != bboxes.size())
+    die("Ghostscript failed to produce the right number of bboxes");
+
+  for (size_t i=0; i<pages.size(); i++)
+    pages[i]->bbox = bboxes[i];
+}
+
 static void process(list<cmd *> &cmds, const char *in_name, const char *out_name)
 {
   in_pdf.processFile(in_name);
@@ -89,14 +118,15 @@ static void process(list<cmd *> &cmds, const char *in_name, const char *out_name
   for (auto inpg: in_pages)
     pages.push_back(new in_page(inpg, ++cnt));
 
+  find_bboxes(pages, in_name);
+
   pages = run_command_list(cmds, pages);
 
   for (auto pg: pages)
     {
-      page_out out;
+      out_context out;
       out.resources = QPDFObjectHandle::newDictionary();
-      // FIXME: What if the source page requires a broader ProcSet?
-      out.resources.replaceKey("/ProcSet", QPDFObjectHandle::parse("[/PDF /Text]"));
+      out.resources.replaceKey("/ProcSet", QPDFObjectHandle::parse("[/PDF]"));
       out.xobjects = QPDFObjectHandle::newDictionary();
       out.resources.replaceKey("/XObject", out.xobjects);
       pg->render(&out, pdf_matrix());
@@ -107,6 +137,8 @@ static void process(list<cmd *> &cmds, const char *in_name, const char *out_name
       QPDFObjectHandle out_page = out_pdf.makeIndirectObject(QPDFObjectHandle::newDictionary());
       out_page.replaceKey("/Type", QPDFObjectHandle::newName("/Page"));
       out_page.replaceKey("/MediaBox", BBox(pg->width, pg->height).to_array());
+      // FIXME:
+      // out_page.replaceKey("/CropBox", pg->bbox.to_array());
       out_page.replaceKey("/Contents", contents);
       out_page.replaceKey("/Resources", out.resources);
       out_pdf.addPage(out_page, false);
@@ -132,6 +164,12 @@ static void process(list<cmd *> &cmds, const char *in_name, const char *out_name
 
 int main(int argc, char **argv)
 {
+  if (argc <= 1 || argc > 1 && !strcmp(argv[1], "--help"))
+    {
+      help();
+      return 0;
+    }
+
   if (argc != 4)
     {
       fprintf(stderr, "Usage: paperjam <commands> <input> <output>\n");