+/*
+ * PaperJam -- Common declarations
+ *
+ * (c) 2018--2022 Martin Mares <mj@ucw.cz>
+ */
+
#include <vector>
#include <list>
+#include <unordered_map>
+#include <cmath>
-#include "pdf-tools.h"
+using namespace std;
typedef unsigned int uint;
#define NONRET __attribute__((noreturn))
+#define UNUSED __attribute__((unused))
+#define FORMAT_CHECK(x,y,z) __attribute__((format(x,y,z)))
-struct pipeline;
+static inline bool is_zero(double z)
+{
+ return fabs(z) < 1e-6;
+}
-union arg_val {
- string *s;
- double d;
- pipeline *p;
-};
+static inline bool is_equal(double x, double y)
+{
+ return is_zero(x-y);
+}
+
+void debug(const char *msg, ...) FORMAT_CHECK(printf, 1, 2);
+void warn(const char *msg, ...) FORMAT_CHECK(printf, 1, 2);
+void die(const char *msg, ...) FORMAT_CHECK(printf, 1, 2) NONRET;
+
+// This one is called during execution of commands and propagated as an exception
+void err(const char *msg, ...) FORMAT_CHECK(printf, 1, 2) NONRET;
+
+#include "pdf-tools.h"
+
+/*** Representation of commands ***/
+
+struct pipeline;
+struct cmd;
enum arg_type {
AT_STRING,
+ AT_INT,
AT_DOUBLE,
AT_DIMEN,
- AT_PIPELINE, // Pipeline has an empty name
+ AT_SWITCH,
AT_TYPE_MASK = 0xffff,
AT_MANDATORY = 0x10000,
AT_POSITIONAL = 0x20000,
struct arg_def {
const char *name;
uint type;
+ const char *help;
+};
+
+class arg_val {
+public:
+ virtual bool given() { return false; }
+ virtual int as_int(int def) { return def; }
+ virtual double as_double(double def) { return def; }
+ virtual const string as_string(const string def) { return def; }
+ virtual string dump() { return "<undef>"; }
};
-struct page_out {
+extern arg_val null_arg;
+
+struct out_context {
+ QPDF *pdf;
+ QPDFObjectHandle resources;
+ QPDFObjectHandle xobjects;
+ QPDFObjectHandle egstates;
+ string contents;
+ int res_cnt;
+ string new_resource(const string type);
+ out_context() { res_cnt = 0; }
};
struct page {
- double width;
+ int index; // Position in the source PDF, 0 for synthesized pages
+ double width; // Physical dimensions of media
double height;
- void render(page_out *out, pdf_matrix xform);
+ BBox image_box; // Bounds useful contents
+ virtual void render(out_context *out UNUSED, pdf_matrix xform UNUSED) { abort(); }
+ virtual void debug_dump() = 0;
+ page(double _w=0, double _h=0) : index(0), width(_w), height(_h), image_box() { }
+ page(page *p)
+ {
+ index = p->index;
+ width = p->width;
+ height = p->height;
+ image_box = p->image_box;
+ }
};
-struct cmd {
+struct empty_page : public page {
+ void render(out_context *out UNUSED, pdf_matrix xform UNUSED) { }
+ void debug_dump() { debug("Empty page"); }
+ empty_page(double _w=0, double _h=0) : page(_w, _h) { };
};
-struct cmd_args {
- vector<arg_val> arg;
- vector<bool> arg_given;
+struct cmd_exec {
+ virtual vector<page *> process(vector <page *> &pages UNUSED) = 0;
};
struct cmd_def {
const char *name;
const arg_def *arg_defs;
- cmd (*constructor)(cmd_args *args);
+ bool has_pipeline;
+ cmd_exec *(*constructor)(cmd *cmd);
+ const char *help;
+};
+
+struct cmd {
+ const cmd_def *def;
+ unordered_map<string, arg_val *> args;
+ pipeline *pipe;
+ cmd_exec *exec;
+ arg_val *arg(const string name)
+ {
+ auto it = args.find(name);
+ if (it != args.end())
+ return it->second;
+ else
+ return &null_arg;
+ }
};
struct pipeline_selector {
struct pipeline_branch {
vector<pipeline_selector> selectors;
- list<cmd> commands;
+ list<cmd *> commands;
};
struct pipeline {
vector<pipeline_branch *> branches;
};
+
+/*** Modules ***/
+
+// paperjam.cc
+
+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;
+public:
+ paperjam_error(string m) : message(m) { }
+ const char *what() const noexcept override { return message.c_str(); }
+};
+
+// parse.cc
+
+void parse(const char *in, list<cmd *> &cmds);
+void parser_help();
+
+// cmds.cc
+
+extern const cmd_def cmd_table[];
+
+// pdf.cc
+
+void debug_pages(vector<page *> &pages);
+void process(list<cmd *> &cmds);
+vector<page *> run_command_list(list<cmd *> &cmds, vector<page *> &pages);
+vector<BBox> gs_bboxes(const char *in);
+
+class xform_page : public page {
+ page *orig_page;
+ pdf_matrix xform;
+ const char *description;
+public:
+ void render(out_context *out, pdf_matrix xform) override;
+ void debug_dump() override;
+ xform_page(page *p, const char *desc, pdf_matrix xf);
+};