9 class null_cmd : public cmd_exec {
10 vector<page *> process(vector<page *> &pages) { return pages; }
13 static const arg_def no_args[] = {
17 static cmd_exec *null_ctor(cmd *c UNUSED)
24 class move_cmd : public cmd_exec {
27 vector<page *> process(vector<page *> &pages);
30 class xform_page : public page {
34 void render(page_out *out, pdf_matrix xform);
35 xform_page(page *_orig, double _w, double _h) : page(_w, _h), orig_page(_orig) { }
38 void xform_page::render(page_out *out, pdf_matrix parent_xform)
40 orig_page->render(out, xform * parent_xform);
43 vector<page *> move_cmd::process(vector<page *> &pages)
48 xform_page *q = new xform_page(p, p->width, p->height);
55 static const arg_def move_args[] = {
56 { "x", AT_DIMEN | AT_MANDATORY | AT_POSITIONAL },
57 { "y", AT_DIMEN | AT_MANDATORY | AT_POSITIONAL },
61 static cmd_exec *move_ctor(cmd *c)
63 move_cmd *m = new move_cmd;
64 m->x = c->args.at(0)->as_double(0);
65 m->y = c->args.at(1)->as_double(0);
71 class scale_cmd : public cmd_exec {
73 double x_factor, y_factor;
74 vector<page *> process(vector<page *> &pages);
77 vector<page *> scale_cmd::process(vector<page *> &pages)
82 xform_page *q = new xform_page(p, x_factor*p->width, y_factor*p->height);
83 q->xform.scale(x_factor, y_factor);
89 static const arg_def scale_args[] = {
90 { "x", AT_DOUBLE | AT_MANDATORY | AT_POSITIONAL },
91 { "y", AT_DOUBLE | AT_POSITIONAL },
95 static cmd_exec *scale_ctor(cmd *c)
97 scale_cmd *s = new scale_cmd;
98 s->x_factor = c->args.at(0)->as_double(1);
99 s->y_factor = c->args.at(1)->as_double(s->x_factor);
105 class rotate_cmd : public cmd_exec {
108 vector<page *> process(vector<page *> &pages);
111 vector<page *> rotate_cmd::process(vector<page *> &pages)
116 xform_page *q = new xform_page(p, p->width, p->height);
122 q->xform.rotate_deg(-90);
123 q->xform.shift(0, p->width);
124 swap(q->width, q->height);
127 q->xform.rotate_deg(180);
128 q->xform.shift(p->width, p->height);
131 q->xform.rotate_deg(90);
132 q->xform.shift(p->height, 0);
133 swap(q->width, q->height);
143 static const arg_def rotate_args[] = {
144 { "angle", AT_INT | AT_MANDATORY | AT_POSITIONAL },
148 static cmd_exec *rotate_ctor(cmd *c)
150 rotate_cmd *r = new rotate_cmd;
151 r->deg = c->args.at(0)->as_int(0) % 360;
155 die("Rotate requires a multiple of 90 degrees");
161 class select_cmd : public cmd_exec {
164 vector<page *> process(vector<page *> &pages);
167 static int validate_page_index(vector<page *> &pages, int idx)
169 if (idx >= 1 && idx <= (int) pages.size())
171 if (idx <= -1 && idx >= (int) -pages.size())
172 return idx + pages.size();
173 die("Page index %d out of range", idx);
176 vector<page *> select_cmd::process(vector<page *> &pages)
179 for (auto pb: pipe->branches)
181 vector<page *> selected;
182 for (auto ps: pb->selectors)
184 int f = validate_page_index(pages, ps.from);
185 int t = validate_page_index(pages, ps.to);
186 int step = (f <= t) ? 1 : -1;
187 for (int i=f; f<=t; f += step)
188 selected.push_back(pages[i]);
190 auto processed = run_command_list(pb->commands, selected);
191 for (auto p: processed)
197 static cmd_exec *select_ctor(cmd *c)
199 select_cmd *r = new select_cmd;
206 class apply_cmd : public cmd_exec {
209 vector<page *> process(vector<page *> &pages);
212 static pipeline_branch *find_branch(pipeline *pipe, vector <page *> &pages, int idx)
214 for (auto pb: pipe->branches)
215 for (auto ps: pb->selectors)
217 int f = validate_page_index(pages, ps.from);
218 int t = validate_page_index(pages, ps.to);
219 if (f <= idx && idx <= t || t <= idx && idx <= f)
225 vector<page *> apply_cmd::process(vector<page *> &pages)
232 pipeline_branch *pb = find_branch(pipe, pages, cnt);
237 auto processed = run_command_list(pb->commands, tmp);
238 for (auto q: processed)
249 static cmd_exec *apply_ctor(cmd *c)
251 apply_cmd *r = new apply_cmd;
258 class modulo_cmd : public cmd_exec {
262 vector<page *> process(vector<page *> &pages);
265 vector<page *> modulo_cmd::process(vector<page *> &pages)
268 int tuples = ((int) pages.size() + n - 1) / n;
270 for (int tuple=0; tuple < tuples; tuple++)
272 debug("# Tuple %d", tuple);
274 for (auto pb: pipe->branches)
277 for (auto ps: pb->selectors)
281 int step = (f <= t) ? 1 : -1;
282 for (int i=f; i<=t; i += step)
287 else if (i < 0 && i >= -n)
288 j = (tuples-1-tuple)*n + (-i) - 1;
290 die("Modulo: invalid index %d", i);
291 if (j < (int) pages.size())
292 tmp.push_back(pages[j]);
295 page *ref_page = pages[tuple*n];
296 tmp.push_back(new empty_page(ref_page->width, ref_page->height));
300 auto processed = run_command_list(pb->commands, tmp);
301 for (auto q: processed)
310 static const arg_def modulo_args[] = {
311 { "n", AT_INT | AT_MANDATORY | AT_POSITIONAL },
315 static cmd_exec *modulo_ctor(cmd *c)
317 modulo_cmd *m = new modulo_cmd;
318 m->n = c->args.at(0)->as_int(0);
320 die("Modulo must have n > 0");
325 /*** Command table ***/
327 const cmd_def cmd_table[] = {
328 { "null", no_args, 0, null_ctor },
329 { "move", move_args, 0, move_ctor },
330 { "scale", scale_args, 0, scale_ctor },
331 { "rotate", rotate_args, 0, rotate_ctor },
332 { "select", no_args, 1, select_ctor },
333 { "apply", no_args, 1, apply_ctor },
334 { "modulo", modulo_args, 1, modulo_ctor },
335 { NULL, NULL, 0, NULL }