]> mj.ucw.cz Git - paperjam.git/commitdiff
Automatic page rotation based on the /Rotate key
authorMartin Mares <mj@ucw.cz>
Sat, 20 Aug 2022 11:16:25 +0000 (13:16 +0200)
committerMartin Mares <mj@ucw.cz>
Sun, 21 Aug 2022 11:18:48 +0000 (13:18 +0200)
TODO
jam.h
paperjam.1.txt
paperjam.cc
pdf.cc

diff --git a/TODO b/TODO
index 58b14266c1f22bb36a0d307f995cc098bf16fd52..b7dbf22677dc357e072910d3afe039e9396bfa97 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,5 +1,4 @@
 - Integrate pdf-tools.cc with the rest of the code
-- What if an input page specifies /Rotate?
 - "-f" switch
 - What should do modulo(half) with an odd number of tuples? Improve, or at least document.
 - Modulo with last tuple incomplete: sometimes, not padding the last tuple can be useful
diff --git a/jam.h b/jam.h
index fa1e13b164eb98d865112b45a59de4d414584f41..33626040cc3ed58bd70349406f3a0480e7b1d0d9 100644 (file)
--- a/jam.h
+++ b/jam.h
@@ -1,7 +1,7 @@
 /*
  *     PaperJam -- Common declarations
  *
- *     (c) 2018 Martin Mares <mj@ucw.cz>
+ *     (c) 2018--2022 Martin Mares <mj@ucw.cz>
  */
 
 #include <vector>
@@ -152,6 +152,7 @@ extern const char *in_name, *out_name;
 extern bool recalc_bbox;
 extern int debug_level;
 extern int debug_indent;
+extern bool no_auto_transforms;
 
 class paperjam_error : public exception {
   string message;
index 8f2c4bb93b8dd53c24e89bfec35a18a5f6648161..94f3432515527a1f3622348be24077070caf5b1c 100644 (file)
@@ -35,6 +35,11 @@ OPTIONS
 *-d, --debug*::
        Show debugging messages. Increases verbosity when given multiple times.
 
+*--no-auto*::
+       Do not perform automatic transforms. Currently, only one such transform
+       is implemented: rotation of pages based on the *Rotate* property of
+       page objects.
+
 *--help*::
        Show help on options and commands.
 
index 3af52ab9dfb17316c512cb1a9ad320ad5bda5f21..108087a311a669cdcedad79153bdb660c772e258 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     PaperJam -- Main program
  *
- *     (c) 2018 Martin Mares <mj@ucw.cz>
+ *     (c) 2018--2022 Martin Mares <mj@ucw.cz>
  */
 
 #include <cassert>
@@ -17,6 +17,7 @@
 const char *in_name;
 const char *out_name;
 bool recalc_bbox;
+bool no_auto_transforms;
 int debug_level;
 int debug_indent;
 
@@ -69,6 +70,7 @@ void err(const char *msg, ...)
 enum opt {
   OPT_HELP = 256,
   OPT_VERSION,
+  OPT_NO_AUTO,
 };
 
 static const struct option long_opts[] = {
@@ -88,6 +90,7 @@ static void usage()
 Options:\n\
 -b, --bbox             Recalculate bounding boxes\n\
 -d, --debug            Show debugging messages\n\
+    --no-auto          Disable automatic rotation of pages\n\
 \n\
 <command> = <name>(<args>, <named-arg>[=<value>], ...) [<pipeline>]\n\
 <pipeline> = { <stage>, <stage>, ... }\n\
@@ -123,6 +126,9 @@ int main(int argc, char **argv)
       case OPT_HELP:
        usage();
        return 0;
+      case OPT_NO_AUTO:
+       no_auto_transforms = true;
+       break;
       default:
        exit(1);
       }
diff --git a/pdf.cc b/pdf.cc
index bcbfb5d00ff8cdbbeb39aeb21e827d1e7b27329a..9f8dc12bcd5e94c6d620f6d81733e81c9182ea93 100644 (file)
--- a/pdf.cc
+++ b/pdf.cc
@@ -1,7 +1,7 @@
 /*
  *     PaperJam -- Low-level handling of PDFs
  *
- *     (c) 2018 Martin Mares <mj@ucw.cz>
+ *     (c) 2018--2022 Martin Mares <mj@ucw.cz>
  */
 
 #include <cassert>
@@ -33,6 +33,7 @@ public:
   void render(out_context *out, pdf_matrix xform);
   void debug_dump() { debug("Input page %d", index); }
   in_page(QPDFObjectHandle inpg, int idx);
+  int get_rotate();
 };
 
 in_page::in_page(QPDFObjectHandle inpg, int idx)
@@ -75,6 +76,29 @@ void in_page::render(out_context *out, pdf_matrix xform)
   out->contents += "q " + m.to_string() + " cm " + xobj_res + " Do Q ";
 }
 
+int in_page::get_rotate()
+{
+  QPDFObjectHandle rotate = pdf_page.getKey("/Rotate");
+  if (rotate.isNull())
+    return 0;
+  else if (rotate.isInteger())
+    {
+      long long deg = rotate.getIntValue();
+      if (deg < 0 || deg >= 360 || deg % 90)
+       {
+         warn("Page #%d: /Rotate must be 0, 90, 180 or 270", index);
+         return 0;
+       }
+      else
+       return deg;
+    }
+  else
+    {
+      warn("Page #%d: /Rotate is not an integer", index);
+      return 0;
+    }
+}
+
 void debug_pages(vector<page *> &pages)
 {
   if (!debug_level)
@@ -96,6 +120,25 @@ void debug_pages(vector<page *> &pages)
     }
 }
 
+static vector<page *> apply_input_xforms(vector<page *> in_pages)
+{
+  vector<page *> out_pages;
+
+  for (auto pg: in_pages)
+    {
+      in_page * in_pg = dynamic_cast<in_page *>(pg);
+      if (in_pg)
+       {
+         int deg = in_pg->get_rotate();
+         if (deg)
+           pg = new xform_page(pg, "/Rotate", pdf_rotation_matrix(deg, pg->width, pg->height));
+       }
+      out_pages.push_back(pg);
+    }
+
+  return out_pages;
+}
+
 vector<page *> run_command_list(list<cmd *> &cmds, vector<page *> &pages)
 {
   debug("# Input");
@@ -165,6 +208,12 @@ void process(list<cmd *> &cmds)
   if (recalc_bbox)
     do_recalc_bbox(pages, in_name);
 
+  if (!no_auto_transforms)
+    {
+      debug("### Applying input transforms");
+      pages = apply_input_xforms(pages);
+    }
+
   debug("### Running commands");
   pages = run_command_list(cmds, pages);