From: Martin Mares Date: Sat, 20 Aug 2022 11:16:25 +0000 (+0200) Subject: Automatic page rotation based on the /Rotate key X-Git-Tag: v1.2~1 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=298d65bac130d6aa4c925c70f3342eb8e68a4b97;p=paperjam.git Automatic page rotation based on the /Rotate key --- diff --git a/TODO b/TODO index 58b1426..b7dbf22 100644 --- 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 fa1e13b..3362604 100644 --- a/jam.h +++ b/jam.h @@ -1,7 +1,7 @@ /* * PaperJam -- Common declarations * - * (c) 2018 Martin Mares + * (c) 2018--2022 Martin Mares */ #include @@ -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; diff --git a/paperjam.1.txt b/paperjam.1.txt index 8f2c4bb..94f3432 100644 --- a/paperjam.1.txt +++ b/paperjam.1.txt @@ -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. diff --git a/paperjam.cc b/paperjam.cc index 3af52ab..108087a 100644 --- a/paperjam.cc +++ b/paperjam.cc @@ -1,7 +1,7 @@ /* * PaperJam -- Main program * - * (c) 2018 Martin Mares + * (c) 2018--2022 Martin Mares */ #include @@ -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\ = (, [=], ...) []\n\ = { , , ... }\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 bcbfb5d..9f8dc12 100644 --- a/pdf.cc +++ b/pdf.cc @@ -1,7 +1,7 @@ /* * PaperJam -- Low-level handling of PDFs * - * (c) 2018 Martin Mares + * (c) 2018--2022 Martin Mares */ #include @@ -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 &pages) { if (!debug_level) @@ -96,6 +120,25 @@ void debug_pages(vector &pages) } } +static vector apply_input_xforms(vector in_pages) +{ + vector out_pages; + + for (auto pg: in_pages) + { + in_page * in_pg = dynamic_cast(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 run_command_list(list &cmds, vector &pages) { debug("# Input"); @@ -165,6 +208,12 @@ void process(list &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);